Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.h	(revision 2826)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.h	(revision 2828)
@@ -6,4 +6,5 @@
 #include <iostream>
 #include <fstream>
+#include <map>
 
 #include "common.h"
@@ -23,28 +24,17 @@
 	*/
 	bool Read(const std::string &filename);
-	/** Initialises the environment file with default values.
+
+	bool GetFloatParam(std::string &str, float &val) const;
+	bool GetIntParam(std::string &str, int &val) const;
+	bool GetVectorParam(std::string &str, Vector3 &val) const;
+	bool GetBoolParam(std::string &str, bool &val) const;
+
+protected:
+
+	/** Parse this string, return tokens separated by given delimiters
 	*/
-	void Init();
+	void Tokenize(const std::string& str, std::vector<std::string> &tokens, const std::string &delim = " ") const;
 
-
-	//////////
-	//-- members
-
-	int mAssumedVisibleFrames;
-	int mMaxBatchSize;
-
-	int mTrianglesPerVirtualLeaf;
-
-	/// these values get scaled with the frame rate
-	float mKeyForwardMotion;
-	float mKeyRotation;
-
-	int mWinWidth;
-	int mWinHeight;
-
-	Vector3 mPosition;
-	Vector3 mDirection;
-
-	bool mUseFullScreen;
+	std::map<std::string, std::string> mParams;
 };
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.h	(revision 2827)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.h	(revision 2828)
@@ -18,4 +18,5 @@
 	void Reset();
 
+	void SetGraphColor(float *col);
 
 protected:
@@ -29,4 +30,5 @@
 	int mMaxData;
 	int mCurrentIdx;
+	float mGraphColor[3];
 };
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/default.env
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/default.env	(revision 2828)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/default.env	(revision 2828)
@@ -0,0 +1,14 @@
+#############################
+# environment file for the friendlyculling demo
+
+assumedVisibleFrames=10
+maxBatchSize=50
+trianglesPerVirtualLeaf=500
+keyForwardMotion=30.0f
+keyRotation=1.5f
+winWidth=1024
+winHeight=768
+position=483.398f 242.364f 186.078f
+useFullScreen=false
+numSsaoSamples=8
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2827)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2828)
@@ -28,4 +28,5 @@
 #include "glfont2.h"
 #include "PerformanceGraph.h"
+#include "Environment.h"
 
 
@@ -34,4 +35,9 @@
 
 
+static Environment env;
+
+
+/////////////
+//-- textures
 GLuint fbo;
 
@@ -84,6 +90,6 @@
 
 /// these values get scaled with the frame rate
-const static float keyForwardMotion = 30.0f;
-const static float keyRotation = 1.5f;
+static float keyForwardMotion = 30.0f;
+static float keyRotation = 1.5f;
 
 /// elapsed time in milliseconds
@@ -103,8 +109,8 @@
 
 // rendertexture
-const static int texWidth = 1024;
-const static int texHeight = 768;
-//const static int texWidth = 2048;
-//const static int texHeight = 2048;
+static int texWidth = 1024;
+static int texHeight = 768;
+//static int texWidth = 2048;
+//static int texHeight = 2048;
 
 int renderedObjects = 0;
@@ -159,7 +165,11 @@
 PerformanceGraph *perfGraph = NULL;
 
-
+bool useFullScreen = false;
+
+
+// ssao number of samples
 #define NUM_SAMPLES 8
 
+// ssao random spherical samples
 static float samples[NUM_SAMPLES * 2];
 
@@ -281,4 +291,22 @@
 	int returnCode = 0;
 
+	env.Read("src/default.env");
+
+	env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
+	env.GetIntParam(string("maxBatchSize"), maxBatchSize);
+	env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
+
+	env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
+	env.GetFloatParam(string("keyForwardMotion"), keyRotation);
+
+	env.GetIntParam(string("winWidth"), winWidth);
+	env.GetIntParam(string("winHeight"), winHeight);
+
+	env.GetBoolParam(string("useFullScreen"), useFullScreen);
+
+
+
+	///////////////////////////
+
 	camera = new Camera(winWidth, winHeight, fov);
 	camera->SetNear(nearDist);
@@ -295,10 +323,12 @@
 	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
 
-#if 1
-	glutCreateWindow("FriendlyCulling");
-#else
-	glutGameModeString( "1024x768:32@75" ); //the settings for fullscreen mode
-	glutEnterGameMode(); //set glut to fullscreen using the settings in the line above
-#endif
+	if (!useFullScreen)
+		glutCreateWindow("FriendlyCulling");
+	else
+	{
+		glutGameModeString( "1024x768:32@75" ); 
+		glutEnterGameMode(); 
+	}
+
 	glutDisplayFunc(Display);
 	glutKeyboardFunc(KeyBoard);
@@ -1064,4 +1094,25 @@
 		algTime = algTimer.Elapsedms();
 		perfGraph->AddData(algTime);
+
+		/*float col[3];
+		switch (renderMode)
+		{
+		case RenderTraverser::CHCPLUSPLUS:
+			col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f;
+			break;
+		case RenderTraverser::CHC:
+			col[0] = 0.0f; col[1] = 1.0f; col[2] = 1.0f;
+			break;
+		case RenderTraverser::STOP_AND_WAIT:
+			col[0] = 1.0f; col[1] = 1.0f; col[2] = 0.0f;
+			break;
+		case RenderTraverser::CULL_FRUSTUM:
+			col[0] = 1.0f; col[1] = 0.0f; col[2] = 1.0f;
+			break;
+		default:
+			col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f;
+		}
+		perfGraph->SetGraphColor(col);
+		*/
 		perfGraph->Draw();
 	}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.cpp	(revision 2826)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Environment.cpp	(revision 2828)
@@ -8,26 +8,110 @@
 {
 
-bool Environment::Read(const string &filename)
+
+bool Environment::GetFloatParam(std::string &str, float &val) const
 {
+	map<string, string>::const_iterator it = mParams.find(str);
+
+	if (it == mParams.end()) // parameter not found
+		return false;
+	
+	val = (float)atof((*it).second.c_str());
+
 	return true;
 }
 
 
-void Environment::Init()
+bool Environment::GetIntParam(std::string &str, int &val) const
 {
-	/*mAssumedVisibleFrames;
-	mMaxBatchSize;
+	map<string, string>::const_iterator it = mParams.find(str);
 
-	mTrianglesPerVirtualLeaf;
+	if (it == mParams.end()) // parameter not found
+		return false;
+	
+	val = atoi((*it).second.c_str());
 
-	mKeyForwardMotion;
-	mKeyRotation;
+	return true;
+}
 
-	mWinWidth;
-	mWinHeight;
 
-	mPosition;
-*/
-	mUseFullScreen = false;
+bool Environment::GetBoolParam(std::string &str, bool &val) const
+{
+	map<string, string>::const_iterator it = mParams.find(str);
+
+	if (it == mParams.end()) // parameter not found
+		return false;
+	
+	val = (bool)atoi((*it).second.c_str());
+
+	return true;
+}
+
+
+bool Environment::GetVectorParam(std::string &str, Vector3 &val) const
+{
+	map<string, string>::const_iterator it = mParams.find(str);
+
+	static vector<string> tokens;
+	tokens.clear();
+
+	if (it == mParams.end()) // parameter not found
+		return false;
+	
+	Tokenize((*it).second, tokens);
+
+	val.x = (float)atof(tokens[1].c_str());
+	val.y = (float)atof(tokens[2].c_str());
+	val.z = (float)atof(tokens[3].c_str());
+
+	return true;
+}
+
+
+bool Environment::Read(const string &filename)
+{
+	FILE *file;
+	if ((file = fopen(filename.c_str(), "rt")) == NULL)
+		return false;
+
+	char str[256];
+
+	while (fgets(str, 256, file) != NULL)
+	{
+		static vector<string> tokens;
+		tokens.clear();
+
+		Tokenize(str, tokens, "=");
+
+		// this line is a comment
+		if (tokens[0][0] == '#')
+			continue;
+
+		// store parameter
+		mParams[tokens[0]] = tokens[1];
+	}
+
+	return true;
+}
+
+
+void Environment::Tokenize(const string& str,
+						   vector<string> &tokens,
+						   const string &delim) const
+{
+    // skip delimiters the string begins with
+    string::size_type lastPos = str.find_first_not_of(delim, 0);
+    // find next delimiter
+    string::size_type pos = str.find_first_of(delim, lastPos);
+
+	// find tokens until string has been completely parsed
+    while ((string::npos != pos) || (string::npos != lastPos))
+    {
+        // add new token
+        tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // skip delimiters, go to start of next token
+        lastPos = str.find_first_not_of(delim, pos);
+        // found next delimiter
+        pos = str.find_first_of(delim, lastPos);
+    }
 }
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.cpp	(revision 2827)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PerformanceGraph.cpp	(revision 2828)
@@ -6,4 +6,7 @@
 mMaxData(maxData), mCurrentIdx(0)
 {
+	mGraphColor[0] = 1.0f;
+	mGraphColor[1] = 0.0f;
+	mGraphColor[2] = 0.0f;
 }
 
@@ -88,9 +91,7 @@
 	const float scaley = 1.0f / 50.0f;
 
-	glColor4f(1.0f, 0, 0, 1.0f);
+	glColor3fv(mGraphColor);
 
 	glBegin(GL_LINE_STRIP);
-
-	//OUT1("data: " << mData.size());
 
 	for (size_t i = 0; i < mData.size(); ++ i)
@@ -128,2 +129,10 @@
 	mData.clear();
 }
+
+
+void PerformanceGraph::SetGraphColor(float *col)
+{
+	mGraphColor[0] = col[0];
+	mGraphColor[1] = col[1];
+	mGraphColor[2] = col[2];
+}
