Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1163)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTree.h	(revision 1187)
@@ -2,8 +2,8 @@
 #define __KdTreeApp_H__
 
-#include "ExampleApplication.h"
+#include <OgreRenderTargetListener.h>
+#include <ExampleApplication.h>
+#include <ivreader.h>
 #include "TestKdTreeAppListener.h"
-
-#include <ivreader.h>
 
 class KdTreeApp : public ExampleApplication
@@ -19,4 +19,5 @@
 
 protected:
+	SceneNode *mCamNode;
 	SceneNode *mDeathNode;
 	Camera *mTopCam;
@@ -68,3 +69,18 @@
 };
 
+class KdTreeAppRenderTargetListener : public RenderTargetListener
+{
+public:
+	KdTreeAppRenderTargetListener(SceneManager *sceneMgr);
+
+protected:
+	void preViewportUpdate (const RenderTargetViewportEvent &evt);
+	void postRenderTargetUpdate (const RenderTargetEvent &evt);
+
+	SceneManager *mSceneMgr;
+
+	ShadowTechnique mSavedShadowTechnique;
+	ColourValue mSavedAmbientLight;
+};
+
 #endif
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1183)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/include/TestKdTreeAppListener.h	(revision 1187)
@@ -42,4 +42,6 @@
 #include "OgreException.h"
 
+#define VIZ_VIEWPORT_Z_ORDER 10
+
 using namespace Ogre;
 
@@ -78,67 +80,30 @@
 	OverlayElement *mQueriesIssuedInfo;
 
-    void updateStats(void)
-    {
-		static unsigned int opt = 0;
-		static char str[100];
+	EventProcessor* mEventProcessor;
+	InputReader* mInputDevice;
+	SceneNode *mCamNode;
+	Camera* mCamera;
+	Camera* mTopCam;
+	SceneManager *mSceneMgr;
+	Radian mDeathAngle;
 
-        static String currFps = "Current FPS: ";
-        static String avgFps = "Average FPS: ";
-        static String bestFps = "Best FPS: ";
-        static String worstFps = "Worst FPS: ";
-        static String tris = "Triangle Count: ";
+	Vector3 mTranslateVector;
+	RenderWindow* mWindow;
+	bool mStatsOn;
+	bool mUseBufferedInputKeys, mUseBufferedInputMouse, mInputTypeSwitchingOn;
+	unsigned int mNumScreenShots;
+	float mMoveScale;
+	Degree mRotScale;
+	// just to stop toggles flipping too fast
+	Real mTimeUntilNextToggle ;
+	Radian mRotX, mRotY;
+	TextureFilterOptions mFiltering;
+	int mAniso;
 
-        // update stats when necessary
-        try {
-            OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
-            OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
-            OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
-            OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
+	// stuff for the viz camera
+	bool mVizCamera;
+	Vector3 mVizCamTransVect;
 
-            const RenderTarget::FrameStats& stats = mWindow->getStatistics();
-
-            guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
-            guiCurr->setCaption(currFps + StringConverter::toString((int)stats.lastFPS));
-            guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
-                +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
-            guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
-                +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
-
-            OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
-            guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));
-
-            OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
-            guiDbg->setCaption(mWindow->getDebugText());
-
-
-			//-- culling stats
-			mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); 
-			mFrustumCulledNodesInfo->setCaption(str);
-
-			mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); 
-			mQueryCulledNodesInfo->setCaption(str);
-
-			mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt); 
-			mHierarchyNodesInfo->setCaption(str);
-
-			mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt); 
-			mRenderedNodesInfo->setCaption(str);
-
-			// take old value into account in order to create no sudden changes
-			mSceneMgr->getOption("NumQueriesIssued", &opt); 
-			mDelayedQueriesIssued = mDelayedQueriesIssued * 0.8 + (float)opt * 0.2f;
-			sprintf(str,": %d", (int)mDelayedQueriesIssued); 
-			mQueriesIssuedInfo->setCaption(str);
-
-			mSceneMgr->getOption("NumTraversedNodes", &opt); 
-			mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2f;
-			sprintf(str,": %d", (int)mDelayedTraversedNodes); 
-			mTraversedNodesInfo->setCaption(str);
-        }
-        catch(...)
-        {
-            // ignore
-        }
-    }
+    void updateStats(void);
 
 public:
@@ -155,916 +120,38 @@
     // Constructor takes a RenderWindow because it uses that to determine input context
     KdTreeAppListener(RenderWindow* win, SceneManager* sm, Real rs, Real ms, Real rp,
-		bool useBufferedInputKeys = false, bool useBufferedInputMouse = false)
-    {
-        mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
-		mKdTreeOverlay = OverlayManager::getSingleton().getByName("KdTree/DebugOverlay");
+		bool useBufferedInputKeys = false, bool useBufferedInputMouse = false);
 
+    virtual ~KdTreeAppListener();
 
-        mUseBufferedInputKeys = useBufferedInputKeys;
-		mUseBufferedInputMouse = useBufferedInputMouse;
-		mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse;
+	void initOverlayElement(OverlayElement **elInfo, String ext, 
+		String name, int top, String caption);
 
-		if (mInputTypeSwitchingOn)
-		{
-            mEventProcessor = new EventProcessor();
-			mEventProcessor->initialise(win);
-			mEventProcessor->startProcessingEvents();
-			mEventProcessor->addKeyListener(this);
-			mInputDevice = mEventProcessor->getInputReader();
+	void initStatsOverlay();
 
-		}
-        else
-        {
-            mInputDevice = PlatformManager::getSingleton().createInputReader();
-            mInputDevice->initialise(win,true, true);
-        }
+	void initKdTreeOverlay();
 
-		mFreeMove = false;
-		mShowTree = false;
-		mCullCamera = false;
-		mCullTransVec = Vector3::ZERO;
-		mSeqNum = 0;
+	void showDebugOverlay(bool show);
 
-		mDelayedQueriesIssued = 0.0;
-		mDelayedTraversedNodes = 0.0;
+	void toggleVizCamera();
 
-		mCamera = sm->getCamera("PlayerCam");
-		mTopCam = sm->getCamera("TopCam");
-		mSceneMgr = sm;
-        mWindow = win;
-		mRotateSpeed = rs;
-        mMoveSpeed = ms;
-		mRotationPeriod = rp;
-		mDeathAngle = 0;
-        mStatsOn = true;
-		mNumScreenShots = 0;
-		mTimeUntilNextToggle = 0;
-        mSceneDetailIndex = 0;
-        mMoveScale = 0.0f;
-        mRotScale = 0.0f;
-	    mTranslateVector = Vector3::ZERO;
-        mAniso = 8;
-        mFiltering = TFO_ANISOTROPIC;
+    virtual bool processUnbufferedKeyInput(const FrameEvent& evt);
 
-        MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
-        MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
+    bool processUnbufferedMouseInput(const FrameEvent& evt);
 
-		initKdTreeOverlay();
-		initStatsOverlay();
-
-        showDebugOverlay(true);
-    }
-    virtual ~KdTreeAppListener()
-    {
-		if (mInputTypeSwitchingOn)
-		{
-            delete mEventProcessor;
-		}
-        else
-        {
-            PlatformManager::getSingleton().destroyInputReader( mInputDevice );
-        }
-    }
-
-	//-----------------------------------------------------------------------
-	void initOverlayElement(OverlayElement **elInfo, String ext, 
-		String name, int top, String caption)
-	{
-		OverlayElement *el = 
-			OverlayManager::getSingleton().getOverlayElement(ext + name);
-
-		(*elInfo) = OverlayManager::getSingleton().getOverlayElement(ext + name + "Info");
-		(*elInfo)->setCaption(caption);
-
-		el->setTop(top);
-		(*elInfo)->setTop(top);
-	}
-	//-----------------------------------------------------------------------
-	void initStatsOverlay()
-	{
-		const int border_height = 10;
-		const int vert_space = 15;
-
-		//-- visibility culling stats overlay
-		int top = border_height;
-
-		String ext = "KdTree/Visibility/";
-
-		initOverlayElement(&mFrustumCulledNodesInfo, ext, "FrustumCulledNodes", top, ": 0"); top += vert_space;
-		initOverlayElement(&mQueryCulledNodesInfo, ext, "QueryCulledNodes", top, ": 0"); top += vert_space;
-		initOverlayElement(&mTraversedNodesInfo, ext, "TraversedNodes", top, ": 0"); top += vert_space;
-		initOverlayElement(&mHierarchyNodesInfo, ext, "HierarchyNodes", top, ": 0"); top += vert_space;
-		initOverlayElement(&mRenderedNodesInfo, ext, "RenderedNodes", top, ": 0"); top += vert_space;
-		initOverlayElement(&mObjectsCountInfo, ext, "ObjectsCount", top, ": 0"); top += vert_space;
-		initOverlayElement(&mQueriesIssuedInfo, ext, "QueriesIssued", top, ": 0"); top += vert_space;
-
-		OverlayElement *visPanel = OverlayManager::getSingleton().
-			getOverlayElement("KdTree/VisibilityStatsPanel");
-
-		visPanel->setHeight(top + border_height);
-	}
-	//-----------------------------------------------------------------------
-	void initKdTreeOverlay()
-	{
-		const int border_height = 10;
-		const int vert_space = 15;
-		const String na = ": N/A";
-		String sMD, sKT, sKI, sHL, sBM, sRM, sFM;
-
-		int top = border_height;
-
-		String ext = "KdTree/";
-
-		int maxd;
-		if (mSceneMgr->getOption("KdTreeMaxDepth", &maxd))
-			sMD = ": " + StringConverter::toString(maxd);
-		else
-			sMD = na;
-
-		Real kt;
-		if (mSceneMgr->getOption("KT", &kt))
-			sKT = ": " + StringConverter::toString(kt);
-		else
-			sKT = na;
-
-		Real ki;
-		if (mSceneMgr->getOption("KI", &ki))
-			sKI = ": " + StringConverter::toString(ki);
-		else
-			sKI = na;
-
-		int hl;
-		if (mSceneMgr->getOption("HighlightLevel", &hl))
-			sHL = ": " + StringConverter::toString(hl);
-		else
-			sHL = na;
-		if (!mShowTree)
-			sHL = ": off";
-
-		String bm;
-		if (mSceneMgr->getOption("BuildMethod", &bm))
-			sBM = ": " + bm;
-		else
-			sBM = na;
-
-		String rm;
-		if (mSceneMgr->getOption("RenderMethod", &rm))
-		{
-			if (rm == "INT")
-				sRM = ": Internal Frustum Culling";
-			else if (rm == "VFC")
-				sRM = ": View Frustum Culling";
-			else if (rm == "SWC")
-				sRM = ": Stop and Wait Culling";
-			else if (rm == "CHC")
-				sRM = ": Coherent Hierarchical Culling";
-			else
-				sRM = na;
-		}
-		else
-			sRM = na;
-
-		sFM = na;
-		if (mFreeMove)
-			sFM = ": Free";
-		else
-			sFM = ": Ground";
-
-		initOverlayElement(&mRenderMethodInfo, ext, "RenderMethod", top, sRM); top += vert_space;
-		initOverlayElement(&mBuildMethodInfo, ext, "BuildMethod", top, sBM); top += vert_space;
-		initOverlayElement(&mKdTreeMaxDepthInfo, ext, "KdTreeMaxDepth", top, sMD); top += vert_space;
-		initOverlayElement(&mHighlightLevelInfo, ext, "HighlightLevel", top, sHL); top += vert_space;
-		initOverlayElement(&mKTInfo, ext, "KT", top, sKT); top += vert_space;
-		initOverlayElement(&mKIInfo, ext, "KI", top, sKI); top += vert_space;
-		initOverlayElement(&mMovementInfo, ext, "Movement", top, sFM); top += vert_space;
-
-		OverlayElement *visPanel = OverlayManager::getSingleton().
-			getOverlayElement("KdTree/OptionsPanel");
-
-		visPanel->setHeight(top + border_height);
-	}
-
-	void showDebugOverlay(bool show)
-	{
-		if (mDebugOverlay)
-		{
-			if (show)
-			{
-				mDebugOverlay->show();
-				mKdTreeOverlay->show();
-			}
-			else
-			{
-				mDebugOverlay->hide();
-				mKdTreeOverlay->hide();
-			}
-		}
-	}
-
-	void toggleVizCamera()
-	{
-		static const int zorder = 10; 
-		static nodeVizMode = 0;
-
-		nodeVizMode = (nodeVizMode + 1) % NODEVIZ_MODES_NUM;
-
-		if (nodeVizMode != 0)
-		{
-			if (!mCullCamera)
-			{
-				Viewport* tvp = mWindow->addViewport(mTopCam,zorder,0.66,0.66,0.34,0.34);
-				tvp->setBackgroundColour(ColourValue(1.0, 0.0, 0.0));
-				tvp->setOverlaysEnabled(false);
-
-				mTopCam->setAspectRatio(
-					Real(tvp->getActualWidth())/Real(tvp->getActualHeight()));
-				mCullCamera = true;
-				mSceneMgr->setOption("VisualizeCulledNodes", &mCullCamera);
-			}
-
-			bool renderNodesForViz = (nodeVizMode == NODEVIZ_RENDER_NODES) || 
-				(nodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
-			bool renderNodesContentForViz = (nodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
-
-			mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz);
-			mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz);
-		}
-		else
-		{
-			mWindow->removeViewport(zorder);
-			mCullCamera = false;
-			mSceneMgr->setOption("VisualizeCulledNodes", &mCullCamera);
-		}
-	}
-
-    virtual bool processUnbufferedKeyInput(const FrameEvent& evt)
-    {
-		// moving the cull camera
-		if (mInputDevice->isKeyDown(KC_NUMPAD2))
-		{
-			mCullTransVec.y = -mMoveScale;
-		}
-		if (mInputDevice->isKeyDown(KC_NUMPAD8))
-		{
-			mCullTransVec.y = mMoveScale;
-		}
-		if (mInputDevice->isKeyDown(KC_NUMPAD4))
-		{
-			mCullTransVec.x = mMoveScale;
-		}
-		if (mInputDevice->isKeyDown(KC_NUMPAD6))
-		{
-			mCullTransVec.x = -mMoveScale;
-		}
-		if (mInputDevice->isKeyDown(KC_SUBTRACT))
-		{
-			mCullTransVec.z = mMoveScale;
-		}
-		if (mInputDevice->isKeyDown(KC_ADD))
-		{
-			mCullTransVec.z = -mMoveScale;
-		}
-
-		// stuff for the overlay
-		static String sNA = ": N/A";
-
-		static String bmOptions[] = { "Recursive", "PriorityQueue" };
-		static String bmOptionCaptions[] = { ": Recursive", ": PriorityQueue" };
-		static int bmOptionsSize = sizeof(bmOptions) / sizeof(String);
-		static int bmCurrent = 0;
-
-		//static String rmOptions[] = { "Recursive", "Stack", "StopAndWait", "CHC" };
-		static String rmOptions[] = { "INT", "VFC", "SWC", "CHC" };
-		static String rmOptionCaptions[] =
-		{
-			": Internal Frustum Culling",
-			": View Frustum Culling", 
-			": Stop and Wait Culling",
-			": Coherent Hierarchical Culling"
-		};
-		static int rmOptionsSize = sizeof(rmOptions) / sizeof (String);
-		static int rmCurrent = 0;
-
-		if ((mInputDevice->isKeyDown(KC_1) || mInputDevice->isKeyDown(KC_2)) && mTimeUntilNextToggle <= 0)
-		{
-			int currdepth;
-			if (mSceneMgr->getOption("KdTreeMaxDepth", &currdepth))
-			{
-				if (mInputDevice->isKeyDown(KC_1))
-					currdepth--;
-				else if (mInputDevice->isKeyDown(KC_2))
-					currdepth++;
-
-				if (mSceneMgr->setOption("KdTreeMaxDepth", &currdepth))
-				{
-					mKdTreeMaxDepthInfo->setCaption(": " + StringConverter::toString(currdepth));
-					int hl;
-					if (mSceneMgr->getOption("HighlightLevel", &hl))
-						mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
-					else
-						mHighlightLevelInfo->setCaption(sNA);
-				}
-			}
-			else
-			{
-				mKdTreeMaxDepthInfo->setCaption(sNA);
-				mHighlightLevelInfo->setCaption(sNA);
-			}
-
-			if (!mShowTree)
-				mHighlightLevelInfo->setCaption(": off");
-
-			mTimeUntilNextToggle = 0.2;
-		}
-
-		if ((mInputDevice->isKeyDown(KC_3) || mInputDevice->isKeyDown(KC_4)) && mTimeUntilNextToggle <= 0)
-		{
-			int hl;
-			if (mSceneMgr->getOption("HighlightLevel", &hl))
-			{
-				if (mInputDevice->isKeyDown(KC_3))
-					hl--;
-				else if (mInputDevice->isKeyDown(KC_4))
-					hl++;
-
-				if (mSceneMgr->setOption("HighlightLevel", &hl))
-					mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
-			}
-			else
-			{
-				mHighlightLevelInfo->setCaption(sNA);
-			}
-
-			if (!mShowTree)
-				mHighlightLevelInfo->setCaption(": off");
-
-			mTimeUntilNextToggle = 0.2;
-		}
-
-
-		if ((mInputDevice->isKeyDown(KC_5) ||mInputDevice->isKeyDown(KC_6)) && mTimeUntilNextToggle <= 0)
-		{
-			Real kt;
-			if (mSceneMgr->getOption("KT", &kt))
-			{
-				if (mInputDevice->isKeyDown(KC_5))
-					kt -= 0.1;
-				else if (mInputDevice->isKeyDown(KC_6))
-					kt += 0.1;
-
-				if (kt < 0.1)
-					kt = 0.1;
-			
-				if (mSceneMgr->setOption("KT", &kt))
-					mKTInfo->setCaption(": " + StringConverter::toString(kt));
-			}
-			else
-			{
-				mKTInfo->setCaption(sNA);
-			}
-
-			mTimeUntilNextToggle = 0.2;
-		}
-
-		if ((mInputDevice->isKeyDown(KC_7) || mInputDevice->isKeyDown(KC_8)) && mTimeUntilNextToggle <= 0)
-		{
-			Real ki;
-			if (mSceneMgr->getOption("KI", &ki))
-			{
-				if (mInputDevice->isKeyDown(KC_7))
-					ki -= 0.1;
-				else if (mInputDevice->isKeyDown(KC_8))
-					ki += 0.1;
-
-				if (ki < 0.1)
-					ki = 0.1;
-
-				if (mSceneMgr->setOption("KI", &ki))
-					mKIInfo->setCaption(": " + StringConverter::toString(ki));
-			}
-			else
-			{
-				mKIInfo->setCaption(sNA);
-			}
-
-			mTimeUntilNextToggle = 0.2;
-		}
-
-		if (mInputDevice->isKeyDown(KC_X) && mTimeUntilNextToggle <= 0)
-		{
-			String bm;
-			if (mSceneMgr->getOption("BuildMethod", &bm))
-			{
-				for (int idx = 0; idx < bmOptionsSize; idx++)
-					if (bmOptions[idx] == bm)
-						bmCurrent = idx;
-				bmCurrent = (bmCurrent + 1) % bmOptionsSize;
-				if (mSceneMgr->setOption("BuildMethod", &bmOptions[bmCurrent]))
-					mBuildMethodInfo->setCaption(bmOptionCaptions[bmCurrent]);
-			}
-			else
-			{
-				mBuildMethodInfo->setCaption(sNA);
-			}
-
-			mTimeUntilNextToggle = 0.5;
-		}
-
-		if (mInputDevice->isKeyDown(KC_SPACE) && mTimeUntilNextToggle <= 0)
-		{
-			String rm;
-			if (mSceneMgr->getOption("RenderMethod", &rm))
-			{
-				for (int idx = 0; idx < rmOptionsSize; idx++)
-					if (rmOptions[idx] == rm)
-						rmCurrent = idx;
-				rmCurrent = (rmCurrent + 1) % rmOptionsSize;
-				if (mSceneMgr->setOption("RenderMethod", &rmOptions[rmCurrent]))
-					mRenderMethodInfo->setCaption(rmOptionCaptions[rmCurrent]);
-			}
-			else
-			{
-				mRenderMethodInfo->setCaption(sNA);
-			}
-
-			mTimeUntilNextToggle = 0.5;
-		}
-
-		if (mInputDevice->isKeyDown(KC_Q) && mTimeUntilNextToggle <= 0)
-		{
-			mFreeMove = !mFreeMove;
-			String move = "N/A";
-			if (mFreeMove)
-				move = ": Free";
-			else
-				move = ": Ground";
-
-			mMovementInfo->setCaption(move);
-
-			mTimeUntilNextToggle = 0.5;
-		}
-
-
-		if (mInputDevice->isKeyDown(KC_BACK) && mTimeUntilNextToggle <= 0)
-		{
-			mSceneMgr->setOption("RebuildKdTree", 0);
-			mTimeUntilNextToggle = 1;
-		}
-
-		if (mInputDevice->isKeyDown(KC_N) && mTimeUntilNextToggle <= 0)
-		{
-			//Entity * ent = mSceneMgr->createEntity("randominsert" + StringConverter::toString(mSeqNum), "robot.mesh");
-			Entity * ent = mSceneMgr->createEntity("randominsert" + StringConverter::toString(mSeqNum), "razor.mesh");
-			//Vector3 position(Math::RangeRandom(100, 1125), -0, Math::RangeRandom(-1125, 1125));
-			Vector3 position(Math::RangeRandom(-5000, 5000), Math::RangeRandom(-5000, 5000), Math::RangeRandom(-5000, 5000));
-			//Quaternion orientation(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y);
-			Vector3 axis(Math::RangeRandom(-1,1),Math::RangeRandom(-1,1),Math::RangeRandom(-1,1));
-			axis.normalise();
-			Quaternion orientation(Radian(Math::RangeRandom(-Math::PI, Math::PI)), axis);
-			Vector3 scale(Math::RangeRandom(0.5, 5),Math::RangeRandom(0.5, 5),Math::RangeRandom(0.5, 5));
-			SceneNode * anchor = mSceneMgr->getSceneNode("AnchorNode");
-			SceneNode *sn = anchor->createChildSceneNode("RandomInsertNode" + StringConverter::toString(mSeqNum), position, orientation);
-			sn->attachObject(ent);
-			sn->setScale(scale);
-			mTimeUntilNextToggle = 0.5;
-			mSeqNum++;
-		}
-
-		if (mInputDevice->isKeyDown(KC_J) && mTimeUntilNextToggle <= 0)
-		{
-			if (mSeqNum > 0)
-			{
-				mSeqNum--;
-				mSceneMgr->destroySceneNode("RandomInsertNode" + StringConverter::toString(mSeqNum));
-				mSceneMgr->destroyEntity("randominsert" + StringConverter::toString(mSeqNum));
-				mTimeUntilNextToggle = 0.5;
-			}
-		}
-
-		if (mInputDevice->isKeyDown(KC_O) && mTimeUntilNextToggle <= 0)
-		{
-			LogManager::getSingleton().logMessage("############## Camera Position:");
-			LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getPosition()));
-			LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getOrientation()));
-			LogManager::getSingleton().logMessage("############## Cull Camera Position:");
-			LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getPosition()));
-			LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getOrientation()));
-			mTimeUntilNextToggle = 1.0;
-		}
-
-		if (mInputDevice->isKeyDown(KC_B) && mTimeUntilNextToggle <= 0)
-		{
-			mSceneMgr->showBoundingBoxes( ! mSceneMgr->getShowBoundingBoxes() );
-			mTimeUntilNextToggle = 0.5;
-		}
-
-		if (mInputDevice->isKeyDown(KC_C) && mTimeUntilNextToggle <= 0)
-		{
-			toggleVizCamera();
-			mTimeUntilNextToggle = 0.5;
-		}
-
-		if (mInputDevice->isKeyDown(KC_V) && mTimeUntilNextToggle <= 0)
-		{
-			mShowTree = !mShowTree;
-
-			if (mSceneMgr->getTypeName() == "OctreeSceneManager")
-			{
-				//(static_cast<OctreeSceneManager *>(mSceneMgr))->setShowBoxes(mShowTree);
-				mSceneMgr->setOption("ShowOctree", &mShowTree);
-			}
-			else if (mSceneMgr->getTypeName() == "KdTreeSceneManager")
-			{
-				mSceneMgr->setOption("ShowKdTree", &mShowTree);
-				//KdTreeSceneManager *sm = static_cast<KdTreeSceneManager *>(mSceneMgr);
-				//sm->setShowBoxes(!sm->getShowBoxes());
-				//(static_cast<KdTreeSceneManager *>(mSceneMgr))->setShowBoxes(mShowTree);
-			}
-
-			if (!mShowTree)
-				mHighlightLevelInfo->setCaption(": off");
-			else
-			{
-				int hl;
-				if (mSceneMgr->getOption("HighlightLevel", &hl))
-					mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
-				else
-					mHighlightLevelInfo->setCaption(sNA);
-			}
-			
-			mTimeUntilNextToggle = 0.5;
-		}
-
-		if (mInputDevice->isKeyDown(KC_G) && mTimeUntilNextToggle <= 0)
-		{
-			bool toggleShowAllBoxes;
-			mSceneMgr->getOption("ShowAllBoxes", &toggleShowAllBoxes);
-			toggleShowAllBoxes = !toggleShowAllBoxes;
-			mSceneMgr->setOption("ShowAllBoxes", &toggleShowAllBoxes);
-			mTimeUntilNextToggle = 0.2;
-		}
-
-		if (mInputDevice->isKeyDown(KC_H) && mTimeUntilNextToggle <= 0)
-		{
-			bool toggleShow;
-			mSceneMgr->getOption("ShowNodeAABB", &toggleShow);
-			toggleShow = !toggleShow;
-			mSceneMgr->setOption("ShowNodeAABB", &toggleShow);
-			mTimeUntilNextToggle = 0.2;
-		}
-
-		if (mInputDevice->isKeyDown(KC_P))
-		{
-			mWindow->writeContentsToTimestampedFile("Screenshot",".jpg");
-		}
-
-        if (mInputDevice->isKeyDown(KC_A))
-        {
-            // Move camera left
-            mTranslateVector.x = -mMoveScale;
-        }
-
-        if (mInputDevice->isKeyDown(KC_D))
-        {
-            // Move camera RIGHT
-            mTranslateVector.x = mMoveScale;
-        }
-
-        /* Move camera forward by keypress. */
-        if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W) )
-        {
-            mTranslateVector.z = -mMoveScale;
-        }
-
-        /* Move camera backward by keypress. */
-        if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S) )
-        {
-            mTranslateVector.z = mMoveScale;
-        }
-
-        if (mInputDevice->isKeyDown(KC_PGUP))
-        {
-            // Move camera up
-            mTranslateVector.y = mMoveScale;
-        }
-
-        if (mInputDevice->isKeyDown(KC_PGDOWN))
-        {
-            // Move camera down
-            mTranslateVector.y = -mMoveScale;
-        }
-
-        if (mInputDevice->isKeyDown(KC_RIGHT))
-        {
-            mCamera->yaw(-mRotScale);
-        }
-		
-        if (mInputDevice->isKeyDown(KC_LEFT))
-        {
-            mCamera->yaw(mRotScale);
-        }
-
-        if( mInputDevice->isKeyDown( KC_ESCAPE) )
-        {            
-            return false;
-        }
-
-		// see if switching is on, and you want to toggle 
-        if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_M) && mTimeUntilNextToggle <= 0)
-        {
-			switchMouseMode();
-            mTimeUntilNextToggle = 1;
-        }
-
-        if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_K) && mTimeUntilNextToggle <= 0)
-        {
-			// must be going from immediate keyboard to buffered keyboard
-			switchKeyMode();
-            mTimeUntilNextToggle = 1;
-        }
-        if (mInputDevice->isKeyDown(KC_F) && mTimeUntilNextToggle <= 0)
-        {
-            mStatsOn = !mStatsOn;
-            showDebugOverlay(mStatsOn);
-
-            mTimeUntilNextToggle = 1;
-        }
-        if (mInputDevice->isKeyDown(KC_T) && mTimeUntilNextToggle <= 0)
-        {
-            switch(mFiltering)
-            {
-            case TFO_BILINEAR:
-                mFiltering = TFO_TRILINEAR;
-                mAniso = 1;
-                break;
-            case TFO_TRILINEAR:
-                mFiltering = TFO_ANISOTROPIC;
-                mAniso = 8;
-                break;
-            case TFO_ANISOTROPIC:
-                mFiltering = TFO_BILINEAR;
-                mAniso = 1;
-                break;
-            default:
-                break;
-            }
-            MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
-            MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
-
-
-            showDebugOverlay(mStatsOn);
-
-            mTimeUntilNextToggle = 1;
-        }
-
-        if (mInputDevice->isKeyDown(KC_SYSRQ) && mTimeUntilNextToggle <= 0)
-        {
-			char tmp[20];
-			sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots);
-            mWindow->writeContentsToFile(tmp);
-            mTimeUntilNextToggle = 0.5;
-			mWindow->setDebugText(String("Wrote ") + tmp);
-        }
-		
-		if (mInputDevice->isKeyDown(KC_R) && mTimeUntilNextToggle <=0)
-		{
-			mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;
-			switch(mSceneDetailIndex) {
-				case 0 : mCamera->setPolygonMode(PM_SOLID) ; break ;
-				case 1 : mCamera->setPolygonMode(PM_WIREFRAME) ; break ;
-				case 2 : mCamera->setPolygonMode(PM_POINTS) ; break ;
-			}
-			mTimeUntilNextToggle = 0.5;
-		}
-
-        static bool displayCameraDetails = false;
-        if (mInputDevice->isKeyDown(KC_P) && mTimeUntilNextToggle <= 0)
-        {
-            displayCameraDetails = !displayCameraDetails;
-            mTimeUntilNextToggle = 0.5;
-            if (!displayCameraDetails)
-                mWindow->setDebugText("");
-        }
-        if (displayCameraDetails)
-        {
-            // Print camera details
-            mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) + " " + 
-                "O: " + StringConverter::toString(mCamera->getDerivedOrientation()));
-        }
-
-        // Return true to continue rendering
-        return true;
-    }
-
-    bool processUnbufferedMouseInput(const FrameEvent& evt)
-    {
-        /* Rotation factors, may not be used if the second mouse button is pressed. */
-
-        /* If the second mouse button is pressed, then the mouse movement results in 
-           sliding the camera, otherwise we rotate. */
-        if( mInputDevice->getMouseButton( 1 ) )
-        {
-            mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
-            mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
-        }
-        else
-        {
-            mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
-            mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
-        }
-
-
-		return true;
-	}
-
-	void moveCamera()
-	{
-
-        // Make all the changes to the camera
-        // Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW (e.g. airplane)
-        mCamera->yaw(mRotX);
-        mCamera->pitch(mRotY);
-        mCamera->moveRelative(mTranslateVector);
-		mTopCam->moveRelative(mCullTransVec);
-
-		if (!mFreeMove)
-		{
-			Vector3 pos = mCamera->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")
-				{
-					mCamera->setPosition(pos.x, it->movable->getWorldBoundingBox().getCenter().y + 3, pos.z);
-					break;
-				}
-				it++;
-			}
-			OGRE_DELETE(rsquery);
-		}
-	}
+	void moveCamera();
 
     // Override frameStarted event to process that (don't care about frameEnded)
-    bool frameStarted(const FrameEvent& evt)
-    {
-        if(mWindow->isClosed())
-            return false;
+    bool frameStarted(const FrameEvent& evt);
 
-        if (!mInputTypeSwitchingOn)
-    	{
-            mInputDevice->capture();
-        }
+    bool frameEnded(const FrameEvent& evt);
 
+	void switchMouseMode();
 
-		if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys)
-		{
-			// one of the input modes is immediate, so setup what is needed for immediate mouse/key movement
-			if (mTimeUntilNextToggle >= 0) 
-				mTimeUntilNextToggle -= evt.timeSinceLastFrame;
+	void switchKeyMode();
 
-			// If this is the first frame, pick a speed
-			if (evt.timeSinceLastFrame == 0)
-			{
-				mMoveScale = 1;
-				mRotScale = 0.1;
-			}
-			// Otherwise scale movement units by time passed since last frame
-			else
-			{
-				// Move about 100 units per second,
-				mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
-				// Take about 10 seconds for full rotation
-				mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
-			}
-			mRotX = 0;
-            mRotY = 0;
-	        mTranslateVector = Vector3::ZERO;
-			mCullTransVec = Vector3::ZERO;
-		}
+	void keyClicked(KeyEvent* e);
 
-        if (mUseBufferedInputKeys)
-        {
-            // no need to do any processing here, it is handled by event processor and 
-			// you get the results as KeyEvents
-        }
-        else
-        {
-            if (processUnbufferedKeyInput(evt) == false)
-			{
-				return false;
-			}
-        }
-        if (mUseBufferedInputMouse)
-        {
-            // no need to do any processing here, it is handled by event processor and 
-			// you get the results as MouseEvents
-        }
-        else
-        {
-            if (processUnbufferedMouseInput(evt) == false)
-			{
-				return false;
-			}
-        }
-
-		if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys)
-		{
-			// one of the input modes is immediate, so update the movement vector
-
-			moveCamera();
-
-		}
-
-		Camera	*followCam = mSceneMgr->getCamera("FollowCam");
-		if (followCam->getAutoTrackTarget() != 0)
-		{
-			// Move the death thingy & update lookat camera FOV
-			SceneNode *deathPivotNode = mSceneMgr->getSceneNode("deathPivotNode");
-			SceneNode *deathNode = mSceneMgr->getSceneNode("movingNode");
-			SceneNode *pivotNode = mSceneMgr->getSceneNode("pivotNode");
-
-			Vector3 fcpos = followCam->getPosition();
-			Vector3 oldpos = deathNode->getWorldPosition();
-			
-			Radian deltaAngle = Radian(evt.timeSinceLastFrame / mRotationPeriod * Math::TWO_PI);
-			deathPivotNode->rotate(Vector3::UNIT_Y, deltaAngle);
-			pivotNode->rotate(Vector3::UNIT_Y, deltaAngle * 4);
-			
-			Vector3 pos = deathNode->getWorldPosition();
-
-			Real olddist = (oldpos - fcpos).length();
-			Real dist = (pos - fcpos).length();
-
-			Radian oldfov = followCam->getFOVy();
-			Radian fov = Radian(olddist / dist) * oldfov;
-
-			followCam->setFOVy(fov);
-		}
-
-		return true;
-    }
-
-    bool frameEnded(const FrameEvent& evt)
-    {
-        updateStats();
-        return true;
-    }
-
-	void switchMouseMode() 
-	{
-        mUseBufferedInputMouse = !mUseBufferedInputMouse;
-		mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
-	}
-	void switchKeyMode() 
-	{
-        mUseBufferedInputKeys = !mUseBufferedInputKeys;
-		mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
-	}
-
-	void keyClicked(KeyEvent* e) 
-	{
-		if (e->getKeyChar() == 'm')
-		{
-			switchMouseMode();
-		}
-		else if (e->getKeyChar() == 'k')
-		{
-
-			switchKeyMode();
-		}
-
-	}
-	void keyPressed(KeyEvent* e) {}
-	void keyReleased(KeyEvent* e) {}
-
-protected:
-    EventProcessor* mEventProcessor;
-    InputReader* mInputDevice;
-    Camera* mCamera;
-	Camera* mTopCam;
-	SceneManager *mSceneMgr;
-	Radian mDeathAngle;
-
-    Vector3 mTranslateVector;
-    RenderWindow* mWindow;
-    bool mStatsOn;
-    bool mUseBufferedInputKeys, mUseBufferedInputMouse, mInputTypeSwitchingOn;
-	unsigned int mNumScreenShots;
-    float mMoveScale;
-    Degree mRotScale;
-    // just to stop toggles flipping too fast
-    Real mTimeUntilNextToggle ;
-    Radian mRotX, mRotY;
-    TextureFilterOptions mFiltering;
-    int mAniso;
-
-	// stuff for the culling camera
-	bool mCullCamera;
-	Vector3 mCullTransVec;
+	void keyPressed(KeyEvent* e) {};
+	void keyReleased(KeyEvent* e) {};
 };
 
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/scripts/TestKdTree.vcproj
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/scripts/TestKdTree.vcproj	(revision 1177)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/scripts/TestKdTree.vcproj	(revision 1187)
@@ -141,4 +141,7 @@
 				RelativePath="..\src\TestKdTree.cpp">
 			</File>
+			<File
+				RelativePath="..\src\TestKdTreeAppListener.cpp">
+			</File>
 		</Filter>
 		<Filter
Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1165)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTree.cpp	(revision 1187)
@@ -122,9 +122,15 @@
 		mTopCam->setPosition(Vector3(1232, 3990, -1477));
 		// walkthrough view
-		mCamera->setPosition(Vector3(1102.56, 181.845, -350.305));
-		mCamera->setOrientation(Quaternion(-0.977321, -0.117497, -0.174903, 0.0210273));
+		mCamNode->setPosition(Vector3(1102.56, 181.845, -350.305));
+		//mCamNode->setOrientation(Quaternion(-0.977321, -0.117497, -0.174903, 0.0210273));
+
+		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");
@@ -244,6 +250,5 @@
 
 		// Skybox
-		// mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2);
-	
+		mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2);
 	}
 
@@ -271,4 +276,5 @@
 	mFrameListener->showDebugOverlay( true );
 	mRoot->addFrameListener(mFrameListener);
+	mWindow->addListener(new KdTreeAppRenderTargetListener(mSceneMgr));
 }
 
@@ -283,18 +289,22 @@
     // Create the camera
     mCamera = mSceneMgr->createCamera("PlayerCam");
+	mCamera->setNearClipDistance(1);
+
+	mCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("PlayerCamNode", Vector3(0,0,0));
+	mCamNode->attachObject(mCamera);
+	
 
     // Position it at 500 in Z direction
     //mCamera->setPosition(Vector3(0,50,500));
 	//mCamera->setPosition(Vector3(500,256,666));
-	mCamera->setPosition(Vector3(1280,600,1666));
+	//mCamera->setPosition(Vector3(1280,600,1666));
     // Look back along -Z
     //mCamera->lookAt(Vector3(0,50,-300));
-	mCamera->lookAt(Vector3(-20,30,10));
-    mCamera->setNearClipDistance(5);
-
-	mFollowCam = mSceneMgr->createCamera("FollowCam");
-	mFollowCam->setPosition(Vector3(800,150,800));
-	mFollowCam->setNearClipDistance(5);
-	mFollowCam->setFOVy(Angle(15));
+	//mCamera->lookAt(Vector3(-20,30,10));
+
+	//mFollowCam = mSceneMgr->createCamera("FollowCam");
+	//mFollowCam->setPosition(Vector3(800,150,800));
+	//mFollowCam->setNearClipDistance(5);
+	//mFollowCam->setFOVy(Angle(15));
 
 	mTopCam = mSceneMgr->createCamera("TopCam");
@@ -303,6 +313,17 @@
 	mTopCam->pitch(Radian(-Math::HALF_PI));
 	mTopCam->setCullingFrustum(mCamera);
-	//mTopCam->setProjectionType(PT_ORTHOGRAPHIC);
-	//mTopCam->lookAt(Vector3(0,0,0));
+	mTopCam->setNearClipDistance(1);
+
+	// infinite far plane?
+	if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
+	{
+		mTopCam->setFarClipDistance(0);
+		mCamera->setFarClipDistance(0);
+	}
+	else
+	{
+		mTopCam->setFarClipDistance(20000);
+		mCamera->setFarClipDistance(20000);
+	}	
 }
 
@@ -445,2 +466,45 @@
 	return false;
 }
+
+/**********************************************************************/
+/*           VisualizationRenderTargetListener implementation         */
+/**********************************************************************/
+
+
+//-----------------------------------------------------------------------
+KdTreeAppRenderTargetListener::KdTreeAppRenderTargetListener(SceneManager *sceneMgr)
+:RenderTargetListener(), mSceneMgr(sceneMgr)
+{
+}
+//-----------------------------------------------------------------------
+void KdTreeAppRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt)
+{
+	// visualization viewport
+	const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER;
+	const bool nShowViz = !showViz;
+
+	mSavedShadowTechnique = mSceneMgr->getShadowTechnique();
+	mSavedAmbientLight = mSceneMgr->getAmbientLight();
+
+	// -- ambient light must be full for visualization, shadows disabled
+	if (showViz)
+	{
+		mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));
+		mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
+	}
+
+	mSceneMgr->setOption("PrepareVisualization", &showViz);
+	mSceneMgr->setOption("SkyBoxEnabled", &nShowViz);
+	//mSceneMgr->setOption("SkyPlaneEnabled", &showViz);
+
+	RenderTargetListener::preViewportUpdate(evt);
+}
+//-----------------------------------------------------------------------
+void KdTreeAppRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt)
+{
+	// reset values
+	mSceneMgr->setShadowTechnique(mSavedShadowTechnique);
+	mSceneMgr->setAmbientLight(mSavedAmbientLight);
+
+	RenderTargetListener::postRenderTargetUpdate(evt);
+}
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTree.h	(revision 1183)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTree.h	(revision 1187)
@@ -207,4 +207,7 @@
 			virtual bool isEmpty() const = 0;
 			virtual bool hasGeometry() const = 0;
+
+			virtual void queueVisibleObjects(unsigned long currentFrame, 
+				Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes) = 0;
 			
 			// consider using typesafe callback functions
@@ -288,10 +291,10 @@
 			int mLevel;
 			AxisAlignedBox mAABB;
-		protected:
-			WireBoundingBox * mWBB;
 
 			// for the CHC hierarchy interface
 			/** the real extent of the node. */
 			AxisAlignedBox mWorldAABB;
+		protected:
+			WireBoundingBox * mWBB;
 			
 			unsigned int mLastRendered;
@@ -327,4 +330,15 @@
 			virtual bool hasGeometry() const { return false; };
 
+			virtual void queueVisibleObjects(unsigned long currentFrame, 
+				Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes)
+			{
+				if (showBoxes)
+				{
+					WireBoundingBox * wbb = getWireBoundingBox();
+					if (wbb)
+						queue->addRenderable(wbb);
+				}
+			}
+
 			// branches do not posses geometry => just merge child aabbs
 			virtual void _updateBounds(bool recurse = true)
@@ -334,7 +348,7 @@
 
 				if (mLeft)
-					mWorldAABB.merge(mLeft->_getWorldAABB());
+					mWorldAABB.merge(mLeft->mWorldAABB);
 				if (mRight)
-					mWorldAABB.merge(mRight->_getWorldAABB());
+					mWorldAABB.merge(mRight->mWorldAABB);
 
 				// update parent recursively
@@ -367,4 +381,7 @@
 			virtual bool hasGeometry() const { return !mKdRenderables.empty(); };
 
+			virtual void queueVisibleObjects(unsigned long currentFrame, 
+				Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes);
+
 			// update the world aabb based on the contained geometry
 			virtual void _updateBounds(bool recurse = true);
@@ -430,4 +447,6 @@
 		typedef KdTree::Branch * BranchPtr;
 		typedef KdTree::Leaf * LeafPtr;
+
+		typedef std::list<NodePtr> NodeList;
 		typedef std::set<LeafPtr> LeafSet;
 
@@ -484,6 +503,5 @@
 
 		// test visibility of objects and add to render	queue
-		void queueVisibleObjects(Camera* cam, RenderQueue* queue, bool onlyShadowCasters, 
-			RenderMethod renderMethod, bool showBoxes = false);
+		void queueVisibleObjects(Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes = false);
 
 		// self-explanatory ...
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1185)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1187)
@@ -16,5 +16,5 @@
 #include "OgreKdTree.h"
 
-#define KDTREE_MAX_DEPTH 20
+#define KDTREE_MAX_DEPTH 12
 
 namespace Ogre
@@ -134,5 +134,7 @@
 	/** Render a list of scenenodes
 	*/
-	virtual void _renderNodes(const KdRenderableList& nodelist, Camera * cam,
+	//virtual void _renderNodes(const KdRenderableList& nodelist, Camera * cam,
+	//	bool onlyShadowCasters, int leavePassesInQueue);
+	virtual void _renderNode(KdTree::NodePtr node, Camera * cam,
 		bool onlyShadowCasters, int leavePassesInQueue);
 
@@ -227,5 +229,6 @@
 
 	// remember visited scene nodes for viz
-	KdRenderableList mVisibleNodes;
+	//KdRenderableList mVisibleNodes;
+	KdTree::NodeList mVisibleNodes;
 
 	/************************************************************************/
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneNode.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneNode.h	(revision 1173)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneNode.h	(revision 1187)
@@ -43,4 +43,7 @@
 		virtual AxisAlignedBox getBoundingBox() const;
 
+		// custom render op, show bounding box instead of axes
+		//virtual void getRenderOperation(RenderOperation& op);
+
 		//virtual void _findVisibleObjects(Camera* cam, RenderQueue* queue, 
 		//	bool includeChildren = true, bool displayNodes = false, bool onlyShadowCasters = false);
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1185)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1187)
@@ -61,6 +61,6 @@
 
 // test
-//String chc = "CHC";
-//setOption("RenderMethod", &chc);
+String chc = "CHC";
+setOption("RenderMethod", &chc);
 }
 
@@ -557,5 +557,5 @@
 		getRenderQueue()->clear();
 		if (mKdTree)
-			mKdTree->queueVisibleObjects(cam, getRenderQueue(), onlyShadowCasters, mRenderMethod, mShowBoxes);
+			mKdTree->queueVisibleObjects(cam, getRenderQueue(), onlyShadowCasters, mShowBoxes);
 	}
 	else
@@ -578,5 +578,5 @@
 				getRenderQueue()->clear();
 				if (mKdTree)
-					mKdTree->queueVisibleObjects(cam, getRenderQueue(), onlyShadowCasters, mRenderMethod, mShowBoxes);
+					mKdTree->queueVisibleObjects(cam, getRenderQueue(), onlyShadowCasters, mShowBoxes);
 			}
 
@@ -697,13 +697,19 @@
 			if (mUseDepthPass)
 			{
-				KdRenderableList::const_iterator it, it_end = mVisibleNodes.end();
-
-				//getRenderQueue()->clear();
-				for (it = mVisibleNodes.begin(); it != it_end; ++ it)
+				//KdRenderableList::const_iterator it, it_end = mVisibleNodes.end();
+
+				////getRenderQueue()->clear();
+				//for (it = mVisibleNodes.begin(); it != it_end; ++ it)
+				//{
+				//	(*it)->queueObjects(mCameraInProgress, getRenderQueue(), false);
+				//}
+				KdTree::NodeList::const_iterator it, end = mVisibleNodes.end();
+				for (it = mVisibleNodes.begin(); it != end; it++)
 				{
-					(*it)->queueObjects(mCameraInProgress, getRenderQueue(), false);
+					(*it)->queueVisibleObjects(mHierarchyInterface->GetFrameId(), mCameraInProgress,
+						getRenderQueue(), false, mShowBoxes);
 				}
 			}
-#endif	
+#endif
 			//-- now we can render all remaining queue objects
 			//-- used for depth pass, transparents, overlay
@@ -724,25 +730,28 @@
 }
 
-void KdTreeSceneManager::_renderNodes(const KdRenderableList& nodelist, Camera * cam, 
-	bool onlyShadowCasters, int leavePassesInQueue)
-{
-#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//void KdTreeSceneManager::_renderNodes(const KdRenderableList& nodelist, Camera * cam, 
+//	bool onlyShadowCasters, int leavePassesInQueue)
+void KdTreeSceneManager::_renderNode(KdTree::NodePtr node, Camera * cam, 
+									 bool onlyShadowCasters, int leavePassesInQueue)
+{
 	RenderQueueGroup *currentGroup = 
 		getRenderQueue()->getQueueGroup(getRenderQueue()->getDefaultQueueGroup());
 	currentGroup->clear(leavePassesInQueue);
-#else
-	getRenderQueue()->clear();
-#endif
-	KdRenderableList::const_iterator it = nodelist.begin();
-	KdRenderableList::const_iterator end = nodelist.end();
-	while (it != end)
-	{
-		if (!(*it)->isQueued(mHierarchyInterface->GetFrameId(), cam))
-		{
-			mVisibleNodes.push_back(*it);
-			(*it)->queueObjects(cam, getRenderQueue(), onlyShadowCasters);
-		}
-		it++;
-	}
+
+	node->queueVisibleObjects(mHierarchyInterface->GetFrameId(), cam, getRenderQueue(),
+		onlyShadowCasters, mShowBoxes);
+	mVisibleNodes.push_back(node);
+
+	//KdRenderableList::const_iterator it = nodelist.begin();
+	//KdRenderableList::const_iterator end = nodelist.end();
+	//while (it != end)
+	//{
+	//	if (!(*it)->isQueued(mHierarchyInterface->GetFrameId(), cam))
+	//	{
+	//		mVisibleNodes.push_back(*it);
+	//		(*it)->queueObjects(cam, getRenderQueue(), onlyShadowCasters);
+	//	}
+	//	it++;
+	//}
 
 	_renderQueueGroupObjects(currentGroup, QueuedRenderableCollection::OM_PASS_GROUP);
@@ -957,17 +966,20 @@
 		nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
 
-		for (KdRenderableList::iterator it = mVisibleNodes.begin(); it != mVisibleNodes.end(); ++it)
+		for (KdTree::NodeList::iterator it = mVisibleNodes.begin(); it != mVisibleNodes.end(); ++it)
 		{
 			if (mRenderNodesForViz)
 			{
-				KdTreeSceneNode * node = static_cast<KdTreeSceneNode *>(*it);
-				// render the leaf nodes
-				if (node->numAttachedObjects() && 
-					!node->numChildren() && 
-					(node->getAttachedObject(0)->getMovableType() == "Entity") &&
-					node->getAttachedObject(0)->isVisible())
-				{
-					getRenderQueue()->addRenderable(node);
-				}
+				//KdTreeSceneNode * node = static_cast<KdTreeSceneNode *>(*it);
+				//// render the leaf nodes
+				//if (node->numAttachedObjects() && 
+				//	!node->numChildren() && 
+				//	(node->getAttachedObject(0)->getMovableType() == "Entity") &&
+				//	node->getAttachedObject(0)->isVisible())
+				//{
+				//	//getRenderQueue()->addRenderable(node);
+				//	node->_addBoundingBoxToQueue(getRenderQueue());
+				//}
+
+				/*** TODO: fix this ... maybe revert to original state, not quite happy now! ***/
 
 				// addbounding boxes instead of node itself
@@ -977,5 +989,7 @@
 			if (mRenderNodesContentForViz) 
 			{
-				(*it)->queueObjects(cam, getRenderQueue(), false);
+				//(*it)->queueObjects(cam, getRenderQueue(), false);
+				(*it)->queueVisibleObjects(mHierarchyInterface->GetFrameId(), 
+					cam, getRenderQueue(), false, mShowBoxes);
 			}
 		}
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeHierarchyInterface.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeHierarchyInterface.cpp	(revision 1173)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeHierarchyInterface.cpp	(revision 1187)
@@ -58,10 +58,5 @@
 		KdTreeSceneManager * ksm = static_cast<KdTreeSceneManager *>(mSceneManager);
 
-		// render only if the node is a leaf
-		if (kdnode->isLeaf())
-		{
-			ksm->_renderNodes(KDLEAFPTR_CAST(node)->mKdRenderables, mCamera, 
-				mOnlyShadowCasters, mLeavePassesInQueue);
-		}	
+		ksm->_renderNode(kdnode, mCamera, mOnlyShadowCasters, mLeavePassesInQueue);
 
 		mVisibleNodes.push_back(node);
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneNode.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneNode.cpp	(revision 1183)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneNode.cpp	(revision 1187)
@@ -108,5 +108,6 @@
 			// Tell attached objects about camera position (incase any extra processing they want to do)
 			iobj->second->_notifyCurrentCamera(cam);
-			if (!onlyShadowCasters || iobj->second->getCastShadows())
+			if (iobj->second->isVisible() &&
+				(!onlyShadowCasters || iobj->second->getCastShadows()))
 			{
 				iobj->second->_updateRenderQueue(queue);
@@ -175,4 +176,15 @@
 	}
 
+	//void KdTreeSceneNode::getRenderOperation(RenderOperation& op)
+	//{
+	//	if (mWireBoundingBox == NULL) 
+	//	{
+	//		mWireBoundingBox = new WireBoundingBox();
+	//	}
+
+	//	mWireBoundingBox->setupBoundingBox(mWorldAABB);
+	//	mWireBoundingBox->getRenderOperation(op);
+	//}
+
 	// DEBUG
 	String KdTreeSceneNode::dumpToString()
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp	(revision 1183)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTree.cpp	(revision 1187)
@@ -22,4 +22,5 @@
 
 #define KDTREE_LOGNAME "KdTreeBuild.log"
+#define PLT_SIZE 101
 
 namespace Ogre
@@ -28,4 +29,6 @@
 	Real PlaneEvent::KI = 1.0;
 
+	//----------------------------------------------------------------------------
+	// determine if this event is left or right of the reference event
 	void PlaneEvent::classify(const PlaneEvent& e, PlaneEvent::Side side)
 	{
@@ -57,4 +60,6 @@
 	}
 
+	//----------------------------------------------------------------------------
+	// clip this event to an aabb (move it so that the plane on one of the box planes)
 	PlaneEvent PlaneEvent::clip(AxisAlignedBox& box, PlaneEvent::Dimension dim)
 	{
@@ -68,29 +73,11 @@
 	}
 
+	//----------------------------------------------------------------------------
+	// the surface area heuristic to determine the cost of splitting the parent aabb
+	// along the plane represented by this event
 	void PlaneEvent::SAH(const AxisAlignedBox& parent, int nLeft, int nPlane, int nRight, SplitInfo& split)
 	{
-
-#ifdef KDTREE_DEBUG_OFF
 		Real mu = splitBox(parent, split.bleft, split.bright);
-		Real sav = surfaceArea(parent); // optimize?? called several times for the same box
-		Real savl = surfaceArea(split.bleft);
-		Real savr = surfaceArea(split.bright);
-		Real pl = savl / sav;
-		Real pr = savr / sav;
-		Real costl = splitCost(pl, pr, nLeft + nPlane, nRight, mu);
-		Real costr = splitCost(pl, pr, nLeft, nPlane + nRight, mu);
-
-		Log * log = LogManager::getSingleton().getLog(KDTREE_LOGNAME);
-		log->logMessage("SAH: SA-parent=" + StringConverter::toString(sav) + 
-			"\n\tSA-left=" + StringConverter::toString(savl) + 
-			" SA-right=" + StringConverter::toString(savr) + 
-			"\n\tp-left=" + StringConverter::toString(pl) + 
-			" p-right=" + StringConverter::toString(pr) +
-			"\n\tmu=" + StringConverter::toString(mu) +
-			"\n\tcost-left=" + StringConverter::toString(costl) +
-			" cost-right=" + StringConverter::toString(costr));
-#else
-		Real mu = splitBox(parent, split.bleft, split.bright);
-		Real sav = surfaceArea(parent); // optimize?? called several times for the same box
+		Real sav = surfaceArea(parent);
 		Real pl = surfaceArea(split.bleft) / sav;
 		Real pr = surfaceArea(split.bright) / sav;
@@ -98,5 +85,4 @@
 		Real costr = splitCost(pl, pr, nLeft, nPlane + nRight, mu);
 
-#endif
 		if (costl < costr)
 		{
@@ -117,20 +103,14 @@
 	}
 
+	//----------------------------------------------------------------------------
+	// split the parent aabb with the plane in this event
 	Real PlaneEvent::splitBox(const AxisAlignedBox& parent, AxisAlignedBox& left, AxisAlignedBox& right)
 	{
 		Vector3 bmin = parent.getMinimum();
 		Vector3 bmax = parent.getMaximum();
-#ifdef KDTREE_DEBUG_OFF
-		if(bmin[mDimension] > mPosition[mDimension] || bmax[mDimension] < mPosition[mDimension])
-		{
-			Log * log = LogManager::getSingleton().getLog(KDTREE_LOGNAME);
-			log->logMessage("SPLITBOX SNAFU in event " + print() +
-				"\n\tmin=" + StringConverter::toString(bmin[mDimension]) + 
-				" split=" + StringConverter::toString(mPosition[mDimension]) + 
-				" max=" + StringConverter::toString(bmax[mDimension]));
-		}
-#endif
 		// calculate the penalty for spliting the box that way
-		Real mu = lookupPenalty((mPosition[mDimension] - bmin[mDimension]) / (bmax[mDimension] - bmin[mDimension]));
+		Real mu = lookupPenalty(
+			(mPosition[mDimension] - bmin[mDimension]) / 
+			(bmax[mDimension] - bmin[mDimension]));
 		// set corners which are the same as parent AABB
 		left.setMinimum(bmin);
@@ -146,8 +126,51 @@
 	}
 
+	//----------------------------------------------------------------------------
+	// compute surface area of a box ... DUH!
+	Real PlaneEvent::surfaceArea(const AxisAlignedBox& box)
+	{
+		Vector3 sides = box.getMaximum() - box.getMinimum();
+		return	2 * sides.x * sides.y +
+			2 * sides.y * sides.z +
+			2 * sides.z * sides.x;
+	}
+
+	//----------------------------------------------------------------------------
+	// lookup the penalty for placing the splitting plane near to the edge of the AABB
+	// 0.0 <= p <= 1.0, p = 0.5 means the plane divides the aabb in half
+	Real PlaneEvent::lookupPenalty(Real p)
+	{
+		// precomputed table of {x^6 + 1|0 <= x <= 1}
+		static Real mPenaltyLookupTable[PLT_SIZE];
+		static bool init_done = false;
+
+		if (!init_done)
+		{
+			Real step = 1.0  / (PLT_SIZE - 1);
+			Real x = 0.0; 
+			//LogManager::getSingleton().logMessage("### Calculating Lookup Table ###");
+			for (int i = 0; i < PLT_SIZE; i++)
+			{
+				mPenaltyLookupTable[i] = Math::Pow(x, 6) + 1.0;
+				x += step;
+				//LogManager::getSingleton().logMessage("### mPenaltyLookupTable[" + StringConverter::toString(i,3) + "]=" + StringConverter::toString(mPenaltyLookupTable[i]));
+			}
+			init_done = true;
+			//LogManager::getSingleton().logMessage("### Lookup Table Calculated ###");
+		}
+
+		// normalize p to [0,1]
+		Real x = Math::Abs(p * 2 - 1);
+		// compute index
+		int i = Math::IFloor(x * (PLT_SIZE - 1));
+
+		return mPenaltyLookupTable[i];
+	}
+
+	//----------------------------------------------------------------------------
+	// compute cost of the split, reward splitting of empty space (lambda, const),
+	// penalize splitting off 'thin' slices (mu, const)
 	Real PlaneEvent::splitCost(Real pLeft, Real pRight, int nLeft, int nRight)
 	{
-		//assert(pLeft <= 1.0 && pRight <= 1.0);
-
 		// reward splitting off chunks of empty space
 		Real lambda = 1.0;
@@ -157,5 +180,5 @@
 		}
 
-		// penalize splitting off small chunks
+		// penalize splitting off small chunks (thin slices)
 		Real mu = 1.0;
 		if (pLeft < 0.1 || pRight < 0.1 || pLeft > 0.9 || pRight > 0.9)
@@ -164,12 +187,11 @@
 		}
 		return lambda * mu * (KT + (KI * (pLeft*nLeft + pRight*nRight)));
-		
-		//return lambda * (KT + (KI * (pLeft*nLeft + pRight*nRight)));
-	}
-
+	}
+
+	//----------------------------------------------------------------------------
+	// compute cost of the split, reward splitting of empty space (lambda, const),
+	// penalize splitting off 'thin' slices (mu, parameter)
 	Real PlaneEvent::splitCost(Real pLeft, Real pRight, int nLeft, int nRight, Real mu)
 	{
-		//assert(pLeft <= 1.0 && pRight <= 1.0);
-
 		// reward splitting off chunks of empty space
 		Real lambda = 1.0;
@@ -182,22 +204,9 @@
 	}
 
-	Real PlaneEvent::surfaceArea(const AxisAlignedBox& box)
-	{
-		Vector3 sides = box.getMaximum() - box.getMinimum();
-#ifdef KDTREE_DEBUG_OFF
-		if(sides.x < 0 || sides.y < 0 || sides.z < 0)
-		{
-			Log * log = LogManager::getSingleton().getLog(KDTREE_LOGNAME);
-			log->logMessage("AABB SNAFU: x=" + StringConverter::toString(sides.x) + 
-				" y=" + StringConverter::toString(sides.y) + " z=" + StringConverter::toString(sides.z) +
-				" BOX=" + StringConverter::toString(box.getMinimum()) + "," + StringConverter::toString(box.getMaximum()));
-		}
-#endif
-		return	2 * sides.x * sides.y +
-				2 * sides.y * sides.z +
-				2 * sides.z * sides.x;
-	}
-
-	void PlaneEvent::pqSAH(Real globalSA, Real parentSA, int nLeft, int nPlane, int nRight, AxisAlignedBox& parentBox, SplitInfo& split)
+	//----------------------------------------------------------------------------
+	// surface area heuristic modified for the priority queue method of building
+	// the probabilities (p, pl, pr) are relative to the global (all enclosing) aabb
+	void PlaneEvent::pqSAH(Real globalSA, Real parentSA, int nLeft, int nPlane, int nRight, 
+		AxisAlignedBox& parentBox, SplitInfo& split)
 	{
 		Real mu = splitBox(parentBox, split.bleft, split.bright);
@@ -226,48 +235,12 @@
 	}
 
+	//----------------------------------------------------------------------------
+	// compute split cost without any penalties
 	Real PlaneEvent::pqSplitCost(Real pParent, Real pLeft, Real pRight, int nLeft, int nRight, Real mu)
 	{
-		// reward splitting off chunks of empty space
-		//Real lambda = 1.0;
-		//if (nLeft == 0 || nRight == 0)
-		//{
-		//	lambda = 0.8;
-		//}
-
-		return /* lambda * mu * */ (pParent*KT + (KI * (pLeft*nLeft + pRight*nRight)));
-	}
-
-#define PLT_SIZE 101
-
-	// lookup the penalty for placing the splitting plane near to the edge of the AABB
-	// 0.0 <= p <= 1.0, p = 0.5 means the plane divides the aabb in half
-	Real PlaneEvent::lookupPenalty(Real p)
-	{
-		// precomputed table of {x^6 + 1|0 <= x <= 1}
-		static Real mPenaltyLookupTable[PLT_SIZE];
-		static bool init_done = false;
-
-		if (!init_done)
-		{
-			Real step = 1.0  / (PLT_SIZE - 1);
-			Real x = 0.0; 
-			//LogManager::getSingleton().logMessage("### Calculating Lookup Table ###");
-			for (int i = 0; i < PLT_SIZE; i++)
-			{
-				mPenaltyLookupTable[i] = Math::Pow(x, 6) + 1.0;
-				x += step;
-				//LogManager::getSingleton().logMessage("### mPenaltyLookupTable[" + StringConverter::toString(i,3) + "]=" + StringConverter::toString(mPenaltyLookupTable[i]));
-			}
-			init_done = true;
-			//LogManager::getSingleton().logMessage("### Lookup Table Calculated ###");
-		}
-
-		// normalize p to [0,1]
-		Real x = Math::Abs(p * 2 - 1);
-		int i = Math::IFloor(x * (PLT_SIZE - 1));
-
-		return mPenaltyLookupTable[i];
-	}
-
+		return pParent * KT + (KI * (pLeft * nLeft + pRight * nRight));
+	}
+
+	//----------------------------------------------------------------------------
 	// DEBUG
 	String PlaneEvent::print()
@@ -290,4 +263,5 @@
 	};
 
+	//----------------------------------------------------------------------------
 	String SplitInfo::print()
 	{
@@ -308,4 +282,5 @@
 	};
 
+	//----------------------------------------------------------------------------
 	String KdTree::SplitCandidate::print()
 	{		
@@ -361,4 +336,8 @@
 	}
 
+	/************************************************************************/
+	/* KdTree insert/delete functions                                       */
+	/************************************************************************/
+
 	void KdTree::remove(KdRenderable * rend)
 	{
@@ -640,11 +619,12 @@
 	}
 
+	/************************************************************************/
+	/* KdTree build functions                                               */
+	/************************************************************************/
+
 	void KdTree::build(KdRenderable * sceneRoot)
 	{
-		// DEBUG
-		//LogManager *lm = LogManager::getSingletonPtr();
 		Timer *timer = Root::getSingleton().getTimer();
 		unsigned long t1, t2, t3, t4;
-		//AxisAlignedBox aabb;
 
 		mStats.clear();
@@ -662,12 +642,4 @@
 
 		mStats.mNumSceneNodes = nObjects;
-		// <DEBUG>
-		//lm->logMessage("# of perfect splits " + StringConverter::toString(events.size()));
-		//PlaneEventList::iterator it;
-		//for (it = events.begin(); it != events.end(); it++)
-		//{
-		//	lm->logMessage(it->print());
-		//}
-		// </DEBUG>
 
 		assert(! aabb.isNull() && "Teh stubid worldAABB iz NULL ... waht now?");
@@ -702,4 +674,5 @@
 		mBuildLog->logMessage("Time for tree build: " + StringConverter::toString(t4 - t3) + "µs");
 		mBuildLog->logMessage("Total time: " + StringConverter::toString(t4 - t1) + "µs");
+		mBuildLog->logMessage("Tree Depth: " + StringConverter::toString(mMaxDepth));
 		mBuildLog->logMessage("Number of Objects: " + StringConverter::toString(mStats.mNumSceneNodes));
 		mBuildLog->logMessage("Number of Leaves: " + StringConverter::toString(mStats.mNumLeaves));
@@ -723,18 +696,12 @@
 			it++;
 		}
+
 		events.sort();
+		
 		// HACK
 		if (aabb.isNull())
 		{
-			//LogManager::getSingleton().logMessage("AABB empty, using node AABB.");
 			aabb = nodeaabb;
 		}
-
-		// this must never happen!!
-		//AxisAlignedBox isect = aabb.intersection(nodeaabb);
-		//if (isect.getMinimum() != nodeaabb.getMinimum() || isect.getMaximum() != nodeaabb.getMaximum())
-		//{
-		//	LogManager::getSingleton().logMessage("#+#+#+#+#+ SceneNodes outside of node AABB.");
-		//}
 
 		if (mBuildMethod == KDBM_RECURSIVE)
@@ -760,23 +727,10 @@
 		}
 
-#ifdef KDTREE_DEBUG_OFF
-		mBuildLog->logMessage("events.size()=" + StringConverter::toString(events.size()));
-#endif
-#ifdef KDTREE_DEBUG_OFF
-		PlaneEventList::iterator xit, xbegin, xend;
-		xbegin = events.begin();
-		xend = events.end();
-		xit = xbegin;
-		while (xit != xend)
-		{
-			mBuildLog->logMessage(xit->print());
-			xit++;
-		}
-#endif
-
 		/************************************************/
 		/**************** BEGIN FINDPLANE ***************/
 		/************************************************/
 		// find optimal split plane and split node accordingly
+
+		// initialize
 		const int dim = 3;
 		int pStart, pOn, pEnd;
@@ -789,5 +743,4 @@
 		SplitInfo split, best;
 		best.cost = Math::POS_INFINITY;
-
 
 		PlaneEventList::iterator begin = events.begin();
@@ -821,24 +774,4 @@
 		}
 
-#ifdef KDTREE_DEBUG_OFF
-		Real lvol = best.bleft.volume();
-		Real rvol = best.bright.volume();
-
-		if (lvol == 0 || rvol == 0)
-		{
-			mBuildLog->logMessage("WARNING INVALID SPLIT!!!");
-			String side;
-			if (best.side == PlaneEvent::PES_LEFT)
-				side = "left";
-			else
-				side = "right";
-
-			mBuildLog->logMessage("Splitting node on level " + StringConverter::toString(level) + 
-				"\n\tcost=" + StringConverter::toString(best.cost) + " term=" + StringConverter::toString(PlaneEvent::KI*nObjects) +
-				" side=" + side +
-				"\n\tVolume: left=" + StringConverter::toString(lvol) +
-				" right=" + StringConverter::toString(rvol));
-		}
-#endif
 		/************************************************/
 		/**************** BEGIN TERMINATE ***************/
@@ -858,5 +791,4 @@
 				{
 					leaf->insert(rend);
-					//LogManager::getSingleton().logMessage("++ Adding SceneNode: " + (static_cast<KdTreeSceneNode *>(rend))->getName());
 				}
 				it++;
@@ -873,4 +805,5 @@
 		/**************** BEGIN CLASSIFY ****************/
 		/************************************************/
+		// split the event list in left and right sub-lists
 		else
 		{
@@ -896,5 +829,5 @@
 			while (it != end)
 			{
-				// right-only nodes get moved
+				// right-only nodes go in right list
 				if (it->getRenderable()->getSide() == PlaneEvent::PES_RIGHT)
 				{
@@ -904,23 +837,8 @@
 						nRightS++;
 					}
-
 					eventsRight.push_back(*it);
 				}
-				// both-only nodes get copied
-				// must clip AABBs to child AABB !!!
-				else if (it->getRenderable()->getSide() == PlaneEvent::PES_BOTH)
-				{
-					if (!it->getRenderable()->isClassified())
-					{
-						it->getRenderable()->setClassified(true);
-						nBothS++;
-					}
-
-					//eventsRight.push_back(*it);
-					//eventsLeft.push_back(*it);
-					eventsRight.push_back(it->clip(best.bright, best.event.getDimension()));
-					eventsLeft.push_back(it->clip(best.bleft, best.event.getDimension()));
-				}
-				else
+				// left-only nodes go in left list
+				else if (it->getRenderable()->getSide() == PlaneEvent::PES_LEFT)
 				{
 					if (!it->getRenderable()->isClassified())
@@ -931,12 +849,20 @@
 					eventsLeft.push_back(*it);
 				}
+				// remaining nodes go in both lists, bust must be clipped to prevent
+				// events from lying outside the new nodes aabb
+				else
+				{
+					if (!it->getRenderable()->isClassified())
+					{
+						it->getRenderable()->setClassified(true);
+						nBothS++;
+					}
+					eventsRight.push_back(it->clip(best.bright, best.event.getDimension()));
+					eventsLeft.push_back(it->clip(best.bleft, best.event.getDimension()));
+				}
 				it++;
 			}
 
-#ifdef KDTREE_DEBUG_OFF
-			mBuildLog->logMessage("Splitting on " + best.event.print());
-			mBuildLog->logMessage("eventsLeft.size()=" + StringConverter::toString(eventsLeft.size()));
-			mBuildLog->logMessage("eventsRight.size()=" + StringConverter::toString(eventsRight.size()));
-#endif
+			// create a new branch node and continue recursion
 			KdTree::Branch * branch = new KdTree::Branch(level, aabb, parent, best.event.getSplitPlane(), best.side);
 
@@ -956,7 +882,4 @@
 			// update bounding box
 			branch->_updateBounds(false);
-
-
-			//assert(branch->mRight || branch->mLeft);
 
 			return branch;
@@ -979,12 +902,7 @@
 		// inital split candidate
 		SplitInfo * best = pqFindPlane(e, nObjects, aabb, globalSA);
-		SplitCandidate splitcandidate(e, nObjects, aabb, parent, globalTreeCost, globalTreeCost - best->cost, best, PlaneEvent::PES_BOTH);
+		SplitCandidate splitcandidate(e, nObjects, aabb, parent, globalTreeCost, 
+			globalTreeCost - best->cost, best, PlaneEvent::PES_BOTH);
 		pqueue.push(splitcandidate);
-
-#ifdef KDTREE_DEBUG_OFF
-		//mBuildLog->logMessage("best.pevent=" + best->event.print() + 
-		//	" events.size()=" + StringConverter::toString(events.size()));
-		mBuildLog->logMessage("New split on " + splitcandidate.print());
-#endif
 
 
@@ -1001,10 +919,4 @@
 				level = sc.parent->mLevel + 1;
 			}
-
-#ifdef KDTREE_DEBUG_OFF
-			//mBuildLog->logMessage("Splitting on " + sc.best->event.print() +
-			//	" sc.events.size()=" + StringConverter::toString(sc.events->size()));
-			mBuildLog->logMessage("Splitting on " + sc.print());
-#endif
 
 			/************************************************/
@@ -1012,5 +924,4 @@
 			/************************************************/
 			// check terminating condition
-			//if (best.cost > PlaneEvent::KI*sc.nObjects || level >= mMaxDepth)
 			if (sc.decrease < 0.0 || level >= mMaxDepth)
 			{
@@ -1028,5 +939,4 @@
 					{
 						leaf->insert(rend);
-						//LogManager::getSingleton().logMessage("++ Adding SceneNode: " + (static_cast<KdTreeSceneNode *>(rend))->getName());
 					}
 					it++;
@@ -1053,36 +963,16 @@
 				while (it != end)
 				{
-#ifdef KDTREE_DEBUG_OFF
-					mBuildLog->logMessage(it->print());
-#endif
 					it->getRenderable()->setSide(PlaneEvent::PES_BOTH);
 					it->getRenderable()->setClassified(false);
 					it++;
 				}
+
 				// now classify all renderables. do they belong to the left child, the right child or both?
-#ifdef KDTREE_DEBUG_OFF
-				bool bla = true;
 				it = begin;
 				while (it != end)
 				{
 					it->classify(sc.best->event, sc.best->side);
-					if (*it == sc.best->event)
-					{
-						mBuildLog->logMessage("YEEPEE classified against valid event");
-						bla = false;
-					}
 					it++;
 				}
-				if (bla)
-					mBuildLog->logMessage("FUCKIT! Invalid classification");
-#else
-				it = begin;
-				while (it != end)
-				{
-					it->classify(sc.best->event, sc.best->side);
-					it++;
-				}
-#endif
-
 
 				// divide the event lists
@@ -1091,4 +981,5 @@
 				while (it != end)
 				{
+					// right-only events go in the right list
 					if (it->getRenderable()->getSide() == PlaneEvent::PES_RIGHT)
 					{
@@ -1101,16 +992,6 @@
 						eventsRight->push_back(*it);
 					}
-					else if (it->getRenderable()->getSide() == PlaneEvent::PES_BOTH)
-					{
-						if (!it->getRenderable()->isClassified())
-						{
-							it->getRenderable()->setClassified(true);
-							nBothS++;
-						}
-
-						eventsRight->push_back(it->clip(sc.best->bright, sc.best->event.getDimension()));
-						eventsLeft->push_back(it->clip(sc.best->bleft, sc.best->event.getDimension()));
-					}
-					else
+					// left-only events go in the left list
+					else if (it->getRenderable()->getSide() == PlaneEvent::PES_LEFT)
 					{
 						if (!it->getRenderable()->isClassified())
@@ -1121,64 +1002,28 @@
 						eventsLeft->push_back(*it);
 					}
+					// the rest goes in both lists after being clipped
+					else
+					{
+						if (!it->getRenderable()->isClassified())
+						{
+							it->getRenderable()->setClassified(true);
+							nBothS++;
+						}
+
+						eventsRight->push_back(it->clip(sc.best->bright, sc.best->event.getDimension()));
+						eventsLeft->push_back(it->clip(sc.best->bleft, sc.best->event.getDimension()));
+					}
 					it++;
 				}
 
-#ifdef KDTREE_DEBUG_OFF
-				mBuildLog->logMessage("#### Splitting node on level " + StringConverter::toString(level));
-				Plane * vplane;
-				int count = 0;
-				PlaneEventList::iterator vit, vbegin, vend;
-				vbegin = eventsLeft->begin();
-				vend = eventsLeft->end();
-				vit = vbegin;
-				while (vit != vend)
-				{
-					vplane = vit->getSplitPlane();
-					if (!sc.best.bleft.intersects(*vplane))
-					{
-						mBuildLog->logMessage("Invalid event classification! Plane: " + 
-						StringConverter::toString(vplane->normal) + ", " + StringConverter::toString(-vplane->d) +
-						" Box: |" + StringConverter::toString(sc.best.bleft.getMinimum()) + "|" +
-						StringConverter::toString(sc.best.bleft.getMaximum()) + "|");
-						count++;
-					}
-					OGRE_DELETE(vplane);
-					vit++;
-				}
-				mBuildLog->logMessage("@@@@ Number of invalid events on the left: " + 
-					StringConverter::toString(count) +
-					" Number of events on both sides: " + StringConverter::toString(nBothS));
-				count = 0;
-				vbegin = eventsRight->begin();
-				vend = eventsRight->end();
-				vit = vbegin;
-				while (vit != vend)
-				{
-					vplane = vit->getSplitPlane();
-					if (!sc.best.bright.intersects(*vplane))
-					{
-						mBuildLog->logMessage("Invalid event classification! Plane: " + 
-						StringConverter::toString(vplane->normal) + ", " + StringConverter::toString(-vplane->d) +
-						" Box: |" + StringConverter::toString(sc.best.bright.getMinimum()) + "|" +
-						StringConverter::toString(sc.best.bright.getMaximum()) + "|");
-						count++;
-					}
-					OGRE_DELETE(vplane);
-					vit++;
-				}
-				mBuildLog->logMessage("@@@@ Number of invalid events on the right: " + 
-					StringConverter::toString(count) +
-					" Number of events on both sides: " + StringConverter::toString(nBothS));
-#endif
-
+				// create a new branch node
 				KdTree::Branch * branch = 
 					new KdTree::Branch(level, sc.aabb, sc.parent, sc.best->event.getSplitPlane(), sc.best->side);
 
-				//Real decr = (PlaneEvent::surfaceArea(sc.aabb)/globalSA*PlaneEvent::KI*sc.nObjects) - sc.best.cost;
 				globalTreeCost -= sc.decrease;
 
-				//mBuildLog->logMessage("Splitting, cost is now " + StringConverter::toString(globalTreeCost) + "");
-
-				// now create the child nodes and continue recursion
+
+				// now for each potential child node, compute the split plane and the cost decrease
+				// and place them in the queue
 				if (eventsLeft->size() > 0)
 				{
@@ -1188,17 +1033,4 @@
 						branch, old, old - best->cost, best, PlaneEvent::PES_LEFT);
 					pqueue.push(scleft);
-
-#ifdef KDTREE_DEBUG_OFF
-					//mBuildLog->logMessage("best.pevent: " + best->event.print() + 
-					//	" eventsLeft.size()=" + StringConverter::toString(eventsLeft->size()));
-					mBuildLog->logMessage("New split on " + scleft.print());
-					Plane * plane = best->event.getSplitPlane();
-					if (!sc.best->bleft.intersects(*plane))
-					{
-						mBuildLog->logMessage("Best plane outside parent box on level " + 
-							StringConverter::toString(level));
-					}
-					OGRE_DELETE(plane);
-#endif
 				}
 				// cleanup
@@ -1207,4 +1039,5 @@
 					delete eventsLeft;
 				}
+
 				if (eventsRight->size() > 0)
 				{
@@ -1214,17 +1047,4 @@
 						branch, old, old - best->cost, best, PlaneEvent::PES_RIGHT);
 					pqueue.push(scright);
-
-#ifdef KDTREE_DEBUG_OFF
-					//mBuildLog->logMessage("best.pevent: " + best->event.print() + 
-					//	" eventsRight.size()=" + StringConverter::toString(eventsRight->size()));
-					mBuildLog->logMessage("New split on " + scright.print());
-					Plane * plane = best->event.getSplitPlane();
-					if (!sc.best->bright.intersects(*plane))
-					{
-						mBuildLog->logMessage("Best plane outside parent box on level " + 
-							StringConverter::toString(level));
-					}
-					OGRE_DELETE(plane);
-#endif
 				}
 				// cleanup
@@ -1273,4 +1093,5 @@
 	}
 
+	//-------------------------------------------------------------------------
 	SplitInfo * KdTree::pqFindPlane(PlaneEventList * events, int nObjects, AxisAlignedBox& aabb, Real globalSA)
 	{
@@ -1320,15 +1141,17 @@
 	}
 
-	void KdTree::queueVisibleObjects(Camera* cam, RenderQueue* queue, bool onlyShadowCasters, 
-		KdTree::RenderMethod renderMethod, bool showBoxes)
-	{
-		// for now only recurse or stack render methods
+	/************************************************************************/
+	/* KdTree rendering functions                                           */
+	/************************************************************************/
+
+	//-------------------------------------------------------------------------
+	void KdTree::queueVisibleObjects(Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes)
+	{
 		if (mKdRoot)
-		{
 			recQueueVisibleObjects(mKdRoot, Root::getSingleton().getCurrentFrameNumber(),
 				cam, queue, onlyShadowCasters, showBoxes);
-		}
-	}
-
+	}
+
+	//-------------------------------------------------------------------------
 	void KdTree::recQueueVisibleObjects(KdTree::Node * node, unsigned long currentFrame, 
 		Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes)
@@ -1383,4 +1206,9 @@
 	}
 
+	/************************************************************************/
+	/* KdTree debug & helper functions                                      */
+	/************************************************************************/
+
+	//-------------------------------------------------------------------------
 	void KdTree::dump()
 	{
@@ -1390,4 +1218,5 @@
 	}
 
+	//-------------------------------------------------------------------------
 	void KdTree::dump(KdTree::Node * node)
 	{
@@ -1411,5 +1240,6 @@
 			{
 				scenenode = dynamic_cast<KdTreeSceneNode *>(*it);
-				log->logMessage(pad + "# Leaf   level " + StringConverter::toString(node->mLevel) + 
+				log->logMessage(pad + "# Leaf   level " + 
+					StringConverter::toString(node->mLevel) + 
 					" SceneNode " + scenenode->getName());
 				log->logMessage(pad + "## Objects: " + scenenode->dumpToString());
@@ -1422,10 +1252,12 @@
 			if (branch->mLeft)
 			{
-				log->logMessage(pad + "# Branch level " + StringConverter::toString(node->mLevel) + " Left Child");
+				log->logMessage(pad + "# Branch level " + 
+					StringConverter::toString(node->mLevel) + " Left Child");
 				dump(branch->mLeft);
 			}
 			if (branch->mRight)
 			{
-				log->logMessage(pad + "# Branch level " + StringConverter::toString(node->mLevel) + " Right Child");
+				log->logMessage(pad + "# Branch level " + 
+					StringConverter::toString(node->mLevel) + " Right Child");
 				dump(branch->mRight);
 			}
@@ -1433,4 +1265,5 @@
 	}
 
+	//-------------------------------------------------------------------------
 	Real KdTree::calcCost()
 	{
@@ -1441,4 +1274,5 @@
 	}
 
+	//-------------------------------------------------------------------------
 	Real KdTree::calcCost(KdTree::Node * node, Real vs)
 	{
@@ -1449,13 +1283,20 @@
 		{
 			KdTree::Leaf * leaf = KDLEAFPTR_CAST(node);
-			return (PlaneEvent::surfaceArea(node->mAABB)/vs)*PlaneEvent::KI*leaf->mKdRenderables.size();
+			return (PlaneEvent::surfaceArea(node->mAABB)/vs) *
+				PlaneEvent::KI * leaf->mKdRenderables.size();
 		}
 		else
 		{
 			KdTree::Branch * branch = KDBRANCHPTR_CAST(node);
-			return (PlaneEvent::surfaceArea(node->mAABB)/vs)*PlaneEvent::KT + calcCost(branch->mLeft, vs) + calcCost(branch->mRight, vs);
-		}
-	}
-
+			return (PlaneEvent::surfaceArea(node->mAABB)/vs) * PlaneEvent::KT + 
+				calcCost(branch->mLeft, vs) + calcCost(branch->mRight, vs);
+		}
+	}
+
+	/************************************************************************/
+	/* KdTree::Node/Branch/Leaf functions                                   */
+	/************************************************************************/
+
+	//-------------------------------------------------------------------------
 	KdTree::Leaf::~Leaf()
 	{
@@ -1472,4 +1313,27 @@
 	}
 
+	void KdTree::Leaf::queueVisibleObjects(unsigned long currentFrame, 
+		Camera* cam, RenderQueue* queue, bool onlyShadowCasters, bool showBoxes)
+	{
+		KdRenderableList::iterator it  = mKdRenderables.begin();
+		KdRenderableList::iterator end = mKdRenderables.end();
+		while (it != end)
+		{			
+			if (!(*it)->isQueued(currentFrame, cam))
+			{
+				(*it)->queueObjects(cam, queue, onlyShadowCasters);
+			}
+			it++;
+		}
+
+		if (showBoxes)
+		{
+			WireBoundingBox * wbb = getWireBoundingBox();
+			if (wbb)
+				queue->addRenderable(wbb);
+		}
+	}
+
+	//-------------------------------------------------------------------------
 	// update the world aabb based on the contained geometry
 	void KdTree::Leaf::_updateBounds(bool recurse)
