Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1273)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1274)
@@ -31,5 +31,4 @@
 	mRenderTargerListener(0)
 	{
-
 	}
 
@@ -88,4 +87,8 @@
 	void createMaterials(void);
 	void createSimpleScene(void);
+	void createTerrainScene(Real max_x, Real max_y, Real max_z);
+	Vector3 clampToGround(const Vector3& vect, Real offset, Real cap);
+
+	RaySceneQuery* mRaySceneQuery;
 private:
 	std::string cat(std::string name, int x, int z)
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1273)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1274)
@@ -246,4 +246,5 @@
 	OverlayElement *mDemoStatus;
 	TextAreaOverlayElement *mDemoTime;
+	TextAreaOverlayElement *mDemoFPSDisp;
 
 
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1273)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1274)
@@ -240,4 +240,6 @@
 	{
 		createSimpleScene();
+		mCamNode->setPosition(Vector3(1280,600,1666));
+		mCamNode->setOrientation(Quaternion(0.936893, -0.124586, 0.323813, 0.04306));
 	}
 	// load terrain, but only if terrainscenemanager selected
@@ -275,15 +277,31 @@
 		plane.normal = -Vector3::UNIT_Y;
 
-		// add one robot
-		//Entity *robot = mSceneMgr->createEntity("TheRobot","robot.mesh");
-		//SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("TheRobotNode");
-		//node->attachObject(robot);
+		// read interesting params from config file
+		ConfigFile terrainconf;
+		std::stringstream s;
+		Real x,y,z;
+		
+		terrainconf.load(terrain_cfg);
+
+		s << terrainconf.getSetting("PageWorldX");
+		s >> x;
+		s.clear();
+
+		s << terrainconf.getSetting("MaxHeight");
+		s >> y;
+		s.clear();
+
+		s << terrainconf.getSetting("PageWorldZ");
+		s >> z;
+		s.clear();
+
 		// add stuff minus gound plane
-		mSelectEntities &= ~ENT_PLN;
-		createSimpleScene();
+		createTerrainScene(x, y + 1500, z);
 
 		// Set a nice viewpoint
 		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));
 	}
 	// load scene from file
@@ -300,4 +318,82 @@
 		mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
 	}
+}
+
+// fill terrain with robots, spaceships & whatever
+void KdTreeApp::createTerrainScene(Real max_x, Real max_y, Real max_z)
+{
+	Vector3 scale(0.3, 0.3, 0.3);
+	Entity *deaths;
+	SceneNode *nodes;
+	std::string entName;
+	std::string nodeName;
+	int i;
+	Real min_x = 100, min_y = 0, min_z = 100;
+	max_x -= 100; max_z -= 100;
+
+	SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode");
+
+	if (mSelectEntities & ENT_RND)
+	{
+		entName = "randomdeath";
+		nodeName = "RandomDeathNode";
+		for (i = 0; i < mRandomCount; i++)
+		{
+			Vector3 pos = clampToGround(Vector3(
+				Math::RangeRandom(min_x, max_x), 
+				max_y, 
+				Math::RangeRandom(min_z, max_z)), 0, max_y);
+			deaths = mSceneMgr->createEntity(cat(entName,666,i),"robot.mesh");
+			if (mShadowsEnabled)
+				deaths->setCastShadows(true);
+			nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName,666,i), pos,
+				Quaternion(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y));
+			nodes->attachObject(deaths);
+			nodes->setScale(scale);
+		}
+	}
+
+	if (mSelectEntities & ENT_SPC)
+	{
+		entName = "randomspaceship";
+		nodeName = "RandomSpaceshipNode";
+		for (i = 0; i < mRandomCount; i++)
+		{
+			Vector3 pos = clampToGround(Vector3(
+				Math::RangeRandom(min_x, max_x), 
+				max_y, 
+				Math::RangeRandom(min_z, max_z)),
+				Math::RangeRandom(20, 500), max_y);
+			deaths = mSceneMgr->createEntity(cat(entName,666,i),"razor.mesh");
+			if (mShadowsEnabled)
+				deaths->setCastShadows(true);
+			nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName,666,i), pos,
+				Quaternion(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y));
+			nodes->attachObject(deaths);
+			nodes->setScale(scale);
+		}
+	}
+
+	if (mSelectEntities & ENT_MOV)
+	{
+		Entity *movingDeath = mSceneMgr->createEntity("movingDeath","robot.mesh");
+		if (mShadowsEnabled)
+			movingDeath->setCastShadows( true );
+
+		SceneNode *deathPivotNode = mSceneMgr->getRootSceneNode()->
+			createChildSceneNode("deathPivotNode", Vector3((min_x + max_x)/2,0,(min_z + max_z)/2));
+		mMoveNode = deathPivotNode->createChildSceneNode("movingNode", Vector3(0, 0, mRotationRadius)
+			/*,Quaternion(Radian(Math::HALF_PI), Vector3::UNIT_Y)*/);
+		mMoveNode->attachObject(movingDeath);
+		mMoveNode->setScale(scale);
+
+		Entity *ent_ball = mSceneMgr->createEntity("ball","sphere.mesh");
+		SceneNode *node_pivot = mMoveNode->createChildSceneNode("pivotNode");
+		SceneNode *node_ball = node_pivot->createChildSceneNode("orbitNode", Vector3(120, 40, 0));
+		node_ball->attachObject(ent_ball);
+		node_ball->setScale(scale/10);
+	}
+
+	mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2);
 }
 
@@ -312,7 +408,4 @@
 	Real planeThreeEights = mPlaneDim * 3 / 8;
 	Real planeSixth = mPlaneDim / 6;
-
-	mCamNode->setPosition(Vector3(1280,600,1666));
-	mCamNode->setOrientation(Quaternion(0.936893, -0.124586, 0.323813, 0.04306));
 
 	SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode");
@@ -471,4 +564,8 @@
 		mSceneMgr->setOption("Algorithm", &alg);
 	}
+
+	// create ray query for ground intersection
+	mRaySceneQuery = mSceneMgr->createRayQuery(
+		Ray(Vector3::ZERO, Vector3::NEGATIVE_UNIT_Y));
 }
 
@@ -589,4 +686,47 @@
 }
 
+Vector3 KdTreeApp::clampToGround(const Vector3& vect, Real offset, Real cap)
+{
+	static Ray updateRay;
+	static Vector3 result;
+
+	result = vect;
+
+	if (mOptions.mSceneFiles == TERRAIN_SCENE)
+	{
+		updateRay.setOrigin(vect);
+		updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
+		mRaySceneQuery->setRay(updateRay);
+		RaySceneQueryResult& qryResult = mRaySceneQuery->execute();
+		RaySceneQueryResult::iterator i = qryResult.begin();
+		if (i != qryResult.end() && i->worldFragment)
+		{
+			SceneQuery::WorldFragment* wf = i->worldFragment;
+			result.y = wf->singleIntersection.y;
+		}
+	}
+	else
+	{
+		updateRay.setOrigin(vect);
+		updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
+		mRaySceneQuery->setRay(updateRay);
+		RaySceneQueryResult& qryResult = mRaySceneQuery->execute();
+		RaySceneQueryResult::iterator i = qryResult.begin();
+		while (i != qryResult.end() && i->movable)
+		{
+			if (i->movable->getName() != "PlayerCam")
+			{
+				MovableObject *mov = i->movable;
+				result.y = mov->getWorldBoundingBox().getCenter().y;
+				break;
+			}
+			i++;
+		}
+	}
+
+	result.y = result.y + offset > cap ? cap : result.y + offset;
+
+	return result;
+}
 
 //-----------------------------------------------------------------------
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1273)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1274)
@@ -1105,4 +1105,8 @@
 			StringConverter::toString(s, 2, '0'));
 
+		// set FPS display
+		const RenderTarget::FrameStats& stats = mWindow->getStatistics();
+		mDemoFPSDisp->setCaption(StringConverter::toString((int)stats.lastFPS));
+
 		// store fps when in demo mode
 		if (mOptions.mDemoMode)
@@ -1202,4 +1206,9 @@
 			StringConverter::toString(s, 2, '0'));
 
+		// set FPS display
+		const RenderTarget::FrameStats& stats = mWindow->getStatistics();
+		mDemoFPSDisp->setCaption(StringConverter::toString((int)stats.lastFPS));
+
+		// store frame
 		mFrameList.push_back(FrameInfo(mCamNode->getPosition(), mCamNode->getOrientation(), evt.timeSinceLastFrame));
 	}
@@ -1576,5 +1585,5 @@
 		// demo settings
 		logwrite << "\"" << SCENEMANAGER[mOptions.mSceneManager];
-		if (mOptions.mSceneManager == SM_KDT)
+		if (mOptions.mSceneManager == SM_KDT || mOptions.mSceneManager == SM_KTE)
 		{
 			logwrite << ds << RENDERMETHOD[mOptions.mRenderMethod] << ds << mOptions.mMaxDepth << ds 
@@ -1634,36 +1643,43 @@
 		mDemoStatus = OverlayManager::getSingleton().createOverlayElement("Panel", "KdTree/DemoStatus");
 		mDemoStatus->setMetricsMode(GMM_PIXELS);
-		mDemoStatus->setHorizontalAlignment(GHA_CENTER);
-		mDemoStatus->setVerticalAlignment(GVA_TOP);
-		mDemoStatus->setTop(5);
-		mDemoStatus->setLeft(-16);
 		mDemoStatus->setDimensions(32, 32);
-
-		//mDemoTime = static_cast<TextAreaOverlayElement *>
-		//	(OverlayManager::getSingleton().createOverlayElementFromTemplate(
-		//	"KdTree/Templates/BasicText", "TextArea", "KdTree/DemoTime"));
+		mDemoStatus->setLeft(64);
+
 		mDemoTime = static_cast<TextAreaOverlayElement *>
 			(OverlayManager::getSingleton().createOverlayElement("TextArea", "KdTree/DemoTime"));
 		mDemoTime->setMetricsMode(GMM_PIXELS);
 		mDemoTime->setTop(6);
-		mDemoTime->setLeft(8);
+		mDemoTime->setLeft(104);
 		mDemoTime->setFontName("TrebuchetMSBold");
 		mDemoTime->setCharHeight(24.0);
 		mDemoTime->setCaption("00:00");
 
-		PanelOverlayElement *timeCont = static_cast<PanelOverlayElement *>
+		mDemoFPSDisp = static_cast<TextAreaOverlayElement *>
+			(OverlayManager::getSingleton().createOverlayElement("TextArea", "KdTree/DemoFPS"));
+		mDemoFPSDisp->setMetricsMode(GMM_PIXELS);
+		mDemoFPSDisp->setAlignment(TextAreaOverlayElement::Right);
+		mDemoFPSDisp->setTop(6);
+		mDemoFPSDisp->setLeft(48);
+		mDemoFPSDisp->setFontName("TrebuchetMSBold");
+		mDemoFPSDisp->setCharHeight(24.0);
+		mDemoFPSDisp->setCaption("0");
+
+		PanelOverlayElement *demoCont = static_cast<PanelOverlayElement *>
 			(OverlayManager::getSingleton().createOverlayElement("Panel", "KdTree/DemoTimePanel"));
-		timeCont->setMetricsMode(GMM_PIXELS);
-		timeCont->setHorizontalAlignment(GHA_CENTER);
-		timeCont->setVerticalAlignment(GVA_TOP);
-		timeCont->setTop(5);
-		timeCont->setLeft(16);
-		timeCont->setDimensions(64, 32);
-		timeCont->addChild(mDemoTime);
+		demoCont->setMetricsMode(GMM_PIXELS);
+		demoCont->setHorizontalAlignment(GHA_CENTER);
+		demoCont->setVerticalAlignment(GVA_TOP);
+		demoCont->setTop(5);
+		demoCont->setLeft(-80);
+		demoCont->setDimensions(160, 32);
+		demoCont->addChild(mDemoFPSDisp);
+		demoCont->addChild(mDemoStatus);
+		demoCont->addChild(mDemoTime);
+		//demoCont->setMaterialName("Core/StatsBlockCenter");
 
 		mDemoOverlay = OverlayManager::getSingleton().create("KdTree/DemoOverlay");
 		mDemoOverlay->setZOrder(500);
-		mDemoOverlay->add2D(static_cast<PanelOverlayElement *>(mDemoStatus));
-		mDemoOverlay->add2D(timeCont);
+		//mDemoOverlay->add2D(static_cast<PanelOverlayElement *>(mDemoStatus));
+		mDemoOverlay->add2D(demoCont);
 	}
 
@@ -1677,4 +1693,6 @@
 		mDemoTime->setColourTop(ColourValue(0.5, 0.7, 0.5));
 		mDemoTime->setColourBottom(ColourValue(0.3, 0.5, 0.3));
+		mDemoFPSDisp->setColourTop(ColourValue(0.5, 0.7, 0.5));
+		mDemoFPSDisp->setColourBottom(ColourValue(0.3, 0.5, 0.3));
 		mDemoOverlay->show();
 		break;
@@ -1683,4 +1701,6 @@
 		mDemoTime->setColourTop(ColourValue(0.7, 0.5, 0.5));
 		mDemoTime->setColourBottom(ColourValue(0.5, 0.3, 0.3));
+		mDemoFPSDisp->setColourTop(ColourValue(0.7, 0.5, 0.5));
+		mDemoFPSDisp->setColourBottom(ColourValue(0.5, 0.3, 0.3));
 		mDemoOverlay->show();
 		break;
