Index: /GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt
===================================================================
--- /GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt	(revision 1274)
+++ /GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt	(revision 1285)
@@ -48,4 +48,10 @@
     Append a comment to the logfile. Requires --logfile to have any effect.
     (see DEMOS).
+    
+  --savesceneto <filename>
+  	Specifies file name (with .txt extension) to which the positions of all
+  	entities in the scene will be saved. If the filename is appended to
+  	the scene parameter in the config file, the entities are loaded at
+  	startup
 
   The following options apply only to the KDT and KTE scene managers. They have
@@ -88,12 +94,14 @@
     scene:  Select the scene which shall be loaded.
             If the parameter is empty or missing, the simple test scene is
-            loaded (spaceships & robots).
-            If the parameter is "terrain", the application attempts to load
-            the terrain world geometry, which only works with scene managers
-            supporting this kind of geometry (KTE, OCM, TER). Also a file
-            named "terrain.cfg" and holding all the necessary options for
-            the terrain must be in the same directory.
-            All other values are interpreted as a semicolon-separated list of
-            scene files to load. For now, only the .iv format is supported.
+            loaded (spaceships & robots on a plane).
+            Otherwise the parameter is interpreted as a semicolon-separated
+            list of scene files to load. So far the application supports the
+            following formats:
+            	.iv, .wrl: 	Mesh files like the vienna scene.
+            	.cfg:				Config files for terrain creation. You need to specify
+            							an appropriate scene manager which supports terrain
+            							world geometry rendering (KTE, OCM, TER).
+            	.txt:				Text file created by the application which store
+            							positions of entites (small movable objects)
     movespeed, rotatespeed:
             Set the speed of movement and rotation for the player camera.
@@ -174,4 +182,5 @@
     P     Show/Hide player cam position
     PRINT Save sceen shot
+    F7		Save Entities in the scene to file
 
 DEMOS
Index: /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1274)
+++ /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1285)
@@ -46,4 +46,6 @@
 	}
 
+	// save entities to ascii file
+	bool saveSceneASCII(const String& filename, SceneNode *entityroot);
 protected:
 	KdTreeAppListener *mFrameListener;
@@ -84,4 +86,11 @@
 	bool loadScene(const String& filename);
 	bool loadSceneIV(const String &filename, SceneNode *root, const int index);
+	// loadding world geometry from cfg file - for terrain
+	bool loadSceneCfg(const String &filename, SceneNode *root, const int index);
+	// load entities from ascii file
+	bool loadSceneASCII(const String &filename, SceneNode *root, const int index);
+
+	typedef std::list<SceneNode *> NodeList;
+	void addNodesToList(SceneNode* node, NodeList& list);
 
 	void createMaterials(void);
Index: /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1274)
+++ /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1285)
@@ -66,4 +66,6 @@
 typedef std::list<FrameInfo> FrameList;
 
+class KdTreeApp;
+
 class KdTreeAppListener: public FrameListener, public KeyListener
 {
@@ -120,5 +122,6 @@
 		mDemoMode(false),
 		mEnhancedVisibility(false),
-		mDemoInterval(1.0f)
+		mDemoInterval(1.0f),
+		myApp(0)
 		{
 
@@ -126,4 +129,5 @@
 
 		String mSceneFiles;
+		String mSceneOutfileName;
 		String mDemoInfileName;
 		String mDemoOutfileName;
@@ -142,4 +146,5 @@
 		bool mEnhancedVisibility;
 		Real mDemoInterval;
+		KdTreeApp *myApp;
 	};
 
Index: /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1274)
+++ /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1285)
@@ -6,4 +6,5 @@
 #include "TestKdTree.h"
 #include "WinCmdLineParser.h"
+#include <cstring>
 
 #ifdef __cplusplus
@@ -37,5 +38,6 @@
 				.addOpt("s","scenemgr", ARGUMENT_REQUIRED)
 				.addOpt("","comment", ARGUMENT_REQUIRED)
-				.addOpt("e","enhancevis", ARGUMENT_NONE);
+				.addOpt("e","enhancevis", ARGUMENT_NONE)
+				.addOpt("","savesceneto", ARGUMENT_REQUIRED);
 
 
@@ -46,4 +48,5 @@
 			options.mDemoMode = cmdparser.getOpt("d");
 			options.mEnhancedVisibility = cmdparser.getOpt("e");
+			cmdparser.getOpt("savesceneto", options.mSceneOutfileName);
 
 			std::string tmp;
@@ -302,6 +305,6 @@
 		mCamNode->setPosition(707,2500,528);
 		mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
-		//mCamNode->setPosition(0,0,0);
-		//mCamNode->setOrientation(Quaternion(Radian(Math::PI),Vector3::UNIT_Y));
+		//mCamNode->setPosition(1056.59, 467.412, 783.502);
+		//mCamNode->setOrientation(Quaternion(-0.281354, 0.0204027, 0.956747, 0.0695345));
 	}
 	// load scene from file
@@ -310,4 +313,5 @@
 		// don't load the other stuff
 		loadScene(mOptions.mSceneFiles);
+
 		// top view
 		mTopCam->setPosition(Vector3(1232, 3990, -1477));
@@ -531,4 +535,7 @@
 void KdTreeApp::createFrameListener(void)
 {
+	// set pointer to self in options
+	mOptions.myApp = this;
+
 	mFrameListener = new KdTreeAppListener(mWindow, mSceneMgr, mOptions);
 	//mFrameListener->showDebugOverlay( true );
@@ -760,5 +767,7 @@
 	LogManager::getSingleton().logMessage(d.str());
 
-	bool result = false;
+	bool loadres = false;
+	bool result = filenames.empty() ? false : true;
+
 	std::vector<std::string>::const_iterator fit, fit_end = filenames.end();
 	int i = 0;
@@ -770,27 +779,25 @@
 		if (strstr(fn.c_str(), ".iv") || strstr(fn.c_str(), ".wrl"))
 		{
-			// hack: set postion manually for vienna
-			//mCamNode->setPosition(Vector3(830, 300, -540));
-			//mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
-
 			// load iv files
-			loadSceneIV(fn, mSceneMgr->getRootSceneNode(), i);			
-		}
-
-		result = true;
-	}
-
-
-	/*
-	if (result) 
-	{
-	int intersectables, faces;
-
-	std::stringstream d;
-	d << filename << " parsed successfully.\n"
-	<< "#NUM_OBJECTS (Total numner of objects)\n" << intersectables << "\n"
-	<< "#NUM_FACES (Total numner of faces)\n" << faces << "\n";
-	}
-	*/
+			loadres = loadSceneIV(fn, mSceneMgr->getRootSceneNode(), i);			
+		}
+		else if (strstr(fn.c_str(), ".cfg"))
+		{
+			// load terrain from cfg
+			loadres = loadSceneCfg(fn, mSceneMgr->getRootSceneNode(), i);
+		}
+		else if (strstr(fn.c_str(), ".txt"))
+		{
+			// load entities form text file
+			loadres = loadSceneASCII(fn, mSceneMgr->getRootSceneNode(), i);
+		}
+		else
+		{
+			loadres = false;
+		}
+
+		// result is true only if all files have been succesfully loaded
+		result = result ? loadres : false;
+	}
 
 	return result;
@@ -802,5 +809,5 @@
 	IVReader * mIVReader = new IVReader();
 
-	if (1)
+	if (0)
 	{
 		String logFilename = "IVLog" + Ogre::StringConverter().toString(index) + ".log";
@@ -823,7 +830,189 @@
 		return true;
 	}
-
-	return false;
-}
+	else
+	{
+		OGRE_DELETE(mIVReader);
+
+		return false;
+	}
+}
+
+//-----------------------------------------------------------------------
+bool KdTreeApp::loadSceneCfg(const String &filename, SceneNode *root, const int index)
+{
+	// Set ambient light
+	mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
+	// Create a light
+	Light* l = mSceneMgr->createLight("MainLight");
+	l->setPosition(20,80,50);
+	
+	// try to load world geometry defined in the cfg file
+	mSceneMgr -> setWorldGeometry( filename );
+
+	// return true since we have no feedback from setWorldGeometry
+	return true;
+}
+
+#define MAX_BUF_SIZE 1024
+
+//-----------------------------------------------------------------------
+bool KdTreeApp::loadSceneASCII(const String &filename, SceneNode *root, const int index)
+{
+	typedef std::map<std::string, std::string> EntMeshMap;
+	typedef std::vector<std::string> Line;
+	
+	std::ifstream read;
+	read.open(filename.c_str());
+	if (read.is_open())
+	{
+		char buf[MAX_BUF_SIZE];
+		Line line;
+		std::stringstream s;
+		std::string node, ent, mesh;
+		Vector3 pos;
+		Quaternion or;
+		Vector3 scale;
+		int count;
+		EntMeshMap emm;
+
+		// the node which is parent to all entities
+		SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode");
+
+		while (!read.eof())
+		{
+			line.clear();
+			memset(buf, 0, MAX_BUF_SIZE);
+			read.getline(buf, MAX_BUF_SIZE);
+			splitFilenames(std::string(buf), line);
+			if (line.size() < 5)
+				continue;
+			// see if node not empty
+			s << line[4];
+			s >> count;
+			s.clear();
+			if (count > 0)
+			{
+				// read info
+				node = line[0];
+				s << line[1];
+				s >> pos.x >> pos.y >> pos.z;
+				s.clear();
+				s << line[2];
+				s >> or.x >> or.y >> or.z >> or.w;
+				s.clear();
+				s << line[3];
+				s >> scale.x >> scale.y >> scale.z;
+				s.clear();
+				for (int i = 5; i < 5 + count; i ++)
+				{
+					s << line[i];
+					s >> ent >> mesh;
+					s.clear();
+					emm[ent] = mesh;
+				}
+				// build node
+				SceneNode *newnode = anchor->createChildSceneNode(node, pos, or);
+				newnode->setScale(scale);
+				for (EntMeshMap::iterator emmit = emm.begin(); emmit != emm.end(); emmit ++)
+				{
+					Entity * entity = mSceneMgr->createEntity(emmit->first, emmit->second);
+					newnode->attachObject(entity);
+				}
+				emm.clear();
+			}
+
+
+		}
+
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+//-----------------------------------------------------------------------
+bool KdTreeApp::saveSceneASCII(const String& filename, SceneNode *entityroot)
+{
+	// find all entities under node entityroot and store their name, position
+	//and orientation to a test file
+	std::ofstream write;
+	write.open(filename.c_str());
+	if (write.is_open())
+	{
+		NodeList list;
+		addNodesToList(entityroot, list);
+
+		std::string fs = ";", rs = "\n";
+		std::string entnames;
+		int entcount;
+
+		for (NodeList::iterator it = list.begin(); it != list.end(); it ++)
+		{
+			// fist dump info about node (name, position, orientation, scale)
+			SceneNode * node = *it;
+			write << node->getName() << fs << 
+				StringConverter::toString(node->getPosition()) << fs <<
+				StringConverter::toString(node->getOrientation()) << fs <<
+				StringConverter::toString(node->getScale()) << fs;
+
+			entcount = 0;
+			entnames = "";
+
+			SceneNode::ObjectIterator objIt = node->getAttachedObjectIterator();
+
+			while (objIt.hasMoreElements())
+			{
+				MovableObject *movable = objIt.getNext();
+				if (movable->getMovableType() == "Entity")
+				{
+					Entity *ent = static_cast<Entity *>(movable);
+					entcount++;
+					entnames += fs + ent->getName() + " " + ent->getMesh()->getName();
+
+				}
+			}
+
+			// now dump entity count and names
+			write << entcount << entnames << rs;
+		}
+
+		write.close();
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+
+}
+
+void KdTreeApp::addNodesToList(SceneNode* node, NodeList& list)
+{
+	//// check if node has entities
+	//bool entfound = false;
+
+	//SceneNode::ObjectIterator objIt = node->getAttachedObjectIterator();
+	//while (objIt.hasMoreElements())
+	//{
+	//	MovableObject *movable = objIt.getNext();
+	//	if (movable->getMovableType() == "Entity")
+	//		entfound = true;
+	//}
+
+	//// if yes, add to list
+	//if (entfound)
+	list.push_back(node);
+
+	// check if node has children and add them to list
+	SceneNode::ChildNodeIterator childIt = node->getChildIterator();
+	while (childIt.hasMoreElements())
+	{
+		SceneNode *child = static_cast<SceneNode *>(childIt.getNext());
+		addNodesToList(child, list);
+	}
+}
+
 
 /**********************************************************************/
Index: /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1274)
+++ /GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1285)
@@ -4,4 +4,5 @@
 #include <OgrePanelOverlayElement.h>
 #include "TestKdTreeAppListener.h"
+#include "TestKdTree.h"
 #include <windows.h>
 
@@ -543,4 +544,13 @@
 	}
 
+	if (mInputDevice->isKeyDown(KC_F7) && mTimeUntilNextToggle <= 0)
+	{
+		SceneNode *entnode = mSceneMgr->getSceneNode("AnchorNode");
+		if (!mOptions.myApp->saveSceneASCII(mOptions.mSceneOutfileName, entnode))
+			LogManager::getSingleton().logMessage(
+			"##Error##: Failed to save scene to " + mOptions.mSceneOutfileName);
+		mTimeUntilNextToggle = 0.5;
+	}
+
 	if (mInputDevice->isKeyDown(KC_F9) && mTimeUntilNextToggle <= 0)
 	{
Index: /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h
===================================================================
--- /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1273)
+++ /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1285)
@@ -63,15 +63,5 @@
 	/** Overide from scene manager to destroy kdtree properly (before the scene graph is destroyed)
 	*/
-	virtual void clearScene()
-	{
-		// DEBUG
-		//if (mKdTree)
-		//	mKdTree->dump();
-
-		// must happen before actual scene is cleared
-		OGRE_DELETE(mKdTree);
-
-		SceneManager::clearScene();
-	}
+	virtual void clearScene();
 
 	/************************************************************************/
Index: /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1273)
+++ /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1285)
@@ -67,4 +67,17 @@
 	delete mKdTree;
 }
+
+void KdTreeSceneManager::clearScene()
+{
+	// DEBUG
+	if (mKdTree)
+		mKdTree->dump();
+
+	// must happen before actual scene is cleared
+	OGRE_DELETE(mKdTree);
+
+	SceneManager::clearScene();
+}
+
 
 const String& KdTreeSceneManager::getTypeName(void) const
Index: /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp	(revision 1250)
+++ /GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp	(revision 1285)
@@ -1273,5 +1273,6 @@
 	void KdTree::dump()
 	{
-		LogManager::getSingleton().logMessage("#@#@#@#@ Dumping KdTree #@#@#@#@");
+		//LogManager::getSingleton().logMessage("#@#@#@#@ Dumping KdTree #@#@#@#@");
+		mBuildLog->logMessage("#@#@#@#@ Dumping KdTree #@#@#@#@");
 		if (mKdRoot)
 			dump(mKdRoot);
@@ -1281,5 +1282,5 @@
 	void KdTree::dump(KdTree::Node * node)
 	{
-		LogManager * log = LogManager::getSingletonPtr();
+		//LogManager * log = LogManager::getSingletonPtr();
 		KdTreeSceneNode * scenenode;
 		String pad;
@@ -1300,8 +1301,8 @@
 			{
 				scenenode = dynamic_cast<KdTreeSceneNode *>(*it);
-				log->logMessage(pad + "# Leaf   level " + 
+				mBuildLog->logMessage(pad + "# Leaf   level " + 
 					StringConverter::toString(node->getLevel()) + 
 					" SceneNode " + scenenode->getName());
-				log->logMessage(pad + "## Objects: " + scenenode->dumpToString());
+				mBuildLog->logMessage(pad + "## Objects: " + scenenode->dumpToString());
 				it++;
 			}
@@ -1312,5 +1313,5 @@
 			if (branch->mLeft)
 			{
-				log->logMessage(pad + "# Branch level " + 
+				mBuildLog->logMessage(pad + "# Branch level " + 
 					StringConverter::toString(node->getLevel()) + " Left Child");
 				dump(branch->mLeft);
@@ -1318,5 +1319,5 @@
 			if (branch->mRight)
 			{
-				log->logMessage(pad + "# Branch level " + 
+				mBuildLog->logMessage(pad + "# Branch level " + 
 					StringConverter::toString(node->getLevel()) + " Right Child");
 				dump(branch->mRight);
