diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/AndroidManifest.xml b/OculusMobile/NOMADGearvrT/Projects/Android/AndroidManifest.xml
index f9092ab7117ca2899d906eec61c9bad0b0eaf717..fd0577b7bf7cd61069cfc597df6589e92c3b0d5a 100644
--- a/OculusMobile/NOMADGearvrT/Projects/Android/AndroidManifest.xml
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/AndroidManifest.xml
@@ -1,8 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 		package="com.lrz.NOMADGearvrT"
-		android:versionCode="1"
-		android:versionName="1.0" >
+		android:versionCode="2"
+		android:versionName="1.0" 
+		android:installLocation="auto"
+		>
+		
 	<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
 	<!-- Allow reading of the appropriate lens distortion file for the device. -->
 	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -16,7 +19,7 @@
 	<uses-feature android:name="android.hardware.usb.host" />
 	<!-- Tell the system this app requires OpenGL ES 3.0. -->
 	<!--rgh: For tesselation, we need 3.2-->
-	<uses-feature android:glEsVersion="0x00030002" android:required="true" />
+	<uses-feature android:glEsVersion="0x00030001" android:required="true" />
 	<application
 			android:allowBackup="true"
 			android:icon="@drawable/ic_launcher"
@@ -30,7 +33,8 @@
 				android:label="@string/app_name"
 				android:launchMode="singleTask"
 				android:screenOrientation="landscape"
-				android:configChanges="orientation|screenSize|keyboard|keyboardHidden"> 
+				android:configChanges=	"screenSize|screenLayout|orientation|keyboardHidden|keyboard|navigation"
+				 android:excludeFromRecents="true">
 			<!--Test opening a NOMAD url-->
 			<intent-filter>
 				<action android:name="android.intent.action.VIEW" />
@@ -49,9 +53,10 @@
 					  android:mimeType="application/octet-stream"/>
 			</intent-filter>
 			<!-- This filter lets the apk show up as a launchable icon -->
+			<!-- rgh: hiding as only the gearvrchooser should be shown -->
 			<intent-filter>
 				<action android:name="android.intent.action.MAIN" />
-				<category android:name="android.intent.category.LAUNCHER" />
+				<category android:name="android.intent.category.INFO" />
 			</intent-filter>
 		</activity>
 	</application>
diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/build.gradle b/OculusMobile/NOMADGearvrT/Projects/Android/build.gradle
index 965a20dfaea95d2897cb34b2fe3a28dc34da07fc..a121a6ab886c874426c230c80dd2bd33da2e99d5 100644
--- a/OculusMobile/NOMADGearvrT/Projects/Android/build.gradle
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/build.gradle
@@ -15,6 +15,8 @@ android {
   defaultConfig {
 	minSdkVersion 21
 	targetSdkVersion 21
+	versionCode 2     
+    versionName "0.2"  
   }
   
   sourceSets {
diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/jni/Android.mk b/OculusMobile/NOMADGearvrT/Projects/Android/jni/Android.mk
index 2e0d5ff0d1fbe2acefc308ab605b3c0243520e52..8ea09a2e6431ef1b036c6b453fb26f9010de88a9 100644
--- a/OculusMobile/NOMADGearvrT/Projects/Android/jni/Android.mk
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/jni/Android.mk
@@ -14,7 +14,10 @@ LOCAL_SRC_FILES			:= ../../../Src/OvrApp.cpp ../../../Src/rply/rply.c \
 	../../../Src/NOMADVRLib/UnitCellShaders.cpp \
 	../../../Src/NOMADVRLib/polyhedron.cpp \
 	../../../Src/NOMADVRLib/IsosurfacesGL.cpp \
-	../../../Src/NOMADVRLib/IsoShaders.cpp
+	../../../Src/NOMADVRLib/IsoShaders.cpp \
+	../../../Src/NOMADVRLib/grid.cpp \
+	../../../Src/NOMADVRLib/markerShaders.cpp 
+	
 LOCAL_STATIC_LIBRARIES	:= vrsound vrmodel vrlocale vrgui vrappframework systemutils libovrkernel
 LOCAL_SHARED_LIBRARIES	:= vrapi
 
diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/res/values/strings.xml b/OculusMobile/NOMADGearvrT/Projects/Android/res/values/strings.xml
index 9f542ef4ef14154cc1c52f037977eb53eb6fc711..4db68d309718c2640d8ee0d1874b745874366e81 100644
--- a/OculusMobile/NOMADGearvrT/Projects/Android/res/values/strings.xml
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/res/values/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
 
-    <string name="app_name">NOMADGearvrT</string>
+    <string name="app_name">NOMAD GearVR</string>
     <string name="action_settings">Settings</string>
     <string name="hello_world">Hello world!</string>
 
diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/Filepath.java b/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/Filepath.java
new file mode 100644
index 0000000000000000000000000000000000000000..4645f287a63ed1c2c0ba3901574b7e00da3ece73
--- /dev/null
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/Filepath.java
@@ -0,0 +1,72 @@
+package oculus;
+//This file is the same, except for the package above, as 
+//NOMADgvrT\src\main\java\com\google\vr\ndk\samples\treasurehunt\Filepath.java
+
+//https://stackoverflow.com/questions/3401579/get-filename-and-path-from-uri-from-mediastore/7265235#7265235
+
+class Filepath {
+
+//@SuppressLint("NewApi")
+    public static String getFilePath(android.content.Context context, android.net.Uri uri) throws java.net.URISyntaxException {
+        String selection = null;
+        String[] selectionArgs = null;
+        // Uri is different in versions after KITKAT (Android 4.4), we need to
+        if (android.os.Build.VERSION.SDK_INT >= 19 && android.provider.DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
+            if (isExternalStorageDocument(uri)) {
+                final String docId = android.provider.DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                return android.os.Environment.getExternalStorageDirectory() + "/" + split[1];
+            } else if (isDownloadsDocument(uri)) {
+                final String id = android.provider.DocumentsContract.getDocumentId(uri);
+                uri = android.content.ContentUris.withAppendedId(
+                        android.net.Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+            } else if (isMediaDocument(uri)) {
+                final String docId = android.provider.DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+                if ("image".equals(type)) {
+                    uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    uri = android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+                selection = "_id=?";
+                selectionArgs = new String[]{
+                        split[1]
+                };
+            }
+        }
+        if ("content".equalsIgnoreCase(uri.getScheme())) {
+            String[] projection = {
+                    android.provider.MediaStore.Images.Media.DATA
+            };
+            android.database.Cursor cursor = null;
+            try {
+                cursor = context.getContentResolver()
+                        .query(uri, projection, selection, selectionArgs, null);
+                int column_index = cursor.getColumnIndexOrThrow(android.provider.MediaStore.Images.Media.DATA);
+                if (cursor.moveToFirst()) {
+                    return cursor.getString(column_index);
+                }
+            } catch (Exception e) {
+            }
+        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
+            return uri.getPath();
+        }
+        return null;
+    }
+
+    public static boolean isExternalStorageDocument(android.net.Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    public static boolean isDownloadsDocument(android.net.Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    public static boolean isMediaDocument(android.net.Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
+    }
+
+}
diff --git a/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/MainActivity.java b/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/MainActivity.java
index 2718a85790932fdc6726bec69d94dce44f66a0e5..72cd062f7559a0412d0a6a1cfc842d390bde29f8 100644
--- a/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/MainActivity.java
+++ b/OculusMobile/NOMADGearvrT/Projects/Android/src/oculus/MainActivity.java
@@ -25,49 +25,82 @@ public class MainActivity extends VrActivity {
 		System.loadLibrary("ovrapp");
 	}
 
-    public static native long nativeSetAppInterface( VrActivity act, String fromPackageNameString, String commandString, String uriString );
+//http://stackoverflow.com/questions/8854359/exception-open-failed-eacces-permission-denied-on-android
+// Storage Permissions
+private static final int REQUEST_EXTERNAL_STORAGE = 1;
+private static String[] PERMISSIONS_STORAGE = {
+        android.Manifest.permission.READ_EXTERNAL_STORAGE,
+        android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+};
+
+/**
+ * Checks if the app has permission to write to device storage
+ *
+ * If the app does not has permission then the user will be prompted to grant permissions
+ *
+ * @param activity
+ */
+public static void verifyStoragePermissions(android.app.Activity activity) {
+    // Check if we have write permission
+ /*   int permission =  	android.support.v4.app.ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
 
+    if (permission != android.content.pm.PackageManager.PERMISSION_GRANTED) {
+        // We don't have permission so prompt the user
+        android.support.v4.app.ActivityCompat.requestPermissions(
+                activity,
+                PERMISSIONS_STORAGE,
+                REQUEST_EXTERNAL_STORAGE
+        );
+    }*/
+}
+	
+    public static native long nativeSetAppInterface( VrActivity act, String fromPackageNameString, String commandString, String uriString );
+/*
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, android.content.Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if(requestCode==123 && resultCode==RESULT_OK) {
+		String s=data.getDataString();
+		android.util.Log.d("NOMADGearvrT","OnActivityResult, s="+s);
+		String uriString="";
+     		if (s.startsWith("file://")) {
+			uriString=s.substring(7);
+		} else if (s.startsWith("content://com.asus.filemanager.OpenFileProvider/file")) {
+			uriString=s.substring(52);
+		} else {
+			android.net.Uri u=android.net.Uri.parse(s);
+			try {
+			uriString=Filepath.getFilePath (this.getApplicationContext(), u);
+			} catch (java.net.URISyntaxException e) {
+			android.util.Log.d("NOMADgvrT","URISyntaxException, e="+e);
+			uriString=null;
+			}
+		}
+		android.util.Log.d("NOMADgvrT","OnActivityResult, uri="+uriString);
+		nativeSetConfigFile(uriString, android.os.Environment.getExternalStorageDirectory().getPath() + "/");   
+		nativeLoadConfigFile(nativeTreasureHuntRenderer);    
+        }
+    }	
+	*/
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+		
         super.onCreate(savedInstanceState);
-
+		
+		verifyStoragePermissions(this);
+		
 		Intent intent = getIntent();
 		String commandString = VrActivity.getCommandStringFromIntent( intent );
 		String fromPackageNameString = VrActivity.getPackageStringFromIntent( intent );
-		String uriString = VrActivity.getUriStringFromIntent( intent );
-
-		//rgh: if intent, save to tmp file and pass it over
-		if (uriString.startsWith("content://")) {
-			//http://stackoverflow.com/questions/14364091/retrieve-file-path-from-caught-downloadmanager-intent
-			//http://stackoverflow.com/questions/1477269/write-a-binary-downloaded-file-to-disk-in-java
-			//http://stackoverflow.com/questions/4864875/folder-for-temporary-files-creation-in-android-why-does-data-local-tmp-doesnt
-			uriString="file:///data/local/tmp/material.ncfg";
-			try {
-				java.io.InputStream input = getContentResolver().openInputStream(intent.getData());
-				byte[] buffer = new byte[8 * 1024];
-				java.io.FileOutputStream output = new java.io.FileOutputStream("/data/local/tmp/material.ncfg");
-				try{
-					int bytesRead;
-					while((bytesRead = input.read()) != -1){
-						output.write(buffer, 0, bytesRead);
-					}
-				} finally {
-					try{
-						output.close();
-					} catch (Exception e) {
-						uriString="error";
-					}
-					try {
-						input.close();
-					} catch (java.io.IOException e) {
-						uriString="error";
-					}
-				}
-			} catch (java.io.IOException e) {
-				uriString="error";
-			} 
+		String uriString = VrActivity.getUriStringFromIntent( intent );		
+		android.net.Uri u=android.net.Uri.parse(uriString);
+		try {
+			uriString=Filepath.getFilePath (this.getApplicationContext(), u);
+		} catch (java.net.URISyntaxException e) {
+		android.util.Log.d("NOMADgvrT","URISyntaxException, e="+e);
+		uriString=null;
 		}
-		
+
 		setAppPtr( nativeSetAppInterface( this, fromPackageNameString, commandString, uriString ) );
     }   
 }
diff --git a/OculusMobile/NOMADGearvrT/Src/OvrApp.cpp b/OculusMobile/NOMADGearvrT/Src/OvrApp.cpp
index 2a2cc9e7dc9865892260e7c25c9910f15b2fcf79..a0e1935d5d9cef9618c41f113907e5d2e92d5522 100644
--- a/OculusMobile/NOMADGearvrT/Src/OvrApp.cpp
+++ b/OculusMobile/NOMADGearvrT/Src/OvrApp.cpp
@@ -34,7 +34,7 @@ void eprintf( const char *fmt, ... )
 	vsprintf( buffer, fmt, args );
 	va_end( args );
 
-	LOG("Error in NOMADGearvrT");
+    LOG("Message from NOMADGearvrT");
 	if (*fmt=='\0')
 		LOG("Empty format");
 	LOG("<%s>", buffer);
@@ -105,33 +105,55 @@ void OvrApp::OneTimeInit( const char * fromPackage, const char * launchIntentJSO
 	OVR_UNUSED( fromPackage );
 	OVR_UNUSED( launchIntentJSON );
 
-    LOG("OneTimeInit, launchintentURI");
+    LOG("NOMADGearVRT, OneTimeInit, launchintentURI");
     LOG(launchIntentURI);
-	LOG("launchIntentURI==null");
+	LOG("NOMADGearVRT, launchIntentURI==null");
 	LOG("%d", launchIntentURI==nullptr);
 	//LOG("length of launchIntentURI=%d", strlen(launchIntentURI));
 	//for (unsigned int i=0;i<strlen(launchIntentURI);i++) {
 	//	LOG("<%c>: [%d]", launchIntentURI[i], launchIntentURI[i]);
 	//}
-	const char *defaultURI="file:///sdcard/Oculus/NOMAD/ViveTDefault.ncfg";
-	//open a default file if none given
-	if (!launchIntentURI || !strcmp(launchIntentURI, "")) {
-		LOG(" OneTimeInit changing launchIntentURI");
-		launchIntentURI=defaultURI;
+	
+	const char *configLocation="/sdcard/NOMAD/NOMADGearVR.cfg";
+	const char *defaultURI="/sdcard/Oculus/NOMAD/ViveTDefault.ncfg";
+
+	char finalURI[1024];
+	FILE *cl = fopen (configLocation, "r");
+	if (cl==nullptr) {
+		LOG("NOMADGearVRT, /sdcard/NOMAD/NOMADGearVR.cfg not found, using default at /sdcard/Oculus/NOMAD/ViveTDefault.ncfg");
+		strcpy(finalURI, defaultURI);
+	} else {
+        fgets(finalURI, 1024, cl);
+        //discard newline
+        int l=strlen(finalURI);
+        if (finalURI[l-1]=='\n')
+            finalURI[l-1]='\0';
+		LOG("NOMADGearVRT, /sdcard/NOMAD/NOMADGearVR.cfg found, using contents=%s", finalURI);
+		fclose (cl);
 	}
 	
-		LOG("OneTimeInit, launchintentURI");
+	
+
+	//open a default file if none given
+	//if (!launchIntentURI || !strcmp(launchIntentURI, "")) {
+	//	LOG(" OneTimeInit changing launchIntentURI");
+	//	launchIntentURI=finalURI;
+	//}
+	
+	LOG("NOMADGearVRT OneTimeInit, launchintentURI");
     LOG(launchIntentURI);
 	
 	
-	const char *configfile=launchIntentURI+6; //discard file://
+	const char *configfile=finalURI; 
 	
 	//change cwd so that relative paths work
 	std::string s(configfile);
 	chdir(s.substr(0, s.find_last_of("\\/")).c_str());
 	
+	LOG("NOMADGEARVRT, configfile=%s", configfile);
+	
 	int r;
-	LOG("OneTimeInit, 8");	
+	LOG("NOMADGearVRT OneTimeInit, 8");	
 	if ((r=loadConfigFile(configfile))<0) {
 		if (-100<r) {
 			eprintf(loadConfigFileErrors[-r]);
@@ -150,7 +172,7 @@ void OvrApp::OneTimeInit( const char * fromPackage, const char * launchIntentJSO
 	
 	}
 	if (!solid) {
-		LOG("No atom glyph specified, using Icosahedron");
+		LOG("NOMADGearVRT No atom glyph specified, using Icosahedron");
 		solid=new Solid(Solid::Type::Icosahedron);
 	}
 	LOG("OneTimeInit, 2");
@@ -185,7 +207,7 @@ LOG("OneTimeInit, 4");
 	//rgh: for now, we don't have any tess-ready phones
 	//if (!PrepareAtomShader(&AtomsP, &AtomMatrixLoc)) {
 		hasTess=false;
-		if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc))
+        if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc, &TotalatomsLoc))
 			eprintf ("PrepareAtomShaderNoTess failed");
 	//};
 //LOG("OneTimeInit, 7");	
@@ -197,7 +219,7 @@ LOG("OneTimeInit, 4");
 	if (e!=GL_NO_ERROR)
 		eprintf ("atomTexture error %d", e);
 //LOG("OneTimeInit, 7A");	
-	e=SetupAtoms(&AtomTVAO, &AtomTBuffer);
+    e=SetupAtoms(&AtomTVAO, &AtomTBuffer, &BondIndices);
 	if (e!=GL_NO_ERROR)
 		eprintf ("SetupAtoms error %d", e);
 //LOG("OneTimeInit, 7B");	
@@ -213,6 +235,15 @@ LOG("OneTimeInit, 4");
 	if (ISOS) {
 		PrepareISOShader(&ISOP, &ISOMatrixLoc);
 
+        float m=BACKGROUND[0];
+        m=std::max(m, BACKGROUND[1]);
+        m=std::max(m, BACKGROUND[2]);
+        if (m>0.2f) { //make background darker, preserving colour, so additive blending works
+              for (int i=0;i<3;i++)
+                   BACKGROUND[i]*=0.2f / m;
+        }
+
+
 		std::vector<float> vertices;
 #ifndef INDICESGL32
 		std::vector<short> indices;
@@ -236,10 +267,40 @@ LOG("OneTimeInit, 4");
 		for (int p = 0; p < TIMESTEPS*ISOS; p++) {
 			sprintf(tmpname, "%s%d-%s.ply", PATH, timestep, 
 				plyfiles[p % ISOS]);
-			Matrix4f matFinal=Matrix4f::RotationX(-M_PI_2) *
+
+            Matrix4f matFinal;
+            /*matFinal=Matrix4f::RotationX(-M_PI_2) *
 				Matrix4f::Translation(translations[p%ISOS][0],
 					translations[p%ISOS][1],
 					translations[p%ISOS][2]);
+*/
+//gvr
+            if (voxelSize[0]!=-1) {
+                Matrix4f mvs, abcm, matcubetrans, sctrans, sc;
+                mvs=Matrix4f::Scaling(scaling/(float)voxelSize[0], scaling/(float)voxelSize[1],
+                    scaling/(float)voxelSize[2]);
+                matcubetrans=Matrix4f::Translation(cubetrans[0], cubetrans[1], cubetrans[2]);
+
+                for (int i=0;i<3;i++) {
+                    for(int j=0;j<3;j++)
+                           abcm.M[i][j]=abc[i][j];
+                    abcm.M[i][3]=0;
+                }
+                abcm.M[4][4]=1;
+
+                sc=Matrix4f::Scaling(supercell[0], supercell[1], supercell[2]);
+                sctrans=Matrix4f::Translation(-translations[p%ISOS][2],
+                        -translations[p%ISOS][1], -translations[p%ISOS][0]);
+                matFinal = abcm*sctrans*sc*mvs;
+            } else {
+                matFinal=Matrix4f::Translation(translations[p%ISOS][0], translations[p%ISOS][1],
+                            translations[p%ISOS][2]);
+                matFinal=Matrix4f::Scaling(scaling)*matFinal;
+            }
+//end gvr
+
+
+
 			float t[16];
 			for (int i=0;i<4;i++)
 				for (int j=0;j<4;j++)
@@ -295,7 +356,7 @@ void OvrApp::OneTimeShutdown()
 bool OvrApp::OnKeyEvent( const int keyCode, const int repeatCount, const KeyEventType eventType )
 {
     animateTimesteps=!animateTimesteps;
-	eprintf("OnKeyEvent called!");
+    //eprintf("OnKeyEvent called! keycode=%d", keyCode);
     return true;
     /*if ( GuiSys->OnKeyEvent( keyCode, repeatCount, eventType ) )
     {
@@ -306,7 +367,7 @@ bool OvrApp::OnKeyEvent( const int keyCode, const int repeatCount, const KeyEven
 Matrix4f OvrApp::Frame( const VrFrame & vrFrame )
 {
 	
-	LOG("Start Frame");
+	LOG("NOMADGearVRT Start Frame");
     CenterEyeViewMatrix = vrapi_GetCenterEyeViewMatrix( &app->GetHeadModelParms(), &vrFrame.Tracking, NULL );
 
     if (animateTimesteps) {
@@ -316,7 +377,7 @@ Matrix4f OvrApp::Frame( const VrFrame & vrFrame )
             currentSet++;
             if (currentSet>TIMESTEPS-1)
                 currentSet=0;
-			LOG("currentSet updated, animate timesteps %d", currentSet);
+			LOG("NOMADGearVRT currentSet updated, animate timesteps %d", currentSet);
         }
     }
     Matrix4f rot;
@@ -359,7 +420,8 @@ void OvrApp::RenderIsos(const OVR::Matrix4f eyeViewProjection, int iso) {
 	GLenum e;
 	Matrix4f trans=Matrix4f::Translation(UserTranslation[0], UserTranslation[1], UserTranslation[2]);
 	//trans.translate(iPos).rotateX(-90).translate(UserPosition);
-	Matrix4f transform = eyeViewProjection*trans*Matrix4f::Scaling(0.2);
+    //rgh: prescaled on ply load
+    Matrix4f transform = eyeViewProjection*trans/**Matrix4f::Scaling(scaling)*/*Matrix4f::RotationX(-M_PI_2);
 	float t[16];
 	for (int i=0;i<4;i++)
 		for (int j=0;j<4;j++)
@@ -367,7 +429,7 @@ void OvrApp::RenderIsos(const OVR::Matrix4f eyeViewProjection, int iso) {
 	glUseProgram(ISOP);
 	if ((e = glGetError()) != GL_NO_ERROR)
 		eprintf("1 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
-glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
+    glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
 	if ((e = glGetError()) != GL_NO_ERROR)
 		eprintf("2 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
 
@@ -380,13 +442,17 @@ glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
 		if ((e = glGetError()) != GL_NO_ERROR)
 			eprintf("4 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
 	} else {
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+        glDepthMask(GL_FALSE);
 		for (int i=0;i<ISOS;i++) {
+            //rgh FIXME, redo this when we have the new rendering code for atom trajectories
 			glBindVertexArray(ISOVAO[currentSet*ISOS+i]);
-			glBindBuffer(GL_ARRAY_BUFFER, ISOBuffer[currentSet*ISOS+i]);
+            glBindBuffer(GL_ARRAY_BUFFER, ISOBuffer[currentSet*ISOS+i]);
 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ISOIndices[currentSet*ISOS+i]);
 			glEnableVertexAttribArray(0);
 			glEnableVertexAttribArray(1);
-			glEnableVertexAttribArray(2);
+            glEnableVertexAttribArray(2);
 			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(0*sizeof(float)));
 			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(3*sizeof(float)));
 			glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(6*sizeof(float)));
@@ -397,7 +463,10 @@ glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
 			if ((e = glGetError()) != GL_NO_ERROR)
 				eprintf("6 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
 		}
+        glDisable(GL_BLEND);
+        glDepthMask(GL_TRUE);
 	}
+    glBindVertexArray(0);
 }
 
 
@@ -411,13 +480,15 @@ void OvrApp::RenderAtoms(const float *m) //m[16]
 	
 	if (hasTess) {
 	//FIXME, unimplemented
-		LOG("FIXME, No Tess code for atoms yet!");
+		LOG("NOMADGearVRT FIXME, No Tess code for atoms yet!");
 		return;
 	} else { //no tess
 		glBindVertexArray(AtomVAO[0]);
 		glBindTexture(GL_TEXTURE_2D, textures[1]);
 		glUseProgram(AtomsP);
 		glUniformMatrix4fv(AtomMatrixLoc, 1, GL_FALSE, m);
+        glUniform1f(TotalatomsLoc, (float)getTotalAtomsInTexture());
+
 		if (currentSet==0) {
 			glDrawElements(GL_TRIANGLES, numAtoms[currentSet]* 3 * solid->nFaces, 
 #ifndef INDICESGL32				
@@ -463,21 +534,17 @@ if (!showTrajectories)
 
 int e;
 if (!AtomTVAO) {
-	LOG("RenderAtomTrajectoriesUnitCell, no atoms");
+	LOG("NOMADGearVRT RenderAtomTrajectoriesUnitCell, no atoms");
 	return;
 }
 glBindVertexArray(AtomTVAO[0]);
 
-//glUseProgram(UnitCellP);
-//glUniformMatrix4fv(m_nUnitCellMatrixLocation, 1, GL_FALSE, matrix);
-float color[4]={1,0,0,1};
-glUniform4fv(UnitCellColourLoc, 1, color);
+glUniform4fv(UnitCellColourLoc, 1, atomtrajectorycolour);
 if ((e = glGetError()) != GL_NO_ERROR)
-	eprintf("Gl error after glUniform4fv 2 RenderUnitCell: %d\n", e);
-//glEnableVertexAttribArray(0);
-//glDisableVertexAttribArray(1);
+    eprintf("Gl error after glUniform4fv 2 RenderAtomTrajectoriesUnitCell: %d\n", e);
 
 //LOG("atomtrajectories.size()=%d", atomtrajectories.size());
+//rgh FIXME, old code which does not work with large atom sets!
 glBindBuffer(GL_ARRAY_BUFFER, AtomTBuffer[0]);
 
 for (unsigned int i=0;i<atomtrajectories.size();i++) {
@@ -505,7 +572,7 @@ void OvrApp::RenderUnitCell(const Matrix4f eyeViewProjection)
 	if (UnitCellVAO==0)
 		eprintf ("Error, Unit Cell VAO not loaded");
 	int e;
-	
+    Matrix4f sc=Matrix4f::Scaling(scaling);
 	int p[3];
 	for (p[0]=0;p[0]<repetitions[0];(p[0])++)
 		for (p[1]=0;p[1]<repetitions[1];(p[1])++)
@@ -513,58 +580,72 @@ void OvrApp::RenderUnitCell(const Matrix4f eyeViewProjection)
 				{
 					float delta[3];
 					GetDisplacement(p, delta);
-					Vector3f iPos(delta[0]+UserTranslation[0], delta[1]+UserTranslation[1], delta[2]+UserTranslation[2]);
+                    //delta is in atom coordinates, need rotateX(-90)
+                    Vector3f iPos(delta[0]+UserTranslation[0]/scaling, delta[2]+UserTranslation[1]/scaling,
+                            -delta[1]+UserTranslation[2]/scaling);
 					Matrix4f trans=Matrix4f::Translation(iPos);
-					//trans.translate(iPos).rotateX(-90).translate(UserPosition);
-					Matrix4f transform = eyeViewProjection*trans;
+                    Matrix4f transform = eyeViewProjection*sc*trans*Matrix4f::RotationX(-M_PI_2);
 					float t[16];
 					for (int i=0;i<4;i++)
 						for (int j=0;j<4;j++)
 							t[j*4+i]=transform.M[i][j];
 					glUseProgram(UnitCellP);
 					glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
-					if ((e = glGetError()) != GL_NO_ERROR)
+                    if ((e = glGetError()) != GL_NO_ERROR)
 						eprintf("Gl error after glUniform4fv 1 RenderUnitCell: %d\n", e);
-					float color[4]={1,1,1,1};
-					glUniform4fv(UnitCellColourLoc, 1, color);
-					if ((e = glGetError()) != GL_NO_ERROR)
-						eprintf("Gl error after glUniform4fv 2 RenderUnitCell: %d\n", e);
-					glBindVertexArray(UnitCellVAO);
-					if ((e = glGetError()) != GL_NO_ERROR)
-						eprintf("Gl error after glBindVertexArray RenderUnitCell: %d\n", e);
-					glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);
-					if ((e = glGetError()) != GL_NO_ERROR)
-						eprintf("Gl error after RenderUnitCell: %d\n", e);
+                    if (displayunitcell) {
+                        glUniform4fv(UnitCellColourLoc, 1, unitcellcolour);
+                        if ((e = glGetError()) != GL_NO_ERROR)
+                            eprintf("Gl error after glUniform4fv 2 RenderUnitCell: %d\n", e);
+                        glBindVertexArray(UnitCellVAO);
+                        if ((e = glGetError()) != GL_NO_ERROR)
+                            eprintf("Gl error after glBindVertexArray RenderUnitCell: %d\n", e);
+                        glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);
+                        if ((e = glGetError()) != GL_NO_ERROR)
+                            eprintf("Gl error after RenderUnitCell: %d\n", e);
+                    }
 					//atom trajectories
 					RenderAtomTrajectoriesUnitCell();
 					RenderAtoms(t);
 				}
 }
 
+void OvrApp::RenderAtomTrajectories (const Matrix4f eyeViewProjection)
+{
+    if (!numAtoms)
+        return;
+    const Matrix4f sc=Matrix4f::Scaling(scaling);
+    const Matrix4f trans=Matrix4f::Translation(UserTranslation[0]/scaling,UserTranslation[1]/scaling,
+                UserTranslation[2]/scaling );
+    const Matrix4f transform = eyeViewProjection*sc*trans*Matrix4f::RotationX(-M_PI_2);
+
+    float t[16];
+    for (int i=0;i<4;i++)
+        for (int j=0;j<4;j++)
+            t[j*4+i]=transform.M[i][j];
+
+    glUseProgram(UnitCellP);
+    glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
+    RenderAtomTrajectoriesUnitCell();
+    RenderAtoms(t);
+}
 
 Matrix4f OvrApp::DrawEyeView( const int eye, const float fovDegreesX, const float fovDegreesY, ovrFrameParms & frameParms )
 {
     OVR_UNUSED( frameParms );
-	//LOG ("DrawEyeView 1, timestep=%d", currentSet);
     const Matrix4f eyeViewMatrix = vrapi_GetEyeViewMatrix( &app->GetHeadModelParms(), &CenterEyeViewMatrix, eye );
-    //near, far plane set here: 10000 for earth, 100000 for skymap
     const Matrix4f eyeProjectionMatrix = ovrMatrix4f_CreateProjectionFov( fovDegreesX, fovDegreesY, 0.0f, 0.0f, 1,100000/*1.0f, 0.0f*/ );
     const Matrix4f eyeViewProjection = eyeProjectionMatrix * eyeViewMatrix;
 
     GL( glClearColor( BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 1.0f ) );
     GL( glClear( GL_COLOR_BUFFER_BIT ) );
 
-    //GL(        glEnable (GL_BLEND));
-    //GL(        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
     GL( glDepthFunc(GL_LEQUAL));
-    //GL( glUseProgram( Program.program ) );
-    //GL( glUniformMatrix4fv( Program.uView, 1, GL_TRUE, eyeViewMatrix.M[0] ) );
-    //GL( glUniformMatrix4fv( Program.uProjection, 1, GL_TRUE, eyeProjectionMatrix.M[0] ) );
-
-    //glBindTexture(GL_TEXTURE_2D, textures[0]); //white
-	//LOG ("DrawEyeView 2");
-	RenderUnitCell(eyeViewProjection);
-	//LOG ("DrawEyeView 3");
+
+    if (has_abc)
+        RenderUnitCell(eyeViewProjection);
+    else
+        RenderAtomTrajectories(eyeViewProjection);
 	
 	if (ISOS)
 		RenderIsos(eyeViewProjection, ISOS);
@@ -575,7 +656,6 @@ Matrix4f OvrApp::DrawEyeView( const int eye, const float fovDegreesX, const floa
     GuiSys->RenderEyeView( CenterEyeViewMatrix, eyeViewMatrix, eyeProjectionMatrix );
 
     frameParms.Layers[VRAPI_FRAME_LAYER_TYPE_WORLD].Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION;
-	//LOG("End Frame");
     return eyeViewProjection;
 }
 
diff --git a/OculusMobile/NOMADGearvrT/Src/OvrApp.h b/OculusMobile/NOMADGearvrT/Src/OvrApp.h
index 3c65a7f5420599f423a3235564baf3c101d31818..2fa6be0d587aefd4cd3ffb916e22914ab3a1728b 100644
--- a/OculusMobile/NOMADGearvrT/Src/OvrApp.h
+++ b/OculusMobile/NOMADGearvrT/Src/OvrApp.h
@@ -43,7 +43,7 @@ private:
 	class OVR::ovrLocale *	Locale;
 
     GLuint			AtomsP, UnitCellP; // framework does not provide support for tesselation and provides many things we don't need.
-	GLint		AtomMatrixLoc, UnitCellMatrixLoc, UnitCellColourLoc;
+    GLint		AtomMatrixLoc, TotalatomsLoc, UnitCellMatrixLoc, UnitCellColourLoc;
     GLint				VertexTransformAttribute, VTAGrid;
 
     ovrMatrix4f			CenterEyeViewMatrix;
@@ -54,7 +54,8 @@ private:
     int animateCounter=0;
     GLuint textures[2]; // white, atoms
 	//if no tesselation is available, we still need the tess atoms for the trajectories!
-	GLuint *AtomTVAO=nullptr, *AtomTBuffer=nullptr, *AtomVAO=nullptr, *AtomBuffer=nullptr, *AtomIndices=nullptr,//[2], atoms, extraatoms
+    GLuint *AtomTVAO=nullptr, *AtomTBuffer=nullptr, BondIndices=0, *AtomVAO=nullptr, *AtomBuffer=nullptr,
+        *AtomIndices=nullptr,//[2], atoms, extraatoms
 		UnitCellVAO, UnitCellBuffer, UnitCellIndexBuffer;
 
 	GLuint *ISOVAO=nullptr/*[ISOS*TIMESTEPS]*/, *ISOBuffer=nullptr/*[ISOS*TIMESTEPS]*/,
@@ -65,6 +66,7 @@ private:
 		
 	void RenderAtoms(const float *m);
 	void RenderUnitCell(const OVR::Matrix4f eyeViewProjection);
+    void RenderAtomTrajectories (const OVR::Matrix4f eyeViewProjection);
 	void RenderAtomTrajectoriesUnitCell();
 	bool hasTess=true;
 	void RenderIsos(const OVR::Matrix4f eyeViewProjection, int iso);
diff --git a/libs/rply/rply.c b/libs/rply/rply.c
index c4105ef566ca6c3f0880269423f94316e825526f..f0550388c69aab84224fc21d6e221c01416d548d 100644
--- a/libs/rply/rply.c
+++ b/libs/rply/rply.c
@@ -1,3 +1,26 @@
+/*This code is based on rply, which uses the MIT license*/
+/*This license is compatible with Apache 2.0*/
+
+/* Changes:
+Rub�n Jes�s Garc�a Hern�ndez
+Fix missing initialization, lines 379, 482
+
+/*
+# 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.
+*/
+
 /* ----------------------------------------------------------------------
  * RPly library, read/write PLY files
  * Diego Nehab, IMPA
@@ -6,6 +29,9 @@
  * This library is distributed under the MIT License. See notice
  * at the end of this file.
  * ---------------------------------------------------------------------- */
+
+
+
 #include <stdio.h>
 #include <ctype.h>
 #include <assert.h>
@@ -372,7 +398,7 @@ p_ply ply_open(const char *name, p_ply_error_cb error_cb,
 
 p_ply ply_open_from_file(FILE *fp, p_ply_error_cb error_cb,
         long idata, void *pdata) {
-    p_ply ply;
+    p_ply ply=(void*)0;
     if (error_cb == NULL) error_cb = ply_error_cb;
     assert(fp);
     if (!ply_type_check()) {
@@ -475,7 +501,7 @@ p_ply ply_create(const char *name, e_ply_storage_mode storage_mode,
 
 p_ply ply_create_to_file(FILE *fp, e_ply_storage_mode storage_mode,
         p_ply_error_cb error_cb, long idata, void *pdata) {
-    p_ply ply;
+    p_ply ply=(void*)0;
     assert(fp && storage_mode <= PLY_DEFAULT);
     if (!ply_type_check()) {
         error_cb(ply, "Incompatible type system");
diff --git a/libs/rply/rply.h b/libs/rply/rply.h
index 9fa6da927f32563d06291d327b4d02c0e3aa3963..aba84b03bb40f4277902d8a1e0500b971cfeb8aa 100644
--- a/libs/rply/rply.h
+++ b/libs/rply/rply.h
@@ -8,7 +8,7 @@
  * This library is distributed under the MIT License. See notice
  * at the end of this file.
  * ---------------------------------------------------------------------- */
-
+ 
 #ifdef __cplusplus
 extern "C" {
 #endif