Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt	(revision 1273)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/README.txt	(revision 1273)
@@ -0,0 +1,230 @@
+MANPAGE FOR TestKdTree
+
+NAME
+  TestKdTree.exe
+
+SYNOPSIS
+  TestKdTree [options]
+
+COMMAND LINE OPTIONS
+  -o <filename>, --outfile <filename>
+    Save a recorded demo to file <filename>.
+    See DEMOS for details
+
+  -i <filename>, --infile <filename>
+    Load a demo created by the application from file <filename>.
+    See DEMOS for details.
+
+  -l <filename>, --logfile <filename>
+    Save the FPS log of a demo benchmark in file <filename>. The log is saved
+    as a CSV text file. See DEMOS for details.
+    To have any effect, requires --demomode.
+
+  -d, --demomode
+    Start the application in demomode. See DEMOS for details.
+    Requires --infile, otherwise no benchmark is run.
+
+  -s <sm_id>, --scenemgr <sm_id>
+    Use specified scene manager. So far, the following scene managers are
+    supported:
+      KdTreeSceneManager            sm_id=KDT (DEFAULT)
+      KdTerrainSceneManager         sm_id=KTE
+      OcclusionCullingSceneManager  sm_id=OCM
+      OctreeSceneManager            sm_id=OCT
+      TerrainSceneManager           sm_id=TER
+      DefaultSceneManager           sm_id=GEN
+
+  -r <rm_id>, --rendermode <rm_id>
+    Use specified rendermode within the scene manager, if supported:
+      Internal Frustum Culling      rm_id=INT (KDT, KTE)
+      View Frustum Culling          rm_id=VFC (KDT, KTE, OCM)
+      Stop and Wait Culling         rm_id=SWC (KDT, KTE, OCM)
+      Coherent Hierarchical Culling rm_id=CHC (KDT, KTE, OCM) (DEFAULT)
+    Setting a rendermode for a scene manager that does not support it has
+    no effect. For supported scene managers, render mode switching is also
+    available ingame (see INGAME COMMANDS).
+
+  --comment
+    Append a comment to the logfile. Requires --logfile to have any effect.
+    (see DEMOS).
+
+  The following options apply only to the KDT and KTE scene managers. They have
+  no effect when another scene manager is selected. Besides --enhancevis, they
+  influenc how the KdTree which organizes the scene is built.
+
+  -e, --enhancevis
+    Enable enhanced visibility test (which, sadly, has little or no effect).
+    Only supported with INT render mode.
+    Enhanced visibility tries to abort tree traversal as early as possible by
+    determining if a tree node is fully visible. Then it renders all objects
+    contained within with no further traversal or visibility tests. This
+    setting can also be changed ingame (see INGAME COMMANDS).
+
+  --buildmode <bm_id>
+    Select the mode of building the KdTree.
+      Priority Queue    bm_id=PQ (DEFAULT)
+      Recursive         bm_id=RE
+    This setting can also be changed ingame (see INGAME COMMANDS).
+
+  --maxdepth <n>
+    Limit the maximum depth of the kdtree. The default n is 12. A complete
+    KdTree with depth n has 2^n leaves and 2^(n+1)-1 total nodes. However,
+    depending on the structure of the underying scene, a typical KdTree has
+    far less nodes.
+
+  --kt
+  --ki
+    These parameters define the two "magic numbers" used by the SAH algorithm
+    to determine the cost of splitting a node. In simple terms, KT is the cost
+    of traversing a node on the way down while KI is the cost of intersecting
+    (rendering) a leaf node. KI is multiplied with the number and size of
+    objects within the leaf. The default values are KT=2.0 and KI=1.0, since
+    they seem to produce acceptable trees.
+
+CONFIG FILE
+  The config file must have the name "testKdTree.cfg" and be found in the same
+  directory as the TestKdTree executable. It is used mainly for configuring
+  the simple test scene details. The config file has the following options:
+    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.
+    movespeed, rotatespeed:
+            Set the speed of movement and rotation for the player camera.
+            Movespeed is world units per second, rotatespeed is degrees per
+            second.
+  The following options apply only to the simple test scene:
+    planedim:
+            Size of the base plane
+    randomcount:
+            Number of randomly placed object of each class to generate
+    count, spacing:
+            Number of robots placed in a grid in the center of the scene.
+            Actual number is count^2. Spacing denotes the distance between two
+            robots in a row or column.
+    radius, period:
+            Distance from scene origin and time to complete one circle for the
+            moving robot.
+    shadows:
+            on enables shadows
+    selectentities:
+            Sum up the following numbers to select which entities will appear in
+            the scene:
+              1  robots in grid
+              2  randomly placed robots
+              4  randomly placed spaceships
+              8  moving robot
+              16 base plane
+            So, e.g., 22 is plane with random robots and space ships
+
+INGAME COMMANDS
+
+  ESC   Exit the program
+
+  The following commands can be used from within the game when --demomode
+  is NOT specified:
+
+  Visualisation:
+    F2  Toggle Visualisation camera (lower right): Boxes-Objects-Off-...
+        Works diffently, depending on selected scene manager
+    F3  Toggle Node Visualisation:  Highlighted-All-Off-...
+        Works diffently, depending on selected scene manager
+    F4  Toggle between nodes and bounding box heirarchy (KDT and KTE only)
+    3,4 Decrease/Increase KdTree level which to highlight (KDT and KTE only)
+    B   Show bounding boxes of all objects
+
+  Demos:
+    F5  Start/Stop recoring demo
+    F6  Save recorded demo
+    F9  Start/Stop demo playback
+
+  KdTree building:
+    1,2         Decrease/Increase maximum depth
+    5,6         Decrease/Increase KT
+    7,8         Decrease/Increase KI
+    0           Toggle build mode (Recursive, Priorty Queue)
+    BACKSPACE   Rebuild KdTree with the settings from above.
+
+  Movement:
+    U           Toggle free move, stick to ground
+    W,A,S,D     Forward, Strafe Left, Back, Strafe Right
+    UP,DOWN     Forward, Back
+    LEFT,RIGHT  Turn Left, Turn Right
+    PGUP,PGDOWN Up, Down (when in free move mode)
+    I           Toggle Vis Camera follow, free
+    NUM+,NUM-   Zoom Vis Camera
+    NUM{8,2,4,6}Move vis camera up, down, left right (when free)
+
+  Rendering:
+    SPACE Toggle render mode for (KDT, KTE, OCM), see --rendermode
+    V     Toggle enhanced visibility for (KDT, KTE), see --enhancevis
+    R     Toggle OpenGL/Direct3D render mode (Full, Line, Point)
+    T     Toggle OpenGL/Direct3D texture filtering (Bilinear, Trilinear, Aniso)
+
+  Other:
+    M     Toggle between buffered and unbuffered mouse input
+    K     Toggle between buffered and unbuffered keyboard input
+    F     Show/Hide overlays
+    P     Show/Hide player cam position
+    PRINT Save sceen shot
+
+DEMOS
+  The program has the ability to record, save and load demos, i.e. a path
+  through the scene. The program can save demos in two formats:
+  ASCII (extension .txt) and binary (extension .bin). The file name must
+  have one of these extensions and the format is selected by the program
+  accordingly.
+  Within the program, a demo can be recorded at any time (except when playing
+  back another demo) by pressing the F5 button. A record indicator appears on
+  the top of the screen. By pressing F5 again, the recording is stopped.
+  Pressing F9 will play back the recorded demo and return the player camera to
+  the previous position when it's done. The playback can be stopped by pressing
+  F9.
+  If the demo shall be permanently stored, the program must be launched with
+  the --outfile option, specifying a file to which the demo will be saved. The
+  file name must have on of the above mentioned extensions. If the file allready
+  exists and a demo is saved, it will be overwritten. To save a recorded demo,
+  simply press F6 to store it in the file. If a demo has been allready stored in
+  this session, it will be overwritten.
+  It is recommended to limit the framerate of the application (e.g. by enabling
+  vsync) when recording a demo, since it will produce smaller files.
+  To load a demo from a file, specify it with the --infile command line option.
+  To run a benchmark, a prerecorded demo must be loaded. Also, a logfile has to
+  be specified using the --logfile option. Finally the --demomode option must be
+  set. The program starts with disabled user input and no overlays. After an
+  initial 5 second delay, to stabilize the framerate and preload the scene, the
+  demo is played back and the framerate and other statistics are recored. Then
+  the program exits and writes the stats to the logfile. The benchmark can be
+  interrupted with the ESC key, but then no statistics are recorded.
+  The logfile is in CSV format for easy evaluation in spreadsheet applications.
+  The first row is the header consisting of:
+    The name of the demo file which was used for this benchmark
+    Timestamps of each FPS capture (starting with 0, in seconds)
+    Min, Avg, Max FPS headers
+    Total frames and total time headers
+    Comment header
+  The consecutive rows are filled with demo data, one row per benchmark run,
+  with the settings used for building and rendering in the first column.
+  If the specified logfile does not exist, it is created including the headers.
+  If a log file with the specified name does exists, it is checked if the demo
+  file used in the logfile corresponds with the demo file used in this benchmark
+  run. If the names do not match, or if the logfile cannot be read or written
+  to, the demo is executed but no stats are written. Additionaly, an error
+  message is written in "Ogre.log". However, if the log file exists and the demo
+  name matches, the resulst are appended to the existing logfile, allowing for
+  easy comparison of different settings and options.
+
+BUGS
+  Certainly, but none obvious.
+
+AUTHOR
+  Martin Szydlowski <msz@seclab.tuwien.ac.at>
+  
+LICENSE
+  GPL-ish
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1220)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1273)
@@ -56,5 +56,5 @@
 
 	// scene options
-	String  mSceneFiles;
+	//String  mSceneFiles;
 	Real	mRotationRadius;
 	int		mModelSpacing;
@@ -87,4 +87,5 @@
 
 	void createMaterials(void);
+	void createSimpleScene(void);
 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 1258)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1273)
@@ -49,4 +49,6 @@
 #define VIZ_VIEWPORT_Z_ORDER 10
 
+#define TERRAIN_SCENE "terrain"
+
 using namespace Ogre;
 
@@ -80,6 +82,8 @@
 	{
 		SM_KDT,
+		SM_KTE,
 		SM_OCM,
 		SM_OCT,
+		SM_TER,
 		SM_GEN,
 		SM_SIZE,
@@ -121,4 +125,5 @@
 		}
 
+		String mSceneFiles;
 		String mDemoInfileName;
 		String mDemoOutfileName;
@@ -272,4 +277,6 @@
 	Degree mRotScale;
 	Radian mDeathAngle;
+	// for terrain
+	RaySceneQuery *mRaySceneQuery;
 
 	// just to stop toggles flipping too fast
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1258)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1273)
@@ -181,5 +181,5 @@
 	cfDeath.load("testKdTree.cfg");
 
-	mSceneFiles = cfDeath.getSetting("scene");
+	mOptions.mSceneFiles = cfDeath.getSetting("scene");
 
 	tmp = cfDeath.getSetting("shadows");
@@ -236,4 +236,72 @@
 	createMaterials();
 
+	// load simple scene (planes & robots)
+	if (mOptions.mSceneFiles == "")
+	{
+		createSimpleScene();
+	}
+	// load terrain, but only if terrainscenemanager selected
+	else if (mOptions.mSceneFiles == TERRAIN_SCENE)
+	{
+		Plane waterPlane;
+
+		// Set ambient light
+		mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
+
+		// Create a light
+		Light* l = mSceneMgr->createLight("MainLight");
+		// Accept default settings: point light, white diffuse, just set position
+		// NB I could attach the light to a SceneNode if I wanted it to move automatically with
+		//  other objects, but I don't
+		l->setPosition(20,80,50);
+
+		// Fog
+		// NB it's VERY important to set this before calling setWorldGeometry 
+		// because the vertex program picked will be different
+		//ColourValue fadeColour(0.93, 0.86, 0.76);
+		//mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
+		//mWindow->getViewport(0)->setBackgroundColour(fadeColour);
+		mWindow->getViewport(0)->setBackgroundColour(ColourValue::Blue);
+
+		std::string terrain_cfg("terrain.cfg");
+
+		mSceneMgr -> setWorldGeometry( terrain_cfg );
+
+		// Define the required skyplane
+		Plane plane;
+		// 5000 world units from the camera
+		plane.d = 5000;
+		// Above the camera, facing down
+		plane.normal = -Vector3::UNIT_Y;
+
+		// add one robot
+		//Entity *robot = mSceneMgr->createEntity("TheRobot","robot.mesh");
+		//SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("TheRobotNode");
+		//node->attachObject(robot);
+		// add stuff minus gound plane
+		mSelectEntities &= ~ENT_PLN;
+		createSimpleScene();
+
+		// Set a nice viewpoint
+		mCamNode->setPosition(707,2500,528);
+		mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
+	}
+	// load scene from file
+	else
+	{
+		// don't load the other stuff
+		loadScene(mOptions.mSceneFiles);
+		// top view
+		mTopCam->setPosition(Vector3(1232, 3990, -1477));
+		// walkthrough view
+		mCamNode->setPosition(Vector3(827.885, 184.435, -524.984));
+		mCamNode->setOrientation(Quaternion(0.98935, 0.0348082, -0.141246, 0.00496945));
+
+		mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
+	}
+}
+
+void KdTreeApp::createSimpleScene()
+{
 	Entity *deaths;
 	SceneNode *nodes;
@@ -245,159 +313,125 @@
 	Real planeSixth = mPlaneDim / 6;
 
-	// load scene from file
-	if (mSceneFiles != "")
-	{
-		// don't load the other stuff
-		loadScene(mSceneFiles);
-		// top view
-		mTopCam->setPosition(Vector3(1232, 3990, -1477));
-		// walkthrough view
-		mCamNode->setPosition(Vector3(827.885, 184.435, -524.984));
-		mCamNode->setOrientation(Quaternion(0.98935, 0.0348082, -0.141246, 0.00496945));
-
-		mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
-	}
-	else
-	{
-		mCamNode->setPosition(Vector3(1280,600,1666));
-		mCamNode->setOrientation(Quaternion(0.936893, -0.124586, 0.323813, 0.04306));
-		//mCamera->lookAt(Vector3(-20,30,10));
-
-		SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode");
-		//SceneNode *grndan = anchor->createChildSceneNode("GroundAnchor");
-		SceneNode *grndan = mSceneMgr->getRootSceneNode();
-
-		if (mSelectEntities & ENT_GRID)
+	mCamNode->setPosition(Vector3(1280,600,1666));
+	mCamNode->setOrientation(Quaternion(0.936893, -0.124586, 0.323813, 0.04306));
+
+	SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode");
+	//SceneNode *grndan = anchor->createChildSceneNode("GroundAnchor");
+	SceneNode *grndan = mSceneMgr->getRootSceneNode();
+
+	if (mSelectEntities & ENT_GRID)
+	{
+		for (j = 0, z =  -(mModelCount / 2 * mModelSpacing); j < mModelCount; j++, z += mModelSpacing)
 		{
-			for (j = 0, z =  -(mModelCount / 2 * mModelSpacing); j < mModelCount; j++, z += mModelSpacing)
+			for (i = 0, x = -(mModelCount / 2 * mModelSpacing); i < mModelCount; i++, x += mModelSpacing) 
 			{
-				for (i = 0, x = -(mModelCount / 2 * mModelSpacing); i < mModelCount; i++, x += mModelSpacing) 
-				{
-					deaths = mSceneMgr->createEntity(cat(entName, i, j).c_str(),"robot.mesh");
-					if (mShadowsEnabled)
-						deaths->setCastShadows(true);
-					nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName, i, j).c_str(), Vector3(x, 0 , z));
-					nodes->attachObject(deaths);
-				}
-			}
-		}
-
-		if (mSelectEntities & ENT_RND)
-		{
-			entName = "randomdeath";
-			nodeName = "RandomDeathNode";
-			for (i = 0; i < mRandomCount; i++)
-			{
-				Vector3 pos(
-					Math::RangeRandom(-planeHalf,-planeSixth), 
-					0, 
-					Math::RangeRandom(-planeThreeEights, planeThreeEights));
-				deaths = mSceneMgr->createEntity(cat(entName,666,i),"robot.mesh");
+				deaths = mSceneMgr->createEntity(cat(entName, i, j).c_str(),"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 = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName, i, j).c_str(), Vector3(x, 0 , z));
 				nodes->attachObject(deaths);
 			}
 		}
-
-		if (mSelectEntities & ENT_SPC)
+	}
+
+	if (mSelectEntities & ENT_RND)
+	{
+		entName = "randomdeath";
+		nodeName = "RandomDeathNode";
+		for (i = 0; i < mRandomCount; i++)
 		{
-			entName = "randomspaceship";
-			nodeName = "RandomSpaceshipNode";
-			for (i = 0; i < mRandomCount; i++)
-			{
-				Vector3 pos(
-					//Math::RangeRandom(-planeHalf,-planeSixth), 
-					Math::RangeRandom(planeSixth,planeHalf), 
-					Math::RangeRandom(planeHalf * 0.1, planeHalf), 
-					Math::RangeRandom(-planeThreeEights, planeThreeEights));
-				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);
-			}
+			Vector3 pos(
+				Math::RangeRandom(-planeHalf,-planeSixth), 
+				0, 
+				Math::RangeRandom(-planeThreeEights, planeThreeEights));
+			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);
 		}
-
-		if (mSelectEntities & ENT_MOV)
+	}
+
+	if (mSelectEntities & ENT_SPC)
+	{
+		entName = "randomspaceship";
+		nodeName = "RandomSpaceshipNode";
+		for (i = 0; i < mRandomCount; i++)
 		{
-			Entity *movingDeath = mSceneMgr->createEntity("movingDeath","robot.mesh");
+			Vector3 pos(
+				//Math::RangeRandom(-planeHalf,-planeSixth), 
+				Math::RangeRandom(planeSixth,planeHalf), 
+				Math::RangeRandom(planeHalf * 0.1, planeHalf), 
+				Math::RangeRandom(-planeThreeEights, planeThreeEights));
+			deaths = mSceneMgr->createEntity(cat(entName,666,i),"razor.mesh");
 			if (mShadowsEnabled)
-				movingDeath->setCastShadows( true );
-
-			SceneNode *deathPivotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("deathPivotNode");
-			mMoveNode = deathPivotNode->createChildSceneNode("movingNode", Vector3(0, 0, mRotationRadius)/*,
-				Quaternion(Radian(Math::HALF_PI), Vector3::UNIT_Y)*/);
-			mMoveNode->attachObject(movingDeath);
-
-			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->scale(0.1, 0.1, 0.1);
-			
-
-			//mFollowCam->setAutoTracking(true, mMoveNode);
+				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);
 		}
-		
-		if (mSelectEntities & ENT_PLN)
-		{
-			Plane ground(Vector3::UNIT_Y, 0);
-			MeshManager::getSingleton().createPlane("ground", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
-				ground, mPlaneDim * 4 / 3, mPlaneDim, 20, 20, true, 1, 20, 20, Vector3::UNIT_Z);
-			Entity *ent_ground = mSceneMgr->createEntity("GroundEntity", "ground");
-			ent_ground->setCastShadows(false);
-			ent_ground->setMaterialName("Examples/RustySteel");//("Examples/Rockwall");
-			SceneNode *node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode", Vector3(0, 0, 0));
-			node_ground->attachObject(ent_ground);
-
-			//MeshManager::getSingleton().createPlane("ground2", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
-			//	ground, mPlaneDim/2, mPlaneDim, 10, 20, true, 1, 10, 20, Vector3::UNIT_Z);
-			//ent_ground = mSceneMgr->createEntity("GroundEntity2", "ground2");
-			//ent_ground->setCastShadows(false);
-			//ent_ground->setMaterialName("Examples/RustySteel");
-			//node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode2", Vector3(-mPlaneDim/4, 0, 0));
-			//node_ground->attachObject(ent_ground);
-		}
-
-		// Lights
-		mSceneMgr->setAmbientLight(ColourValue(0.1,0.1,0.1));
-		Light *light = mSceneMgr->createLight("light");
+	}
+
+	if (mSelectEntities & ENT_MOV)
+	{
+		Entity *movingDeath = mSceneMgr->createEntity("movingDeath","robot.mesh");
 		if (mShadowsEnabled)
-		{
-			mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
-			light->setType(Light::LT_POINT);
-			light->setPosition(Vector3(x, 300, z + 200));
-		}
-		else
-		{
-			light->setType(Light::LT_DIRECTIONAL);
-			light->setDirection(-1,-1,-1);
-		}
-		light->setDiffuseColour(ColourValue::White);
-		light->setSpecularColour(ColourValue(1, 1, 0.2));
-
-		// Skybox
-		mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2);
-	}
-
-	/* Some math tests
-	Plane planeX(Vector3::UNIT_X, Vector3(10,10,10));
-	Plane planeY(Vector3::UNIT_Y, Vector3(10,10,10));
-	Plane planeZ(Vector3::UNIT_Z, Vector3(10,10,10));
-	Vector3 vect(20,20,20);
-	Vector3 interX = planeX.projectVector(vect);
-	Vector3 interY = planeY.projectVector(vect);
-	Vector3 interZ = planeZ.projectVector(vect);
-	std::stringstream ssX, ssY, ssZ;
-	ssX << "The intersection of " << planeX << " and " << vect << " is at: " << interX;
-	ssY << "The intersection of " << planeY << " and " << vect << " is at: " << interY;
-	ssZ << "The intersection of " << planeZ << " and " << vect << " is at: " << interZ;
-	LogManager::getSingleton().logMessage(ssX.str());
-	LogManager::getSingleton().logMessage(ssY.str());
-	LogManager::getSingleton().logMessage(ssZ.str());
-	*/
+			movingDeath->setCastShadows( true );
+
+		SceneNode *deathPivotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("deathPivotNode");
+		mMoveNode = deathPivotNode->createChildSceneNode("movingNode", Vector3(0, 0, mRotationRadius)/*,
+																									 Quaternion(Radian(Math::HALF_PI), Vector3::UNIT_Y)*/);
+																									 mMoveNode->attachObject(movingDeath);
+
+		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->scale(0.1, 0.1, 0.1);
+
+
+		//mFollowCam->setAutoTracking(true, mMoveNode);
+	}
+
+	if (mSelectEntities & ENT_PLN)
+	{
+		Plane ground(Vector3::UNIT_Y, 0);
+		MeshManager::getSingleton().createPlane("ground", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
+			ground, mPlaneDim * 4 / 3, mPlaneDim, 20, 20, true, 1, 20, 20, Vector3::UNIT_Z);
+		Entity *ent_ground = mSceneMgr->createEntity("GroundEntity", "ground");
+		ent_ground->setCastShadows(false);
+		ent_ground->setMaterialName("Examples/RustySteel");//("Examples/Rockwall");
+		SceneNode *node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode", Vector3(0, 0, 0));
+		node_ground->attachObject(ent_ground);
+
+		//MeshManager::getSingleton().createPlane("ground2", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
+		//	ground, mPlaneDim/2, mPlaneDim, 10, 20, true, 1, 10, 20, Vector3::UNIT_Z);
+		//ent_ground = mSceneMgr->createEntity("GroundEntity2", "ground2");
+		//ent_ground->setCastShadows(false);
+		//ent_ground->setMaterialName("Examples/RustySteel");
+		//node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode2", Vector3(-mPlaneDim/4, 0, 0));
+		//node_ground->attachObject(ent_ground);
+	}
+
+	// Lights
+	mSceneMgr->setAmbientLight(ColourValue(0.1,0.1,0.1));
+	Light *light = mSceneMgr->createLight("light");
+	if (mShadowsEnabled)
+	{
+		mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
+		light->setType(Light::LT_POINT);
+		light->setPosition(Vector3(x, 300, z + 200));
+	}
+	else
+	{
+		light->setType(Light::LT_DIRECTIONAL);
+		light->setDirection(-1,-1,-1);
+	}
+	light->setDiffuseColour(ColourValue::White);
+	light->setSpecularColour(ColourValue(1, 1, 0.2));
+
+	// Skybox
+	mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2);
 }
 
@@ -418,5 +452,6 @@
 		"MySceneManager");
 	// set params for kdtree scene manager
-	if (mOptions.mSceneManager == KdTreeAppListener::SM_KDT)
+	if (mOptions.mSceneManager == KdTreeAppListener::SM_KDT || 
+		mOptions.mSceneManager == KdTreeAppListener::SM_KTE)
 	{
 		mSceneMgr->setOption("BuildMethod", &mOptions.mBuildMethod);
@@ -530,5 +565,7 @@
 
 	// create play button
-	mat = MaterialManager::getSingleton().create("KdTree/DemoPlayButton", "General");
+	mat = MaterialManager::getSingleton().getByName("KdTree/DemoPlayButton");
+	if (mat.isNull())
+		mat = MaterialManager::getSingleton().create("KdTree/DemoPlayButton", "General");
 	mat->setLightingEnabled(false);
 	tech = mat->getTechnique(0);
@@ -540,5 +577,7 @@
 
 	// create record button
-	mat = MaterialManager::getSingleton().create("KdTree/DemoRecordButton", "General");
+	mat = MaterialManager::getSingleton().getByName("KdTree/DemoRecordButton");
+	if (mat.isNull())
+		mat = MaterialManager::getSingleton().create("KdTree/DemoRecordButton", "General");
 	mat->setLightingEnabled(false);
 	tech = mat->getTechnique(0);
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1265)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1273)
@@ -18,10 +18,12 @@
 const String KdTreeAppListener::BUILDMETHOD[] = { "RE", "PQ" };
 const String KdTreeAppListener::BUILDMETHODCAPTION[] = { "Recursive", "Priority Queue" };
-const String KdTreeAppListener::SCENEMANAGER[] = { "KDT", "OCM", "OCT", "GEN" };
+const String KdTreeAppListener::SCENEMANAGER[] = { "KDT", "KTE", "OCM", "OCT", "TER", "GEN" };
 const String KdTreeAppListener::SCENEMANAGERNAME[] =
 {
 	"KdTreeSceneManager",
+	"KdTreeTerrainSceneManager",
 	"OcclusionCullingSceneManager",
 	"OctreeSceneManager",
+	"TerrainSceneManager",
 	"DefaultSceneManager"
 };
@@ -128,4 +130,5 @@
 mRotScale(0.0f),
 mDeathAngle(0.0f),
+mRaySceneQuery(0),
 // just to stop toggles flipping too fast
 mTimeUntilNextToggle(0.0f),
@@ -159,4 +162,6 @@
 	mTopCam = sm->getCamera("TopCam");
 	mCamNode = sm->getSceneNode("PlayerCamNode");
+
+	mRaySceneQuery = mSceneMgr->createRayQuery(Ray(mCamNode->getPosition(), Vector3::NEGATIVE_UNIT_Y));
 
 	mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
@@ -404,5 +409,7 @@
 	if (mSceneMgr->getTypeName() == "OctreeSceneManager")
 		mSceneMgr->setOption("ShowOctree", &show);
-	else if (mSceneMgr->getTypeName() == "KdTreeSceneManager")
+	else if (
+		mSceneMgr->getTypeName() == "KdTreeSceneManager" ||
+		mSceneMgr->getTypeName() == "KdTreeTerrainSceneManager")
 		mSceneMgr->setOption("ShowKdTree", &show);
 
@@ -965,21 +972,41 @@
 	if (!mFreeMove)
 	{
-		Vector3 pos = mCamNode->getPosition();
-		RaySceneQuery * rsquery = mSceneMgr->createRayQuery(Ray(pos, Vector3::NEGATIVE_UNIT_Y));
-		RaySceneQueryResult& rsresult = rsquery->execute();
-
-		RaySceneQueryResult::iterator it = rsresult.begin();
-		RaySceneQueryResult::iterator end = rsresult.end();
-
-		while (it != end && it->movable)
-		{
-			if (it->movable->getName() != "PlayerCam")
+		if (mOptions.mSceneFiles == TERRAIN_SCENE)
+		{
+			static Vector3 pos;
+			static Ray updateRay;
+			pos = mCamNode->getPosition();
+			updateRay.setOrigin(pos);
+			updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
+			mRaySceneQuery->setRay(updateRay);
+			RaySceneQueryResult& qryResult = mRaySceneQuery->execute();
+			RaySceneQueryResult::iterator i = qryResult.begin();
+			if (i != qryResult.end() && i->worldFragment)
 			{
-				mCamNode->setPosition(pos.x, it->movable->getWorldBoundingBox().getCenter().y + 2, pos.z);
-				break;
+				SceneQuery::WorldFragment* wf = i->worldFragment;
+				mCamNode->setPosition(pos.x, wf->singleIntersection.y + 10, pos.z);
 			}
-			it++;
-		}
-		OGRE_DELETE(rsquery);
+		}
+		else
+		{
+			static Vector3 pos;
+			static Ray updateRay;
+			pos = mCamNode->getPosition();
+			updateRay.setOrigin(pos);
+			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;
+					mCamNode->setPosition(pos.x, mov->getWorldBoundingBox().getCenter().y + 2, pos.z);
+					break;
+				}
+				i++;
+			}
+		}
 	}
 }
