diff --git a/NOMADVRLib/IsosurfacesGL.cpp b/NOMADVRLib/IsosurfacesGL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2a4d5f2b63c770679fe5630559a392320a67a065
--- /dev/null
+++ b/NOMADVRLib/IsosurfacesGL.cpp
@@ -0,0 +1,222 @@
+//#if 0
+
+#include <vector>
+#include "MyGL.h"
+#include "eprintf.h"
+#include "ConfigFile.h" //for isocolours
+#include "IsosurfacesGL.h"
+
+float *CubeVertices=0;
+int *CubeIndices=0;
+int CurrentVertex=-1;
+int CurrentIndex=0;
+
+int vertex_cb(p_ply_argument argument);
+int face_cb(p_ply_argument argument);
+
+inline void mult (float *o/*[4]*/, const float *m/*[16]*/, const float* v/*[4]*/)  //o=m*v
+{
+	
+	for (int i=0;i<4;i++) {
+		o[i]=0;
+		for (int j=0;j<4;j++)
+			o[i]+=m[j*4+i]*v[j];
+	}
+}
+
+inline void normalize (float o[3])
+{
+	float mod=0;
+	for (int i=0;i<3;i++)
+		mod += o[i]*o[i];
+	mod=sqrtf(mod);
+	mod=1.0f/mod;
+	for (int i=0;i<3;i++)
+		o[i]*=mod;
+}
+
+bool AddModelToScene( const float *mat/*[16]*/, std::vector<float> &vertdata, 
+#ifndef INDICESGL32
+	std::vector<short> & vertindices, 
+#else
+	std::vector<GLuint> & vertindices,
+#endif
+	const char * model, bool water, bool colours, int set) 
+{
+
+	CurrentVertex=-1;
+	CurrentIndex=0;
+	 p_ply ply = ply_open(model, NULL, 0, NULL);
+        if (!ply) {
+			//rgh: files may not exist in the case of relative densities (0 density)
+            //eprintf("ply returned null: file %s\n", model);
+            return false;
+        }
+        if (!ply_read_header(ply)) {
+            eprintf("ply: bad header in ply: file %s\n", model);
+            return false;
+        }
+
+		int nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, nullptr, 0);
+        ply_set_read_cb(ply, "vertex", "y", vertex_cb, nullptr, 1);
+        ply_set_read_cb(ply, "vertex", "z", vertex_cb, nullptr, 2);
+
+        ply_set_read_cb(ply, "vertex", "nx", vertex_cb, nullptr, 3);
+        ply_set_read_cb(ply, "vertex", "ny", vertex_cb, nullptr, 4);
+        ply_set_read_cb(ply, "vertex", "nz", vertex_cb, nullptr, 5);
+
+		ply_set_read_cb(ply, "vertex", "red", vertex_cb, nullptr, 6);
+        ply_set_read_cb(ply, "vertex", "green", vertex_cb, nullptr, 7);
+        ply_set_read_cb(ply, "vertex", "blue", vertex_cb, nullptr, 8);
+        ply_set_read_cb(ply, "vertex", "alpha", vertex_cb, nullptr, 9);
+
+		//ply_set_read_cb(ply, "vertex", "texture_u", vertex_cb, this, 10);
+		//ply_set_read_cb(ply, "vertex", "texture_v", vertex_cb, this, 11);
+
+		CubeVertices = new float[nvertices*numComponents]; //xyz, nx, ny, nz, uv, rgba
+
+        int ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0);
+
+        CubeIndices=new int[3*ntriangles];
+
+        //dprintf("PLY %s: v=%ld, t=%ld\n", model, nvertices, ntriangles);
+        if (!ply_read(ply)) {
+            eprintf("Problem in ply_read");
+            return false;
+        }
+        ply_close(ply);
+
+		for (int i = 0; i < 3* ntriangles; i++) {
+			vertindices.push_back(CubeIndices[i]);
+		}
+
+	
+		for (int i = 0; i < nvertices; i++) {
+			//pos
+			float V1[4];
+			for (int j=0;j<3;j++)
+				V1[j] = CubeVertices[i * numComponents +j];
+			V1[3]=1;
+			float V[4];
+			mult(V, mat, V1);
+			for (int j=0;j<3;j++)
+					vertdata.push_back(V[j]);
+			
+			//normals (FIXME should transform with inverse transform, but we think the matrix has uniform scaling and inv transpose = m)
+			//rgh beware: normals are (nx, ny, nz, 0) to avoid being translated !!!
+			for (int j=0;j<3;j++)
+				V1[j] = 0.f; //CubeVertices[i * numComponents + 3+j];
+			V1[3]=0;
+			mult (V, mat, V1);
+			normalize(V);
+			for (int j=0;j<3;j++)
+				vertdata.push_back(V[j]);
+			//colors (untransformed)
+			if (!colours) {
+				for (int j = 0; j < 4; j++)
+					vertdata.push_back(isocolours[set][j]);
+			} else {
+				for (int j = 0; j < 4; j++)
+					vertdata.push_back(CubeVertices[i * numComponents + 6 + j]);
+			}
+		}
+		delete[] CubeVertices;
+		delete[] CubeIndices;
+		CubeVertices=0;
+		CubeIndices=0;
+		return true;
+}
+
+int vertex_cb(p_ply_argument argument) {
+    long what;
+	int ret=ply_get_argument_user_data(argument, nullptr, &what);
+	if (!ret)
+		return 0;
+	if (what == 0)
+		CurrentVertex++;
+    if (what <=5 /* || what >=10*/ ){ //no uvs in these meshes.
+		CubeVertices[CurrentVertex*numComponents+what]=(float)ply_get_argument_value(argument);
+    } else {
+        CubeVertices[CurrentVertex*numComponents+what]=(float)(ply_get_argument_value(argument)/255.0);
+    }
+
+    return 1;
+}
+
+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));
+
+    return 1;
+}
+
+GLenum PrepareGLiso (GLuint vao, GLuint vertbuffer, const std::vector<float> &vertdata, GLuint indbuffer,
+ #ifndef INDICESGL32
+	std::vector<short> & vertindices 
+#else
+	std::vector<GLuint> & vertindices
+#endif
+	)
+{
+	GLenum e;
+	GLsizei stride = sizeof(float) * numComponents; 
+
+	glBindVertexArray(vao);
+	glBindBuffer(GL_ARRAY_BUFFER, vertbuffer);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertdata.size(), &vertdata[0], GL_STATIC_DRAW);
+	if ((e = glGetError()) != GL_NO_ERROR)
+		eprintf("opengl error %d, glBufferData, l %d\n", e, __LINE__);
+				int offset = 0;
+
+	//now pos[3], normal[3], color[4]
+	//pos
+	glEnableVertexAttribArray(0);
+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
+
+	if (glGetError() != GL_NO_ERROR)
+		eprintf("opengl error attrib pointer 0\n");
+
+	//normal
+	offset += 3 * sizeof(GLfloat); //3 floats
+	glEnableVertexAttribArray(1);
+	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
+
+	if ((e=glGetError()) != GL_NO_ERROR)
+		eprintf("opengl error attrib pointer 1\n");
+
+	//color
+	offset += 3 * sizeof(GLfloat); //6 floats
+	glEnableVertexAttribArray(2);
+	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
+
+	if (glGetError() != GL_NO_ERROR)
+		eprintf("opengl error attrib pointer 2\n");
+
+		// populate the index buffer
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indbuffer);
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
+#ifndef INDICESGL32
+		sizeof(uint16_t)
+#else
+		sizeof(GLuint)
+#endif
+		* vertindices.size(),
+		&vertindices[0], GL_STATIC_DRAW);
+
+	if ((e=glGetError()) != GL_NO_ERROR)
+		eprintf("opengl error\n");
+
+	glBindVertexArray(0);
+	glDisableVertexAttribArray(0);
+	glDisableVertexAttribArray(1);
+	glDisableVertexAttribArray(2);
+	return e;
+}
+
+//#endif
\ No newline at end of file
diff --git a/NOMADVRLib/IsosurfacesGL.h b/NOMADVRLib/IsosurfacesGL.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b02ca963141072e49bdad88e9bb3fc9a2c7673b
--- /dev/null
+++ b/NOMADVRLib/IsosurfacesGL.h
@@ -0,0 +1,25 @@
+#ifndef __ISOSURFACESGL_H
+#define __ISOSURFACESGL_H
+
+#include "rply/rply.h"
+
+//number of components in our vertices data xyz+nxnynz+rgba
+#define numComponents 10
+
+bool AddModelToScene( const float *mat/*[16]*/, std::vector<float> &vertdata, 
+#ifndef INDICESGL32
+	std::vector<short> & vertindices, 
+#else
+	std::vector<GLuint> & vertindices,
+#endif
+	const char * model, bool water, bool colours, int set);
+
+GLenum PrepareGLiso (GLuint vao, GLuint vertbuffer, const std::vector<float> &vertdata, GLuint indbuffer,
+ #ifndef INDICESGL32
+	std::vector<short> & vertindices 
+#else
+	std::vector<GLuint> & vertindices
+#endif
+	);
+
+#endif
\ No newline at end of file
diff --git a/OpenVR/TimestepData/hellovr_opengl.vcxproj b/OpenVR/TimestepData/hellovr_opengl.vcxproj
index a16ac61ce1225043e54cafdbee8ff7640a0ddc98..2d4c116e21d584083c7f46569100685866f6d377 100644
--- a/OpenVR/TimestepData/hellovr_opengl.vcxproj
+++ b/OpenVR/TimestepData/hellovr_opengl.vcxproj
@@ -74,6 +74,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <LinkIncremental>true</LinkIncremental>
     <OutDir>$(SolutionDir)..\bin\win64</OutDir>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <LinkIncremental>false</LinkIncremental>
@@ -108,9 +109,10 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>..;../../headers;../thirdparty/glew/glew-1.11.0/include;../thirdparty/sdl2-2.0.3/include;Y:\v2t\software\rapidjson\include;Y:\v2t\software\curl\include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_WINDOWS;INDICESGL32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..;../../headers;../thirdparty/glew/glew-1.11.0/include;../thirdparty/sdl2-2.0.3/include;Y:\v2t\software\rapidjson\include;Y:\v2t\software\curl\include;Y:\v2t\software\openvr\openvr-0.9.19\samples\TimestepData</AdditionalIncludeDirectories>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <EnablePREfast>false</EnablePREfast>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -150,7 +152,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;INDICESGL32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <AdditionalIncludeDirectories>..;../../headers;../thirdparty/glew/glew-1.11.0/include;..\thirdparty\sdl2-2.0.3\include;Y:\v2t\software\rapidjson\include;Y:\v2t\software\openvr\openvr-0.9.19\samples\TimestepData</AdditionalIncludeDirectories>
       <EnablePREfast>false</EnablePREfast>
@@ -176,6 +178,7 @@
     <ClCompile Include="NOMADVRLib\atomsGL.cpp" />
     <ClCompile Include="NOMADVRLib\CompileGLShader.cpp" />
     <ClCompile Include="NOMADVRLib\ConfigFile.cpp" />
+    <ClCompile Include="NOMADVRLib\IsosurfacesGL.cpp" />
     <ClCompile Include="NOMADVRLib\polyhedron.cpp" />
     <ClCompile Include="NOMADVRLib\TessShaders.cpp" />
     <ClCompile Include="NOMADVRLib\UnitCellShaders.cpp" />
@@ -193,6 +196,7 @@
     <ClInclude Include="NOMADVRLib\CompileGLShader.h" />
     <ClInclude Include="NOMADVRLib\ConfigFile.h" />
     <ClInclude Include="NOMADVRLib\eprintf.h" />
+    <ClInclude Include="NOMADVRLib\IsosurfacesGL.h" />
     <ClInclude Include="NOMADVRLib\MyGL.h" />
     <ClInclude Include="NOMADVRLib\polyhedron.h" />
     <ClInclude Include="NOMADVRLib\TessShaders.h" />
diff --git a/OpenVR/TimestepData/hellovr_opengl.vcxproj.filters b/OpenVR/TimestepData/hellovr_opengl.vcxproj.filters
deleted file mode 100644
index ad7d074ff1866915f255dc86b398546a10db384b..0000000000000000000000000000000000000000
--- a/OpenVR/TimestepData/hellovr_opengl.vcxproj.filters
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
-    <Filter Include="Link Libraries">
-      <UniqueIdentifier>{23064a78-3bcb-49ae-8c90-ed419518885d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Shared">
-      <UniqueIdentifier>{8cca1fa3-575c-4e0f-acae-7d4d800be358}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="hellovr_opengl_main.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\shared\lodepng.cpp">
-      <Filter>Shared</Filter>
-    </ClCompile>
-    <ClCompile Include="..\shared\Matrices.cpp">
-      <Filter>Shared</Filter>
-    </ClCompile>
-    <ClCompile Include="..\shared\pathtools.cpp">
-      <Filter>Shared</Filter>
-    </ClCompile>
-    <ClCompile Include="hsv.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\atoms.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\ConfigFile.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\atomsGL.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\TessShaders.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\UnitCellShaders.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\CompileGLShader.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="NOMADVRLib\polyhedron.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="happyhttp\happyhttp.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="rply\rply.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\shared\lodepng.h">
-      <Filter>Shared</Filter>
-    </ClInclude>
-    <ClInclude Include="..\shared\Matrices.h">
-      <Filter>Shared</Filter>
-    </ClInclude>
-    <ClInclude Include="..\shared\Vectors.h">
-      <Filter>Shared</Filter>
-    </ClInclude>
-    <ClInclude Include="..\shared\pathtools.h">
-      <Filter>Shared</Filter>
-    </ClInclude>
-    <ClInclude Include="hsv.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADViveT.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\atoms.hpp">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\atomsGL.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\TessShaders.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\eprintf.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\MyGL.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\CompileGLShader.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\ConfigFile.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\UnitCellShaders.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-    <ClInclude Include="NOMADVRLib\polyhedron.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="NOMADViveT.rc">
-      <Filter>Resource Files</Filter>
-    </ResourceCompile>
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/OpenVR/TimestepData/hellovr_opengl.vcxproj.user b/OpenVR/TimestepData/hellovr_opengl.vcxproj.user
deleted file mode 100644
index 30eb68fb7efab256e771b1700274bf8aa71f5228..0000000000000000000000000000000000000000
--- a/OpenVR/TimestepData/hellovr_opengl.vcxproj.user
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LocalDebuggerCommandArguments>c:\temp\39409.ncfg</LocalDebuggerCommandArguments>
-    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LocalDebuggerCommandArguments>Y:\v2t\software\openvr\NOMAD-bin\shell.txt</LocalDebuggerCommandArguments>
-    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
-  </PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp
index 0a11f2b730d6e455076e25de1afa54f6e9f10428..e0a251e32e20979f0485110a9742e8fed2bb0c23 100644
--- a/OpenVR/TimestepData/hellovr_opengl_main.cpp
+++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp
@@ -40,16 +40,8 @@
 
 #include "NOMADVRLib/polyhedron.h"
 
-static int vertex_cb(p_ply_argument argument);
-static int face_cb(p_ply_argument argument);
+#include "NOMADVRLib/IsosurfacesGL.h"
 
-static float *CubeVertices;
-static int *CubeIndices;
-static int CurrentVertex;
-static int CurrentIndex;
-
-//#define SOLID Tetrahedron //not nicely uniform distribution
-//#define SOLID Icosahedron
 #define TESSSUB 16
 
 //TTF_Font* font;
@@ -65,12 +57,9 @@ static int CurrentIndex;
 */
 #define ZLAYERS 12
 
-//number of components in our vertices data xyz+nxnynz+rgba
-#define numComponents 10
+
 
 #define MAXGPU 300
-//use 32 or 16 bits for index (in case more than 64k vertices / mesh
-#define INDICESGL32 
 
 //shown on https://www.vbw-bayern.de/vbw/Aktionsfelder/Innovation-F-T/Forschung-und-Technologie/Zukunft-digital-Big-Data.jsp
 
@@ -133,14 +122,6 @@ public:
 	void SetupAtoms();
 	void SetupUnitCell();
 
-	bool AddModelToScene(Matrix4 mat, std::vector<float> &vertdata, 
-#ifndef INDICESGL32
-		std::vector<short> & vertindices, 
-#else
-		std::vector<GLuint> & vertindices,
-#endif
-		const char *const data, bool water, bool colours, int set);
-
 	void DrawControllers();
 
 	bool SetupStereoRenderTargets();
@@ -1561,7 +1542,6 @@ void CMainApplication::SetupIsosurfaces()
 			dprintf("opengl error %d, glGenBuffers\n", e);
 
 	}
-	GLsizei stride = sizeof(float) * numComponents; //sizeof(VertexDataScene);
 
 	char tmpname[250];
 	for (int currentlod = 0; currentlod < NUMLODS; currentlod++) {
@@ -1590,7 +1570,8 @@ void CMainApplication::SetupIsosurfaces()
 			Matrix4 matFinal;
 			matFinal.translate(translations[p%ISOS][0], translations[p%ISOS][1], translations[p%ISOS][2]);
 			matFinal = mat*matFinal;
-			if (!AddModelToScene(matFinal, vertdataarray[currentlod][p], vertindicesarray[currentlod][p],
+
+			if (!AddModelToScene(matFinal.get(), vertdataarray[currentlod][p], vertindicesarray[currentlod][p],
 				tmpname, false, isocolours[p%ISOS][0]<0, p%ISOS))
 			{
 				dprintf("Error loading ply file %s\n", tmpname);
@@ -1607,69 +1588,11 @@ void CMainApplication::SetupIsosurfaces()
 #endif
 			m_uiVertcount[currentlod][p] = vertindicesarray[currentlod][p].size();  //rgh: now pos, normal, color
 
-			glBindVertexArray(m_unSceneVAO[currentlod][p]);
-
-			glBindBuffer(GL_ARRAY_BUFFER, m_glSceneVertBuffer[currentlod][p]);
-			glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertdataarray[currentlod][p].size(), &vertdataarray[currentlod][p][0],
-				GL_STATIC_DRAW);
-
-			if ((e = glGetError()) != GL_NO_ERROR)
-				dprintf("opengl error %d, glBufferData, l %d\n", e, __LINE__);
-			int offset = 0;
-
-			//now pos[3], normal[3], color[4]
-			//pos
-			glEnableVertexAttribArray(0);
-			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
-
-			if (glGetError() != GL_NO_ERROR)
-				dprintf("opengl error attrib pointer 0\n");
-
-			//normal
-			offset += 3 * sizeof(GLfloat); //3 floats
-			glEnableVertexAttribArray(1);
-			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
-
-			if (glGetError() != GL_NO_ERROR)
-				dprintf("opengl error attrib pointer 1\n");
-
-			//color
-			offset += 3 * sizeof(GLfloat); //6 floats
-			glEnableVertexAttribArray(2);
-			glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
-
-			if (glGetError() != GL_NO_ERROR)
-				dprintf("opengl error attrib pointer 2\n");
-
-			//uv
-			/*offset += 4 * sizeof(GLfloat); //10 floats
-			glEnableVertexAttribArray(3);
-			glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
-
-			if (glGetError() != GL_NO_ERROR)
-			dprintf("opengl error attrib pointer 3\n");*/
-
-			// populate the index buffer
-			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_unSceneVAOIndices[currentlod][p]);
-			glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
-#ifndef INDICESGL32
-				sizeof(uint16_t)
-#else
-				sizeof(GLuint)
-#endif
-				* vertindicesarray[currentlod][p].size(),
-				&vertindicesarray[currentlod][p][0], GL_STATIC_DRAW);
-
-
-
-			glBindVertexArray(0);
-			glDisableVertexAttribArray(0);
-			glDisableVertexAttribArray(1);
-			glDisableVertexAttribArray(2);
-			//glDisableVertexAttribArray(3);
+			if (GL_NO_ERROR!=PrepareGLiso(m_unSceneVAO[currentlod][p], m_glSceneVertBuffer[currentlod][p], 
+				vertdataarray[currentlod][p], m_unSceneVAOIndices[currentlod][p], vertindicesarray[currentlod][p]))
+				eprintf ("PrepareGLiso, GL error");
+			
 
-			if (glGetError() != GL_NO_ERROR)
-				dprintf("opengl error\n");
 
 			//FIXME: after we go to 64 bits, keep the data in ram
 			vertdataarray[currentlod][p].clear();
@@ -1701,102 +1624,6 @@ void CMainApplication::SetupIsosurfaces()
 	glDisableVertexAttribArray(1);
 }
 
-
-//-----------------------------------------------------------------------------
-// Purpose: Load a ply file
-//-----------------------------------------------------------------------------
-
-
-bool CMainApplication::AddModelToScene( Matrix4 mat, std::vector<float> &vertdata, 
-#ifndef INDICESGL32
-	std::vector<short> & vertindices, 
-#else
-	std::vector<GLuint> & vertindices,
-#endif
-	const char * model, bool water, bool colours, int set) 
-{
-
-	CurrentVertex=-1;
-	CurrentIndex=0;
-	 p_ply ply = ply_open(model, NULL, 0, NULL);
-	 //p_ply ply = ply_open("Y:\\v2t\\media\\visual_designs\\logos_3d\\v2c\\v2cSchrift.ply", NULL, 0, NULL);
-        if (!ply) {
-            dprintf("ply returned null: file %s\n", model);
-            return false;
-        }
-        if (!ply_read_header(ply)) {
-            dprintf("ply: bad header in ply: file %s\n", model);
-            return false;
-        }
-
-        int nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, this, 0);
-        ply_set_read_cb(ply, "vertex", "y", vertex_cb, this, 1);
-        ply_set_read_cb(ply, "vertex", "z", vertex_cb, this, 2);
-
-        ply_set_read_cb(ply, "vertex", "nx", vertex_cb, this, 3);
-        ply_set_read_cb(ply, "vertex", "ny", vertex_cb, this, 4);
-        ply_set_read_cb(ply, "vertex", "nz", vertex_cb, this, 5);
-
-		ply_set_read_cb(ply, "vertex", "red", vertex_cb, this, 6);
-        ply_set_read_cb(ply, "vertex", "green", vertex_cb, this, 7);
-        ply_set_read_cb(ply, "vertex", "blue", vertex_cb, this, 8);
-        ply_set_read_cb(ply, "vertex", "alpha", vertex_cb, this, 9);
-
-		//ply_set_read_cb(ply, "vertex", "texture_u", vertex_cb, this, 10);
-		//ply_set_read_cb(ply, "vertex", "texture_v", vertex_cb, this, 11);
-
-		CubeVertices = new float[nvertices*numComponents]; //xyz, nx, ny, nz, uv, rgba
-
-        int ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0);
-
-        CubeIndices=new int[3*ntriangles];
-
-        //dprintf("PLY %s: v=%ld, t=%ld\n", model, nvertices, ntriangles);
-        if (!ply_read(ply)) {
-            dprintf("Problem in ply_read");
-            return false;
-        }
-        ply_close(ply);
-
-		for (int i = 0; i < 3* ntriangles; i++) {
-			vertindices.push_back(CubeIndices[i]);
-		}
-
-	
-		for (int i = 0; i < nvertices; i++) {
-			//pos
-			Vector4 V1 = Vector4(CubeVertices[i * numComponents + 0],
-				CubeVertices[i * numComponents + 1],
-				CubeVertices[i * numComponents + 2], 1);
-			Vector4 V = mat * V1;
-			vertdata.push_back(V.x);
-			vertdata.push_back(V.y);
-			vertdata.push_back(V.z);
-			//normals (FIXME should transform with inverse transform, but we think the matrix has uniform scaling and inv transpose = m)
-			//rgh beware: normals are (nx, ny, nz, 0) to avoid being translated !!!
-			V1 = Vector4(CubeVertices[i * numComponents + 3],
-				CubeVertices[i * numComponents + 4],
-				CubeVertices[i * numComponents + 5], 0);
-			V = (mat * V1).normalize();
-			vertdata.push_back(V.x);
-			vertdata.push_back(V.y);
-			vertdata.push_back(V.z);
-			//colors (untransformed)
-			if (!colours) {
-				for (int j = 0; j < 4; j++)
-					vertdata.push_back(isocolours[set][j]);
-			} else {
-				for (int j = 0; j < 4; j++)
-					vertdata.push_back(CubeVertices[i * numComponents + 6 + j]);
-			}
-		}
-		delete[] CubeVertices;
-		delete[] CubeIndices;
-		return true;
-}
-
-
-
 //-----------------------------------------------------------------------------
 // Purpose: Draw all of the controllers as X/Y/Z lines
 //-----------------------------------------------------------------------------
@@ -3027,31 +2854,3 @@ int main(int argc, char *argv[])
 }
 
 
-static int vertex_cb(p_ply_argument argument) {
-    long what;
-    int ret=ply_get_argument_user_data(argument, NULL, &what);
-	if (!ret)
-		return 0;
-	if (what == 0)
-		CurrentVertex++;
-    if (what <=5 /* || what >=10*/ ){ //no uvs in these meshes.
-		CubeVertices[CurrentVertex*numComponents+what]=(float)ply_get_argument_value(argument);
-    } else {
-        CubeVertices[CurrentVertex*numComponents+what]=(float)(ply_get_argument_value(argument)/255.0);
-    }
-
-    return 1;
-}
-
-static int face_cb(p_ply_argument argument) {
-    long length, value_index;
-//	int v;
-    ply_get_argument_property(argument, NULL, &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));
-
-    return 1;
-}
\ No newline at end of file