Index: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1188)
+++ GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp	(revision 1188)
@@ -0,0 +1,954 @@
+#include "TestKdTreeAppListener.h"
+
+void KdTreeAppListener::updateStats(void)
+{
+	static unsigned int opt = 0;
+	static char str[100];
+
+	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: ";
+
+	// 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");
+
+		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
+	}
+}
+
+// Constructor takes a RenderWindow because it uses that to determine input context
+KdTreeAppListener::KdTreeAppListener(RenderWindow* win, SceneManager* sm, Real rs, Real ms, Real rp,
+	bool useBufferedInputKeys, bool useBufferedInputMouse)
+{
+	mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
+	mKdTreeOverlay = OverlayManager::getSingleton().getByName("KdTree/DebugOverlay");
+
+
+	mUseBufferedInputKeys = useBufferedInputKeys;
+	mUseBufferedInputMouse = useBufferedInputMouse;
+	mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse;
+
+	if (mInputTypeSwitchingOn)
+	{
+		mEventProcessor = new EventProcessor();
+		mEventProcessor->initialise(win);
+		mEventProcessor->startProcessingEvents();
+		mEventProcessor->addKeyListener(this);
+		mInputDevice = mEventProcessor->getInputReader();
+
+	}
+	else
+	{
+		mInputDevice = PlatformManager::getSingleton().createInputReader();
+		mInputDevice->initialise(win,true, true);
+	}
+
+	mFreeMove = false;
+	mShowTree = false;
+	mVizCamera = false;
+	mVizCamTransVect = Vector3::ZERO;
+	mSeqNum = 0;
+
+	mDelayedQueriesIssued = 0.0;
+	mDelayedTraversedNodes = 0.0;
+
+	mCamera = sm->getCamera("PlayerCam");
+	mTopCam = sm->getCamera("TopCam");
+	mCamNode = sm->getSceneNode("PlayerCamNode");
+	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;
+
+	MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
+	MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
+
+	initKdTreeOverlay();
+	initStatsOverlay();
+
+	showDebugOverlay(true);
+}
+//-----------------------------------------------------------------------
+KdTreeAppListener::~KdTreeAppListener()
+{
+	if (mInputTypeSwitchingOn)
+	{
+		delete mEventProcessor;
+	}
+	else
+	{
+		PlatformManager::getSingleton().destroyInputReader( mInputDevice );
+	}
+}
+//-----------------------------------------------------------------------
+void KdTreeAppListener::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 KdTreeAppListener::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 KdTreeAppListener::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 KdTreeAppListener::showDebugOverlay(bool show)
+{
+	if (mDebugOverlay)
+	{
+		if (show)
+		{
+			mDebugOverlay->show();
+			mKdTreeOverlay->show();
+		}
+		else
+		{
+			mDebugOverlay->hide();
+			mKdTreeOverlay->hide();
+		}
+	}
+}
+
+void KdTreeAppListener::toggleVizCamera()
+{
+	static nodeVizMode = 0;
+
+	nodeVizMode = (nodeVizMode + 1) % NODEVIZ_MODES_NUM;
+
+	if (nodeVizMode != 0)
+	{
+		if (!mVizCamera)
+		{
+			Viewport* tvp = mWindow->addViewport(mTopCam,
+				VIZ_VIEWPORT_Z_ORDER, 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()));
+			mVizCamera = true;
+			mSceneMgr->setOption("VisualizeCulledNodes", &mVizCamera);
+		}
+
+		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(VIZ_VIEWPORT_Z_ORDER);
+		mVizCamera = false;
+		mSceneMgr->setOption("VisualizeCulledNodes", &mVizCamera);
+	}
+}
+
+bool KdTreeAppListener::processUnbufferedKeyInput(const FrameEvent& evt)
+{
+	// moving the cull camera
+	if (mInputDevice->isKeyDown(KC_NUMPAD2))
+	{
+		mVizCamTransVect.y = -mMoveScale;
+	}
+	if (mInputDevice->isKeyDown(KC_NUMPAD8))
+	{
+		mVizCamTransVect.y = mMoveScale;
+	}
+	if (mInputDevice->isKeyDown(KC_NUMPAD4))
+	{
+		mVizCamTransVect.x = mMoveScale;
+	}
+	if (mInputDevice->isKeyDown(KC_NUMPAD6))
+	{
+		mVizCamTransVect.x = -mMoveScale;
+	}
+	if (mInputDevice->isKeyDown(KC_SUBTRACT))
+	{
+		mVizCamTransVect.z = mMoveScale;
+	}
+	if (mInputDevice->isKeyDown(KC_ADD))
+	{
+		mVizCamTransVect.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))
+	{
+		mCamNode->yaw(-mRotScale, Ogre::Node::TS_WORLD);
+	}
+
+	if (mInputDevice->isKeyDown(KC_LEFT))
+	{
+		mCamNode->yaw(mRotScale, Ogre::Node::TS_WORLD);
+	}
+
+	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 KdTreeAppListener::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 KdTreeAppListener::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)
+	mCamNode->yaw(mRotX, Ogre::Node::TS_WORLD);
+	mCamNode->pitch(mRotY);
+	//mCamNode->moveRelative(mTranslateVector);
+	mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector);
+	mTopCam->moveRelative(mVizCamTransVect);
+
+	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")
+			{
+				mCamNode->setPosition(pos.x, it->movable->getWorldBoundingBox().getCenter().y + 2, pos.z);
+				break;
+			}
+			it++;
+		}
+		OGRE_DELETE(rsquery);
+	}
+}
+
+// Override frameStarted event to process that (don't care about frameEnded)
+bool KdTreeAppListener::frameStarted(const FrameEvent& evt)
+{
+	if(mWindow->isClosed())
+		return false;
+
+	if (!mInputTypeSwitchingOn)
+	{
+		mInputDevice->capture();
+	}
+
+
+	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;
+
+		// 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;
+		mVizCamTransVect = Vector3::ZERO;
+	}
+
+	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 KdTreeAppListener::frameEnded(const FrameEvent& evt)
+{
+	updateStats();
+	return true;
+}
+
+void KdTreeAppListener::switchMouseMode() 
+{
+	mUseBufferedInputMouse = !mUseBufferedInputMouse;
+	mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
+}
+void KdTreeAppListener::switchKeyMode() 
+{
+	mUseBufferedInputKeys = !mUseBufferedInputKeys;
+	mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
+}
+
+void KdTreeAppListener::keyClicked(KeyEvent* e) 
+{
+	if (e->getKeyChar() == 'm')
+	{
+		switchMouseMode();
+	}
+	else if (e->getKeyChar() == 'k')
+	{
+
+		switchKeyMode();
+	}
+}
