Index: trunk/VUT/work/todo_occlusionculling.txt
===================================================================
--- trunk/VUT/work/todo_occlusionculling.txt	(revision 61)
+++ trunk/VUT/work/todo_occlusionculling.txt	(revision 61)
@@ -0,0 +1,29 @@
+1) write into ogre forum
+2) mode_render does not do any change
+3) scenenode::_rendervisibleobjects already uses frustum culling
+4) implement for bsp trees
+5) improve mouse control (strave)
+6) cull camera for testing
+7) error when near plane crosses bounding volume
+8) bounding box should be not two parts
+9) implement z-buffer pass
+10) nice scene for dotscenemanager + terrainscenemanager
+11) ask about ogre changes
+12) preprocess: do not always destroy occlusion queries
+13) prevent multiple rendering of objects, scene nodes and hierarchy nodes
+14) learn to create terrains (heightmaps)
+15) work with maya
+16) occlusion culling + transparent materials, shadows!!
+17) minimize code for new scenemanager (macros?)
+18) make more flexible: callbacks
+19) find out how rotations happen
+20) investigate time coherence options (i.e., query only every nth frame
+21) möllers acceleration for frustum culling
+22) update so less code has to be replicated in terrainscenetraverser
+23) implement frustum test where intersect by near plane is considered
+24) tell ogre-people about changes
+25) check glfinish error
+26) also disable frustum culling on mouse click
+27) better comments
+28) setrendermode: change!!!
+29) problems with coherent & geometry not in leave
Index: trunk/VUT/work/TestCullingDotScene/TestCullingDotScene.vcproj
===================================================================
--- trunk/VUT/work/TestCullingDotScene/TestCullingDotScene.vcproj	(revision 61)
+++ trunk/VUT/work/TestCullingDotScene/TestCullingDotScene.vcproj	(revision 61)
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="TestCullingDotScene"
+	ProjectGUID="{BE13944C-D05E-467F-B0AC-8A65A3B5FE60}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\bin\$(ConfigurationName)"
+			IntermediateDirectory="..\..\obj\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\Dependencies\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;../include"
+				PreprocessorDefinitions="_WINDOWS;_STLP_USE_DYNAMIC_LIB;OGRE_LIBRARY_IMPORTS;_DEBUG;WIN32;_STLP_DEBUG"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Plugin_OctreeSceneManager.lib OGREMain_d.LIB CEGUIBase_d.lib OgreGUIRenderer_d.lib Plugin_DotSceneManager.lib"
+				OutputFile="$(OGRE_PATH)/Samples/Common/bin/Debug/TestCullingDotScene.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\Dependencies\Lib\Debug&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\OgreMain\Lib\Debug&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/TestCullingDotScene.pdb"
+				SubSystem="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				RuntimeLibrary="4"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/TestCullingDotScene.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\TestCullingDotSceneApplication.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\TestCullingDotSceneApplication.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="tinyxml"
+			Filter="">
+			<File
+				RelativePath="..\tinyxml\tinystr.cpp">
+			</File>
+			<File
+				RelativePath="..\tinyxml\tinystr.h">
+			</File>
+			<File
+				RelativePath="..\tinyxml\tinyxml.cpp">
+			</File>
+			<File
+				RelativePath="..\tinyxml\tinyxml.h">
+			</File>
+			<File
+				RelativePath="..\tinyxml\tinyxmlerror.cpp">
+			</File>
+			<File
+				RelativePath="..\tinyxml\tinyxmlparser.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.cpp
===================================================================
--- trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.cpp	(revision 61)
+++ trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.cpp	(revision 61)
@@ -0,0 +1,593 @@
+/**
+    \file 
+        TestCullingApplication.cpp
+    \brief
+        Tests the occlusion culling algorithm
+*/
+
+#include <OgreNoMemoryMacros.h>
+#include <CEGUI/CEGUI.h>
+#include <../CEGUIRenderer/include/OgreCEGUIRenderer.h>
+#include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h>
+#include <../CEGUIRenderer/include/OgreCEGUITexture.h>
+#include <OgreMemoryMacros.h>
+
+#include "Ogre.h"
+#include "OgreLight.h"
+#include "tinyxml.h"
+#include "TestCullingDotSceneApplication.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+/***********************************************/
+/* TestCullingDotSceneApplication implementation       */
+/***********************************************/
+void TestCullingDotSceneApplication::ParseDotScene( const String &SceneName, const String& groupName )
+{
+	TiXmlDocument	*XMLDoc;
+	TiXmlElement	*XMLRoot, *XMLNodes, *XMLPathFind;
+	try
+	{
+		DataStreamPtr pStream = ResourceGroupManager::getSingleton().openResource( SceneName, groupName );
+
+		String data = pStream->getAsString();
+
+		// Open the .scene File
+		XMLDoc = new TiXmlDocument();
+		XMLDoc->Parse( data.c_str() );
+		pStream->close();
+		pStream.setNull();
+
+		if( XMLDoc->Error() )
+		{
+			//We'll just log, and continue on gracefully
+			LogManager::getSingleton().logMessage("Error in dotscene demo app!!!!!");
+			delete XMLDoc;
+			return;
+		}
+	}
+	catch(...)
+	{
+		//We'll just log, and continue on gracefully
+		LogManager::getSingleton().logMessage("Error in dotscene demo app!!!!!");
+		delete XMLDoc;
+		return;
+	}
+
+	// Validate the File
+	XMLRoot = XMLDoc->RootElement();
+	if( String( XMLRoot->Value()) != "scene"  ) {
+		LogManager::getSingleton().logMessage( "Error: Invalid .scene File. Missing <scene>" );
+		delete XMLDoc;		
+		return;
+	}
+		
+	XMLNodes = XMLRoot->FirstChildElement( "nodes" );
+	
+	// Read in the scene nodes
+	if( XMLNodes )
+	{
+		TiXmlElement *XMLNode, *XMLPosition, *XMLRotation, *XMLScale,  *XMLEntity, *XMLBillboardSet,  *XMLLight;
+
+		XMLNode = XMLNodes->FirstChildElement( "node" );
+		
+		while( XMLNode )
+		{
+			// Process the current node
+			// Grab the name of the node
+			String NodeName = XMLNode->Attribute("name");
+			// First create the new scene node
+			SceneNode* NewNode = static_cast<SceneNode*>( mSceneMgr->getRootSceneNode()->createChild( NodeName ) );
+
+			Vector3 TempVec;
+			String TempValue;
+				
+			// Now position it...
+			XMLPosition = XMLNode->FirstChildElement("position");
+			
+			if( XMLPosition )
+			{
+				TempValue = XMLPosition->Attribute("x");
+				TempVec.x = StringConverter::parseReal(TempValue);
+				TempValue = XMLPosition->Attribute("y");
+				TempVec.y = StringConverter::parseReal(TempValue);
+				TempValue = XMLPosition->Attribute("z");
+				TempVec.z = StringConverter::parseReal(TempValue);
+				NewNode->setPosition( TempVec );
+			}
+
+			// Rotate it...
+			XMLRotation = XMLNode->FirstChildElement("rotation");
+			if( XMLRotation )
+			{
+				Quaternion TempQuat;
+				TempValue = XMLRotation->Attribute("qx");
+				TempQuat.x = StringConverter::parseReal(TempValue);
+				TempValue = XMLRotation->Attribute("qy");
+				TempQuat.y = StringConverter::parseReal(TempValue);
+				TempValue = XMLRotation->Attribute("qz");
+				TempQuat.z = StringConverter::parseReal(TempValue);
+				TempValue = XMLRotation->Attribute("qw");
+				TempQuat.w = StringConverter::parseReal(TempValue);
+				NewNode->setOrientation( TempQuat );
+			}
+
+			// Scale it.
+			XMLScale = XMLNode->FirstChildElement("scale");
+			
+			if( XMLScale )
+			{
+				TempValue = XMLScale->Attribute("x");
+				TempVec.x = StringConverter::parseReal(TempValue);
+				TempValue = XMLScale->Attribute("y");
+				TempVec.y = StringConverter::parseReal(TempValue);
+				TempValue = XMLScale->Attribute("z");
+				TempVec.z = StringConverter::parseReal(TempValue);
+				NewNode->setScale( TempVec );
+			}
+
+			XMLLight = XMLNode->FirstChildElement( "light" );
+			
+			if( XMLLight )
+				NewNode->attachObject( LoadLight( XMLLight ) );
+
+			// Check for an Entity
+			XMLEntity = XMLNode->FirstChildElement("entity");
+			
+			if( XMLEntity )
+			{
+				if( XMLEntity->Attribute("static") )
+				{
+					if( strcmp( XMLEntity->Attribute("static"), "false" )==0 ){
+						String EntityName, EntityMeshFilename;
+						EntityName = XMLEntity->Attribute( "name" );
+						EntityMeshFilename = XMLEntity->Attribute( "meshFile" );
+
+						// Create entity
+						Entity* NewEntity = mSceneMgr->createEntity(EntityName, EntityMeshFilename);
+						NewNode->attachObject( NewEntity );
+					}
+				}
+			}
+
+			XMLBillboardSet = XMLNode->FirstChildElement( "billboardSet" );
+			if( XMLBillboardSet )
+			{
+				String TempValue;
+
+				BillboardSet* bSet = mSceneMgr->createBillboardSet( NewNode->getName() );
+
+				BillboardType Type;
+				TempValue = XMLBillboardSet->Attribute( "type" );
+				if( TempValue == "orientedCommon" ) 
+					Type = BBT_ORIENTED_COMMON;
+				else if( TempValue == "orientedSelf" )
+					Type = BBT_ORIENTED_SELF;
+				else Type = BBT_POINT;
+
+				BillboardOrigin Origin;
+				TempValue = XMLBillboardSet->Attribute( "type" );
+				if( TempValue == "bottom_left" )
+					Origin = BBO_BOTTOM_LEFT;
+				else if( TempValue == "bottom_center" )
+					Origin = BBO_BOTTOM_CENTER;
+				else if( TempValue == "bottomRight"  )
+					Origin = BBO_BOTTOM_RIGHT;
+				else if( TempValue == "left" )
+					Origin = BBO_CENTER_LEFT;
+				else if( TempValue == "right" )
+					Origin = BBO_CENTER_RIGHT;
+				else if( TempValue == "topLeft" )
+					Origin = BBO_TOP_LEFT;
+				else if( TempValue == "topCenter" )
+					Origin = BBO_TOP_CENTER;
+				else if( TempValue == "topRight" )
+					Origin = BBO_TOP_RIGHT;
+				else 
+					Origin = BBO_CENTER;
+
+				bSet->setBillboardType( Type );
+				bSet->setBillboardOrigin( Origin );
+
+				TempValue = XMLBillboardSet->Attribute( "name" );
+				bSet->setMaterialName( TempValue );
+
+				int width, height;
+				width = StringConverter::parseReal( XMLBillboardSet->Attribute( "width" ) );
+				height = StringConverter::parseReal( XMLBillboardSet->Attribute( "height" ) );
+				bSet->setDefaultDimensions( width, height );
+				bSet->setVisible( true );
+				NewNode->attachObject( bSet );
+
+				TiXmlElement *XMLBillboard;
+
+				XMLBillboard = XMLBillboardSet->FirstChildElement( "billboard" );
+
+				while( XMLBillboard )
+				{
+					Billboard *b;
+					TempValue;
+					TempVec = Vector3( 0, 0, 0 );
+					ColourValue TempColour(1,1,1,1);
+
+					XMLPosition = XMLBillboard->FirstChildElement( "position" );
+					if( XMLPosition ){
+						TempValue = XMLPosition->Attribute("x");
+						TempVec.x = StringConverter::parseReal(TempValue);
+						TempValue = XMLPosition->Attribute("y");
+						TempVec.y = StringConverter::parseReal(TempValue);
+						TempValue = XMLPosition->Attribute("z");
+						TempVec.z = StringConverter::parseReal(TempValue);
+					}
+
+					TiXmlElement* XMLColour = XMLBillboard->FirstChildElement( "colourDiffuse" );
+					if( XMLColour )
+					{
+						TempValue = XMLColour->Attribute("r");
+						TempColour.r = StringConverter::parseReal(TempValue);
+						TempValue = XMLColour->Attribute("g");
+						TempColour.g = StringConverter::parseReal(TempValue);
+						TempValue = XMLColour->Attribute("b");
+						TempColour.b = StringConverter::parseReal(TempValue);
+					}
+
+					b = bSet->createBillboard( TempVec, TempColour);
+
+					XMLBillboard = XMLBillboard->NextSiblingElement( "billboard" );
+				}
+			}
+
+			// Move to the next node
+			XMLNode = XMLNode->NextSiblingElement( "node" );
+		}
+	}
+
+	// Close the XML File
+	delete XMLDoc;
+}
+
+Light* TestCullingDotSceneApplication::LoadLight( TiXmlElement *XMLLight )
+{
+	TiXmlElement *XMLDiffuse, *XMLSpecular, *XMLAttentuation, *XMLPosition;
+
+	// Create a light (point | directional | spot | radPoint)
+	Light* light = mSceneMgr->createLight( XMLLight->Attribute("name") );
+	if( !XMLLight->Attribute("type") || String(XMLLight->Attribute("type")) == "point" )
+		light->setType( Light::LT_POINT );
+	else if( String(XMLLight->Attribute("type")) == "directional")
+		light->setType( Light::LT_DIRECTIONAL );
+	else if( String(XMLLight->Attribute("type")) == "spot")
+		light->setType( Light::LT_SPOTLIGHT );
+	else if( String(XMLLight->Attribute("type")) == "radPoint")
+		light->setType( Light::LT_POINT );
+
+	XMLDiffuse = XMLLight->FirstChildElement("colourDiffuse");
+	if( XMLDiffuse )
+	{
+		ColourValue Diffuse;
+		Diffuse.r = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("r") );
+		Diffuse.g = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("g") );
+		Diffuse.b = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("b") );
+		Diffuse.a = 1;
+		light->setDiffuseColour(Diffuse);
+	}
+	
+	XMLSpecular = XMLLight->FirstChildElement("colourSpecular");
+	
+	if( XMLSpecular )
+	{
+		ColourValue Specular;
+		Specular.r = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("r") );
+		Specular.g = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("g") );
+		Specular.b = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("b") );
+		Specular.a = 1;
+		light->setSpecularColour(Specular);
+	}
+
+	XMLAttentuation = XMLLight->FirstChildElement("lightAttenuation");
+	if( XMLAttentuation )
+	{
+		//get defaults incase not all values specified
+		Real range, constant, linear, quadratic;
+		range = light->getAttenuationRange();
+		constant = light->getAttenuationConstant();
+		linear = light->getAttenuationLinear();
+		quadratic = light->getAttenuationQuadric();
+			
+		if( XMLAttentuation->Attribute("range") )
+			range = StringConverter::parseReal( XMLAttentuation->Attribute("range") );
+		if( XMLAttentuation->Attribute("constant") )
+			constant = StringConverter::parseReal( XMLAttentuation->Attribute("constant") );
+		if( XMLAttentuation->Attribute("linear") )
+			linear = StringConverter::parseReal( XMLAttentuation->Attribute("linear") );
+		if( XMLAttentuation->Attribute("quadratic") )
+			quadratic = StringConverter::parseReal( XMLAttentuation->Attribute("quadratic") );
+			light->setAttenuation( range, constant, linear, quadratic );
+	}
+
+	XMLPosition = XMLLight->FirstChildElement("position");
+	if( XMLPosition ) 
+	{
+		Vector3 p = Vector3(0,0,0);
+		if( XMLPosition->Attribute("x") )
+			p.x = StringConverter::parseReal( XMLPosition->Attribute("x") );
+		if( XMLPosition->Attribute("y") )
+			p.y = StringConverter::parseReal( XMLPosition->Attribute("y") );
+		if( XMLPosition->Attribute("z") )
+			p.z = StringConverter::parseReal( XMLPosition->Attribute("z") );
+            
+		light->setPosition( p );
+	}
+
+	//castShadows		(true | false) "true"
+	light->setCastShadows( true );
+	if( XMLLight->Attribute("visible") )
+		if( String(XMLLight->Attribute("visible")) == "false" )
+				light->setCastShadows( false );
+			
+	//visible			(true | false) "true"		
+	light->setVisible( true );
+	if( XMLLight->Attribute("visible") )
+		if( String(XMLLight->Attribute("visible")) == "false" )
+			light->setVisible( false );
+
+	return light;
+}
+//-----------------------------------------------------------------------
+void TestCullingDotSceneApplication::createScene(void)
+{
+	mSceneMgr->setAmbientLight(ColourValue(0.09f, 0.09f, 0.09f));
+	mSceneMgr->setSkyBox(true, "Examples/MorningSkyBox" );
+		
+	//This is default, though, set it anyway :)
+	ResourceGroupManager::getSingleton().setWorldResourceGroupName("General");
+	mSceneMgr->setWorldGeometry( "MyScene.scene" );
+	//mSceneMgr->SetOctreeVisible( 1 );
+		
+	ParseDotScene( "MyScene.scene", "General" );
+	// CEGUI setup
+	setupGui();
+}
+//-----------------------------------------------------------------------
+void TestCullingDotSceneApplication::setupGui( void )
+{
+	 mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, ST_GENERIC);
+     mGUISystem = new CEGUI::System(mGUIRenderer);
+
+	 // Mouse
+     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
+     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
+	 mGUISystem->setDefaultMouseCursor(
+                (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
+
+	 CEGUI::MouseCursor::getSingleton().show( );
+     
+	/* CEGUI::Window* sheet = 
+            CEGUI::WindowManager::getSingleton().loadWindowLayout(
+                (CEGUI::utf8*)"ogregui.layout"); 
+
+     mGUISystem->setGUISheet(sheet);*/
+}
+//-----------------------------------------------------------------------
+void TestCullingDotSceneApplication::createFrameListener(void)
+{
+	mFrameListener= new MouseQueryListener(mWindow, mCamera, mSceneMgr, mGUIRenderer);
+	mFrameListener->showDebugOverlay(true);
+	mRoot->addFrameListener(mFrameListener);
+}
+//-----------------------------------------------------------------------
+void TestCullingDotSceneApplication::chooseSceneManager(void)
+{
+	mSceneMgr = mRoot->getSceneManager(ST_GENERIC);
+
+}
+//-----------------------------------------------------------------------
+void TestCullingDotSceneApplication::createViewports(void)
+{
+	// Create one viewport, entire window
+	Viewport* vp = mWindow->addViewport(mCamera);
+	// Look back along -Z
+    mCamera->lookAt(Vector3(0, 0, -300));
+	mCamera->setPosition(0 , 100, 600);
+}
+
+/***********************************************/
+/* MouseQueryListener implementation           */
+/***********************************************/
+
+//-----------------------------------------------------------------------
+MouseQueryListener::MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer)
+        : ExampleFrameListener(win, cam, false, true), mGUIRenderer(renderer), 
+		mShutdownRequested(false)
+{
+
+	// Setup default variables
+//	mCurrentObject = NULL;
+	mLMouseDown = false;
+	mRMouseDown = false;
+	mSceneMgr = sceneManager;
+
+    // Reduce move speed
+	mMoveSpeed = 50;
+	mRotateSpeed *= 2;
+
+	mCurrentAlgorithm = 0;//GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING;
+	mThreshold = 0;
+    
+	// Register this so that we get mouse events.
+	mEventProcessor->addMouseListener(this);
+	mEventProcessor->addMouseMotionListener(this);
+	mEventProcessor->addKeyListener(this);
+
+	// show overlay
+	Overlay* pOver = OverlayManager::getSingleton().getByName("Example/VisibilityDemoOverlay"); 
+
+	mAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/AlgorithmInfo");
+	mThresholdInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/ThresholdInfo");
+	mFrustumCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/FrustumCulledNodesInfo");
+	mQueryCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/QueryCulledNodesInfo");
+    mTraversedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/TraversedNodesInfo");
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mThresholdInfo->setCaption(": 0");
+	mFrustumCulledNodesInfo->setCaption(": 0");
+	mQueryCulledNodesInfo->setCaption(": 0");
+	mTraversedNodesInfo->setCaption(": 0");
+
+    pOver->show();
+} // MouseQueryListener
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseMoved (MouseEvent *e)
+{
+	// Update CEGUI with the mouse motion
+    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight());
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::mousePressed(MouseEvent* e)
+{
+     // Left mouse button down
+     if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+     {
+		 CEGUI::MouseCursor::getSingleton().hide( );
+		 mLMouseDown = true;
+     } // if
+     // Right mouse button down
+     else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+     {
+         CEGUI::MouseCursor::getSingleton().hide( );
+         mRMouseDown = true;
+     } // else if
+} // mousePressed
+
+ //-----------------------------------------------------------------------
+void MouseQueryListener::mouseReleased(MouseEvent* e)
+{
+    // Left mouse button up
+    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+    {
+		CEGUI::MouseCursor::getSingleton().show( );
+        mLMouseDown = false;
+    }
+    // Right mouse button up
+    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+    {
+        CEGUI::MouseCursor::getSingleton().show( );
+        mRMouseDown = false;
+    }
+} 
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseDragged (MouseEvent *e)
+ {
+	 // If we are dragging the left mouse button.	 
+	 if ( mLMouseDown )
+	 {
+		mCamera->yaw( -e->getRelX() * mRotateSpeed );
+		mCamera->pitch( -e->getRelY() * mRotateSpeed );
+     }
+	 	 
+	 // If we are dragging the right mouse button.
+	 if ( mRMouseDown )
+	 {
+		 Vector3 translation;
+		 translation.x += -e->getRelX() * 0.13;
+		 translation.y -= -e->getRelY() * 0.13;
+
+		 mCamera->moveRelative(translation);		
+	 }
+}
+//-----------------------------------------------------------------------
+bool MouseQueryListener::frameEnded(const FrameEvent& evt)
+{
+	if (mShutdownRequested)
+		return false;
+
+    if (timeDelay >= 0) 
+        timeDelay -= evt.timeSinceLastFrame;
+
+    KEY_PRESSED(KC_SPACE, 0.3, changeAlgorithm());
+
+	KEY_PRESSED(KC_SUBTRACT, 0.0, changeThreshold(-10));
+	KEY_PRESSED(KC_ADD, 0, changeThreshold(10));
+	//KEY_PRESSED(KC_T, 1, change);
+      
+	changeStats();
+
+    return ExampleFrameListener::frameStarted(evt) && ExampleFrameListener::frameEnded(evt);        
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeThreshold(int incr)
+{
+	mThreshold += incr; if(mThreshold < 0) mThreshold = 0;
+	
+	char str[100]; sprintf(str,": %d", mThreshold);
+
+	mSceneMgr->setOption("Threshold", &mThreshold); 
+	mThresholdInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeAlgorithm()
+{
+//    mCurrentAlgorithm = ++mCurrentAlgorithm % VisibilitySceneTraverser::NUM_RENDERMODES;
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeStats()
+{
+	unsigned int opt = 0;
+	char str[100];
+	
+	mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mFrustumCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mQueryCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumTraversedNodes", &opt); sprintf(str,": %d", opt); 
+	mTraversedNodesInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyPressed(KeyEvent* e)
+{
+	if(e->getKey() == KC_ESCAPE)
+    {
+		mShutdownRequested = true;
+		e->consume();
+		return;
+	}
+
+	CEGUI::System::getSingleton().injectKeyDown(e->getKey());
+	CEGUI::System::getSingleton().injectChar(e->getKeyChar());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyReleased(KeyEvent* e)
+{
+	CEGUI::System::getSingleton().injectKeyUp(e->getKey());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyClicked(KeyEvent* e) 
+{
+	// Do nothing
+	e->consume();
+}
+//-----------------------------------------------------------------------
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+{
+    // Create application object
+    TestCullingDotSceneApplication app;
+
+	try 
+	{
+        app.go();
+    } 
+	catch( Ogre::Exception& e ) 
+	{
+        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+    }	
+
+    return 0;
+}
Index: trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.h
===================================================================
--- trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.h	(revision 61)
+++ trunk/VUT/work/TestCullingDotScene/TestCullingDotSceneApplication.h	(revision 61)
@@ -0,0 +1,110 @@
+/**
+    \file 
+        TestCullingApplication.h
+*/
+#include "CEGUIForwardRefs.h"
+#include "ExampleApplication.h"
+#include "OgreLight.h"
+//#include "OgreVisibilitySceneTraverser.h"
+
+Real timeDelay = 0;
+#define KEY_PRESSED(_key,_timeDelay, _macro) \
+{ \
+    if (mInputDevice->isKeyDown(_key) && timeDelay <= 0) \
+{ \
+    timeDelay = _timeDelay; \
+    _macro ; \
+} \
+}
+
+String mCurrentAlgorithmCaptions[3/*VisibilitySceneTraverser::NUM_RENDERMODES*/] = 
+{
+    "Cull Frustum", 
+	"Stop and Wait", 
+	"Coherent Occlusion Culling"
+};
+
+class MouseQueryListener : public ExampleFrameListener, public MouseListener, public MouseMotionListener
+{
+public:
+
+    MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer);
+
+
+    ~MouseQueryListener( )
+    {
+    }
+
+//	bool frameStarted(const FrameEvent& evt);
+	bool frameEnded(const FrameEvent& evt);
+
+    /* MouseListener callbacks. */
+    virtual void mouseClicked(MouseEvent* e) { }
+    virtual void mouseEntered(MouseEvent* e) { }
+    virtual void mouseExited(MouseEvent* e)  { }
+
+    // This is when the mouse button goes DOWN.
+    virtual void mousePressed(MouseEvent* e);
+
+    // This is when the mouse button is let UP.
+    virtual void mouseReleased(MouseEvent* e);
+
+    /* MouseMotionListener callbacks */
+    virtual void mouseMoved (MouseEvent *e);
+   
+    // This is when the mouse is clicked, held and dragged.
+    virtual void mouseDragged (MouseEvent *e);
+
+    void keyPressed(KeyEvent* e);
+
+	void keyReleased(KeyEvent* e);
+	void keyClicked(KeyEvent* e);
+
+	void changeAlgorithm();
+	void changeThreshold(int incr);
+	void changeStats();
+
+protected:
+    bool mLMouseDown, mRMouseDown;     // True if the mouse buttons are down
+    SceneManager *mSceneMgr;           // A pointer to the scene manager
+    
+	CEGUI::Renderer *mGUIRenderer;     // cegui renderer
+	
+	bool mShutdownRequested;
+	int mCurrentAlgorithm;
+	int mThreshold;
+
+	OverlayElement *mAlgorithmInfo;
+	OverlayElement *mThresholdInfo;
+	OverlayElement *mFrustumCulledNodesInfo;
+	OverlayElement *mQueryCulledNodesInfo;
+    OverlayElement *mTraversedNodesInfo;
+	OverlayElement *mSceneNodesInfo;
+};
+
+
+class TestCullingDotSceneApplication : public ExampleApplication
+{
+public:
+	//~TestCullingDotSceneApplication();
+
+protected:
+	void createScene(void);
+	void createFrameListener(void);
+	void setupGui(void);
+	void ParseDotScene( const String &SceneName, const String& groupName );
+	Light* LoadLight( TiXmlElement *XMLLight );
+
+	virtual void createViewports(void);
+
+	CEGUI::OgreCEGUIRenderer *mGUIRenderer;
+	CEGUI::System *mGUISystem;
+
+private:
+	void chooseSceneManager(void);
+
+	//SceneManager* mSceneMgr;
+	//Entity* mShip;
+	//SceneNode* mShipNode;
+};
+
Index: trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsw
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsw	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsw	(revision 61)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Demo_TestCullingTerrain"=.\TestCullingTerrainApplication.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Index: trunk/VUT/work/TestCullingTerrain/TestCullingTerrain.vcproj
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TestCullingTerrain.vcproj	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TestCullingTerrain.vcproj	(revision 61)
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="TestCullingTerrain"
+	ProjectGUID="{248F19A6-2FE0-4F5D-8928-E0EA10609887}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\bin\$(ConfigurationName)"
+			IntermediateDirectory="..\..\obj\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			ReferencesPath="">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\Dependencies\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;../include"
+				PreprocessorDefinitions="_WINDOWS;_STLP_USE_DYNAMIC_LIB;OGRE_LIBRARY_IMPORTS;_DEBUG;WIN32;_STLP_DEBUG;PLUGIN_TERRAIN_IMPORTS"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Plugin_OctreeSceneManager.lib OGREMain_d.LIB CEGUIBase_d.lib OgreGUIRenderer_d.lib Plugin_DotSceneManager.lib"
+				OutputFile="$(OGRE_PATH)/Samples/Common/bin/Debug/TestCullingTerrain.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\Dependencies\Lib\Debug&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\OgreMain\Lib\Debug&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/TestCullingTerrain.pdb"
+				SubSystem="2"
+				ImportLibrary=""
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\..\Samples\Common\Include, ..\..\..\OgreMain\include"
+				PreprocessorDefinitions="_WINDOWS,_STLP_USE_DYNAMIC_LIB,OGRE_LIBRARY_IMPORTS,_RELEASE,WIN32,_STLP_RELEASE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OGREMain.LIB"
+				OutputFile="..\..\..\Samples\Common\Bin\Release\TestCullingTerrain.exe"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\..\OgreMain\Lib\Release"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\TerrainContentGenerator.cpp">
+			</File>
+			<File
+				RelativePath=".\TestCullingTerrainApplication.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\TerrainContentGenerator.h">
+			</File>
+			<File
+				RelativePath=".\TestCullingTerrainApplication.h">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.cpp
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.cpp	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.cpp	(revision 61)
@@ -0,0 +1,96 @@
+/**
+    \file 
+        TerrainContentGenerator.cpp
+    \brief
+        Creates content for the terrain,
+*/
+#include "TerrainContentGenerator.h"
+
+//-----------------------------------------------------------------------
+TerrainContentGenerator::TerrainContentGenerator( SceneManager *sm, RayQueryExecutor *rayQueryEx )
+{
+	mSceneMgr = sm;
+	mRayQueryExecutor = rayQueryEx;
+
+	mMinTranslation = Vector3(-70.0f, -70.0f, 0.0f);
+	mMaxTranslation = Vector3(70.0f, 70.0f, 600.0f);
+
+	mMinAngle = 0;
+	mMaxAngle = 360;
+
+	mCount = 0;
+}
+//-----------------------------------------------------------------------
+void TerrainContentGenerator::generateScene( int numObjects )
+{
+	srand (time (0));
+	
+	Vector3 rotationRatio;
+	Vector3 translationRatio;
+
+	for(int i=0; i < numObjects; i++)
+	{
+		rotationRatio.x = rand() / (float) RAND_MAX;
+		rotationRatio.y = rand() / (float) RAND_MAX;
+		rotationRatio.z = rand() / (float) RAND_MAX;
+
+		translationRatio.x = rand() / (float) RAND_MAX;
+		translationRatio.y = rand() / (float) RAND_MAX;
+		translationRatio.z = rand() / (float) RAND_MAX;
+
+		generateSceneObject(translationRatio, rotationRatio, i, "sphere.mesh");
+	}
+}
+//-----------------------------------------------------------------------
+void TerrainContentGenerator::generateSceneObject(const Vector3 &translationRatio, 
+					 const Vector3 &rotationRatio, const int idx, const String& entName)
+{
+	// Setup the ray scene query
+	Real rotation = mMinAngle + rotationRatio.x * (mMaxAngle - mMinAngle);
+	Vector3 translation = mMinTranslation + translationRatio * (mMaxTranslation - mMinTranslation);
+
+	translation.y = 5000;
+    
+	Vector3 queryResult;
+
+	if(mRayQueryExecutor->executeRayQuery(&queryResult, translation, Vector3::NEGATIVE_UNIT_Y))
+	{
+		char name[16];
+		sprintf( name, "%s%d", entName.c_str(), mCount++);
+
+		Entity *ent = mSceneMgr->createEntity(name, entName);
+		SceneNode *currentObject = mSceneMgr->getRootSceneNode( )->createChildSceneNode( String(name) + "Node", queryResult);
+		currentObject->attachObject(ent);
+		currentObject->setScale(0.1f, 0.1f, 0.1f);
+	}
+}
+//-----------------------------------------------------------------------
+RayQueryExecutor::RayQueryExecutor( SceneManager *sm )
+{
+	mRaySceneQuery = sm->createRayQuery(Ray());
+}
+//-----------------------------------------------------------------------
+RayQueryExecutor::~RayQueryExecutor()
+{
+	delete mRaySceneQuery;
+}
+//-----------------------------------------------------------------------
+bool RayQueryExecutor::executeRayQuery( Vector3 *result, const Vector3 &pos, const Vector3 &dir )
+{
+	Ray ray(pos, dir);
+    mRaySceneQuery->setRay(ray);
+
+    // Perform the scene query
+    RaySceneQueryResult &queryResult = mRaySceneQuery->execute();
+    RaySceneQueryResult::iterator it = queryResult.begin( );
+
+	if (it != queryResult.end() && it->worldFragment)
+	{
+		SceneQuery::WorldFragment* wf = it->worldFragment;
+
+		*result = wf->singleIntersection; 
+		return true;
+	}
+
+	return false;
+}
Index: trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.cpp
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.cpp	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.cpp	(revision 61)
@@ -0,0 +1,420 @@
+/**
+    \file 
+        TestCullingTerrainApplication.cpp
+    \brief
+        Tests the occlusion culling algorithm
+*/
+
+#include <OgreNoMemoryMacros.h>
+#include <CEGUI/CEGUI.h>
+#include <../CEGUIRenderer/include/OgreCEGUIRenderer.h>
+#include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h>
+#include <../CEGUIRenderer/include/OgreCEGUITexture.h>
+#include <OgreMemoryMacros.h>
+
+#include "Ogre.h"
+#include "TestCullingTerrainApplication.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+
+/************************************************/
+/* TestCullingTerrainApplication implementation */
+/************************************************/
+TestCullingTerrainApplication::~TestCullingTerrainApplication()
+{
+	delete mRayQueryExecutor;
+	delete mTerrainContentGenerator;
+}
+
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::createCamera( void )
+{
+	// Create the camera
+	mCamera = mSceneMgr->createCamera("PlayerCam");
+
+	// Position it at 500 in Z direction
+	mCamera->setPosition(Vector3(128,25,128));
+
+	// Look back along -Z
+    mCamera->lookAt(Vector3(0,0,-300));
+    mCamera->setNearClipDistance(1);
+    mCamera->setFarClipDistance(1000);
+}
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::generateSceneObject(const Vector3 &translationRatio, 
+					 const Vector3 &rotationRatio, const int idx, const String& entName)
+{
+	// Setup the ray scene query
+	/*Vector3 rotation = mMinAngle + rotationRatio * (mMaxAngle - mMinAngle);
+	Vector3 translation = mMinTranslation + translationRatio * (mMaxTranslation - mMinTranslation);
+
+	translation.y = 5000;
+    Ray ray(translation, Vector3::NEGATIVE_UNIT_Y);
+    mRaySceneQuery->setRay(ray);
+
+    // Execute query
+	RaySceneQueryResult &result = mRaySceneQuery->execute();
+	RaySceneQueryResult::iterator itr = result.begin( );
+
+	// Get results, create a node/entity on the position
+	if ( itr != result.end() && itr->worldFragment )
+	{
+		char name[16];
+		sprintf( name, "%s%d", entName.c_str(), mCount++ );
+
+		Entity *ent = mSceneMgr->createEntity( name, entName );
+		SceneNode currentObject = mSceneMgr->getRootSceneNode( )->createChildSceneNode( String(name) + "Node", itr->worldFragment->singleIntersection );
+		currentObject->attachObject( ent );
+		currentObject->setScale( 0.1f, 0.1f, 0.1f );
+	}*/
+}
+
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::createScene( void )
+{
+	mRayQueryExecutor = new RayQueryExecutor(mSceneMgr);
+	mTerrainContentGenerator = new TerrainContentGenerator(mSceneMgr, mRayQueryExecutor);
+	// Set ambient light
+	mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
+	
+	// Create a light
+	Light* l = mSceneMgr->createLight("MainLight");
+	// Accept default settings: point light, white diffuse, just set position
+	// NB I could attach the light to a SceneNode if I wanted it to move automatically with
+	//  other objects, but I don't
+	l->setPosition(20,80,50);
+
+	// --Fog
+	// NB it's VERY important to set this before calling setWorldGeometry 
+	// because the vertex program picked will be different
+	ColourValue fadeColour(0.93, 0.86, 0.76);
+	mWindow->getViewport(0)->setBackgroundColour(fadeColour);
+	//mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
+
+	// Create a skybox
+    //mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 500, false);
+	//mSceneMgr->setSkyDome( true, "Examples/CloudySky", 5, 8, 500, false );
+
+	/*	// Define the required skyplane
+	Plane plane;
+	// 5000 world units from the camera
+	plane.d = 5000;
+	// Above the camera, facing down
+	plane.normal = -Vector3::UNIT_Y;
+	// Create the plane 10000 units wide, tile the texture 3 times
+    mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane",10000,3);*/
+
+	std::string terrain_cfg("terrain.cfg");
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+	terrain_cfg = mResourcePath + terrain_cfg;
+#endif
+	mSceneMgr -> setWorldGeometry( terrain_cfg );
+	// Infinite far plane?
+	if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
+	{
+		mCamera->setFarClipDistance(0);
+	}
+
+	// Set a nice viewpoint
+	mCamera->setPosition(707,2500,528);
+	mCamera->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
+
+	// CEGUI setup
+	setupGui();
+}
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::setupGui( void )
+{
+	 mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, ST_EXTERIOR_CLOSE);
+     mGUISystem = new CEGUI::System(mGUIRenderer);
+
+	 // Mouse
+     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
+     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
+	 mGUISystem->setDefaultMouseCursor(
+                (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
+
+	 CEGUI::MouseCursor::getSingleton().show( );
+}
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::createFrameListener(void)
+{
+	mFrameListener= new MouseQueryListener(mWindow, mCamera, mSceneMgr, mGUIRenderer, mRayQueryExecutor);
+	mFrameListener->showDebugOverlay(true);
+	mRoot->addFrameListener(mFrameListener);
+}
+//-----------------------------------------------------------------------
+void TestCullingTerrainApplication::chooseSceneManager(void)
+{
+    //mSceneMgr = mRoot->getSceneManager(ST_GENERIC);
+	mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE);
+}
+
+/***********************************************/
+/* MouseQueryListener implementation           */
+/***********************************************/
+//-----------------------------------------------------------------------
+MouseQueryListener::MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer, RayQueryExecutor *rqe)
+        : ExampleFrameListener(win, cam, false, true), mGUIRenderer(renderer), mShutdownRequested(false), mRayQueryExecutor(rqe)
+{
+
+	// Setup default variables
+	mCurrentObject = NULL;
+	mLMouseDown = false;
+	mRMouseDown = false;
+	mSceneMgr = sceneManager;
+
+    // Reduce move speed
+	mMoveSpeed = 50;
+	mRotateSpeed *= 2;
+
+	mCurrentAlgorithm = 0;//VisibilitySceneTraverser::RENDER_COHERENT;
+	mThreshold = 0;
+    
+	// Register this so that we get mouse events.
+	mEventProcessor->addMouseListener(this);
+	mEventProcessor->addMouseMotionListener(this);
+	mEventProcessor->addKeyListener(this);
+
+	mRaySceneQuery = mSceneMgr->createRayQuery(Ray());
+
+	// show overlay
+	Overlay* pOver = OverlayManager::getSingleton().getByName("Example/VisibilityDemoOverlay"); 
+
+	mAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/AlgorithmInfo");
+	mThresholdInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/ThresholdInfo");
+	mFrustumCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/FrustumCulledNodesInfo");
+	mQueryCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/QueryCulledNodesInfo");
+    mTraversedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/TraversedNodesInfo");
+	mSceneNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/SceneNodesInfo");
+	mHierarchyNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/HierarchyNodesInfo");
+	mRenderedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/RenderedNodesInfo");
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mThresholdInfo->setCaption(": 0");
+	mFrustumCulledNodesInfo->setCaption(": 0");
+	mQueryCulledNodesInfo->setCaption(": 0");
+	mTraversedNodesInfo->setCaption(": 0");
+	mSceneNodesInfo->setCaption(": 0");
+	mHierarchyNodesInfo->setCaption(": 0");
+	mRenderedNodesInfo->setCaption(": 0");
+		
+    pOver->show();
+} 
+//-----------------------------------------------------------------------
+MouseQueryListener::~MouseQueryListener( )
+{
+	delete mRaySceneQuery;
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseMoved (MouseEvent *e)
+{
+	// Update CEGUI with the mouse motion
+    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight());
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::mousePressed(MouseEvent* e)
+{
+     // Left mouse button down
+     if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+     {
+		 CEGUI::MouseCursor::getSingleton().hide( );
+
+		 // Setup the ray scene query
+         Ray mouseRay = mCamera->getCameraToViewportRay( e->getX(), e->getY() );
+         mRaySceneQuery->setRay( mouseRay );
+
+         // Execute query
+         RaySceneQueryResult &result = mRaySceneQuery->execute();
+         RaySceneQueryResult::iterator itr = result.begin( );
+
+         // Get results, create a node/entity on the position
+         if ( itr != result.end() && itr->worldFragment )
+         {
+			 char name[16];
+             sprintf( name, "Robot%d", mCount++ );
+
+             Entity *ent = mSceneMgr->createEntity( name, "robot.mesh" );
+             mCurrentObject = mSceneMgr->getRootSceneNode( )->createChildSceneNode( String(name) + "Node", itr->worldFragment->singleIntersection );
+             mCurrentObject->attachObject( ent );
+             mCurrentObject->setScale( 0.1f, 0.1f, 0.1f );
+         }
+
+         mLMouseDown = true; 
+     }
+     // Right mouse button down
+     else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+     {
+         CEGUI::MouseCursor::getSingleton().hide( );
+         mRMouseDown = true;
+     } // else if
+} // mousePressed
+
+ //-----------------------------------------------------------------------
+void MouseQueryListener::mouseReleased(MouseEvent* e)
+{
+    // Left mouse button up
+    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+    {
+		CEGUI::MouseCursor::getSingleton().show( );
+        mLMouseDown = false;
+    }
+    // Right mouse button up
+    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+    {
+        CEGUI::MouseCursor::getSingleton().show( );
+        mRMouseDown = false;
+    }
+} 
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseDragged (MouseEvent *e)
+ {
+	 // If we are dragging the left mouse button.	 	 
+	 if ( mLMouseDown )
+     {
+		 Ray mouseRay = mCamera->getCameraToViewportRay( e->getX(), e->getY() );
+		 mRaySceneQuery->setRay( mouseRay );
+
+		 RaySceneQueryResult &result = mRaySceneQuery->execute();
+		 RaySceneQueryResult::iterator itr = result.begin( );
+
+		 if ( itr != result.end() && itr->worldFragment )
+		 {
+			 mCurrentObject->setPosition( itr->worldFragment->singleIntersection );
+		 } 
+     }
+	 // If we are dragging the right mouse button.
+	 if ( mRMouseDown )
+	 {
+		 mCamera->yaw( -e->getRelX() * mRotateSpeed );
+		 mCamera->pitch( -e->getRelY() * mRotateSpeed );
+	 }
+}
+//-----------------------------------------------------------------------
+bool MouseQueryListener::frameStarted(const FrameEvent &evt)
+{
+	// clamp to terrain
+	Vector3 camPos = mCamera->getPosition( );
+    Ray cameraRay( Vector3(camPos.x, 5000.0f, camPos.z), Vector3::NEGATIVE_UNIT_Y );
+    mRaySceneQuery->setRay( cameraRay );
+
+    // Perform the scene query
+    RaySceneQueryResult &queryResult = mRaySceneQuery->execute();
+    RaySceneQueryResult::iterator it = queryResult.begin( );
+
+	if (it != queryResult.end() && it->worldFragment)
+	{
+		SceneQuery::WorldFragment* wf = it->worldFragment;
+
+		mCamera->setPosition(mCamera->getPosition().x, wf->singleIntersection.y + 10, 
+			mCamera->getPosition().z);
+	}
+	 
+	return ExampleFrameListener::frameStarted(evt);
+}
+//-----------------------------------------------------------------------
+bool MouseQueryListener::frameEnded(const FrameEvent& evt)
+{
+	if (mShutdownRequested)
+		return false;
+
+    if (timeDelay >= 0) 
+        timeDelay -= evt.timeSinceLastFrame;
+
+    KEY_PRESSED(KC_SPACE, 0.3, changeAlgorithm());
+
+	KEY_PRESSED(KC_SUBTRACT, 0, changeThreshold(-10));
+	KEY_PRESSED(KC_ADD, 0, changeThreshold(10));
+	//KEY_PRESSED(KC_T, 1, change);
+      
+	changeStats();
+
+    return ExampleFrameListener::frameStarted(evt) && ExampleFrameListener::frameEnded(evt);        
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeThreshold(int incr)
+{
+	mThreshold += incr; if(mThreshold < 0) mThreshold = 0;
+	
+	char str[100]; sprintf(str,": %d", mThreshold);
+
+	mSceneMgr->setOption("Threshold", &mThreshold); 
+	mThresholdInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeAlgorithm()
+{
+    //mCurrentAlgorithm = ++mCurrentAlgorithm % VisibilitySceneTraverser::NUM_RENDERMODES;
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeStats()
+{
+	unsigned int opt = 0;
+	char str[100];
+	
+	mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mFrustumCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mQueryCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumTraversedNodes", &opt); sprintf(str,": %d", opt); 
+	mTraversedNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumSceneNodes", &opt); sprintf(str,": %d", opt); 
+	mSceneNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumOctreeNodes", &opt); sprintf(str,": %d", opt); 
+	mHierarchyNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt); 
+	mRenderedNodesInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyPressed(KeyEvent* e)
+{
+	if(e->getKey() == KC_ESCAPE)
+    {
+		mShutdownRequested = true;
+		e->consume();
+		return;
+	}
+
+	CEGUI::System::getSingleton().injectKeyDown(e->getKey());
+	CEGUI::System::getSingleton().injectChar(e->getKeyChar());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyReleased(KeyEvent* e)
+{
+	CEGUI::System::getSingleton().injectKeyUp(e->getKey());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyClicked(KeyEvent* e) 
+{
+	// Do nothing
+	e->consume();
+}
+//-----------------------------------------------------------------------
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+{
+    // Create application object
+    TestCullingTerrainApplication app;
+
+	try 
+	{
+        app.go();
+    } 
+	catch( Ogre::Exception& e ) 
+	{
+        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+    }	
+
+    return 0;
+}
Index: trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsp
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsp	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.dsp	(revision 61)
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="Demo_TestCullingTerrainApplication" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Demo_TestCullingTerrainApplication - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "TestCullingTerrainApplication.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "TestCullingTerrainApplication.mak" CFG="Demo_TestCullingTerrainApplication - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Demo_TestCullingTerrainApplication - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "Demo_TestCullingTerrainApplication - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Demo_TestCullingTerrainApplication - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "..\bin\Release"
+# PROP BASE Intermediate_Dir "..\obj\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\bin\Release"
+# PROP Intermediate_Dir "..\obj\Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /I "$(OGRE_PATH)\OgreMain\include" /I "$(OGRE_PATH)\Samples/Common/include" /D "NDEBUG" /D "_MBCS" /D "_WINDOWS" /D "WIN32" /YX /FD /Zm1000 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OgreMain.lib /nologo /subsystem:windows /machine:I386 /out:"$(OGRE_PATH)\Samples\Common\Bin\Release\Demo_TestCullingTerrainApplication.exe" /libpath:"$(OGRE_PATH)\OgreMain\lib\release" 
+# SUBTRACT LINK32 /profile /debug
+
+!ELSEIF  "$(CFG)" == "Demo_TestCullingTerrainApplication - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\bin\Debug"
+# PROP BASE Intermediate_Dir "..\obj\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\bin\Debug"
+# PROP Intermediate_Dir "..\obj\Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "$(OGRE_PATH)\OgreMain\include" /I "$(OGRE_PATH)\Samples/Common/include" /D "_MBCS" /D "_WINDOWS" /D "_DEBUG" /D "WIN32" /FD /GZ /Zm1000 /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OgreMain_d.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBCMT" /out:"$(OGRE_PATH)\Samples\Common\Bin\Debug\Demo_TestCullingTerrainApplication.exe" /pdbtype:sept /libpath:"$(OGRE_PATH)\OgreMain\lib\debug" 
+# SUBTRACT LINK32 /verbose
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Demo_TestCullingTerrainApplication - Win32 Release"
+# Name "Demo_TestCullingTerrainApplication - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=TestCullingTerrainApplication.cpp
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Index: trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.h
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.h	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TerrainContentGenerator.h	(revision 61)
@@ -0,0 +1,46 @@
+/**
+    \file 
+        TerrainContentGenerator.h
+*/
+#include "ExampleApplication.h"
+
+class RayQueryExecutor
+{
+public:
+	RayQueryExecutor( SceneManager *sm );
+	~RayQueryExecutor( );
+	bool executeRayQuery( Vector3 *result, const Vector3 &pos, const Vector3 &dir );
+protected:
+	RaySceneQuery *mRaySceneQuery;
+};
+
+class TerrainContentGenerator
+{
+public:
+	TerrainContentGenerator(  SceneManager *sm, RayQueryExecutor *rayQueryEx );
+	/** Generates a the scene hierarchy with random values .
+	@param number of objects to generate
+	*/
+	void generateScene( int numObjects );
+	/** 
+		generates a new scene object 
+		@param tranlationRatio ratio between minimal and maximal possible translation
+		@param rotationRatio ratio between minimal and maximal possible rotation
+		@idx the index of the new object
+		@entName the name of the object entity
+	*/
+	void generateSceneObject( const Vector3 &translationRatio, const Vector3 &rotationRatio, 
+							  const int idx, const String &entName );
+
+protected:
+
+	Real mMinAngle;
+	Real mMaxAngle;
+	Vector3 mMaxTranslation;
+	Vector3 mMinTranslation;
+
+	RayQueryExecutor *mRayQueryExecutor;
+	SceneManager *mSceneMgr;
+	int mCount;		// The number of objects on the screen
+};
+
Index: trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.h
===================================================================
--- trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.h	(revision 61)
+++ trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.h	(revision 61)
@@ -0,0 +1,127 @@
+/**
+    \file 
+        TestCullingTerrainApplication.h
+*/
+#include "CEGUIForwardRefs.h"
+#include "ExampleApplication.h"
+#include "TerrainContentGenerator.h"
+
+Real timeDelay = 0;
+#define KEY_PRESSED(_key,_timeDelay, _macro) \
+{ \
+    if (mInputDevice->isKeyDown(_key) && timeDelay <= 0) \
+{ \
+    timeDelay = _timeDelay; \
+    _macro ; \
+} \
+}
+
+String mCurrentAlgorithmCaptions[3/*VisibilitySceneTraverser::NUM_RENDERMODES*/] = 
+{
+    "Cull Frustum", 
+	"Stop and Wait", 
+	"Coherent Occlusion Culling"
+};
+
+class MouseQueryListener : public ExampleFrameListener, public MouseListener, public MouseMotionListener
+{
+public:
+
+    MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, 
+		CEGUI::Renderer *renderer, RayQueryExecutor *rqe);
+
+
+    ~MouseQueryListener( );
+
+	bool frameStarted(const FrameEvent& evt);
+	bool frameEnded(const FrameEvent& evt);
+
+    /* MouseListener callbacks. */
+    virtual void mouseClicked(MouseEvent* e) { }
+    virtual void mouseEntered(MouseEvent* e) { }
+    virtual void mouseExited(MouseEvent* e)  { }
+
+    // This is when the mouse button goes DOWN.
+    virtual void mousePressed(MouseEvent* e);
+
+    // This is when the mouse button is let UP.
+    virtual void mouseReleased(MouseEvent* e);
+
+    /* MouseMotionListener callbacks */
+    virtual void mouseMoved (MouseEvent *e);
+   
+    // This is when the mouse is clicked, held and dragged.
+    virtual void mouseDragged (MouseEvent *e);
+
+    void keyPressed(KeyEvent* e);
+
+	void keyReleased(KeyEvent* e);
+	void keyClicked(KeyEvent* e);
+
+	void changeAlgorithm();
+	void changeThreshold(int incr);
+	void changeStats();
+
+protected:
+    bool mLMouseDown, mRMouseDown;     // True if the mouse buttons are down
+    SceneManager *mSceneMgr;           // A pointer to the scene manager
+    
+	CEGUI::Renderer *mGUIRenderer;     // cegui renderer
+	
+	bool mShutdownRequested;
+	int mCurrentAlgorithm;
+	int mThreshold;
+
+	OverlayElement *mAlgorithmInfo;
+	OverlayElement *mThresholdInfo;
+	OverlayElement *mFrustumCulledNodesInfo;
+	OverlayElement *mQueryCulledNodesInfo;
+    OverlayElement *mTraversedNodesInfo;
+	OverlayElement *mHierarchyNodesInfo;
+	OverlayElement *mSceneNodesInfo;
+	OverlayElement *mRenderedNodesInfo;
+
+	SceneNode *mCurrentObject;         // The newly created object
+	RaySceneQuery *mRaySceneQuery;     // The ray scene query pointer
+	int mCount;                        // The number of robots on the screen
+
+	RayQueryExecutor *mRayQueryExecutor;
+};
+
+
+class TestCullingTerrainApplication : public ExampleApplication
+{
+public:
+	~TestCullingTerrainApplication();
+
+protected:
+	void createScene(void);
+	void createFrameListener(void);
+	void setupGui(void);
+	virtual void createCamera(void);
+
+	/** 
+		generates a new scene object 
+		@param tranlationRatio ratio between minimal and maximal possible translation
+		@param rotationRatio ratio between minimal and maximal possible rotation
+		@idx the index of the new object
+		@entName the name of the object entity
+	*/
+	void generateSceneObject(const Vector3 &translationRatio, const Vector3 &rotationRatio, 
+							 const int idx, const String &entName);
+
+	CEGUI::OgreCEGUIRenderer *mGUIRenderer;
+	CEGUI::System *mGUISystem;
+	RayQueryExecutor *mRayQueryExecutor;
+	TerrainContentGenerator *mTerrainContentGenerator;
+
+	Vector3 mMinTranslation;
+	Vector3 mMaxTranslation;
+
+	Vector3 mMinAngle;
+	Vector3 mMaxAngle;
+
+private:
+	void chooseSceneManager(void);
+};
+
Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 61)
@@ -0,0 +1,154 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef _HardwareOcclusionQuery__
+#define _HardwareOcclusionQuery__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+
+
+/**
+  * Hardware occlusion query flags
+  */
+typedef enum _OCCLUSIONQUERY 
+{
+	HWOCCLUSIONQUERY_FLUSH,   /** Direct3D uses this, but not OpenGL */
+	HWOCCLUSIONQUERY_NOFLUSH, /** To decide if the driver should flush all batched API calls to serve an occlusion query faster. */
+} HW_OCCLUSIONQUERY;
+
+/**
+  * This is a abstract class that that provides the interface for the query class for 
+  * hardware occlusion.
+  *
+  * @author Lee Sandberg
+  */
+class _OgreExport HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+	/**
+	  * Object public member functions
+	  */
+
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	HardwareOcclusionQuery();
+
+	/**
+	  * Object destructor
+	  */
+	virtual ~HardwareOcclusionQuery();
+
+	/**
+	  * Starts the hardware occlusion query
+	  * @Remarks	Simple usage: Create one or more OcclusionQuery object one per outstanding query or one per tested object 
+	  *				OcclusionQuery* m_pOcclusionQuery;
+	  *				createOcclusionQuery( &m_pOcclusionQuery );
+	  *				In the rendering loop:
+	  *				Draw all occluders
+	  *				m_pOcclusionQuery->startOcclusionQuery();
+	  *				Draw the polygons to be tested
+	  *				m_pOcclusionQuery->endOcclusionQuery();
+	  *
+	  *				Results must be pulled using:
+	  *				UINT	m_uintNumberOfPixelsVisable;
+	  *				pullOcclusionQuery( &m_dwNumberOfPixelsVisable );
+	  *				You may not get the result directlly after the first pass or frame.
+	  *				Objects not visable must be tested every frame, visable objects may be tested less freqvent.
+	  *			
+	  */
+	virtual void beginOcclusionQuery() = 0;
+
+	/**
+	  * Ends the hardware occlusion test
+	  */
+	virtual void endOcclusionQuery() = 0;
+
+	/**
+      * Pulls the hardware occlusion query too see if there is a result.
+      * @retval NumOfFragments will get the resulting number of fragments.
+      * @return True if success or false if not.
+	  * @Remarks Hardware occlusion is an assyncronius process the result may take a frame or so.
+	  *			one idea is to test pass1 and if not visable skip pass2. Also note that objects
+	  *			not visable must be tested evrey frame. Visable objects don't need testing every frame.
+	  *			Testing non visable objects can be don unlit, no texture with low LOD object.
+	  *        0 will generate all the levels till 1x1. [default: 0]
+      */
+	virtual bool pullOcclusionQuery( unsigned int* NumOfFragments ) = 0;
+
+	/**
+      * Pulls the hardware occlusion query too see if there is a result.
+      * @retval NumOfFragments will get the resulting number of fragments.
+      * @return True if success or false if not.
+	  * @Remarks In DX9 mode specifying OCCLUSIONQUERY_FLUSH as the flag, will case the driver to flush whatever API calls are batched.
+	  * In OpenGL mode it makes no difference if you specify OCCLUSIONQUERY_FLUSH or OCCLUSIONQUERY_NOFLUSH.
+      */
+	virtual bool pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ) = 0;
+
+	/**
+	  * Let's you get the last pixel count with out doing the hardware occlusion test
+	  * @return The last fragment count from the last test.
+	  * Remarks This function won't give you new values, just the old value.
+	  */
+	virtual unsigned int getLastQuerysPixelcount() = 0;
+
+	/**
+	  *   
+	  * @Remarks This function allows you to set how often the hardware occlusion really are sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 1 only the half of your queries are sent 
+	  * for all visable objects. 2 will result in 25% of all queries to acctualy be sent. 
+	  * New and none visable objects will be tested all the time.
+	  * This functionality is here because this class can keep track on visable and none visable objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+	virtual void	setSkipRate( int skip ) = 0;
+	virtual int		getSkipRate() = 0;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/**
+	  *   
+	  * @Remarks This function returns true if the result of the 
+	  * query is already availbable, false otherwise.
+	  */
+	virtual bool resultAvailable() = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+//----------------------------------------------------------------------
+// Private members
+//--
+private:
+
+};
+
+}
+#endif
+
Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneNode.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneNode.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneNode.h	(revision 61)
@@ -0,0 +1,458 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef _SceneNode_H__
+#define _SceneNode_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreNode.h"
+#include "OgreIteratorWrappers.h"
+#include "OgreAxisAlignedBox.h"
+
+namespace Ogre {
+
+    /** Class representing a node in the scene graph.
+        @remarks
+            A SceneNode is a type of Node which is used to organise objects in a scene.
+            It has the same hierarchical transformation properties of the generic Node class,
+            but also adds the ability to attach world objects to the node, and stores hierarchical
+            bounding volumes of the nodes in the tree.
+            Child nodes are contained within the bounds of the parent, and so on down the
+            tree, allowing for fast culling.
+    */
+    class _OgreExport SceneNode : public Node
+    {
+    public:
+        typedef HashMap<String, MovableObject*> ObjectMap;
+        typedef MapIterator<ObjectMap> ObjectIterator;
+		typedef ConstMapIterator<ObjectMap> ConstObjectIterator;
+
+    protected:
+        ObjectMap mObjectsByName;
+        mutable LightList mLightList;
+        mutable bool mLightListDirty;
+
+		/// Pointer to a Wire Bounding Box for this Node
+		WireBoundingBox *mWireBoundingBox;
+		/// Flag that determines if the bounding box of the node should be displayed
+		bool mShowBoundingBox;
+
+        /// SceneManager which created this node
+        SceneManager* mCreator;
+
+        /// World-Axis aligned bounding box, updated only through _update
+        AxisAlignedBox mWorldAABB;
+
+        /** Tells the SceneNode to update the world bound info it stores.
+        */
+        virtual void _updateBounds(void);
+
+        /** See Node. */
+        Node* createChildImpl(void);
+
+        /** See Node. */
+        Node* createChildImpl(const String& name);
+
+		/** See Node */
+		void setParent(Node* parent);
+
+		/** Internal method for setting whether the node is in the scene 
+			graph.
+		*/
+		void setInSceneGraph(bool inGraph);
+
+        /// Whether to yaw around a fixed axis.
+        bool mYawFixed;
+        /// Fixed axis to yaw around
+        Vector3 mYawFixedAxis;
+
+        /// Auto tracking target
+        SceneNode* mAutoTrackTarget;
+        /// Tracking offset for fine tuning
+        Vector3 mAutoTrackOffset;
+        /// Local 'normal' direction vector
+        Vector3 mAutoTrackLocalDirection;
+		/// Is this node a current part of the scene graph?
+		bool mIsInSceneGraph;
+    public:
+        /** Constructor, only to be called by the creator SceneManager.
+        @remarks
+            Creates a node with a generated name.
+        */
+        SceneNode(SceneManager* creator);
+        /** Constructor, only to be called by the creator SceneManager.
+        @remarks
+            Creates a node with a specified name.
+        */
+        SceneNode(SceneManager* creator, const String& name);
+        ~SceneNode();
+
+        /** Adds an instance of a scene object to this node.
+        @remarks
+            Scene objects can include Entity objects, Camera objects, Light objects, 
+            ParticleSystem objects etc. Anything that subclasses from MovableObject.
+        */
+        virtual void attachObject(MovableObject* obj);
+
+        /** Reports the number of objects attached to this node.
+        */
+        virtual unsigned short numAttachedObjects(void) const;
+
+        /** Retrieves a pointer to an attached object.
+        @remarks Retrieves by index, see alternate version to retrieve by name. The index
+        of an object may change as other objects are added / removed.
+        */
+        virtual MovableObject* getAttachedObject(unsigned short index);
+
+        /** Retrieves a pointer to an attached object.
+        @remarks Retrieves by object name, see alternate version to retrieve by index.
+        */
+        virtual MovableObject* getAttachedObject(const String& name);
+
+        /** Detaches the indexed object from this scene node.
+        @remarks
+            Detaches by index, see the alternate version to detach by name. Object indexes
+            may change as other objects are added / removed.
+        */
+        virtual MovableObject* detachObject(unsigned short index);
+        /** Detaches an object by pointer. */
+        virtual void detachObject(MovableObject* obj);
+
+        /** Detaches the named object from this node and returns a pointer to it. */
+        virtual MovableObject* detachObject(const String& name);
+
+        /** Detaches all objects attached to this node.
+        */
+        virtual void detachAllObjects(void);
+
+		/** Determines whether this node is in the scene graph, ie
+			whether it's ulitimate ancestor is the root scene node.
+		*/
+		virtual bool isInSceneGraph(void) const { return mIsInSceneGraph; }
+
+		/** Notifies this SceneNode that it is the root scene node. 
+		@remarks
+			Only SceneManager should call this!
+		*/
+		virtual void _notifyRootNode(void) { mIsInSceneGraph = true; }
+			
+
+        /** Internal method to update the Node.
+            @note
+                Updates this scene node and any relevant children to incorporate transforms etc.
+                Don't call this yourself unless you are writing a SceneManager implementation.
+            @param
+                updateChildren If true, the update cascades down to all children. Specify false if you wish to
+                update children separately, e.g. because of a more selective SceneManager implementation.
+            @param
+                parentHasChanged This flag indicates that the parent xform has changed,
+                    so the child should retrieve the parent's xform and combine it with its own
+                    even if it hasn't changed itself.
+        */
+        virtual void _update(bool updateChildren, bool parentHasChanged);
+
+        /** Internal method which locates any visible objects attached to this node and adds them to the passed in queue.
+            @remarks
+                Should only be called by a SceneManager implementation, and only after the _updat method has been called to
+                ensure transforms and world bounds are up to date.
+                SceneManager implementations can choose to let the search cascade automatically, or choose to prevent this
+                and select nodes themselves based on some other criteria.
+            @param
+                cam The active camera
+            @param
+                queue The SceneManager's rendering queue
+            @param
+                includeChildren If true, the call is cascaded down to all child nodes automatically.
+            @param
+                displayNodes If true, the nodes themselves are rendered as a set of 3 axes as well
+                    as the objects being rendered. For debugging purposes.
+        */
+        virtual void _findVisibleObjects(Camera* cam, RenderQueue* queue, 
+            bool includeChildren = true, bool displayNodes = false, bool onlyShadowCasters = false);
+
+        /** Gets the axis-aligned bounding box of this node (and hence all subnodes).
+        @remarks
+            Recommended only if you are extending a SceneManager, because the bounding box returned
+            from this method is only up to date after the SceneManager has called _update.
+        */
+        virtual AxisAlignedBox _getWorldAABB(void) const;
+
+        /** Retrieves an iterator which can be used to efficiently step through the objects 
+            attached to this node.
+        @remarks
+            This is a much faster way to go through <B>all</B> the objects attached to the node
+            than using getAttachedObject. But the iterator returned is only valid until a change
+            is made to the collection (ie an addition or removal) so treat the returned iterator
+            as transient, and don't add / remove items as you go through the iterator, save changes
+            until the end, or retrieve a new iterator after making the change. Making changes to
+            the object returned through the iterator is OK though.
+        */
+        virtual ObjectIterator getAttachedObjectIterator(void);
+        /** Retrieves an iterator which can be used to efficiently step through the objects 
+            attached to this node.
+        @remarks
+            This is a much faster way to go through <B>all</B> the objects attached to the node
+            than using getAttachedObject. But the iterator returned is only valid until a change
+            is made to the collection (ie an addition or removal) so treat the returned iterator
+            as transient, and don't add / remove items as you go through the iterator, save changes
+            until the end, or retrieve a new iterator after making the change. Making changes to
+            the object returned through the iterator is OK though.
+        */
+		virtual ConstObjectIterator getAttachedObjectIterator(void) const;
+
+        /** Gets the creator of this scene node. 
+        @remarks
+            This method returns the SceneManager which created this node.
+            This can be useful for destroying this node.
+        */
+        SceneManager* getCreator(void) const;
+
+        /** This method removes and destroys the named child and all of its children.
+        @remarks
+            Unlike removeChild, which removes a single named child from this
+            node but does not destroy it, this method destroys the child
+            and all of it's children. 
+        @par
+            Use this if you wish to recursively destroy a node as well as 
+            detaching it from it's parent. Note that any objects attached to
+            the nodes will be detached but will not themselves be destroyed.
+        */
+        virtual void removeAndDestroyChild(const String& name);
+
+        /** This method removes and destroys the child and all of its children.
+        @remarks
+            Unlike removeChild, which removes a single named child from this
+            node but does not destroy it, this method destroys the child
+            and all of it's children. 
+        @par
+            Use this if you wish to recursively destroy a node as well as 
+            detaching it from it's parent. Note that any objects attached to
+            the nodes will be detached but will not themselves be destroyed.
+        */
+        virtual void removeAndDestroyChild(unsigned short index);
+
+        /** Removes and destroys all children of this node.
+        @remarks
+            Use this to destroy all child nodes of this node and remove
+            them from the scene graph. Note that all objects attached to this
+            node will be detached but will not be destroyed.
+        */
+        virtual void removeAndDestroyAllChildren(void);
+
+        /** Allows the showing of the node's bounding box.
+        @remarks
+            Use this to show or hide the bounding box of the node.
+        */
+		virtual void showBoundingBox(bool bShow);
+
+        /** Add the bounding box to the rendering queue.
+        */
+		virtual void _addBoundingBoxToQueue(RenderQueue* queue);
+
+        /** This allows scene managers to determine if the node's bounding box
+			should be added to the rendering queue.
+        @remarks
+            Scene Managers that implement their own _findVisibleObjects will have to 
+			check this flag and then use _addBoundingBoxToQueue to add the bounding box
+			wireframe.
+        */
+		virtual bool getShowBoundingBox() const;
+
+        /** Creates an unnamed new SceneNode as a child of this node.
+        @param
+            translate Initial translation offset of child relative to parent
+        @param
+            rotate Initial rotation relative to parent
+        */
+        virtual SceneNode* createChildSceneNode(
+            const Vector3& translate = Vector3::ZERO, 
+            const Quaternion& rotate = Quaternion::IDENTITY );
+
+        /** Creates a new named SceneNode as a child of this node.
+        @remarks
+            This creates a child node with a given name, which allows you to look the node up from 
+            the parent which holds this collection of nodes.
+            @param
+                translate Initial translation offset of child relative to parent
+            @param
+                rotate Initial rotation relative to parent
+        */
+        virtual SceneNode* createChildSceneNode(const String& name, const Vector3& translate = Vector3::ZERO, const Quaternion& rotate = Quaternion::IDENTITY);
+
+        /** Allows retrieval of the nearest lights to the centre of this SceneNode.
+        @remarks
+            This method allows a list of lights, ordered by proximity to the centre of
+            this SceneNode, to be retrieved. Multiple access to this method when neither 
+            the node nor the lights have moved will result in the same list being returned
+            without recalculation. Can be useful when implementing Renderable::getLights.
+        @param radius Optional parameter to specify lights intersecting a given radius of
+            this SceneNode's centre.
+        */
+        const LightList& findLights(Real radius) const;
+
+        /** Tells the node whether to yaw around it's own local Y axis or a fixed axis of choice.
+        @remarks
+        This method allows you to change the yaw behaviour of the node - by default, it
+        yaws around it's own local Y axis when told to yaw with TS_LOCAL, this makes it
+        yaw around a fixed axis. 
+        You only really need this when you're using auto tracking (see setAutoTracking,
+        because when you're manually rotating a node you can specify the TransformSpace
+        in which you wish to work anyway.
+        @param
+        useFixed If true, the axis passed in the second parameter will always be the yaw axis no
+        matter what the node orientation. If false, the node returns to it's default behaviour.
+        @param
+        fixedAxis The axis to use if the first parameter is true.
+        */
+        void setFixedYawAxis( bool useFixed, const Vector3& fixedAxis = Vector3::UNIT_Y );
+
+		/** Rotate the node around the Y-axis.
+		*/
+		virtual void yaw(const Radian& angle, TransformSpace relativeTo = TS_LOCAL);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+		inline void yaw(Real degrees, TransformSpace relativeTo = TS_LOCAL) {
+			yaw ( Angle(degrees), relativeTo );
+		}
+#endif//OGRE_FORCE_ANGLE_TYPES
+        /** Sets the node's direction vector ie it's local -z.
+        @remarks
+        Note that the 'up' vector for the orientation will automatically be 
+        recalculated based on the current 'up' vector (i.e. the roll will 
+        remain the same). If you need more control, use setOrientation.
+        @param x,y,z The components of the direction vector
+        @param relativeTo The space in which this direction vector is expressed
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void setDirection(Real x, Real y, Real z, 
+            TransformSpace relativeTo = TS_LOCAL, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+
+        /** Sets the node's direction vector ie it's local -z.
+        @remarks
+        Note that the 'up' vector for the orientation will automatically be 
+        recalculated based on the current 'up' vector (i.e. the roll will 
+        remain the same). If you need more control, use setOrientation.
+        @param vec The direction vector
+        @param relativeTo The space in which this direction vector is expressed
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void setDirection(const Vector3& vec, TransformSpace relativeTo = TS_LOCAL, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+        /** Points the local -Z direction of this node at a point in space.
+        @param targetPoint A vector specifying the look at point.
+        @param relativeTo The space in which the point resides
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void lookAt( const Vector3& targetPoint, TransformSpace relativeTo,
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+        /** Enables / disables automatic tracking of another SceneNode.
+        @remarks
+        If you enable auto-tracking, this SceneNode will automatically rotate to
+        point it's -Z at the target SceneNode every frame, no matter how 
+        it or the other SceneNode move. Note that by default the -Z points at the 
+        origin of the target SceneNode, if you want to tweak this, provide a 
+        vector in the 'offset' parameter and the target point will be adjusted.
+        @param enabled If true, tracking will be enabled and the next 
+        parameter cannot be null. If false tracking will be disabled and the 
+        current orientation will be maintained.
+        @param target Pointer to the SceneNode to track. Make sure you don't
+        delete this SceneNode before turning off tracking (e.g. SceneManager::clearScene will
+        delete it so be careful of this). Can be null if and only if the enabled param is false.
+        @param localDirectionVector The local vector considered to be the usual 'direction'
+        of the node; normally the local -Z but can be another direction.
+        @param offset If supplied, this is the target point in local space of the target node
+        instead of the origin of the target node. Good for fine tuning the look at point.
+        */
+        void setAutoTracking(bool enabled, SceneNode* target = 0, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z,
+            const Vector3& offset = Vector3::ZERO);
+		/** Get the auto tracking target for this node, if any. */
+        SceneNode* getAutoTrackTarget(void) { return mAutoTrackTarget; }
+		/** Get the auto tracking offset for this node, if the node is auto tracking. */
+		const Vector3& getAutoTrackOffset(void) { return mAutoTrackOffset; }
+		/** Get the auto tracking local direction for this node, if it is auto tracking. */
+		const Vector3& getAutoTrackLocalDirection(void) { return mAutoTrackLocalDirection; }
+		/** Internal method used by OGRE to update auto-tracking cameras. */
+        void _autoTrack(void);
+        /** Gets the parent of this SceneNode. */
+        SceneNode* getParentSceneNode(void) const;
+        /** Makes all objects attached to this node become visible / invisble.
+        @remarks    
+            This is a shortcut to calling setVisible() on the objects attached
+            to this node, and optionally to all objects attached to child
+            nodes. 
+        @param visible Whether the objects are to be made visible or invisible
+        @param cascade If true, this setting cascades into child nodes too.
+        */
+        void setVisible(bool visible, bool cascade = true);
+        /** Inverts the visibility of all objects attached to this node.
+        @remarks    
+        This is a shortcut to calling setVisible(!isVisible()) on the objects attached
+        to this node, and optionally to all objects attached to child
+        nodes. 
+        @param cascade If true, this setting cascades into child nodes too.
+        */
+        void flipVisibility(bool cascade = true);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	public:
+		/** Returns last visited frame id. */
+		int lastVisited(void);
+		/** Set to current frame id.
+        @param current frame id.
+        */
+		void setLastVisited(int frameid);
+		/** Makes this node become visible / invisble.
+        @param visible Whether this node is to be made visible or invisible
+        */
+		void setNodeVisible(bool visible);
+		/** Returns true if this node is marked visible, false otherwise. */
+		bool isNodeVisible(void);
+
+		/** Frame id when this octree was last rendered. 
+		@return last rendered frame id
+		*/	
+		int lastRendered(void);
+		/** Sets frame id when this octree was last rendered. 
+		@param last rendered frame id
+		*/
+		void setLastRendered(int frameid);
+
+	protected:
+		int mLastVisited;
+		bool mVisible;
+		int mLastRendered;
+
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+
+    };
+
+
+}// namespace
+
+#endif
Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreFrustum.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreFrustum.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreFrustum.h	(revision 61)
@@ -0,0 +1,474 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Frustum_H__
+#define __Frustum_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreMovableObject.h"
+#include "OgreRenderable.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreVertexIndexData.h"
+#include "OgreMovablePlane.h"
+
+namespace Ogre
+{
+    /** Specifies perspective (realistic) or orthographic (architectural) projection.
+    */
+    enum ProjectionType
+    {
+        PT_ORTHOGRAPHIC,
+        PT_PERSPECTIVE
+    };
+
+    /** Worldspace clipping planes.
+    */
+    enum FrustumPlane
+    {
+        FRUSTUM_PLANE_NEAR   = 0,
+        FRUSTUM_PLANE_FAR    = 1,
+        FRUSTUM_PLANE_LEFT   = 2,
+        FRUSTUM_PLANE_RIGHT  = 3,
+        FRUSTUM_PLANE_TOP    = 4,
+        FRUSTUM_PLANE_BOTTOM = 5
+    };
+
+    /** A frustum represents a pyramid, capped at the near and far end which is
+        used to represent either a visible area or a projection area. Can be used
+        for a number of applications.
+    */
+    class _OgreExport Frustum : public MovableObject, public Renderable
+    {
+    protected:
+        /// Orthographic or perspective?
+        ProjectionType mProjType;
+
+        /// y-direction field-of-view (default 45)
+        Radian mFOVy;
+        /// Far clip distance - default 10000
+        Real mFarDist;
+        /// Near clip distance - default 100
+        Real mNearDist;
+        /// x/y viewport ratio - default 1.3333
+        Real mAspect;
+
+        /// The 6 main clipping planes
+        mutable Plane mFrustumPlanes[6];
+
+        /// Stored versions of parent orientation / position
+        mutable Quaternion mLastParentOrientation;
+        mutable Vector3 mLastParentPosition;
+
+        /// Pre-calced projection matrix
+        mutable Matrix4 mProjMatrix;
+        /// Pre-calced standard projection matrix
+        mutable Matrix4 mStandardProjMatrix;
+        /// Pre-calced view matrix
+        mutable Matrix4 mViewMatrix;
+        /// Something's changed in the frustrum shape?
+        mutable bool mRecalcFrustum;
+        /// Something re the view pos has changed
+        mutable bool mRecalcView;
+
+
+        /** Temp coefficient values calculated from a frustum change,
+            used when establishing the frustum planes when the view changes
+        */
+        mutable Real mCoeffL[2], mCoeffR[2], mCoeffB[2], mCoeffT[2];
+
+
+
+		
+        // Internal functions for calcs
+        virtual void updateFrustum(void) const;
+        virtual void updateView(void) const;
+        virtual bool isViewOutOfDate(void) const;
+        virtual bool isFrustumOutOfDate(void) const;
+        /// Signal to update frustum information.
+        virtual void invalidateFrustum(void) const;
+        /// Signal to update view information.
+        virtual void invalidateView(void) const;
+
+        /// Shared class-level name for Movable type
+        static String msMovableType;
+
+        mutable AxisAlignedBox mBoundingBox;
+        mutable VertexData mVertexData;
+
+        MaterialPtr mMaterial;
+        mutable Vector3 mWorldSpaceCorners[8];
+
+        /// Is this frustum to act as a reflection of itself?
+        bool mReflect;
+		/// Derived reflection matrix
+        mutable Matrix4 mReflectMatrix;
+        /// Fixed reflection plane
+		mutable Plane mReflectPlane;
+		/// Pointer to a reflection plane (automatically updated)
+		const MovablePlane* mLinkedReflectPlane;
+		/// Record of the last world-space reflection plane info used
+		mutable Plane mLastLinkedReflectionPlane;
+		
+        /// Is this frustum using an oblique depth projection?
+		bool mObliqueDepthProjection;
+		/// Fixed oblique projection plane
+		mutable Plane mObliqueProjPlane;
+		/// Pointer to oblique projection plane (automatically updated)
+		const MovablePlane* mLinkedObliqueProjPlane;
+		/// Record of the last world-space oblique depth projection plane info used
+		mutable Plane mLastLinkedObliqueProjPlane;
+
+		
+		/** Get the derived position of this frustum. */
+        virtual const Vector3& getPositionForViewUpdate(void) const;
+        /** Get the derived orientation of this frustum. */
+        virtual const Quaternion& getOrientationForViewUpdate(void) const;
+
+
+    public:
+
+        Frustum();
+        virtual ~Frustum();
+        /** Sets the Y-dimension Field Of View (FOV) of the frustum.
+            @remarks
+                Field Of View (FOV) is the angle made between the frustum's position, and the edges
+                of the 'screen' onto which the scene is projected. High values (90+ degrees) result in a wide-angle,
+                fish-eye kind of view, low values (30- degrees) in a stretched, telescopic kind of view. Typical values
+                are between 45 and 60 degrees.
+            @par
+                This value represents the VERTICAL field-of-view. The horizontal field of view is calculated from
+                this depending on the dimensions of the viewport (they will only be the same if the viewport is square).
+            @note
+                Setting the FOV overrides the value supplied for frustum::setNearClipPlane.
+         */
+        virtual void setFOVy(const Radian& fovy);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        inline void setFOVy(Real fovy) {
+            setFOVy ( Angle(fovy) );
+        }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Retrieves the frustums Y-dimension Field Of View (FOV).
+        */
+        virtual const Radian& getFOVy(void) const;
+
+        /** Sets the position of the near clipping plane.
+            @remarks
+                The position of the near clipping plane is the distance from the frustums position to the screen
+                on which the world is projected. The near plane distance, combined with the field-of-view and the
+                aspect ratio, determines the size of the viewport through which the world is viewed (in world
+                co-ordinates). Note that this world viewport is different to a screen viewport, which has it's
+                dimensions expressed in pixels. The frustums viewport should have the same aspect ratio as the
+                screen viewport it renders into to avoid distortion.
+            @param
+                near The distance to the near clipping plane from the frustum in world coordinates.
+         */
+        virtual void setNearClipDistance(Real nearDist);
+
+        /** Sets the position of the near clipping plane.
+        */
+        virtual Real getNearClipDistance(void) const;
+
+        /** Sets the distance to the far clipping plane.
+            @remarks
+                The view frustrum is a pyramid created from the frustum position and the edges of the viewport.
+                This method sets the distance for the far end of that pyramid. 
+                Different applications need different values: e.g. a flight sim
+                needs a much further far clipping plane than a first-person 
+                shooter. An important point here is that the larger the ratio 
+                between near and far clipping planes, the lower the accuracy of
+                the Z-buffer used to depth-cue pixels. This is because the
+                Z-range is limited to the size of the Z buffer (16 or 32-bit) 
+                and the max values must be spread over the gap between near and
+                far clip planes. As it happens, you can affect the accuracy far 
+                more by altering the near distance rather than the far distance, 
+                but keep this in mind.
+            @param
+                far The distance to the far clipping plane from the frustum in 
+                world coordinates.If you specify 0, this means an infinite view
+                distance which is useful especially when projecting shadows; but
+                be careful not to use a near distance too close.
+        */
+        virtual void setFarClipDistance(Real farDist);
+
+        /** Retrieves the distance from the frustum to the far clipping plane.
+        */
+        virtual Real getFarClipDistance(void) const;
+
+        /** Sets the aspect ratio for the frustum viewport.
+            @remarks
+                The ratio between the x and y dimensions of the rectangular area visible through the frustum
+                is known as aspect ratio: aspect = width / height .
+            @par
+                The default for most fullscreen windows is 1.3333 - this is also assumed by Ogre unless you
+                use this method to state otherwise.
+        */
+        virtual void setAspectRatio(Real ratio);
+
+        /** Retreives the current aspect ratio.
+        */
+        virtual Real getAspectRatio(void) const;
+
+        /** Gets the projection matrix for this frustum. Mainly for use by OGRE internally.
+        @remarks
+            This method retrieves the rendering-API dependent version of the projection
+            matrix. If you want a 'typical' projection matrix then use 
+            getStandardProjectionMatrix.
+
+        */
+        virtual const Matrix4& getProjectionMatrix(void) const;
+        /** Gets the 'standard' projection matrix for this frustum, ie the 
+        projection matrix which conforms to standard right-handed rules.
+        @remarks
+            This differs from the rendering-API dependent getProjectionMatrix
+            in that it always returns a right-handed projection matrix result 
+            no matter what rendering API is being used - this is required for
+            vertex and fragment programs for example. However, the resulting depth
+            range may still vary between render systems since D3D uses [0,1] and 
+            GL uses [-1,1], and the range must be kept the same between programmable
+            and fixed-function pipelines.
+        */
+        virtual const Matrix4& getStandardProjectionMatrix(void) const;
+
+        /** Gets the view matrix for this frustum. Mainly for use by OGRE internally.
+        */
+        virtual const Matrix4& getViewMatrix(void) const;
+
+        /** Retrieves a specified plane of the frustum.
+            @remarks
+                Gets a reference to one of the planes which make up the frustum frustum, e.g. for clipping purposes.
+        */
+        virtual const Plane& getFrustumPlane( unsigned short plane ) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding box to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding sphere to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the sphere was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Sphere& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given vertex is visible in the Frustum.
+            @param
+                vert Vertex to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
+
+
+        /** Overridden from MovableObject */
+        const AxisAlignedBox& getBoundingBox(void) const;
+
+        /** Overridden from MovableObject */
+		Real getBoundingRadius(void) const;
+
+		/** Overridden from MovableObject */
+        void _updateRenderQueue(RenderQueue* queue);
+
+        /** Overridden from MovableObject */
+        const String& getMovableType(void) const;
+
+        /** Overridden from MovableObject */
+        const String& getName(void) const;
+
+        /** Overridden from MovableObject */
+        void _notifyCurrentCamera(Camera* cam);
+
+        /** Overridden from Renderable */
+        const MaterialPtr& getMaterial(void) const;
+
+        /** Overridden from Renderable */
+        void getRenderOperation(RenderOperation& op);
+
+        /** Overridden from Renderable */
+        void getWorldTransforms(Matrix4* xform) const;
+
+        /** Overridden from Renderable */
+        const Quaternion& getWorldOrientation(void) const;
+
+        /** Overridden from Renderable */
+        const Vector3& getWorldPosition(void) const;
+
+        /** Overridden from Renderable */
+        Real getSquaredViewDepth(const Camera* cam) const;
+
+        /** Overridden from Renderable */
+        const LightList& getLights(void) const;
+
+        /** Gets the world space corners of the frustum.
+        @remarks
+            The corners are ordered as follows: top-right near, 
+            top-left near, bottom-left near, bottom-right near, 
+            top-right far, top-left far, bottom-left far, bottom-right far.
+        */
+        virtual const Vector3* getWorldSpaceCorners(void) const;
+
+        /** Sets the type of projection to use (orthographic or perspective). Default is perspective.
+        */
+        virtual void setProjectionType(ProjectionType pt);
+
+        /** Retrieves info on the type of projection used (orthographic or perspective).
+        */
+        virtual ProjectionType getProjectionType(void) const;
+
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const Plane& p);
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified. Note that this version of the method links to a plane
+		so that changes to it are picked up automatically. It is important that
+		this plane continues to exist whilst this object does; do not destroy
+		the plane before the frustum.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const MovablePlane* p);
+
+        /** Disables reflection modification previously turned on with enableReflection */
+        virtual void disableReflection(void);
+
+        /// Returns whether this frustum is being reflected
+        virtual bool isReflected(void) const { return mReflect; }
+        /// Returns the reflection matrix of the frustum if appropriate
+        virtual const Matrix4& getReflectionMatrix(void) const { return mReflectMatrix; }
+        /// Returns the reflection plane of the frustum if appropriate
+        virtual const Plane& getReflectionPlane(void) const { return mReflectPlane; }
+
+        /** Project a sphere onto the near plane and get the bounding rectangle. 
+        @param sphere The world-space sphere to project
+        @param radius Radius of the sphere
+        @param left, top, right, bottom Pointers to destination values, these
+            will be completed with the normalised device coordinates (in the 
+            range {-1,1})
+        @returns true if the sphere was projected to a subset of the near plane,
+            false if the entire near plane was contained
+        */
+        virtual bool projectSphere(const Sphere& sphere, 
+            Real* left, Real* top, Real* right, Real* bottom) const;
+
+
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to 
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@par 
+			This version of the method links to a plane, rather than requiring
+			a by-value plane definition, and therefore you can 
+			make changes to the plane (e.g. by moving / rotating the node it is
+			attached to) and they will automatically affect this object.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const MovablePlane* plane);
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to  
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const Plane& plane);
+		/** Disables any custom near clip plane. */
+		virtual void disableCustomNearClipPlane(void);
+		
+
+        /// Small constant used to reduce far plane projection to avoid inaccuracies
+        static const Real INFINITE_FAR_PLANE_ADJUST;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		//added by matt: 050405
+		/** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding box to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+			@param
+				intersects returns the information if the box intersects the near plane.
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy = 0) const;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    };
+
+
+}
+
+#endif 
Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 61)
@@ -0,0 +1,1882 @@
+/*-------------------------------------------------------------------------
+This source file is a part of OGRE
+(Object-oriented Graphics Rendering Engine)
+
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This library is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License (LGPL) as 
+published by the Free Software Foundation; either version 2.1 of the 
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License 
+along with this library; if not, write to the Free Software Foundation, 
+Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
+http://www.gnu.org/copyleft/lesser.txt
+-------------------------------------------------------------------------*/
+#ifndef __SceneManager_H__
+#define __SceneManager_H__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+#include "OgreSceneNode.h"
+#include "OgrePlane.h"
+#include "OgreQuaternion.h"
+#include "OgreColourValue.h"
+#include "OgreCommon.h"
+#include "OgreRenderQueue.h"
+#include "OgreAnimationState.h"
+#include "OgreSceneQuery.h"
+#include "OgreAutoParamDataSource.h"
+#include "OgreAnimationState.h"
+#include "OgreRenderQueue.h"
+#include "OgreRenderQueueSortingGrouping.h"
+#include "OgreRectangle2D.h"
+
+namespace Ogre {
+
+    /** Structure for holding a position & orientation pair. */
+    struct ViewPoint
+    {
+        Vector3 position;
+        Quaternion orientation;
+    };
+
+	// Forward declarations
+	class DefaultIntersectionSceneQuery;
+	class DefaultRaySceneQuery;
+	class DefaultSphereSceneQuery;
+	class DefaultAxisAlignedBoxSceneQuery;
+
+    /** Manages the rendering of a 'scene' i.e. a collection of primitives.
+        @remarks
+            This class defines the basic behaviour of the 'Scene Manager' family. These classes will
+            organise the objects in the scene and send them to the rendering system, a subclass of
+            RenderSystem. This basic superclass does no sorting, culling or organising of any sort.
+        @par
+            Subclasses may use various techniques to organise the scene depending on how they are
+            designed (e.g. BSPs, octrees etc). As with other classes, methods preceded with '_' are
+            designed to be called by other classes in the Ogre system, not by user applications,
+            although this is not forbidden.
+        @author
+            Steve Streeting
+        @version
+            1.0
+     */
+    class _OgreExport SceneManager
+    {
+		friend class DefaultIntersectionSceneQuery; 
+	    friend class DefaultRaySceneQuery;
+	    friend class DefaultSphereSceneQuery;
+	    friend class DefaultAxisAlignedBoxSceneQuery;
+        friend class DefaultPlaneBoundedVolumeListSceneQuery;
+    public:
+        /// Query mask which will be used for world geometry @see SceneQuery
+        static unsigned long WORLD_GEOMETRY_QUERY_MASK;
+        /** Comparator for material map, for sorting materials into render order (e.g. transparent last).
+        */
+        struct materialLess
+        {
+            _OgreExport bool operator()(const Material* x, const Material* y) const;
+        };
+        /// Comparator for sorting lights relative to a point
+        struct lightLess
+        {
+            _OgreExport bool operator()(const Light* a, const Light* b) const;
+        };
+
+        /// Describes the stage of rendering when performing complex illumination
+        enum IlluminationRenderStage
+        {
+            /// No special illumination stage
+            IRS_NONE,
+            /// Ambient stage, when background light is added
+            IRS_AMBIENT,
+            /// Diffuse / specular stage, when individual light contributions are added
+            IRS_PER_LIGHT,
+            /// Decal stage, when texture detail is added to the lit base
+            IRS_DECAL,
+            /// Render to texture stage, used for texture based shadows
+            IRS_RENDER_TO_TEXTURE,
+            /// Modulative render from shadow texture stage
+            IRS_RENDER_MODULATIVE_PASS
+        };
+
+		/** Enumeration of the possible modes allowed for processing the special case
+		render queue list.
+		@see SceneManager::setSpecialCaseRenderQueueMode
+		*/
+		enum SpecialCaseRenderQueueMode
+		{
+			/// Render only the queues in the special case list
+			SCRQM_INCLUDE,
+			/// Render all except the queues in the special case list
+			SCRQM_EXCLUDE
+		};
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		/** added by matt: Render content of current scene node.
+			@param node scene node to be rendered
+			@param cam current camera
+		*/
+		void _renderSceneNode( Camera *cam, SceneNode *node );
+		
+		/** deletes all queues which we were currently processing
+			@remark clears renderqueue after rendering scene node
+		*/
+		void _deleteRenderedQueueGroups();
+	
+		
+		void myrenderSingleObject(Renderable* rend, Pass* pass, bool doLightIteration, 
+            const LightList* manualLightList = 0)
+		{
+			setPass(pass);
+			renderSingleObject(rend, pass, doLightIteration, manualLightList);}
+
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		/** Internal method used by _renderVisibleObjects to deal with renderables
+            which override the camera's own view / projection materices. made
+			public by matt */
+        void useRenderableViewProjMode(Renderable* pRend);
+		
+    protected:
+
+        /// Queue of objects for rendering
+        RenderQueue* mRenderQueue;
+
+        /// Current ambient light, cached for RenderSystem
+        ColourValue mAmbientLight;
+
+        /// The rendering system to send the scene to
+        RenderSystem *mDestRenderSystem;
+
+        typedef std::map<String, Camera* > CameraList;
+
+        /** Central list of cameras - for easy memory management and lookup.
+        */
+        CameraList mCameras;
+
+        typedef std::map<String, Light* > SceneLightList;
+
+        /** Central list of lights - for easy memory management and lookup.
+        */
+        SceneLightList mLights;
+
+
+        typedef std::map<String, Entity* > EntityList;
+
+        /** Central list of entities - for easy memory management and lookup.
+        */
+        EntityList mEntities;
+
+        typedef std::map<String, BillboardSet* > BillboardSetList;
+
+        /** Central list of billboard sets - for easy memory management and lookup.
+        */
+        BillboardSetList mBillboardSets;
+
+		typedef std::map<String, StaticGeometry* > StaticGeometryList;
+		StaticGeometryList mStaticGeometryList;
+
+        typedef std::map<String, SceneNode*> SceneNodeList;
+
+        /** Central list of SceneNodes - for easy memory management.
+            @note
+                Note that this list is used only for memory management; the structure of the scene
+                is held using the hierarchy of SceneNodes starting with the root node. However you
+                can look up nodes this way.
+        */
+        SceneNodeList mSceneNodes;
+
+        /// Camera in progress
+        Camera* mCameraInProgress;
+        /// Current Viewport
+        Viewport* mCurrentViewport;
+
+        /// Root scene node
+        SceneNode* mSceneRoot;
+
+        /// Autotracking scene nodes
+        typedef std::set<SceneNode*> AutoTrackingSceneNodes;
+        AutoTrackingSceneNodes mAutoTrackingSceneNodes;
+
+        // Sky params
+        // Sky plane
+        Entity* mSkyPlaneEntity;
+        Entity* mSkyDomeEntity[5];
+        Entity* mSkyBoxEntity[6];
+
+        SceneNode* mSkyPlaneNode;
+        SceneNode* mSkyDomeNode;
+        SceneNode* mSkyBoxNode;
+
+        bool mSkyPlaneEnabled;
+        bool mSkyPlaneDrawFirst;
+        Plane mSkyPlane;
+        // Sky box
+        bool mSkyBoxEnabled;
+        bool mSkyBoxDrawFirst;
+        Quaternion mSkyBoxOrientation;
+        // Sky dome
+        bool mSkyDomeEnabled;
+        bool mSkyDomeDrawFirst;
+        Quaternion mSkyDomeOrientation;
+        // Fog
+        FogMode mFogMode;
+        ColourValue mFogColour;
+        Real mFogStart;
+        Real mFogEnd;
+        Real mFogDensity;
+
+		typedef std::set<RenderQueueGroupID> SpecialCaseRenderQueueList;
+		SpecialCaseRenderQueueList mSpecialCaseQueueList;
+		SpecialCaseRenderQueueMode mSpecialCaseQueueMode;
+		RenderQueueGroupID mWorldGeometryRenderQueue;
+
+        /** Internal method for initialising the render queue.
+        @remarks
+            Subclasses can use this to install their own RenderQueue implementation.
+        */
+        virtual void initRenderQueue(void);
+        /** Retrieves the internal render queue. */
+        virtual RenderQueue* getRenderQueue(void);
+        /** Internal method for setting up the renderstate for a rendering pass.
+            @param
+                pass The Pass details to set.
+            @returns
+                A Pass object that was used instead of the one passed in, can
+                happen when rendering shadow passes
+        */
+        virtual Pass* setPass(Pass* pass);
+        /// A pass designed to let us render shadow colour on white for texture shadows
+        Pass* mShadowCasterPlainBlackPass;
+        /// A pass designed to let us render shadow receivers for texture shadows
+        Pass* mShadowReceiverPass;
+        /** Internal method for turning a regular pass into a shadow caster pass.
+        @remarks
+            This is only used for texture shadows, basically we're trying to
+            ensure that objects are rendered solid black.
+            This method will usually return the standard solid black pass for
+            all fixed function passes, but will merge in a vertex program
+            and fudge the AutpoParamDataSource to set black lighting for
+            passes with vertex programs. 
+        */
+        Pass* deriveShadowCasterPass(Pass* pass);
+        /** Internal method for turning a regular pass into a shadow receiver pass.
+        @remarks
+        This is only used for texture shadows, basically we're trying to
+        ensure that objects are rendered with a projective texture.
+        This method will usually return a standard single-texture pass for
+        all fixed function passes, but will merge in a vertex program
+        for passes with vertex programs. 
+        */
+        Pass* deriveShadowReceiverPass(Pass* pass);
+    
+        /** Internal method to validate whether a Pass should be allowed to render.
+        @remarks
+            Called just before a pass is about to be used for rendering a group to
+            allow the SceneManager to omit it if required. A return value of false
+            skips this pass. 
+        */
+        bool validatePassForRendering(Pass* pass);
+
+        /** Internal method to validate whether a Renderable should be allowed to render.
+        @remarks
+        Called just before a pass is about to be used for rendering a Renderable to
+        allow the SceneManager to omit it if required. A return value of false
+        skips it. 
+        */
+        bool validateRenderableForRendering(Pass* pass, Renderable* rend);
+
+        enum BoxPlane
+        {
+            BP_FRONT = 0,
+            BP_BACK = 1,
+            BP_LEFT = 2,
+            BP_RIGHT = 3,
+            BP_UP = 4,
+            BP_DOWN = 5
+        };
+
+        /* Internal utility method for creating the planes of a skybox.
+        */
+        MeshPtr createSkyboxPlane(
+            BoxPlane bp,
+            Real distance,
+            const Quaternion& orientation,
+            const String& groupName);
+
+        /* Internal utility method for creating the planes of a skydome.
+        */
+        MeshPtr createSkydomePlane(
+            BoxPlane bp,
+            Real curvature, Real tiling, Real distance,
+            const Quaternion& orientation,
+            int xsegments, int ysegments, int ySegmentsToKeep, 
+            const String& groupName);
+
+        // Flag indicating whether SceneNodes will be rendered as a set of 3 axes
+        bool mDisplayNodes;
+
+        /// Storage of animations, lookup by name
+        typedef std::map<String, Animation*> AnimationList;
+        AnimationList mAnimationsList;
+        AnimationStateSet mAnimationStates;
+
+        /// Controller flag for determining if we need to set view/proj matrices
+        bool mCamChanged;
+
+        typedef std::vector<RenderQueueListener*> RenderQueueListenerList;
+        RenderQueueListenerList mRenderQueueListeners;
+
+        /// Internal method for firing the queue start event, returns true if queue is to be skipped
+        bool fireRenderQueueStarted(RenderQueueGroupID id);
+        /// Internal method for firing the queue end event, returns true if queue is to be repeated
+        bool fireRenderQueueEnded(RenderQueueGroupID id);
+
+        /** Internal method for setting the destination viewport for the next render. */
+        virtual void setViewport(Viewport *vp);
+
+		/** Flag that indicates if all of the scene node's bounding boxes should be shown as a wireframe. */
+		bool mShowBoundingBoxes;       
+
+        /** Internal utility method for rendering a single object. 
+        @remarks
+            Assumes that the pass has already been set up.
+        @param rend The renderable to issue to the pipeline
+        @param pass The pass which is being used
+        @param doLightIteration If true, this method will issue the renderable to
+            the pipeline possibly multiple times, if the pass indicates it should be
+            done once per light
+        @param manualLightList Only applicable if doLightIteration is false, this
+            method allows you to pass in a previously determined set of lights
+            which will be used for a single render of this object.
+        */
+        virtual void renderSingleObject(Renderable* rend, Pass* pass, bool doLightIteration, 
+            const LightList* manualLightList = 0);
+
+        /// Utility class for calculating automatic parameters for gpu programs
+        AutoParamDataSource mAutoParamDataSource;
+
+        ShadowTechnique mShadowTechnique;
+        bool mDebugShadows;
+        ColourValue mShadowColour;
+        Pass* mShadowDebugPass;
+        Pass* mShadowStencilPass;
+        Pass* mShadowModulativePass;
+		bool mShadowMaterialInitDone;
+        LightList mLightsAffectingFrustum;
+        HardwareIndexBufferSharedPtr mShadowIndexBuffer;
+		size_t mShadowIndexBufferSize;
+        Rectangle2D* mFullScreenQuad;
+        Real mShadowDirLightExtrudeDist;
+        IlluminationRenderStage mIlluminationStage;
+        unsigned short mShadowTextureSize;
+        unsigned short mShadowTextureCount;
+		PixelFormat mShadowTextureFormat;
+        typedef std::vector<RenderTexture*> ShadowTextureList;
+        ShadowTextureList mShadowTextures;
+        RenderTexture* mCurrentShadowTexture;
+		bool mShadowUseInfiniteFarPlane;
+        /** Internal method for locating a list of lights which could be affecting the frustum. 
+        @remarks
+            Custom scene managers are encouraged to override this method to make use of their
+            scene partitioning scheme to more efficiently locate lights, and to eliminate lights
+            which may be occluded by word geometry.
+        */
+        virtual void findLightsAffectingFrustum(const Camera* camera);
+        /// Internal method for setting up materials for shadows
+        virtual void initShadowVolumeMaterials(void);
+        /// Internal method for creating shadow textures (texture-based shadows)
+        virtual void createShadowTextures(unsigned short size, unsigned short count, 
+			PixelFormat fmt);
+        /// Internal method for preparing shadow textures ready for use in a regular render
+        virtual void prepareShadowTextures(Camera* cam, Viewport* vp);
+
+        /** Internal method for rendering all the objects for a given light into the 
+            stencil buffer.
+        @param light The light source
+        @param cam The camera being viewed from
+        */
+        virtual void renderShadowVolumesToStencil(const Light* light, const Camera* cam);
+        /** Internal utility method for setting stencil state for rendering shadow volumes. 
+        @param secondpass Is this the second pass?
+        @param zfail Should we be using the zfail method?
+        @param twosided Should we use a 2-sided stencil?
+        */
+        virtual void setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided);
+        /** Render a set of shadow renderables. */
+        void renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
+            Pass* pass, const LightList *manualLightList, unsigned long flags,
+            bool secondpass, bool zfail, bool twosided);
+        typedef std::vector<ShadowCaster*> ShadowCasterList;
+        ShadowCasterList mShadowCasterList;
+        SphereSceneQuery* mShadowCasterSphereQuery;
+        AxisAlignedBoxSceneQuery* mShadowCasterAABBQuery;
+        Real mShadowFarDist;
+        Real mShadowFarDistSquared;
+        Real mShadowTextureOffset; // proportion of texture offset in view direction e.g. 0.4
+        Real mShadowTextureFadeStart; // as a proportion e.g. 0.6
+        Real mShadowTextureFadeEnd; // as a proportion e.g. 0.9
+		bool mShadowTextureSelfShadow;
+		Pass* mShadowTextureCustomCasterPass;
+		Pass* mShadowTextureCustomReceiverPass;
+		String mShadowTextureCustomCasterVertexProgram;
+		String mShadowTextureCustomReceiverVertexProgram;
+		GpuProgramParametersSharedPtr mShadowTextureCustomCasterVPParams;
+		GpuProgramParametersSharedPtr mShadowTextureCustomReceiverVPParams;
+		bool mShadowTextureCasterVPDirty;
+		bool mShadowTextureReceiverVPDirty;
+
+
+        GpuProgramParametersSharedPtr mInfiniteExtrusionParams;
+        GpuProgramParametersSharedPtr mFiniteExtrusionParams;
+
+        /// Inner class to use as callback for shadow caster scene query
+        class _OgreExport ShadowCasterSceneQueryListener : public SceneQueryListener
+        {
+        protected:
+			SceneManager* mSceneMgr;
+            ShadowCasterList* mCasterList;
+            bool mIsLightInFrustum;
+            const PlaneBoundedVolumeList* mLightClipVolumeList;
+            const Camera* mCamera;
+            const Light* mLight;
+            Real mFarDistSquared;
+        public:
+            ShadowCasterSceneQueryListener(SceneManager* sm) : mSceneMgr(sm),
+				mCasterList(0), mIsLightInFrustum(false), mLightClipVolumeList(0), 
+                mCamera(0) {}
+            // Prepare the listener for use with a set of parameters  
+            void prepare(bool lightInFrustum, 
+                const PlaneBoundedVolumeList* lightClipVolumes, 
+                const Light* light, const Camera* cam, ShadowCasterList* casterList, 
+                Real farDistSquared) 
+            {
+                mCasterList = casterList;
+                mIsLightInFrustum = lightInFrustum;
+                mLightClipVolumeList = lightClipVolumes;
+                mCamera = cam;
+                mLight = light;
+                mFarDistSquared = farDistSquared;
+            }
+            bool queryResult(MovableObject* object);
+            bool queryResult(SceneQuery::WorldFragment* fragment);
+        };
+
+        ShadowCasterSceneQueryListener* mShadowCasterQueryListener;
+
+        /** Internal method for locating a list of shadow casters which 
+            could be affecting the frustum for a given light. 
+        @remarks
+            Custom scene managers are encouraged to override this method to add optimisations, 
+            and to add their own custom shadow casters (perhaps for world geometry)
+        */
+        virtual const ShadowCasterList& findShadowCastersForLight(const Light* light, 
+            const Camera* camera);
+		/** Render the objects in a given queue group 
+		*/
+		virtual void renderQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group in the ordinary way */
+        virtual void renderBasicQueueGroupObjects(RenderQueueGroup* pGroup);
+		/** Render a group with the added complexity of additive stencil shadows. */
+		virtual void renderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup* group);
+		/** Render a group with the added complexity of additive stencil shadows. */
+		virtual void renderModulativeStencilShadowedQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group rendering only shadow casters. */
+        virtual void renderTextureShadowCasterQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group rendering only shadow receivers. */
+        virtual void renderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group with the added complexity of additive stencil shadows. */
+        virtual void renderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup* group);
+		/** Render a set of objects, see renderSingleObject for param definitions */
+		virtual void renderObjects(const RenderPriorityGroup::SolidRenderablePassMap& objs, 
+            bool doLightIteration, const LightList* manualLightList = 0);
+        /** Render a set of objects, see renderSingleObject for param definitions */
+		virtual void renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs, 
+            bool doLightIteration, const LightList* manualLightList = 0);
+		/** Render those objects in the transparent pass list which have shadow casting forced on
+		@remarks
+			This function is intended to be used to render the shadows of transparent objects which have
+			transparency_casts_shadows set to 'on' in their material
+		*/
+		virtual void renderTransparentShadowCasterObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs, 
+			bool doLightIteration, const LightList* manualLightList = 0);
+
+    public:
+        /** Default constructor.
+        */
+        SceneManager();
+
+        /** Default destructor.
+        */
+        virtual ~SceneManager();
+
+        /** Creates a camera to be managed by this scene manager.
+            @remarks
+                This camera must be added to the scene at a later time using
+                the attachObject method of the SceneNode class.
+            @param
+                name Name to give the new camera.
+        */
+        virtual Camera* createCamera(const String& name);
+
+        /** Retrieves a pointer to the named camera.
+        */
+        virtual Camera* getCamera(const String& name);
+
+        /** Removes a camera from the scene.
+            @remarks
+                This method removes a previously added camera from the scene.
+                The camera is deleted so the caller must ensure no references
+                to it's previous instance (e.g. in a SceneNode) are used.
+            @param
+                cam Pointer to the camera to remove
+        */
+        virtual void removeCamera(Camera *cam);
+
+        /** Removes a camera from the scene.
+            @remarks
+                This method removes an camera from the scene based on the
+                camera's name rather than a pointer.
+        */
+        virtual void removeCamera(const String& name);
+
+        /** Removes (and destroys) all cameras from the scene.
+        */
+        virtual void removeAllCameras(void);
+
+        /** Creates a light for use in the scene.
+            @remarks
+                Lights can either be in a fixed position and independent of the
+                scene graph, or they can be attached to SceneNodes so they derive
+                their position from the parent node. Either way, they are created
+                using this method so that the SceneManager manages their
+                existence.
+            @param
+                name The name of the new light, to identify it later.
+        */
+        virtual Light* createLight(const String& name);
+
+        /** Returns a pointer to the named Light which has previously been added to the scene.
+        */
+        virtual Light* getLight(const String& name);
+
+        /** Removes the named light from the scene and destroys it.
+            @remarks
+                Any pointers held to this light after calling this method will be invalid.
+        */
+        virtual void removeLight(const String& name);
+
+        /** Removes the light from the scene and destroys it based on a pointer.
+            @remarks
+                Any pointers held to this light after calling this method will be invalid.
+        */
+        virtual void removeLight(Light* light);
+        /** Removes and destroys all lights in the scene.
+        */
+        virtual void removeAllLights(void);
+
+        /** Populate a light list with an ordered set of the lights which are closest
+        to the position specified.
+        @remarks
+            Note that since directional lights have no position, they are always considered
+            closer than any point lights and as such will always take precedence. 
+        @par
+            Subclasses of the default SceneManager may wish to take into account other issues
+            such as possible visibility of the light if that information is included in their
+            data structures. This basic scenemanager simply orders by distance, eliminating 
+            those lights which are out of range.
+        @par
+            The number of items in the list max exceed the maximum number of lights supported
+            by the renderer, but the extraneous ones will never be used. In fact the limit will
+            be imposed by Pass::getMaxSimultaneousLights.
+        @param position The position at which to evaluate the list of lights
+        @param radius The bounding radius to test
+        @param destList List to be populated with ordered set of lights; will be cleared by 
+            this method before population.
+        */
+        virtual void _populateLightList(const Vector3& position, Real radius, LightList& destList);
+
+
+        /** Creates an instance of a SceneNode.
+            @remarks
+                Note that this does not add the SceneNode to the scene hierarchy.
+                This method is for convenience, since it allows an instance to
+                be created for which the SceneManager is responsible for
+                allocating and releasing memory, which is convenient in complex
+                scenes.
+            @par
+                To include the returned SceneNode in the scene, use the addChild
+                method of the SceneNode which is to be it's parent.
+            @par
+                Note that this method takes no parameters, and the node created is unnamed (it is
+                actually given a generated name, which you can retrieve if you want).
+                If you wish to create a node with a specific name, call the alternative method
+                which takes a name parameter.
+        */
+        virtual SceneNode* createSceneNode(void);
+
+        /** Creates an instance of a SceneNode with a given name.
+            @remarks
+                Note that this does not add the SceneNode to the scene hierarchy.
+                This method is for convenience, since it allows an instance to
+                be created for which the SceneManager is responsible for
+                allocating and releasing memory, which is convenient in complex
+                scenes.
+            @par
+                To include the returned SceneNode in the scene, use the addChild
+                method of the SceneNode which is to be it's parent.
+            @par
+                Note that this method takes a name parameter, which makes the node easier to
+                retrieve directly again later.
+        */
+        virtual SceneNode* createSceneNode(const String& name);
+
+        /** Destroys a SceneNode with a given name.
+        @remarks
+            This allows you to physically delete an individual SceneNode if you want to.
+            Note that this is not normally recommended, it's better to allow SceneManager
+            to delete the nodes when the scene is cleared.
+        */
+        virtual void destroySceneNode(const String& name);
+
+        /** Gets the SceneNode at the root of the scene hierarchy.
+            @remarks
+                The entire scene is held as a hierarchy of nodes, which
+                allows things like relative transforms, general changes in
+                rendering state etc (See the SceneNode class for more info).
+                In this basic SceneManager class, the application using
+                Ogre is free to structure this hierarchy however it likes,
+                since it has no real significance apart from making transforms
+                relative to each node (more specialised subclasses will
+                provide utility methods for building specific node structures
+                e.g. loading a BSP tree).
+            @par
+                However, in all cases there is only ever one root node of
+                the hierarchy, and this method returns a pointer to it.
+        */
+        virtual SceneNode* getRootSceneNode(void) const;
+
+        /** Retrieves a named SceneNode from the scene graph.
+        @remarks
+            If you chose to name a SceneNode as you created it, or if you
+            happened to make a note of the generated name, you can look it
+            up wherever it is in the scene graph using this method.
+        */
+        virtual SceneNode* getSceneNode(const String& name) const;
+
+        /** Create an Entity (instance of a discrete mesh).
+            @param
+                entityName The name to be given to the entity (must be unique).
+            @param
+                meshName The name of the Mesh it is to be based on (e.g. 'knot.oof'). The
+                mesh will be loaded if it is not already.
+        */
+        virtual Entity* createEntity(const String& entityName, const String& meshName);
+
+        /** Prefab shapes available without loading a model.
+            @note
+                Minimal implementation at present.
+            @todo
+                Add more prefabs (teapots, teapots!!!)
+        */
+        enum PrefabType {
+            PT_PLANE
+        };
+
+        /** Create an Entity (instance of a discrete mesh) from a range of prefab shapes.
+            @param
+                entityName The name to be given to the entity (must be unique).
+            @param
+                ptype The prefab type.
+        */
+        virtual Entity* createEntity(const String& entityName, PrefabType ptype);
+        /** Retrieves a pointer to the named Entity. */
+        virtual Entity* getEntity(const String& name);
+
+        /** Removes & destroys an Entity from the SceneManager.
+            @warning
+                Must only be done if the Entity is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene if you are unsure use clearScene.
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeEntity(Entity* ent);
+
+        /** Removes & destroys an Entity from the SceneManager by name.
+            @warning
+                Must only be done if the Entity is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene if you are unsure use clearScene.
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeEntity(const String& name);
+
+        /** Removes & destroys all Entities.
+            @warning
+                Again, use caution since no Entity must be referred to
+                elsewhere e.g. attached to a SceneNode otherwise a crash
+                is likely. Use clearScene if you are unsure (it clears SceneNode
+                entries too.)
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeAllEntities(void);
+
+        /** Empties the entire scene, inluding all SceneNodes, Entities, Lights, 
+            BillboardSets etc. Cameras are not deleted at this stage since
+            they are still referenced by viewports, which are not destroyed during
+            this process.
+        */
+        virtual void clearScene(void);
+
+        /** Sets the ambient light level to be used for the scene.
+            @remarks
+                This sets the colour and intensity of the ambient light in the scene, i.e. the
+                light which is 'sourceless' and illuminates all objects equally.
+                The colour of an object is affected by a combination of the light in the scene,
+                and the amount of light that object reflects (in this case based on the Material::ambient
+                property).
+            @remarks
+                By default the ambient light in the scene is ColourValue::Black, i.e. no ambient light. This
+                means that any objects rendered with a Material which has lighting enabled (see Material::setLightingEnabled)
+                will not be visible unless you have some dynamic lights in your scene.
+        */
+        void setAmbientLight(const ColourValue& colour);
+
+        /** Returns the ambient light level to be used for the scene.
+        */
+        const ColourValue& getAmbientLight(void) const;
+
+        /** Sets the source of the 'world' geometry, i.e. the large, mainly static geometry
+            making up the world e.g. rooms, landscape etc.
+            @remarks
+                Depending on the type of SceneManager (subclasses will be specialised
+                for particular world geometry types) you have requested via the Root or
+                SceneManagerEnumerator classes, you can pass a filename to this method and it
+                will attempt to load the world-level geometry for use. If you try to load
+                an inappropriate type of world data an exception will be thrown. The default
+                SceneManager cannot handle any sort of world geometry and so will always
+                throw an exception. However subclasses like BspSceneManager can load
+                particular types of world geometry e.g. "q3dm1.bsp".
+            @par
+                World geometry will be loaded via the 'common' resource paths and archives set in the
+                ResourceManager class.
+        */
+        virtual void setWorldGeometry(const String& filename);
+
+        /** Estimate the number of loading stages required to load the named
+            world geometry. 
+        @remarks
+            This method should be overridden by SceneManagers that provide
+            custom world geometry that can take some time to load. They should
+            return from this method a count of the number of stages of progress
+            they can report on whilst loading. During real loading (setWorldGeomtry),
+            they should call ResourceGroupManager::_notifyWorldGeometryProgress exactly
+            that number of times when loading the geometry for real.
+        @note 
+            The default is to return 0, ie to not report progress. 
+        */
+        virtual size_t estimateWorldGeometry(const String& filename) { return 0; }
+
+        /** Asks the SceneManager to provide a suggested viewpoint from which the scene should be viewed.
+            @remarks
+                Typically this method returns the origin unless a) world geometry has been loaded using
+                SceneManager::setWorldGeometry and b) that world geometry has suggested 'start' points.
+                If there is more than one viewpoint which the scene manager can suggest, it will always suggest
+                the first one unless the random parameter is true.
+            @param
+                random If true, and there is more than one possible suggestion, a random one will be used. If false
+                the same one will always be suggested.
+            @return
+                On success, true is returned.
+            @par
+                On failiure, false is returned.
+        */
+        virtual ViewPoint getSuggestedViewpoint(bool random = false);
+
+        /** Method for setting a specific option of the Scene Manager. These options are usually
+            specific for a certain implemntation of the Scene Manager class, and may (and probably
+            will) not exist across different implementations.
+            @param
+                strKey The name of the option to set
+            @param
+                pValue A pointer to the value - the size should be calculated by the scene manager
+                based on the key
+            @return
+                On success, true is returned.
+            @par
+                On failiure, false is returned.
+        */
+        virtual bool setOption( const String& strKey, const void* pValue ) { return false; }
+
+        /** Method for getting the value of an implementation-specific Scene Manager option.
+            @param
+                strKey The name of the option
+            @param
+                pDestValue A pointer to a memory location where the value will
+                be copied. Currently, the memory will be allocated by the
+                scene manager, but this may change
+            @return
+                On success, true is returned and pDestValue points to the value of the given
+                option.
+            @par
+                On failiure, false is returned and pDestValue is set to NULL.
+        */
+        virtual bool getOption( const String& strKey, void* pDestValue ) { return false; }
+
+        /** Method for verifying wether the scene manager has an implementation-specific
+            option.
+            @param
+                strKey The name of the option to check for.
+            @return
+                If the scene manager contains the given option, true is returned.
+            @remarks
+                If it does not, false is returned.
+        */
+        virtual bool hasOption( const String& strKey ) const { return false; }
+        /** Method for getting all possible values for a specific option. When this list is too large
+            (i.e. the option expects, for example, a float), the return value will be true, but the
+            list will contain just one element whose size will be set to 0.
+            Otherwise, the list will be filled with all the possible values the option can
+            accept.
+            @param
+                strKey The name of the option to get the values for.
+            @param
+                refValueList A reference to a list that will be filled with the available values.
+            @return
+                On success (the option exists), true is returned.
+            @par
+                On failure, false is returned.
+        */
+        virtual bool getOptionValues( const String& strKey, StringVector& refValueList ) { return false; }
+
+        /** Method for getting all the implementation-specific options of the scene manager.
+            @param
+                refKeys A reference to a list that will be filled with all the available options.
+            @return
+                On success, true is returned. On failiure, false is returned.
+        */
+        virtual bool getOptionKeys( StringVector& refKeys ) { return false; }
+
+        /** Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class.
+            @remarks
+                This must be done before issuing objects to the rendering pipeline, since derived transformations from
+                parent nodes are not updated until required. This SceneManager is a basic implementation which simply
+                updates all nodes from the root. This ensures the scene is up to date but requires all the nodes
+                to be updated even if they are not visible. Subclasses could trim this such that only potentially visible
+                nodes are updated.
+        */
+        virtual void _updateSceneGraph(Camera* cam);
+
+        /** Internal method which parses the scene to find visible objects to render.
+            @remarks
+                If you're implementing a custom scene manager, this is the most important method to
+                override since it's here you can apply your custom world partitioning scheme. Once you
+                have added the appropriate objects to the render queue, you can let the default
+                SceneManager objects _renderVisibleObjects handle the actual rendering of the objects
+                you pick.
+            @par
+                Any visible objects will be added to a rendering queue, which is indexed by material in order
+                to ensure objects with the same material are rendered together to minimise render state changes.
+        */
+        virtual void _findVisibleObjects(Camera* cam, bool onlyShadowCasters);
+
+        /** Internal method for applying animations to scene nodes.
+        @remarks
+            Uses the internally stored AnimationState objects to apply animation to SceneNodes.
+        */
+        virtual void _applySceneAnimations(void);
+
+        /** Sends visible objects found in _findVisibleObjects to the rendering engine.
+        */
+        virtual void _renderVisibleObjects(void);
+
+        /** Prompts the class to send its contents to the renderer.
+            @remarks
+                This method prompts the scene manager to send the
+                contents of the scene it manages to the rendering
+                pipeline, possibly preceded by some sorting, culling
+                or other scene management tasks. Note that this method is not normally called
+                directly by the user application; it is called automatically
+                by the Ogre rendering loop.
+            @param camera Pointer to a camera from whose viewpoint the scene is to
+                be rendered.
+            @param vp The target viewport
+            @param includeOverlays Whether or not overlay objects should be rendered
+        */
+        virtual void _renderScene(Camera* camera, Viewport* vp, bool includeOverlays);
+
+        /** Internal method for queueing the sky objects with the params as 
+            previously set through setSkyBox, setSkyPlane and setSkyDome.
+        */
+        virtual void _queueSkiesForRendering(Camera* cam);
+
+
+
+        /** Notifies the scene manager of its destination render system
+            @remarks
+                Called automatically by RenderSystem::addSceneManager
+                this method simply notifies the manager of the render
+                system to which its output must be directed.
+            @param
+                sys Pointer to the RenderSystem subclass to be used as a render target.
+        */
+        virtual void _setDestinationRenderSystem(RenderSystem* sys);
+
+        /** Enables / disables a 'sky plane' i.e. a plane at constant
+            distance from the camera representing the sky.
+            @remarks
+                You can create sky planes yourself using the standard mesh and
+                entity methods, but this creates a plane which the camera can
+                never get closer or further away from - it moves with the camera.
+                (NB you could create this effect by creating a world plane which
+                was attached to the same SceneNode as the Camera too, but this
+                would only apply to a single camera whereas this plane applies to
+                any camera using this scene manager).
+            @note
+                To apply scaling, scrolls etc to the sky texture(s) you
+                should use the TextureUnitState class methods.
+            @param
+                enable True to enable the plane, false to disable it
+            @param
+                plane Details of the plane, i.e. it's normal and it's
+                distance from the camera.
+            @param
+                materialName The name of the material the plane will use
+            @param
+                scale The scaling applied to the sky plane - higher values
+                mean a bigger sky plane - you may want to tweak this
+                depending on the size of plane.d and the other
+                characteristics of your scene
+            @param
+                tiling How many times to tile the texture across the sky.
+                Applies to all texture layers. If you need finer control use
+                the TextureUnitState texture coordinate transformation methods.
+            @param
+                drawFirst If true, the plane is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the plane.d value is large enough that no objects
+                will 'poke through' the sky plane when it is rendered.
+			@param
+				bow If zero, the plane will be completely flat (like previous
+				versions.  If above zero, the plane will be curved, allowing
+				the sky to appear below camera level.  Curved sky planes are 
+				simular to skydomes, but are more compatable with fog.
+            @param xsegments, ysegments
+                Determines the number of segments the plane will have to it. This
+                is most important when you are bowing the plane, but may also be useful
+                if you need tesselation on the plane to perform per-vertex effects.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyPlane(
+            bool enable,
+            const Plane& plane, const String& materialName, Real scale = 1000,
+            Real tiling = 10, bool drawFirst = true, Real bow = 0, 
+            int xsegments = 1, int ysegments = 1, 
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Enables / disables a 'sky box' i.e. a 6-sided box at constant
+            distance from the camera representing the sky.
+            @remarks
+                You could create a sky box yourself using the standard mesh and
+                entity methods, but this creates a plane which the camera can
+                never get closer or further away from - it moves with the camera.
+                (NB you could create this effect by creating a world box which
+                was attached to the same SceneNode as the Camera too, but this
+                would only apply to a single camera whereas this skybox applies
+                to any camera using this scene manager).
+            @par
+                The material you use for the skybox can either contain layers
+                which are single textures, or they can be cubic textures, i.e.
+                made up of 6 images, one for each plane of the cube. See the
+                TextureUnitState class for more information.
+            @param
+                enable True to enable the skybox, false to disable it
+            @param
+                materialName The name of the material the box will use
+            @param
+                distance Distance in world coorinates from the camera to
+                each plane of the box. The default is normally OK.
+            @param
+                drawFirst If true, the box is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the distance value is large enough that no
+                objects will 'poke through' the sky box when it is rendered.
+            @param
+                orientation Optional parameter to specify the orientation
+                of the box. By default the 'top' of the box is deemed to be
+                in the +y direction, and the 'front' at the -z direction.
+                You can use this parameter to rotate the sky if you want.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyBox(
+            bool enable, const String& materialName, Real distance = 5000,
+            bool drawFirst = true, const Quaternion& orientation = Quaternion::IDENTITY,
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Enables / disables a 'sky dome' i.e. an illusion of a curved sky.
+            @remarks
+                A sky dome is actually formed by 5 sides of a cube, but with
+                texture coordinates generated such that the surface appears
+                curved like a dome. Sky domes are appropriate where you need a
+                realistic looking sky where the scene is not going to be
+                'fogged', and there is always a 'floor' of some sort to prevent
+                the viewer looking below the horizon (the distortion effect below
+                the horizon can be pretty horrible, and there is never anyhting
+                directly below the viewer). If you need a complete wrap-around
+                background, use the setSkyBox method instead. You can actually
+                combine a sky box and a sky dome if you want, to give a positional
+                backdrop with an overlayed curved cloud layer.
+            @par
+                Sky domes work well with 2D repeating textures like clouds. You
+                can change the apparant 'curvature' of the sky depending on how
+                your scene is viewed - lower curvatures are better for 'open'
+                scenes like landscapes, whilst higher curvatures are better for
+                say FPS levels where you don't see a lot of the sky at once and
+                the exaggerated curve looks good.
+            @param
+                enable True to enable the skydome, false to disable it
+            @param
+                materialName The name of the material the dome will use
+            @param
+                curvature The curvature of the dome. Good values are
+                between 2 and 65. Higher values are more curved leading to
+                a smoother effect, lower values are less curved meaning
+                more distortion at the horizons but a better distance effect.
+            @param
+                tiling How many times to tile the texture(s) across the
+                dome.
+            @param
+                distance Distance in world coorinates from the camera to
+                each plane of the box the dome is rendered on. The default
+                is normally OK.
+            @param
+                drawFirst If true, the dome is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the distance value is large enough that no
+                objects will 'poke through' the sky when it is rendered.
+            @param
+                orientation Optional parameter to specify the orientation
+                of the dome. By default the 'top' of the dome is deemed to
+                be in the +y direction, and the 'front' at the -z direction.
+                You can use this parameter to rotate the sky if you want.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyDome(
+            bool enable, const String& materialName, Real curvature = 10,
+            Real tiling = 8, Real distance = 4000, bool drawFirst = true,
+            const Quaternion& orientation = Quaternion::IDENTITY,
+            int xsegments = 16, int ysegments = 16, int ysegments_keep = -1,
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Sets the fogging mode applied to the scene.
+            @remarks
+                This method sets up the scene-wide fogging effect. These settings
+                apply to all geometry rendered, UNLESS the material with which it
+                is rendered has it's own fog settings (see Material::setFog).
+            @param
+                mode Set up the mode of fog as described in the FogMode
+                enum, or set to FOG_NONE to turn off.
+            @param
+                colour The colour of the fog. Either set this to the same
+                as your viewport background colour, or to blend in with a
+                skydome or skybox.
+            @param
+                expDensity The density of the fog in FOG_EXP or FOG_EXP2
+                mode, as a value between 0 and 1. The default is 0.001. 
+            @param
+                linearStart Distance in world units at which linear fog starts to
+                encroach. Only applicable if mode is
+                FOG_LINEAR.
+            @param
+                linearEnd Distance in world units at which linear fog becomes completely
+                opaque. Only applicable if mode is
+                FOG_LINEAR.
+        */
+        void setFog(
+            FogMode mode = FOG_NONE, const ColourValue& colour = ColourValue::White,
+            Real expDensity = 0.001, Real linearStart = 0.0, Real linearEnd = 1.0);
+
+        /** Returns the fog mode for the scene.
+        */
+        virtual FogMode getFogMode(void) const;
+
+        /** Returns the fog colour for the scene.
+        */
+        virtual const ColourValue& getFogColour(void) const;
+
+        /** Returns the fog start distance for the scene.
+        */
+        virtual Real getFogStart(void) const;
+
+        /** Returns the fog end distance for the scene.
+        */
+        virtual Real getFogEnd(void) const;
+
+        /** Returns the fog density for the scene.
+        */
+        virtual Real getFogDensity(void) const;
+
+
+        /** Creates a new BillboardSet for use with this scene manager.
+            @remarks
+                This method creates a new BillboardSet which is registered with
+                the SceneManager. The SceneManager will destroy this object when
+                it shuts down or when the SceneManager::clearScene method is
+                called, so the caller does not have to worry about destroying
+                this object (in fact, it definitely should not do this).
+            @par
+                See the BillboardSet documentations for full details of the
+                returned class.
+            @param
+                name The name to give to this billboard set. Must be unique.
+            @param
+                poolSize The initial size of the pool of billboards (see BillboardSet for more information)
+            @see
+                BillboardSet
+        */
+        virtual BillboardSet* createBillboardSet(const String& name, unsigned int poolSize = 20);
+
+        /** Retrieves a pointer to the named BillboardSet.
+        */
+        virtual BillboardSet* getBillboardSet(const String& name);
+
+        /** Removes & destroys an BillboardSet from the SceneManager.
+            @warning
+                Must only be done if the BillboardSet is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene. If you are unsure, use clearScene.
+        */
+        virtual void removeBillboardSet(BillboardSet* set);
+
+        /** Removes & destroys an BillboardSet from the SceneManager by name.
+            @warning
+                Must only be done if the BillboardSet is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene. If you are unsure, use clearScene.
+        */
+        virtual void removeBillboardSet(const String& name);
+
+        /** Removes & destroys all BillboardSets.
+        @warning
+        Again, use caution since no BillboardSet must be referred to
+        elsewhere e.g. attached to a SceneNode otherwise a crash
+        is likely. Use clearScene if you are unsure (it clears SceneNode
+        entries too.)
+        @see
+        SceneManager::clearScene
+        */
+        virtual void removeAllBillboardSets(void);
+
+        /** Tells the SceneManager whether it should render the SceneNodes which 
+            make up the scene as well as the objects in the scene.
+        @remarks
+            This method is mainly for debugging purposes. If you set this to 'true',
+            each node will be rendered as a set of 3 axes to allow you to easily see
+            the orientation of the nodes.
+        */
+        virtual void setDisplaySceneNodes(bool display);
+
+        /** Creates an animation which can be used to animate scene nodes.
+        @remarks
+            An animation is a collection of 'tracks' which over time change the position / orientation
+            of Node objects. In this case, the animation will likely have tracks to modify the position
+            / orientation of SceneNode objects, e.g. to make objects move along a path.
+        @par
+            You don't need to use an Animation object to move objects around - you can do it yourself
+            using the methods of the Node in your FrameListener class. However, when you need relatively
+            complex scripted animation, this is the class to use since it will interpolate between
+            keyframes for you and generally make the whole process easier to manage.
+        @par
+            A single animation can affect multiple Node objects (each AnimationTrack affects a single Node).
+            In addition, through animation blending a single Node can be affected by multiple animations,
+            athough this is more useful when performing skeletal animation (see Skeleton::createAnimation).
+        @par
+            Note that whilst it uses the same classes, the animations created here are kept separate from the
+            skeletal animations of meshes (each Skeleton owns those animations).
+        @param name The name of the animation, must be unique within this SceneManager.
+        @param length The total length of the animation.
+        */
+        virtual Animation* createAnimation(const String& name, Real length);
+
+        /** Looks up an Animation object previously created with createAnimation. */
+        virtual Animation* getAnimation(const String& name) const;
+
+        /** Destroys an Animation. 
+        @remarks
+            You should ensure that none of your code is referencing this animation objects since the 
+            memory will be freed.
+        */
+        virtual void destroyAnimation(const String& name);
+
+        /** Removes all animations created using this SceneManager. */
+        virtual void destroyAllAnimations(void);
+
+        /** Create an AnimationState object for managing application of animations.
+        @remarks
+            You can create Animation objects for animating SceneNode obejcts using the
+            createAnimation method. However, in order to actually apply those animations
+            you have to call methods on Node and Animation in a particular order (namely
+            Node::resetToInitialState and Animation::apply). To make this easier and to
+            help track the current time position of animations, the AnimationState object
+            is provided. </p>
+            So if you don't want to control animation application manually, call this method,
+            update the returned object as you like every frame and let SceneManager apply 
+            the animation state for you.
+        @par
+            Remember, AnimationState objects are disabled by default at creation time. 
+            Turn them on when you want them using their setEnabled method.
+        @par
+            Note that any SceneNode affected by this automatic animation will have it's state
+            reset to it's initial position before application of the animation. Unless specifically
+            modified using Node::setInitialState the Node assumes it's initial state is at the
+            origin. If you want the base state of the SceneNode to be elsewhere, make your changes
+            to the node using the standard transform methods, then call setInitialState to 
+            'bake' this reference position into the node.
+        @param animName The name of an animation created already with createAnimation.
+        */
+        virtual AnimationState* createAnimationState(const String& animName);
+
+        /** Retrieves animation state as previously created using createAnimationState */
+        virtual AnimationState* getAnimationState(const String& animName);
+
+        /** Destroys an AnimationState. 
+        @remarks
+            You should ensure that none of your code is referencing this animation 
+            state object since the memory will be freed.
+        */
+        virtual void destroyAnimationState(const String& name);
+
+        /** Removes all animation states created using this SceneManager. */
+        virtual void destroyAllAnimationStates(void);
+
+        /** Manual rendering method, for advanced users only.
+        @remarks
+            This method allows you to send rendering commands through the pipeline on
+            demand, bypassing OGRE's normal world processing. You should only use this if you
+            really know what you're doing; OGRE does lots of things for you that you really should
+            let it do. However, there are times where it may be useful to have this manual interface,
+            for example overlaying something on top of the scene rendered by OGRE.
+        @par
+            Because this is an instant rendering method, timing is important. The best 
+            time to call it is from a RenderTargetListener event handler.
+        @par
+            Don't call this method a lot, it's designed for rare (1 or 2 times per frame) use. 
+            Calling it regularly per frame will cause frame rate drops!
+        @param rend A RenderOperation object describing the rendering op
+        @param pass The Pass to use for this render
+        @param vp Pointer to the viewport to render to
+        @param worldMatrix The transform to apply from object to world space
+        @param viewMatrix The transform to apply from world to view space
+        @param projMatrix The transform to apply from view to screen space
+        @param doBeginEndFrame If true, beginFrame() and endFrame() are called, 
+            otherwise not. You should leave this as false if you are calling
+            this within the main render loop.
+        */
+        virtual void manualRender(RenderOperation* rend, Pass* pass, Viewport* vp, 
+            const Matrix4& worldMatrix, const Matrix4& viewMatrix, const Matrix4& projMatrix, 
+            bool doBeginEndFrame = false) ;
+
+        /** Registers a new RenderQueueListener which will be notified when render queues
+            are processed.
+        */
+        virtual void addRenderQueueListener(RenderQueueListener* newListener);
+
+        /** Removes a listener previously added with addRenderQueueListener. */
+        virtual void removeRenderQueueListener(RenderQueueListener* delListener);
+
+		/** Adds an item to the 'special case' render queue list.
+		@remarks
+			Normally all render queues are rendered, in their usual sequence, 
+			only varying if a RenderQueueListener nominates for the queue to be 
+			repeated or skipped. This method allows you to add a render queue to 
+			a 'special case' list, which varies the behaviour. The effect of this
+			list depends on the 'mode' in which this list is in, which might be
+			to exclude these render queues, or to include them alone (excluding
+			all other queues). This allows you to perform broad selective
+			rendering without requiring a RenderQueueListener.
+		@param qid The identifier of the queue which should be added to the
+			special case list. Nothing happens if the queue is already in the list.
+		*/
+		virtual void addSpecialCaseRenderQueue(RenderQueueGroupID qid);
+		/** Removes an item to the 'special case' render queue list.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param qid The identifier of the queue which should be removed from the
+			special case list. Nothing happens if the queue is not in the list.
+		*/
+		virtual void removeSpecialCaseRenderQueue(RenderQueueGroupID qid);
+		/** Clears the 'special case' render queue list.
+		@see SceneManager::addSpecialCaseRenderQueue
+		*/
+		virtual void clearSpecialCaseRenderQueues(void);
+		/** Sets the way the special case render queue list is processed.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param mode The mode of processing
+		*/
+		virtual void setSpecialCaseRenderQueueMode(SpecialCaseRenderQueueMode mode);
+		/** Gets the way the special case render queue list is processed. */
+		virtual SpecialCaseRenderQueueMode getSpecialCaseRenderQueueMode(void);
+		/** Returns whether or not the named queue will be rendered based on the
+			current 'special case' render queue list and mode.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param qid The identifier of the queue which should be tested
+		@returns true if the queue will be rendered, false otherwise
+		*/
+		virtual bool isRenderQueueToBeProcessed(RenderQueueGroupID qid);
+
+		/** Sets the render queue that the world geometry (if any) this SceneManager
+			renders will be associated with.
+		@remarks
+			SceneManagers which provide 'world geometry' should place it in a 
+			specialised render queue in order to make it possible to enable / 
+			disable it easily using the addSpecialCaseRenderQueue method. Even 
+			if the SceneManager does not use the render queues to render the 
+			world geometry, it should still pick a queue to represent it's manual
+			rendering, and check isRenderQueueToBeProcessed before rendering.
+		@note
+			Setting this may not affect the actual ordering of rendering the
+			world geometry, if the world geometry is being rendered manually
+			by the SceneManager. If the SceneManager feeds world geometry into
+			the queues, however, the ordering will be affected. 
+		*/
+		virtual void setWorldGeometryRenderQueue(RenderQueueGroupID qid);
+		/** Gets the render queue that the world geometry (if any) this SceneManager
+			renders will be associated with.
+		@remarks
+			SceneManagers which provide 'world geometry' should place it in a 
+			specialised render queue in order to make it possible to enable / 
+			disable it easily using the addSpecialCaseRenderQueue method. Even 
+			if the SceneManager does not use the render queues to render the 
+			world geometry, it should still pick a queue to represent it's manual
+			rendering, and check isRenderQueueToBeProcessed before rendering.
+		*/
+		virtual RenderQueueGroupID getWorldGeometryRenderQueue(void);
+
+		/** Allows all bounding boxes of scene nodes to be displayed. */
+		virtual void showBoundingBoxes(bool bShow);
+
+		/** Returns if all bounding boxes of scene nodes are to be displayed */
+		virtual bool getShowBoundingBoxes() const;
+
+        /** Internal method for notifying the manager that a SceneNode is autotracking. */
+        virtual void _notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack);
+
+        
+        /** Creates an AxisAlignedBoxSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param box Details of the box which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual AxisAlignedBoxSceneQuery* 
+            createAABBQuery(const AxisAlignedBox& box, unsigned long mask = 0xFFFFFFFF);
+        /** Creates a SphereSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            for a spherical region. See SceneQuery and SphereSceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param sphere Details of the sphere which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual SphereSceneQuery* 
+            createSphereQuery(const Sphere& sphere, unsigned long mask = 0xFFFFFFFF);
+        /** Creates a PlaneBoundedVolumeListSceneQuery for this scene manager. 
+        @remarks
+        This method creates a new instance of a query object for this scene manager, 
+        for a region enclosed by a set of planes (normals pointing inwards). 
+        See SceneQuery and PlaneBoundedVolumeListSceneQuery for full details.
+        @par
+        The instance returned from this method must be destroyed by calling
+        SceneManager::destroyQuery when it is no longer required.
+        @param volumes Details of the volumes which describe the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+        certain objects; see SceneQuery for details.
+        */
+        virtual PlaneBoundedVolumeListSceneQuery* 
+            createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, unsigned long mask = 0xFFFFFFFF);
+
+
+        /** Creates a RaySceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            looking for objects which fall along a ray. See SceneQuery and RaySceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param ray Details of the ray which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual RaySceneQuery* 
+            createRayQuery(const Ray& ray, unsigned long mask = 0xFFFFFFFF);
+        //PyramidSceneQuery* createPyramidQuery(const Pyramid& p, unsigned long mask = 0xFFFFFFFF);
+        /** Creates an IntersectionSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for locating
+            intersecting objects. See SceneQuery and IntersectionSceneQuery
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual IntersectionSceneQuery* 
+            createIntersectionQuery(unsigned long mask = 0xFFFFFFFF);
+
+        /** Destroys a scene query of any type. */
+        virtual void destroyQuery(SceneQuery* query);
+
+        typedef MapIterator<SceneLightList> LightIterator;
+        typedef MapIterator<EntityList> EntityIterator;
+        typedef MapIterator<CameraList> CameraIterator;
+        typedef MapIterator<BillboardSetList> BillboardSetIterator;
+        typedef MapIterator<AnimationList> AnimationIterator;
+
+        /** Returns a specialised MapIterator over all lights in the scene. */
+        LightIterator getLightIterator(void) {
+            return LightIterator(mLights.begin(), mLights.end());
+        }
+        /** Returns a specialised MapIterator over all entities in the scene. */
+        EntityIterator getEntityIterator(void) {
+            return EntityIterator(mEntities.begin(), mEntities.end());
+        }
+        /** Returns a specialised MapIterator over all cameras in the scene. */
+        CameraIterator getCameraIterator(void) {
+            return CameraIterator(mCameras.begin(), mCameras.end());
+        }
+        /** Returns a specialised MapIterator over all BillboardSets in the scene. */
+        BillboardSetIterator getBillboardSetIterator(void) {
+            return BillboardSetIterator(mBillboardSets.begin(), mBillboardSets.end());
+        }
+        /** Returns a specialised MapIterator over all animations in the scene. */
+        AnimationIterator getAnimationIterator(void) {
+            return AnimationIterator(mAnimationsList.begin(), mAnimationsList.end());
+        }
+        /** Returns a specialised MapIterator over all animation states in the scene. */
+        AnimationStateIterator getAnimationStateIterator(void) {
+            return AnimationStateIterator(mAnimationStates.begin(), mAnimationStates.end());
+        }
+
+        /** Sets the general shadow technique to be used in this scene.
+        @remarks   
+            There are multiple ways to generate shadows in a scene, and each has 
+            strengths and weaknesses. 
+            <ul><li>Stencil-based approaches can be used to 
+            draw very long, extreme shadows without loss of precision and the 'additive'
+            version can correctly show the shadowing of complex effects like bump mapping
+            because they physically exclude the light from those areas. However, the edges
+            are very sharp and stencils cannot handle transparency, and they involve a 
+            fair amount of CPU work in order to calculate the shadow volumes, especially
+            when animated objects are involved.</li>
+            <li>Texture-based approaches are good for handling transparency (they can, for
+            example, correctly shadow a mesh which uses alpha to represent holes), and they
+            require little CPU overhead, and can happily shadow geometry which is deformed
+            by a vertex program, unlike stencil shadows. However, they have a fixed precision 
+            which can introduce 'jaggies' at long range and have fillrate issues of their own.</li>
+            </ul>
+        @par
+            We support 2 kinds of stencil shadows, and 2 kinds of texture-based shadows, and one
+            simple decal approach. The 2 stencil approaches differ in the amount of multipass work 
+            that is required - the modulative approach simply 'darkens' areas in shadow after the 
+            main render, which is the least expensive, whilst the additive approach has to perform 
+            a render per light and adds the cumulative effect, whcih is more expensive but more 
+            accurate. The texture based shadows both work in roughly the same way, the only difference is
+            that the shadowmap approach is slightly more accurate, but requires a more recent
+            graphics card.
+        @par
+            Note that because mixing many shadow techniques can cause problems, only one technique
+            is supported at once. Also, you should call this method at the start of the 
+            scene setup. 
+        @param technique The shadowing technique to use for the scene.
+        */
+        virtual void setShadowTechnique(ShadowTechnique technique);
+        
+        /** Gets the current shadow technique. */
+        virtual ShadowTechnique getShadowTechnique(void) const { return mShadowTechnique; }
+
+        /** Enables / disables the rendering of debug information for shadows. */
+        virtual void setShowDebugShadows(bool debug) { mDebugShadows = debug; }
+        /** Are debug shadows shown? */
+        virtual bool getShowDebugShadows(void ) const { return mDebugShadows; }
+
+        /** Set the colour used to modulate areas in shadow. 
+        @remarks This is only applicable for shadow techniques which involve 
+            darkening the area in shadow, as opposed to masking out the light. 
+            This colour provided is used as a modulative value to darken the
+            areas.
+        */
+        virtual void setShadowColour(const ColourValue& colour);
+        /** Get the colour used to modulate areas in shadow. 
+        @remarks This is only applicable for shadow techniques which involve 
+        darkening the area in shadow, as opposed to masking out the light. 
+        This colour provided is used as a modulative value to darken the
+        areas.
+        */
+        virtual const ColourValue& getShadowColour(void) const;
+        /** Sets the distance a shadow volume is extruded for a directional light.
+        @remarks
+            Although directional lights are essentially infinite, there are many
+            reasons to limit the shadow extrusion distance to a finite number, 
+            not least of which is compatibility with older cards (which do not
+            support infinite positions), and shadow caster elimination.
+        @par
+            The default value is 10,000 world units. This does not apply to
+            point lights or spotlights, since they extrude up to their 
+            attenuation range.
+        */
+        virtual void setShadowDirectionalLightExtrusionDistance(Real dist); 
+        /** Gets the distance a shadow volume is extruded for a directional light.
+        */
+        virtual Real getShadowDirectionalLightExtrusionDistance(void) const;
+        /** Sets the maximum distance away from the camera that shadows
+        will be visible.
+        @remarks
+        Shadow techniques can be expensive, therefore it is a good idea
+        to limit them to being rendered close to the camera if possible,
+        and to skip the expense of rendering shadows for distance objects.
+        This method allows you to set the distance at which shadows will no
+        longer be rendered.
+        @note
+        Each shadow technique can interpret this subtely differently.
+        For example, one technique may use this to eliminate casters,
+        another might use it to attenuate the shadows themselves.
+        You should tweak this value to suit your chosen shadow technique
+        and scene setup.
+        */
+        virtual void setShadowFarDistance(Real distance);
+        /** Gets the maximum distance away from the camera that shadows
+        will be visible.
+        */
+        virtual Real getShadowFarDistance(void) const
+        { return mShadowFarDist; }
+
+		/** Sets the maximum size of the index buffer used to render shadow
+		 	primitives.
+		@remarks
+			This method allows you to tweak the size of the index buffer used
+			to render shadow primitives (including stencil shadow volumes). The
+			default size is 51,200 entries, which is 100k of GPU memory, or
+			enough to render approximately 17,000 triangles. You can reduce this
+			as long as you do not have any models / world geometry chunks which 
+			could require more than the amount you set.
+		@par
+			The maximum number of triangles required to render a single shadow 
+			volume (including light and dark caps when needed) will be 3x the 
+			number of edges on the light silhouette, plus the number of 
+			light-facing triangles.	On average, half the 
+			triangles will be facing toward the light, but the number of 
+			triangles in the silhouette entirely depends on the mesh - 
+			angular meshes will have a higher silhouette tris/mesh tris
+			ratio than a smooth mesh. You can estimate the requirements for
+			your particular mesh by rendering it alone in a scene with shadows
+			enabled and a single light - rotate it or the light and make a note
+			of how high the triangle count goes (remembering to subtract the 
+			mesh triangle count)
+		@param size The number of indexes; divide this by 3 to determine the
+			number of triangles.
+		*/
+		virtual void setShadowIndexBufferSize(size_t size);
+        /// Get the size of the shadow index buffer
+		virtual size_t getShadowIndexBufferSize(void) const
+		{ return mShadowIndexBufferSize; }
+        /** Set the size of the texture used for texture-based shadows.
+        @remarks
+            The larger the shadow texture, the better the detail on 
+            texture based shadows, but obviously this takes more memory.
+            The default size is 512. Sizes must be a power of 2.
+        */
+        virtual void setShadowTextureSize(unsigned short size);
+        /// Get the size of the texture used for texture based shadows
+        unsigned short getShadowTextureSize(void) const {return mShadowTextureSize; }
+        /** Set the pixel format of the textures used for texture-based shadows.
+        @remarks
+			By default, a colour texture is used (PF_X8R8G8B8) for texture shadows,
+			but if you want to use more advanced texture shadow types you can 
+			alter this. If you do, you will have to also call
+			setShadowTextureCasterMaterial and setShadowTextureReceiverMaterial
+			to provide shader-based materials to use these customised shadow
+			texture formats.
+        */
+        virtual void setShadowTexturePixelFormat(PixelFormat fmt);
+        /// Get the format of the textures used for texture based shadows
+        PixelFormat getShadowTexturePixelFormat(void) const {return mShadowTextureFormat; }
+        /** Set the number of textures allocated for texture-based shadows.
+        @remarks
+            The default number of textures assigned to deal with texture based
+            shadows is 1; however this means you can only have one light casting
+            shadows at the same time. You can increase this number in order to 
+            make this more flexible, but be aware of the texture memory it will use.
+        */
+        virtual void setShadowTextureCount(unsigned short count);
+        /// Get the number of the textures allocated for texture based shadows
+        unsigned short getShadowTextureCount(void) const {return mShadowTextureCount; }
+        /** Sets the size and count of textures used in texture-based shadows. 
+        @remarks
+            @see setShadowTextureSize and setShadowTextureCount for details, this
+            method just allows you to change both at once, which can save on 
+            reallocation if the textures have already been created.
+        */
+        virtual void setShadowTextureSettings(unsigned short size, unsigned short count, 
+			PixelFormat fmt = PF_X8R8G8B8);
+        /** Sets the proportional distance which a texture shadow which is generated from a
+            directional light will be offset into the camera view to make best use of texture space.
+        @remarks
+            When generating a shadow texture from a directional light, an approximation is used
+            since it is not possible to render the entire scene to one texture. 
+            The texture is projected onto an area centred on the camera, and is
+            the shadow far distance * 2 in length (it is square). This wastes
+            a lot of texture space outside the frustum though, so this offset allows
+            you to move the texture in front of the camera more. However, be aware
+            that this can cause a little shadow 'jittering' during rotation, and
+            that if you move it too far then you'll start to get artefacts close 
+            to the camera. The value is represented as a proportion of the shadow
+            far distance, and the default is 0.6.
+        */
+        virtual void setShadowDirLightTextureOffset(Real offset) { mShadowTextureOffset = offset;}
+        /** Sets the proportional distance at which texture shadows begin to fade out.
+        @remarks
+            To hide the edges where texture shadows end (in directional lights)
+            Ogre will fade out the shadow in the distance. This value is a proportional
+            distance of the entire shadow visibility distance at which the shadow
+            begins to fade out. The default is 0.7
+        */
+        virtual void setShadowTextureFadeStart(Real fadeStart) 
+        { mShadowTextureFadeStart = fadeStart; }
+        /** Sets the proportional distance at which texture shadows finish to fading out.
+        @remarks
+        To hide the edges where texture shadows end (in directional lights)
+        Ogre will fade out the shadow in the distance. This value is a proportional
+        distance of the entire shadow visibility distance at which the shadow
+        is completely invisible. The default is 0.9.
+        */
+        virtual void setShadowTextureFadeEnd(Real fadeEnd) 
+        { mShadowTextureFadeEnd = fadeEnd; }
+
+		/** Sets whether or not texture shadows should attempt to self-shadow.
+		@remarks
+			The default implementation of texture shadows uses a fixed-function 
+			colour texture projection approach for maximum compatibility, and 
+			as such cannot support self-shadowing. However, if you decide to 
+			implement a more complex shadowing technique using the 
+			setShadowTextureCasterMaterial and setShadowTextureReceiverMaterial 
+			there is a possibility you may be able to support 
+			self-shadowing (e.g by implementing a shader-based shadow map). In 
+			this case you might want to enable this option.
+		@param selfShadow Whether to attempt self-shadowing with texture shadows
+		*/
+		virtual void setShadowTextureSelfShadow(bool selfShadow) 
+		{ mShadowTextureSelfShadow = selfShadow; }
+		/// Gets whether or not texture shadows attempt to self-shadow.
+		virtual bool getShadowTextureSelfShadow(void) const 
+		{ return mShadowTextureSelfShadow; }
+		/** Sets the default material to use for rendering shadow casters.
+		@remarks
+			By default shadow casters are rendered into the shadow texture using
+			an automatically generated fixed-function pass. This allows basic
+			projective texture shadows, but it's possible to use more advanced
+			shadow techniques by overriding the caster and receiver materials, for
+			example providing vertex and fragment programs to implement shadow
+			maps.
+		@par
+			You can rely on the ambient light in the scene being set to the 
+			requested texture shadow colour, if that's useful. 
+		@note
+			Individual objects may also override the vertex program in
+			your default material if their materials include 
+			shadow_caster_vertex_program_ref shadow_receiver_vertex_program_ref
+			entries, so if you use both make sure they are compatible.
+		@note
+			Only a single pass is allowed in your material, although multiple
+			techniques may be used for hardware fallback.
+		*/
+		virtual void setShadowTextureCasterMaterial(const String& name);
+		/** Sets the default material to use for rendering shadow receivers.
+		@remarks
+			By default shadow receivers are rendered as a post-pass using basic
+			modulation. This allows basic projective texture shadows, but it's 
+			possible to use more advanced shadow techniques by overriding the 
+			caster and receiver materials, for example providing vertex and 
+			fragment programs to implement shadow maps.
+		@par
+			You can rely on texture unit 0 containing the shadow texture, and 
+			for the unit to be set to use projective texturing from the light 
+			(only useful if you're using fixed-function, which is unlikely; 
+			otherwise you should rely on the texture_viewproj_matrix auto binding)
+		@note
+			Individual objects may also override the vertex program in
+			your default material if their materials include 
+			shadow_caster_vertex_program_ref shadow_receiver_vertex_program_ref
+			entries, so if you use both make sure they are compatible.
+		@note
+			Only a single pass is allowed in your material, although multiple
+			techniques may be used for hardware fallback.
+		*/
+		virtual void setShadowTextureReceiverMaterial(const String& name);
+
+		/** Sets whether we should use an inifinite camera far plane
+			when rendering stencil shadows.
+		@remarks
+			Stencil shadow coherency is very reliant on the shadow volume
+			not being clipped by the far plane. If this clipping happens, you
+			get a kind of 'negative' shadow effect. The best way to achieve
+			coherency is to move the far plane of the camera out to infinity,
+			thus preventing the far plane from clipping the shadow volumes.
+			When combined with vertex program extrusion of the volume to 
+			infinity, which	Ogre does when available, this results in very
+			robust shadow volumes. For this reason, when you enable stencil 
+			shadows, Ogre automatically changes your camera settings to 
+			project to infinity if the card supports it. You can disable this
+			behaviour if you like by calling this method; although you can 
+			never enable infinite projection if the card does not support it.
+		@par	
+			If you disable infinite projection, or it is not available, 
+			you need to be far more careful with your light attenuation /
+			directional light extrusion distances to avoid clipping artefacts
+			at the far plane.
+		@note
+			Recent cards will generally support infinite far plane projection.
+			However, we have found some cases where they do not, especially
+			on Direct3D. There is no standard capability we can check to 
+			validate this, so we use some heuristics based on experience:
+			<UL>
+			<LI>OpenGL always seems to support it no matter what the card</LI>
+			<LI>Direct3D on non-vertex program capable systems (including 
+			vertex program capable cards on Direct3D7) does not
+			support it</LI>
+			<LI>Direct3D on GeForce3 and GeForce4 Ti does not seem to support
+			infinite projection<LI>
+			</UL>
+			Therefore in the RenderSystem implementation, we may veto the use
+			of an infinite far plane based on these heuristics. 
+		*/
+        virtual void setShadowUseInfiniteFarPlane(bool enable) {
+            mShadowUseInfiniteFarPlane = enable; }
+
+		/** Creates a StaticGeometry instance suitable for use with this
+			SceneManager.
+		@remarks
+			StaticGeometry is a way of batching up geometry into a more 
+			efficient form at the expense of being able to move it. Please 
+			read the StaticGeometry class documentation for full information.
+		@param name The name to give the new object
+		@returns The new StaticGeometry instance
+		*/
+		virtual StaticGeometry* createStaticGeometry(const String& name);
+		/** Retrieve a previously created StaticGeometry instance. */
+		virtual StaticGeometry* getStaticGeometry(const String& name) const;
+		/** Remove & destroy a StaticGeometry instance. */
+		virtual void removeStaticGeometry(StaticGeometry* geom);
+		/** Remove & destroy a StaticGeometry instance. */
+		virtual void removeStaticGeometry(const String& name);
+		/** Remove & destroy all StaticGeometry instances. */
+		virtual void removeAllStaticGeometry(void);
+
+		
+    };
+
+    /** Default implementation of IntersectionSceneQuery. */
+    class _OgreExport DefaultIntersectionSceneQuery : 
+        public IntersectionSceneQuery
+    {
+    public:
+        DefaultIntersectionSceneQuery(SceneManager* creator);
+        ~DefaultIntersectionSceneQuery();
+
+        /** See IntersectionSceneQuery. */
+        void execute(IntersectionSceneQueryListener* listener);
+    };
+
+    /** Default implementation of RaySceneQuery. */
+	class _OgreExport DefaultRaySceneQuery : public RaySceneQuery
+    {
+    public:
+        DefaultRaySceneQuery(SceneManager* creator);
+        ~DefaultRaySceneQuery();
+
+        /** See RayScenQuery. */
+        void execute(RaySceneQueryListener* listener);
+    };
+    /** Default implementation of SphereSceneQuery. */
+	class _OgreExport DefaultSphereSceneQuery : public SphereSceneQuery
+    {
+    public:
+        DefaultSphereSceneQuery(SceneManager* creator);
+        ~DefaultSphereSceneQuery();
+
+        /** See SceneQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    /** Default implementation of PlaneBoundedVolumeListSceneQuery. */
+    class _OgreExport DefaultPlaneBoundedVolumeListSceneQuery : public PlaneBoundedVolumeListSceneQuery
+    {
+    public:
+        DefaultPlaneBoundedVolumeListSceneQuery(SceneManager* creator);
+        ~DefaultPlaneBoundedVolumeListSceneQuery();
+
+        /** See SceneQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    /** Default implementation of AxisAlignedBoxSceneQuery. */
+	class _OgreExport DefaultAxisAlignedBoxSceneQuery : public AxisAlignedBoxSceneQuery
+    {
+    public:
+        DefaultAxisAlignedBoxSceneQuery(SceneManager* creator);
+        ~DefaultAxisAlignedBoxSceneQuery();
+
+        /** See RayScenQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    
+
+
+} // Namespace
+
+
+
+#endif
Index: trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneNode.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 61)
@@ -0,0 +1,644 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+#include "OgreSceneNode.h"
+
+#include "OgreException.h"
+#include "OgreEntity.h"
+#include "OgreCamera.h"
+#include "OgreLight.h"
+#include "OgreMath.h"
+#include "OgreSceneManager.h"
+#include "OgreMovableObject.h"
+#include "OgreWireBoundingBox.h"
+
+namespace Ogre {
+    //-----------------------------------------------------------------------
+    SceneNode::SceneNode(SceneManager* creator) 
+    : Node(), mLightListDirty(true), mWireBoundingBox(0), 
+	mShowBoundingBox(false), mCreator(creator), 
+	mYawFixed(false), mAutoTrackTarget(0), mIsInSceneGraph(false)
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false), mLastRendered(-1)
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    {
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::SceneNode(SceneManager* creator, const String& name) 
+    : Node(name), mLightListDirty(true), mWireBoundingBox(0), 
+	mShowBoundingBox(false), mCreator(creator), mYawFixed(false), 
+	mAutoTrackTarget(0), mIsInSceneGraph(false)
+	#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false)
+	#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    {
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::~SceneNode()
+    {
+        // Detach all objects, do this manually to avoid needUpdate() call 
+        // which can fail because of deleted items
+		ObjectMap::iterator itr;
+		MovableObject* ret;
+		for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
+		{
+		  ret = itr->second;
+		  ret->_notifyAttached((SceneNode*)0);
+		}
+        mObjectsByName.clear();
+
+        if (mWireBoundingBox) {
+			delete mWireBoundingBox;
+		}
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_update(bool updateChildren, bool parentHasChanged)
+    {
+        Node::_update(updateChildren, parentHasChanged);
+        _updateBounds();
+        mLightListDirty = true;
+
+    }
+    //-----------------------------------------------------------------------
+	void SceneNode::setParent(Node* parent)
+	{
+		Node::setParent(parent);
+
+		if (parent)
+		{
+			SceneNode* sceneParent = static_cast<SceneNode*>(parent);
+			setInSceneGraph(sceneParent->isInSceneGraph());
+		}
+		else
+		{
+			setInSceneGraph(false);
+		}
+	}
+    //-----------------------------------------------------------------------
+	void SceneNode::setInSceneGraph(bool inGraph)
+	{
+		if (inGraph != mIsInSceneGraph)
+		{
+			mIsInSceneGraph = inGraph;
+			// Tell children
+	        ChildNodeMap::iterator child;
+    	    for (child = mChildren.begin(); child != mChildren.end(); ++child)
+        	{
+            	SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+				sceneChild->setInSceneGraph(inGraph);
+			}
+		}
+	}
+    //-----------------------------------------------------------------------
+    void SceneNode::attachObject(MovableObject* obj)
+    {
+        obj->_notifyAttached(this);
+
+        // Also add to name index
+        std::pair<ObjectMap::iterator, bool> insresult = 
+            mObjectsByName.insert(ObjectMap::value_type(obj->getName(), obj));
+        assert(insresult.second && "Object was not attached because an object of the "
+            "same name was already attached to this node.");
+
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    unsigned short SceneNode::numAttachedObjects(void) const
+    {
+        return static_cast< unsigned short >( mObjectsByName.size() );
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::getAttachedObject(unsigned short index)
+    {
+        if (index < mObjectsByName.size())
+        {
+            ObjectMap::iterator i = mObjectsByName.begin();
+            // Increment (must do this one at a time)            
+            while (index--)++i;
+
+            return i->second;
+        }
+        else
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttachedObject");
+        }
+        return 0;
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::getAttachedObject(const String& name)
+    {
+        // Look up 
+        ObjectMap::iterator i = mObjectsByName.find(name);
+
+        if (i == mObjectsByName.end())
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Attached object " + 
+                name + " not found.", "SceneNode::getAttachedObject");
+        }
+
+        return i->second;
+
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::detachObject(unsigned short index)
+    {
+        MovableObject* ret;
+        if (index < mObjectsByName.size())
+        {
+
+            ObjectMap::iterator i = mObjectsByName.begin();
+            // Increment (must do this one at a time)            
+            while (index--)++i;
+
+            ret = i->second;
+            mObjectsByName.erase(i);
+            ret->_notifyAttached((SceneNode*)0);
+
+            // Make sure bounds get updated (must go right to the top)
+            needUpdate();
+
+            return ret;
+
+        }
+        else
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttchedEntity");
+        }
+        return 0;
+
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::detachObject(const String& name)
+    {
+        ObjectMap::iterator it = mObjectsByName.find(name);
+        if (it == mObjectsByName.end())
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Object " + name + " is not attached "
+                "to this node.", "SceneNode::detachObject");
+        }
+        MovableObject* ret = it->second;
+        mObjectsByName.erase(it);
+        ret->_notifyAttached((SceneNode*)0);
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+        
+        return ret;
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::detachObject(MovableObject* obj)
+    {
+        ObjectMap::iterator i, iend;
+        iend = mObjectsByName.end();
+        for (i = mObjectsByName.begin(); i != iend; ++i)
+        {
+            if (i->second == obj)
+            {
+                mObjectsByName.erase(i);
+                break;
+            }
+        }
+        obj->_notifyAttached((SceneNode*)0);
+
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::detachAllObjects(void)
+    {
+		ObjectMap::iterator itr;
+		MovableObject* ret;
+		for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
+		{
+		  ret = itr->second;
+		  ret->_notifyAttached((SceneNode*)0);
+		}
+        mObjectsByName.clear();
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_updateBounds(void)
+    {
+        // Reset bounds first
+        mWorldAABB.setNull();
+
+        // Update bounds from own attached objects
+        ObjectMap::iterator i;
+        for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
+        {
+            // Merge world bounds of each object
+            mWorldAABB.merge(i->second->getWorldBoundingBox(true));
+        }
+
+        // Merge with children
+        ChildNodeMap::iterator child;
+        for (child = mChildren.begin(); child != mChildren.end(); ++child)
+        {
+            SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+            mWorldAABB.merge(sceneChild->mWorldAABB);
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, 
+        bool includeChildren, bool displayNodes, bool onlyShadowCasters)
+    {
+        // Check self visible
+        if (!cam->isVisible(mWorldAABB))
+            return;
+
+        // Add all entities
+        ObjectMap::iterator iobj;
+        ObjectMap::iterator iobjend = mObjectsByName.end();
+        for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj)
+        {
+            // Tell attached objects about camera position (incase any extra processing they want to do)
+            iobj->second->_notifyCurrentCamera(cam);
+            if (iobj->second->isVisible() && 
+                (!onlyShadowCasters || iobj->second->getCastShadows()))
+            {
+                iobj->second->_updateRenderQueue(queue);
+            }
+        }
+
+        if (includeChildren)
+        {
+            ChildNodeMap::iterator child, childend;
+            childend = mChildren.end();
+            for (child = mChildren.begin(); child != childend; ++child)
+            {
+                SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+                sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
+            }
+        }
+
+        if (displayNodes)
+        {
+            // Include self in the render queue
+            queue->addRenderable(this);
+        }
+
+		// Check if the bounding box should be shown.
+		// See if our flag is set or if the scene manager flag is set.
+		if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes())) 
+		{ 
+			_addBoundingBoxToQueue(queue);
+		}
+
+
+    }
+
+
+	void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
+		// Create a WireBoundingBox if needed.
+		if (mWireBoundingBox == NULL) {
+			mWireBoundingBox = new WireBoundingBox();
+		}
+		mWireBoundingBox->setupBoundingBox(mWorldAABB);
+		queue->addRenderable(mWireBoundingBox);
+	}
+
+	void SceneNode::showBoundingBox(bool bShow) {
+		mShowBoundingBox = bShow;
+	}
+
+	bool SceneNode::getShowBoundingBox() const {
+		return mShowBoundingBox;
+	}
+
+
+    //-----------------------------------------------------------------------
+    Node* SceneNode::createChildImpl(void)
+    {
+        assert(mCreator);
+        return mCreator->createSceneNode();
+    }
+    //-----------------------------------------------------------------------
+    Node* SceneNode::createChildImpl(const String& name)
+    {
+        assert(mCreator);
+        return mCreator->createSceneNode(name);
+    }
+    //-----------------------------------------------------------------------
+    AxisAlignedBox SceneNode::_getWorldAABB(void) const
+    {
+        return mWorldAABB;
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void)
+    {
+        return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
+    }
+	//-----------------------------------------------------------------------
+	SceneNode::ConstObjectIterator SceneNode::getAttachedObjectIterator(void) const
+	{
+		return ConstObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
+	}
+    //-----------------------------------------------------------------------
+    SceneManager* SceneNode::getCreator(void) const
+    {
+        return mCreator;
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyChild(const String& name)
+    {
+        SceneNode* pChild = static_cast<SceneNode*>(getChild(name));
+        pChild->removeAndDestroyAllChildren();
+
+        removeChild(name);
+        pChild->getCreator()->destroySceneNode(name);
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyChild(unsigned short index)
+    {
+        SceneNode* pChild = static_cast<SceneNode*>(getChild(index));
+        pChild->removeAndDestroyAllChildren();
+
+        removeChild(index);
+        pChild->getCreator()->destroySceneNode(pChild->getName());
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyAllChildren(void)
+    {
+        ChildNodeMap::iterator i, iend;
+        iend = mChildren.end();
+        for (i = mChildren.begin(); i != iend; ++i)
+        {
+            SceneNode* sn = static_cast<SceneNode*>(i->second);
+            sn->removeAndDestroyAllChildren();
+            sn->getCreator()->destroySceneNode(sn->getName());
+        }
+	    mChildren.clear();
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+	SceneNode* SceneNode::createChildSceneNode(const Vector3& translate, 
+        const Quaternion& rotate)
+	{
+		return static_cast<SceneNode*>(this->createChild(translate, rotate));
+	}
+    //-----------------------------------------------------------------------
+    SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate, 
+		const Quaternion& rotate)
+	{
+		return static_cast<SceneNode*>(this->createChild(name, translate, rotate));
+	}
+    //-----------------------------------------------------------------------
+    const LightList& SceneNode::findLights(Real radius) const
+    {
+        // TEMP FIX
+        // If a scene node is static and lights have moved, light list won't change
+        // can't use a simple global boolean flag since this is only called for
+        // visible nodes, so temporarily visible nodes will not be updated
+        // Since this is only called for visible nodes, skip the check for now
+        //if (mLightListDirty)
+        if (mCreator)
+        {
+            // Use SceneManager to calculate
+            mCreator->_populateLightList(this->_getDerivedPosition(), radius, mLightList);
+            mLightListDirty = false;
+        }
+        return mLightList;
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setAutoTracking(bool enabled, SceneNode* target, 
+        const Vector3& localDirectionVector,
+        const Vector3& offset)
+    {
+        if (enabled)
+        {
+            mAutoTrackTarget = target;
+            mAutoTrackOffset = offset;
+            mAutoTrackLocalDirection = localDirectionVector;
+        }
+        else
+        {
+            mAutoTrackTarget = 0;
+        }
+        if (mCreator)
+            mCreator->_notifyAutotrackingSceneNode(this, enabled);
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
+    {
+        mYawFixed = useFixed;
+        mYawFixedAxis = fixedAxis;
+    }
+
+	//-----------------------------------------------------------------------
+	void SceneNode::yaw(const Radian& angle, TransformSpace relativeTo)
+	{
+		if (mYawFixed)
+		{
+			rotate(mYawFixedAxis, angle, relativeTo);
+		}
+		else
+		{
+			rotate(Vector3::UNIT_Y, angle, relativeTo);
+		}
+
+	}
+    //-----------------------------------------------------------------------
+    void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        setDirection(Vector3(x,y,z), relativeTo, localDirectionVector);
+    }
+
+    //-----------------------------------------------------------------------
+    void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        // Do nothing if given a zero vector
+        if (vec == Vector3::ZERO) return;
+
+        // Adjust vector so that it is relative to local Z
+        Vector3 zAdjustVec;
+        if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
+        {
+            zAdjustVec = -vec;
+        }
+        else
+        {
+            Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
+            zAdjustVec = localToUnitZ * vec;
+        }
+        zAdjustVec.normalise();
+
+        Quaternion targetOrientation;
+        if( mYawFixed )
+        {
+            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
+            xVec.normalise();
+
+            Vector3 yVec = zAdjustVec.crossProduct( xVec );
+            yVec.normalise();
+            
+            targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
+        }
+        else
+        {
+
+            // Get axes from current quaternion
+            Vector3 axes[3];
+            _getDerivedOrientation().ToAxes(axes);
+            Quaternion rotQuat;
+            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f)
+            {
+                // Oops, a 180 degree turn (infinite possible rotation axes)
+                // Default to yaw i.e. use current UP
+                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
+            }
+            else
+            {
+                // Derive shortest arc to new direction
+                rotQuat = axes[2].getRotationTo(zAdjustVec);
+
+            }
+            targetOrientation = rotQuat * mOrientation;
+        }
+
+        if (relativeTo == TS_LOCAL || !mParent)
+        {
+            setOrientation(targetOrientation);
+        }
+        else
+        {
+            if (relativeTo == TS_PARENT)
+            {
+                setOrientation(targetOrientation * mParent->getOrientation().Inverse());
+            }
+            else if (relativeTo == TS_WORLD)
+            {
+                setOrientation(targetOrientation * mParent->_getDerivedOrientation().Inverse());
+            }
+        }
+
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        this->setDirection(targetPoint - _getDerivedPosition(), relativeTo, 
+            localDirectionVector);
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_autoTrack(void)
+    {
+        // NB assumes that all scene nodes have been updated
+        if (mAutoTrackTarget)
+        {
+            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset, 
+                TS_WORLD, mAutoTrackLocalDirection);
+            // update self & children
+            _update(true, true);
+        }
+    }
+    //-----------------------------------------------------------------------
+    SceneNode* SceneNode::getParentSceneNode(void) const
+    {
+        return static_cast<SceneNode*>(getParent());
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setVisible(bool visible, bool cascade)
+    {
+        ObjectMap::iterator oi, oiend;
+        oiend = mObjectsByName.end();
+        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
+        {
+            oi->second->setVisible(visible);
+        }
+
+        if (cascade)
+        {
+            ChildNodeMap::iterator i, iend;
+            iend = mChildren.end();
+            for (i = mChildren.begin(); i != iend; ++i)
+            {
+                static_cast<SceneNode*>(i->second)->setVisible(visible, cascade);
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::flipVisibility(bool cascade)
+    {
+        ObjectMap::iterator oi, oiend;
+        oiend = mObjectsByName.end();
+        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
+        {
+            oi->second->setVisible(!oi->second->isVisible());
+        }
+
+        if (cascade)
+        {
+            ChildNodeMap::iterator i, iend;
+            iend = mChildren.end();
+            for (i = mChildren.begin(); i != iend; ++i)
+            {
+                static_cast<SceneNode*>(i->second)->flipVisibility(cascade);
+            }
+        }
+    }
+	#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//-----------------------------------------------------------------------	
+	int SceneNode::lastVisited(void)
+	{
+		return mLastVisited;
+	}
+	//-----------------------------------------------------------------------
+	void SceneNode::setLastVisited(int frameid)
+	{
+		mLastVisited = frameid;
+	}
+	//-----------------------------------------------------------------------	
+	void SceneNode::setNodeVisible(bool visible)
+	{
+		mVisible = visible;
+	}
+	//-----------------------------------------------------------------------	
+	bool SceneNode::isNodeVisible(void)
+	{
+		return mVisible;
+	}
+	//-----------------------------------------------------------------------	
+	int SceneNode::lastRendered(void)
+	{
+		return mLastRendered;
+	}
+	//-----------------------------------------------------------------------
+	void SceneNode::setLastRendered(int frameid)
+	{
+		mLastRendered = frameid;
+	}
+	#endif //GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: trunk/VUT/work/ogre_changes/OgreMain/src/OgreFrustum.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/src/OgreFrustum.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/src/OgreFrustum.cpp	(revision 61)
@@ -0,0 +1,847 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+#include "OgreFrustum.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreSceneNode.h"
+#include "OgreSphere.h"
+#include "OgreLogManager.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreCamera.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+#include "OgreMaterialManager.h"
+#include "OgreRenderSystem.h"
+
+namespace Ogre {
+
+    String Frustum::msMovableType = "Frustum";
+    const Real Frustum::INFINITE_FAR_PLANE_ADJUST = 0.00001;
+    //-----------------------------------------------------------------------
+    Frustum::Frustum() : 
+        mProjType(PT_PERSPECTIVE), 
+        mFOVy(Radian(Math::PI/4.0)), 
+        mFarDist(100000.0f), 
+        mNearDist(100.0f), 
+        mAspect(1.33333333333333f), 
+        mProjMatrix(Matrix4::ZERO), 
+        mViewMatrix(Matrix4::ZERO), 
+        mRecalcFrustum(true), 
+        mRecalcView(true), 
+        mReflect(false), 
+        mReflectMatrix(Matrix4::ZERO), 
+        mLinkedReflectPlane(0),
+        mObliqueDepthProjection(false), 
+        mLinkedObliqueProjPlane(0)
+    {
+        // Initialise vertex & index data
+        mVertexData.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
+        mVertexData.vertexCount = 32;
+        mVertexData.vertexStart = 0;
+        mVertexData.vertexBufferBinding->setBinding( 0,
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+                sizeof(float)*3, 32, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY) );
+
+        // Initialise material
+        mMaterial = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
+        
+        // Alter superclass members
+        mVisible = false;
+        mParentNode = 0;
+
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        mLastLinkedObliqueProjPlane.normal = Vector3::ZERO;
+
+
+        updateView();
+    }
+
+    //-----------------------------------------------------------------------
+    Frustum::~Frustum()
+    {
+        // Do nothing
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFOVy(const Radian& fov)
+    {
+        mFOVy = fov;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const Radian& Frustum::getFOVy(void) const
+    {
+        return mFOVy;
+    }
+
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFarClipDistance(Real farPlane)
+    {
+        mFarDist = farPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getFarClipDistance(void) const
+    {
+        return mFarDist;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setNearClipDistance(Real nearPlane)
+    {
+        if (nearPlane <= 0)
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.",
+                "Frustum::setNearClipDistance");
+        mNearDist = nearPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getNearClipDistance(void) const
+    {
+        return mNearDist;
+    }
+
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getStandardProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mStandardProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getViewMatrix(void) const
+    {
+        updateView();
+
+        return mViewMatrix;
+
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane& Frustum::getFrustumPlane(unsigned short plane) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        return mFrustumPlanes[plane];
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
+    {
+        // Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // Get corners of the box
+        const Vector3* pCorners = bound.getAllCorners();
+
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            if (mFrustumPlanes[plane].getSide(pCorners[0]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[1]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[2]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[3]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[4]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[5]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[6]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[7]) == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // For each plane, see if sphere is on negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            // If the distance from sphere center to plane is negative, and 'more negative' 
+            // than the radius of the sphere, sphere is outside frustum
+            if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius())
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustum(void) const
+    {
+        if (isFrustumOutOfDate())
+        {
+            // Common calcs
+            Radian thetaY (mFOVy * 0.5f);
+            Real tanThetaY = Math::Tan(thetaY);
+            Real tanThetaX = tanThetaY * mAspect;
+            Real vpTop = tanThetaY * mNearDist;
+            Real vpRight = tanThetaX * mNearDist;
+            Real vpBottom = -vpTop;
+            Real vpLeft = -vpRight;
+
+            RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
+            // Recalc if frustum params changed
+            if (mProjType == PT_PERSPECTIVE)
+            {
+
+                // PERSPECTIVE transform, API specific
+                renderSystem->_makeProjectionMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mProjMatrix);
+
+                // PERSPECTIVE transform, API specific for Gpu Programs
+                renderSystem->_makeProjectionMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
+
+                if (mObliqueDepthProjection)
+                {
+                    // Translate the plane into view space
+                    Plane viewSpaceNear = mViewMatrix * mObliqueProjPlane;
+                    renderSystem->_applyObliqueDepthProjection(
+                        mProjMatrix, viewSpaceNear, false);
+                    renderSystem->_applyObliqueDepthProjection(
+                        mStandardProjMatrix, viewSpaceNear, true);
+                }
+            }
+            else if (mProjType == PT_ORTHOGRAPHIC)
+            {
+                // ORTHOGRAPHIC projection, API specific 
+                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mProjMatrix);
+
+                // ORTHOGRAPHIC projection, non-API specific 
+                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
+
+
+            }
+
+            
+            // Calculate bounding box (local)
+            // Box is from 0, down -Z, max dimensions as determined from far plane
+            // If infinite view frustum just pick a far value
+            Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+            Real farTop = tanThetaY * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real farRight = tanThetaX * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real farBottom = -farTop;
+            Real farLeft = -farRight;
+            Vector3 min(-farRight, -farTop, 0);
+            Vector3 max(farRight, farTop, -farDist);
+            mBoundingBox.setExtents(min, max);
+
+            // Calculate vertex positions (local)
+            // 0 is the origin
+            // 1, 2, 3, 4 are the points on the near plane, top left first, clockwise
+            // 5, 6, 7, 8 are the points on the far plane, top left first, clockwise
+            HardwareVertexBufferSharedPtr vbuf = mVertexData.vertexBufferBinding->getBuffer(0);
+            float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
+
+            // near plane (remember frustum is going in -Z direction)
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            // far plane (remember frustum is going in -Z direction)
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            // Sides of the pyramid
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            // Sides of the box
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;  *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+
+            vbuf->unlock();
+
+            mRecalcFrustum = false;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isViewOutOfDate(void) const
+    {
+        bool returnVal = false;
+        // Attached to node?
+        if (mParentNode)
+        {
+            if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation &&
+                mParentNode->_getDerivedPosition() == mLastParentPosition)
+            {
+                returnVal = false;
+            }
+            else
+            {
+                // Ok, we're out of date with SceneNode we're attached to
+                mLastParentOrientation = mParentNode->_getDerivedOrientation();
+                mLastParentPosition = mParentNode->_getDerivedPosition();
+                returnVal = true;
+            }
+        }
+        // Deriving reflection from linked plane?
+        if (mReflect && mLinkedReflectPlane && 
+            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
+        {
+            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+            returnVal = true;
+        }
+
+        return mRecalcView || returnVal;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isFrustumOutOfDate(void) const
+    {
+        // Deriving custom near plane from linked plane?
+        bool returnVal = false;
+        if (mObliqueDepthProjection)
+        {
+            // Always out of date since plane needs to be in view space
+            returnVal = true;
+            // Update derived plane
+            if (mLinkedObliqueProjPlane && 
+                !(mLastLinkedObliqueProjPlane == mLinkedObliqueProjPlane->_getDerivedPlane()))
+            {
+                mObliqueProjPlane = mLinkedObliqueProjPlane->_getDerivedPlane();
+                mLastLinkedObliqueProjPlane = mObliqueProjPlane;
+            }
+        }
+
+        return mRecalcFrustum || returnVal;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::updateView(void) const
+    {
+        if (isViewOutOfDate())
+        {
+            // ----------------------
+            // Update the view matrix
+            // ----------------------
+
+            // View matrix is:
+            //
+            //  [ Lx  Uy  Dz  Tx  ]
+            //  [ Lx  Uy  Dz  Ty  ]
+            //  [ Lx  Uy  Dz  Tz  ]
+            //  [ 0   0   0   1   ]
+            //
+            // Where T = -(Transposed(Rot) * Pos)
+
+            // This is most efficiently done using 3x3 Matrices
+
+            // Get orientation from quaternion
+
+			Matrix3 rot;
+            const Quaternion& orientation = getOrientationForViewUpdate();
+            const Vector3& position = getPositionForViewUpdate();
+			orientation.ToRotationMatrix(rot);
+
+            // Make the translation relative to new axes
+            Matrix3 rotT = rot.Transpose();
+            Vector3 trans = -rotT * position;
+
+            // Make final matrix
+            mViewMatrix = Matrix4::IDENTITY;
+            mViewMatrix = rotT; // fills upper 3x3
+            mViewMatrix[0][3] = trans.x;
+            mViewMatrix[1][3] = trans.y;
+            mViewMatrix[2][3] = trans.z;
+
+            // Deal with reflections
+            if (mReflect)
+            {
+                mViewMatrix = mViewMatrix * mReflectMatrix;
+            }
+
+            // -------------------------
+            // Update the frustum planes
+            // -------------------------
+            updateFrustum();
+
+            Matrix4 combo = mStandardProjMatrix * mViewMatrix;
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
+
+            // Renormalise any normals which were not unit length
+            for(int i=0; i<6; i++ ) 
+            {
+                float length = mFrustumPlanes[i].normal.normalise();
+                mFrustumPlanes[i].d /= length;
+            }
+
+            // Update worldspace corners
+            Matrix4 eyeToWorld = mViewMatrix.inverse();
+            // Get worldspace frustum corners
+            // Treat infinite fardist as some arbitrary far value
+            Real farDist = (mFarDist == 0)? 100000 : mFarDist;
+            Real y = Math::Tan(mFOVy * 0.5);
+            Real x = mAspect * y;
+            Real neary = y * mNearDist;
+            Real fary = y * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real nearx = x * mNearDist;
+            Real farx = x * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            // near
+            mWorldSpaceCorners[0] = eyeToWorld * Vector3( nearx,  neary, -mNearDist);
+            mWorldSpaceCorners[1] = eyeToWorld * Vector3(-nearx,  neary, -mNearDist);
+            mWorldSpaceCorners[2] = eyeToWorld * Vector3(-nearx, -neary, -mNearDist);
+            mWorldSpaceCorners[3] = eyeToWorld * Vector3( nearx, -neary, -mNearDist);
+            // far
+            mWorldSpaceCorners[4] = eyeToWorld * Vector3( farx,  fary, -farDist);
+            mWorldSpaceCorners[5] = eyeToWorld * Vector3(-farx,  fary, -farDist);
+            mWorldSpaceCorners[6] = eyeToWorld * Vector3(-farx, -fary, -farDist);
+            mWorldSpaceCorners[7] = eyeToWorld * Vector3( farx, -fary, -farDist);
+
+
+            mRecalcView = false;
+
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getAspectRatio(void) const
+    {
+        return mAspect;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setAspectRatio(Real r)
+    {
+        mAspect = r;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const AxisAlignedBox& Frustum::getBoundingBox(void) const
+    {
+        return mBoundingBox;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::_updateRenderQueue(RenderQueue* queue)
+    {
+        // Add self 
+        queue->addRenderable(this);
+    }
+    //-----------------------------------------------------------------------
+    const String& Frustum::getMovableType(void) const
+    {
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+	Real Frustum::getBoundingRadius(void) const
+	{
+        return (mFarDist == 0)? 100000 : mFarDist;
+	}
+    //-----------------------------------------------------------------------
+    const MaterialPtr& Frustum::getMaterial(void) const
+    {
+        return mMaterial;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::getRenderOperation(RenderOperation& op) 
+    {
+        updateView();
+        updateFrustum();
+        op.operationType = RenderOperation::OT_LINE_LIST;
+        op.useIndexes = false;
+        op.vertexData = &mVertexData;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::getWorldTransforms(Matrix4* xform) const 
+    {
+        if (mParentNode)
+            mParentNode->getWorldTransforms(xform);
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Frustum::getWorldOrientation(void) const 
+    {
+        if (mParentNode)
+            return mParentNode->_getDerivedOrientation();
+        else
+            return Quaternion::IDENTITY;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Frustum::getWorldPosition(void) const 
+    {
+        if (mParentNode)
+            return mParentNode->_getDerivedPosition();
+        else
+            return Vector3::ZERO;
+    }
+    //-----------------------------------------------------------------------
+    Real Frustum::getSquaredViewDepth(const Camera* cam) const 
+    {
+        // Calc from centre
+        if (mParentNode)
+            return (cam->getDerivedPosition() 
+                - mParentNode->_getDerivedPosition()).squaredLength();
+        else
+            return 0;
+    }
+    //-----------------------------------------------------------------------
+    const LightList& Frustum::getLights(void) const 
+    {
+        // N/A
+        static LightList ll;
+        return ll;
+    }
+    //-----------------------------------------------------------------------
+    const String& Frustum::getName(void) const
+    {
+        // NA
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::_notifyCurrentCamera(Camera* cam)
+    {
+        // NA
+    }
+
+    // -------------------------------------------------------------------
+    void Frustum::invalidateFrustum() const
+    {
+        mRecalcFrustum = true;
+    }
+    // -------------------------------------------------------------------
+    void Frustum::invalidateView() const
+    {
+        mRecalcView = true;
+    }
+    // -------------------------------------------------------------------
+    const Vector3* Frustum::getWorldSpaceCorners(void) const
+    {
+        updateView();
+
+        return mWorldSpaceCorners;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::setProjectionType(ProjectionType pt)
+    {
+        mProjType = pt;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    ProjectionType Frustum::getProjectionType(void) const
+    {
+        return mProjType;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Frustum::getPositionForViewUpdate(void) const
+    {
+        return mLastParentPosition;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Frustum::getOrientationForViewUpdate(void) const
+    {
+        return mLastParentOrientation;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const Plane& p)
+    {
+        mReflect = true;
+        mReflectPlane = p;
+        mLinkedReflectPlane = 0;
+        mReflectMatrix = Math::buildReflectionMatrix(p);
+        invalidateView();
+
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const MovablePlane* p)
+    {
+        mReflect = true;
+        mLinkedReflectPlane = p;
+        mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+        mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+        mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+        invalidateView();
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::disableReflection(void)
+    {
+        mReflect = false;
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        invalidateView();
+    }
+    //---------------------------------------------------------------------
+    bool Frustum::projectSphere(const Sphere& sphere, 
+        Real* left, Real* top, Real* right, Real* bottom) const
+    {
+        // initialise
+        *left = *bottom = -1.0f;
+        *right = *top = 1.0f;
+
+        // Transform light position into camera space
+        Vector3 eyeSpacePos = getViewMatrix() * sphere.getCenter();
+
+        if (eyeSpacePos.z < 0)
+        {
+            Real r = sphere.getRadius();
+            // early-exit
+            if (eyeSpacePos.squaredLength() <= r * r)
+                return false;
+
+            Vector3 screenSpacePos = getStandardProjectionMatrix() * eyeSpacePos;
+
+
+            // perspective attenuate
+            Vector3 spheresize(r, r, eyeSpacePos.z);
+            spheresize = getStandardProjectionMatrix() * spheresize;
+
+            Real possLeft = screenSpacePos.x - spheresize.x;
+            Real possRight = screenSpacePos.x + spheresize.x;
+            Real possTop = screenSpacePos.y + spheresize.y;
+            Real possBottom = screenSpacePos.y - spheresize.y;
+
+            *left = std::max(static_cast<Real>(-1.0), possLeft);
+            *right = std::min(static_cast<Real>(1.0), possRight);
+            *top = std::min(static_cast<Real>(1.0), possTop);
+            *bottom = std::max(static_cast<Real>(-1.0), possBottom);
+
+        }
+
+        return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f);
+
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const MovablePlane* plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = plane;
+        mObliqueProjPlane = plane->_getDerivedPlane();
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const Plane& plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = 0;
+        mObliqueProjPlane = plane;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::disableCustomNearClipPlane(void)
+    {
+        mObliqueDepthProjection = false;
+        mLinkedObliqueProjPlane = 0;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+	//added by matt: 050405
+    bool Frustum::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
+	{
+		intersects = false;
+
+		// Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // Get corners of the box
+        const Vector3* pCorners = bound.getAllCorners();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+			
+			int corner = 0;
+			bool visible = false;
+
+			while((corner < 8) && (!visible || ((plane == FRUSTUM_PLANE_NEAR) && !intersects)))
+			{
+				if(mFrustumPlanes[plane].getSide(pCorners[corner++]) == Plane::NEGATIVE_SIDE)
+				{
+					if(plane == FRUSTUM_PLANE_NEAR)
+						intersects = true;
+				}
+				else
+				{
+					visible = true;
+				}
+			}
+            
+			if(!visible)
+			{
+				// ALL corners on negative side therefore out of view
+				if (culledBy)
+					*culledBy = (FrustumPlane)plane;
+				return false;
+            }
+		}
+
+        return true;
+    }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+} // namespace Ogre
Index: trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 61)
@@ -0,0 +1,4209 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+
+#include "OgreSceneManager.h"
+
+#include "OgreCamera.h"
+#include "OgreRenderSystem.h"
+#include "OgreMeshManager.h"
+#include "OgreMesh.h"
+#include "OgreSubMesh.h"
+#include "OgreEntity.h"
+#include "OgreSubEntity.h"
+#include "OgreLight.h"
+#include "OgreMath.h"
+#include "OgreControllerManager.h"
+#include "OgreMaterialManager.h"
+#include "OgreAnimation.h"
+#include "OgreAnimationTrack.h"
+#include "OgreRenderQueueSortingGrouping.h"
+#include "OgreOverlay.h"
+#include "OgreOverlayManager.h"
+#include "OgreStringConverter.h"
+#include "OgreRenderQueueListener.h"
+#include "OgreBillboardSet.h"
+#include "OgrePass.h"
+#include "OgreTechnique.h"
+#include "OgreTextureUnitState.h"
+#include "OgreException.h"
+#include "OgreLogManager.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreRoot.h"
+#include "OgreSpotShadowFadePng.h"
+#include "OgreGpuProgramManager.h"
+#include "OgreGpuProgram.h"
+#include "OgreShadowVolumeExtrudeProgram.h"
+#include "OgreDataStream.h"
+#include "OgreStaticGeometry.h"
+#include <windows.h> //matt: remove later
+// This class implements the most basic scene manager
+
+#include <cstdio>
+
+namespace Ogre {
+
+//-----------------------------------------------------------------------
+unsigned long SceneManager::WORLD_GEOMETRY_QUERY_MASK = 0x80000000;
+//-----------------------------------------------------------------------
+SceneManager::SceneManager() :
+mRenderQueue(0),
+mSkyPlaneEntity(0),
+mSkyPlaneNode(0),
+mSkyDomeNode(0),
+mSkyBoxNode(0),
+mSkyPlaneEnabled(false),
+mSkyBoxEnabled(false),
+mSkyDomeEnabled(false),
+mFogMode(FOG_NONE),
+mSpecialCaseQueueMode(SCRQM_EXCLUDE),
+mWorldGeometryRenderQueue(RENDER_QUEUE_WORLD_GEOMETRY_1),
+mShadowCasterPlainBlackPass(0),
+mShadowReceiverPass(0),
+mDisplayNodes(false),
+mShowBoundingBoxes(false),
+mShadowTechnique(SHADOWTYPE_NONE),
+mDebugShadows(false),
+mShadowColour(ColourValue(0.25, 0.25, 0.25)),
+mShadowDebugPass(0),
+mShadowStencilPass(0),
+mShadowModulativePass(0),
+mShadowMaterialInitDone(false),
+mShadowIndexBufferSize(51200),
+mFullScreenQuad(0),
+mShadowDirLightExtrudeDist(10000),
+mIlluminationStage(IRS_NONE),
+mShadowTextureSize(512),
+mShadowTextureCount(1),
+mShadowTextureFormat(PF_X8R8G8B8),
+mShadowUseInfiniteFarPlane(true),
+mShadowCasterSphereQuery(0),
+mShadowCasterAABBQuery(0),
+mShadowFarDist(0),
+mShadowFarDistSquared(0),
+mShadowTextureOffset(0.6), 
+mShadowTextureFadeStart(0.7), 
+mShadowTextureFadeEnd(0.9),
+mShadowTextureSelfShadow(false),
+mShadowTextureCustomCasterPass(0),
+mShadowTextureCustomReceiverPass(0),
+mShadowTextureCasterVPDirty(false),
+mShadowTextureReceiverVPDirty(false)
+{
+    // Root scene node
+    mSceneRoot = new SceneNode(this, "root node");
+	mSceneRoot->_notifyRootNode();
+
+    // init sky
+    size_t i;
+    for (i = 0; i < 6; ++i)
+    {
+        mSkyBoxEntity[i] = 0;
+    }
+    for (i = 0; i < 5; ++i)
+    {
+        mSkyDomeEntity[i] = 0;
+    }
+
+	mShadowCasterQueryListener = new ShadowCasterSceneQueryListener(this);
+
+
+}
+//-----------------------------------------------------------------------
+SceneManager::~SceneManager()
+{
+    clearScene();
+    removeAllCameras();
+	delete mShadowCasterQueryListener;
+    delete mSceneRoot;
+    delete mFullScreenQuad;
+    delete mShadowCasterSphereQuery;
+    delete mShadowCasterAABBQuery;
+    delete mRenderQueue;
+}
+//-----------------------------------------------------------------------
+RenderQueue* SceneManager::getRenderQueue(void)
+{
+    if (!mRenderQueue)
+    {
+        initRenderQueue();
+    }
+    return mRenderQueue;
+}
+//-----------------------------------------------------------------------
+void SceneManager::initRenderQueue(void)
+{
+    mRenderQueue = new RenderQueue();
+    // init render queues that do not need shadows
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_BACKGROUND)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_OVERLAY)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_EARLY)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_LATE)->setShadowsEnabled(false);
+}
+//-----------------------------------------------------------------------
+void SceneManager::addSpecialCaseRenderQueue(RenderQueueGroupID qid)
+{
+	mSpecialCaseQueueList.insert(qid);
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeSpecialCaseRenderQueue(RenderQueueGroupID qid)
+{
+	mSpecialCaseQueueList.erase(qid);
+}
+//-----------------------------------------------------------------------
+void SceneManager::clearSpecialCaseRenderQueues(void)
+{
+	mSpecialCaseQueueList.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSpecialCaseRenderQueueMode(SceneManager::SpecialCaseRenderQueueMode mode)
+{
+	mSpecialCaseQueueMode = mode;
+}
+//-----------------------------------------------------------------------
+SceneManager::SpecialCaseRenderQueueMode SceneManager::getSpecialCaseRenderQueueMode(void)
+{
+	return mSpecialCaseQueueMode;
+}
+//-----------------------------------------------------------------------
+bool SceneManager::isRenderQueueToBeProcessed(RenderQueueGroupID qid)
+{
+	bool inList = mSpecialCaseQueueList.find(qid) != mSpecialCaseQueueList.end();
+	return (inList && mSpecialCaseQueueMode == SCRQM_INCLUDE)
+		|| (!inList && mSpecialCaseQueueMode == SCRQM_EXCLUDE);
+}
+//-----------------------------------------------------------------------
+void SceneManager::setWorldGeometryRenderQueue(RenderQueueGroupID qid)
+{
+	mWorldGeometryRenderQueue = qid;
+}
+//-----------------------------------------------------------------------
+RenderQueueGroupID SceneManager::getWorldGeometryRenderQueue(void)
+{
+	return mWorldGeometryRenderQueue;
+}
+//-----------------------------------------------------------------------
+Camera* SceneManager::createCamera(const String& name)
+{
+    // Check name not used
+    if (mCameras.find(name) != mCameras.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A camera with the name " + name + " already exists",
+            "SceneManager::createCamera" );
+    }
+
+    Camera *c = new Camera(name, this);
+    mCameras.insert(CameraList::value_type(name, c));
+
+
+    return c;
+}
+
+//-----------------------------------------------------------------------
+Camera* SceneManager::getCamera(const String& name)
+{
+    CameraList::iterator i = mCameras.find(name);
+    if (i == mCameras.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Camera with name " + name,
+            "SceneManager::getCamera");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeCamera(Camera *cam)
+{
+    // Find in list
+    CameraList::iterator i = mCameras.begin();
+    for (; i != mCameras.end(); ++i)
+    {
+        if (i->second == cam)
+        {
+            mCameras.erase(i);
+            // notify render targets
+            mDestRenderSystem->_notifyCameraRemoved(cam);
+            delete cam;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeCamera(const String& name)
+{
+    // Find in list
+    CameraList::iterator i = mCameras.find(name);
+    if (i != mCameras.end())
+    {
+        // Notify render system
+        mDestRenderSystem->_notifyCameraRemoved(i->second);
+        delete i->second;
+        mCameras.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllCameras(void)
+{
+
+    CameraList::iterator i = mCameras.begin();
+    for (; i != mCameras.end(); ++i)
+    {
+        // Notify render system
+        mDestRenderSystem->_notifyCameraRemoved(i->second);
+        delete i->second;
+    }
+    mCameras.clear();
+}
+
+//-----------------------------------------------------------------------
+Light* SceneManager::createLight(const String& name)
+{
+    // Check name not used
+    if (mLights.find(name) != mLights.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A light with the name " + name + " already exists",
+            "SceneManager::createLight" );
+    }
+
+    Light *l = new Light(name);
+    mLights.insert(SceneLightList::value_type(name, l));
+    return l;
+}
+
+//-----------------------------------------------------------------------
+Light* SceneManager::getLight(const String& name)
+{
+    SceneLightList::iterator i = mLights.find(name);
+    if (i == mLights.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Light with name " + name,
+            "SceneManager::getLight");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeLight(Light *l)
+{
+    // Find in list
+    SceneLightList::iterator i = mLights.begin();
+    for (; i != mLights.end(); ++i)
+    {
+        if (i->second == l)
+        {
+            mLights.erase(i);
+            delete l;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeLight(const String& name)
+{
+    // Find in list
+    SceneLightList::iterator i = mLights.find(name);
+    if (i != mLights.end())
+    {
+        delete i->second;
+        mLights.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllLights(void)
+{
+
+    SceneLightList::iterator i = mLights.begin();
+    for (; i != mLights.end(); ++i)
+    {
+        delete i->second;
+    }
+    mLights.clear();
+}
+//-----------------------------------------------------------------------
+bool SceneManager::lightLess::operator()(const Light* a, const Light* b) const
+{
+    return a->tempSquareDist < b->tempSquareDist;
+}
+//-----------------------------------------------------------------------
+void SceneManager::_populateLightList(const Vector3& position, Real radius, LightList& destList)
+{
+    // Really basic trawl of the lights, then sort
+    // Subclasses could do something smarter
+    destList.clear();
+    Real squaredRadius = radius * radius;
+
+    SceneLightList::iterator i, iend;
+    iend = mLights.end();
+    for (i = mLights.begin(); i != iend; ++i)
+    {
+        Light* lt = i->second;
+        if (lt->isVisible())
+        {
+            if (lt->getType() == Light::LT_DIRECTIONAL)
+            {
+                // No distance
+                lt->tempSquareDist = 0.0f;
+                destList.push_back(lt);
+            }
+            else
+            {
+                // Calc squared distance
+                lt->tempSquareDist = (lt->getDerivedPosition() - position).squaredLength();
+                lt->tempSquareDist -= squaredRadius;
+                // only add in-range lights
+                Real range = lt->getAttenuationRange();
+                if (lt->tempSquareDist <= (range * range))
+                {
+                    destList.push_back(lt);
+                }
+            }
+        }
+    }
+
+    // Sort
+    std::sort(destList.begin(), destList.end(), lightLess());
+
+
+}
+//-----------------------------------------------------------------------
+Entity* SceneManager::createEntity(const String& entityName, PrefabType ptype)
+{
+    switch (ptype)
+    {
+    case PT_PLANE:
+        return createEntity(entityName, "Prefab_Plane");
+
+        break;
+    }
+
+    OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+        "Unknown prefab type for entity " + entityName,
+        "SceneManager::createEntity");
+}
+
+//-----------------------------------------------------------------------
+Entity* SceneManager::createEntity(
+                                   const String& entityName,
+                                   const String& meshName )
+{
+    // Check name not used
+    EntityList::iterator it = mEntities.find( entityName );
+    if( it != mEntities.end() )
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "An entity with the name " + entityName + " already exists",
+            "SceneManager::createEntity" );
+    }
+
+    // Get mesh (load if required)
+    MeshPtr pMesh = MeshManager::getSingleton().load( 
+        meshName, 
+        // note that you can change the group by pre-loading the mesh 
+        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
+
+    // Create entity
+    Entity* e = new Entity( entityName, pMesh, this );
+
+    // Add to internal list
+    mEntities[entityName] = e; //.insert(EntityList::value_type(entityName, e));
+
+    return e;
+}
+
+//-----------------------------------------------------------------------
+Entity* SceneManager::getEntity(const String& name)
+{
+    EntityList::iterator i = mEntities.find(name);
+    if (i == mEntities.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Entity with name " + name,
+            "SceneManager::getEntity");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeEntity(Entity *cam)
+{
+    // Find in list
+    EntityList::iterator i = mEntities.begin();
+    for (; i != mEntities.end(); ++i)
+    {
+        if (i->second == cam)
+        {
+            mEntities.erase(i);
+            delete cam;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeEntity(const String& name)
+{
+    // Find in list
+    EntityList::iterator i = mEntities.find(name);
+    if (i != mEntities.end())
+    {
+        delete i->second;
+        mEntities.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllEntities(void)
+{
+
+    EntityList::iterator i = mEntities.begin();
+    for (; i != mEntities.end(); ++i)
+    {
+        delete i->second;
+    }
+    mEntities.clear();
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllBillboardSets(void)
+{
+    // Delete all BillboardSets
+    for (BillboardSetList::iterator bi = mBillboardSets.begin();
+        bi != mBillboardSets.end(); ++bi)
+    {
+        delete bi->second;
+    }
+    mBillboardSets.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::clearScene(void)
+{
+	removeAllStaticGeometry();
+    // Delete all SceneNodes, except root that is
+    for (SceneNodeList::iterator i = mSceneNodes.begin();
+        i != mSceneNodes.end(); ++i)
+    {
+        delete i->second;
+    }
+    mSceneNodes.clear();
+    mAutoTrackingSceneNodes.clear();
+
+    // Clear root node of all children
+    mSceneRoot->removeAllChildren();
+    mSceneRoot->detachAllObjects();
+
+    removeAllEntities();
+    removeAllBillboardSets();
+    removeAllLights();
+
+    // Clear animations
+    destroyAllAnimations();
+
+    // Remove sky nodes since they've been deleted
+    mSkyBoxNode = mSkyPlaneNode = mSkyDomeNode = 0;
+    mSkyBoxEnabled = mSkyPlaneEnabled = mSkyDomeEnabled = false; 
+
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::createSceneNode(void)
+{
+    SceneNode* sn = new SceneNode(this);
+    assert(mSceneNodes.find(sn->getName()) == mSceneNodes.end());
+    mSceneNodes[sn->getName()] = sn;
+    return sn;
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::createSceneNode(const String& name)
+{
+    // Check name not used
+    if (mSceneNodes.find(name) != mSceneNodes.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A scene node with the name " + name + " already exists",
+            "SceneManager::createSceneNode" );
+    }
+
+    SceneNode* sn = new SceneNode(this, name);
+    mSceneNodes[sn->getName()] = sn;
+    return sn;
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroySceneNode(const String& name)
+{
+    SceneNodeList::iterator i = mSceneNodes.find(name);
+
+    if (i == mSceneNodes.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
+            "SceneManager::destroySceneNode");
+    }
+
+    // Find any scene nodes which are tracking this node, and turn them off
+    AutoTrackingSceneNodes::iterator ai, aiend;
+    aiend = mAutoTrackingSceneNodes.end();
+    for (ai = mAutoTrackingSceneNodes.begin(); ai != aiend; ++ai)
+    {
+        SceneNode* n = *ai;
+        // Tracking this node
+        if (n->getAutoTrackTarget() == i->second)
+        {
+            // turn off, this will notify SceneManager to remove
+            n->setAutoTracking(false);
+            // no need to reset iterator since set erase does not invalidate
+        }
+        // node is itself a tracker
+        else if (n == i->second)
+        {
+            mAutoTrackingSceneNodes.erase(ai);
+        }
+    }
+
+    delete i->second;
+    mSceneNodes.erase(i);
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::getRootSceneNode(void) const
+{
+    return mSceneRoot;
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::getSceneNode(const String& name) const
+{
+    SceneNodeList::const_iterator i = mSceneNodes.find(name);
+
+    if (i == mSceneNodes.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
+            "SceneManager::getSceneNode");
+    }
+
+    return i->second;
+
+}
+//-----------------------------------------------------------------------
+Pass* SceneManager::setPass(Pass* pass)
+{
+    static bool lastUsedVertexProgram = false;
+    static bool lastUsedFragmentProgram = false;
+
+    if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
+    {
+        // Derive a special shadow caster pass from this one
+        pass = deriveShadowCasterPass(pass);
+    }
+    else if (mIlluminationStage == IRS_RENDER_MODULATIVE_PASS)
+    {
+        pass = deriveShadowReceiverPass(pass);
+    }
+
+    // TEST
+    /*
+    LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) + 
+    " of " + pass->getParent()->getParent()->getName());
+    */
+    bool passSurfaceAndLightParams = true;
+
+    if (pass->hasVertexProgram())
+    {
+        mDestRenderSystem->bindGpuProgram(pass->getVertexProgram()->_getBindingDelegate());
+        // bind parameters later since they can be per-object
+        lastUsedVertexProgram = true;
+        // does the vertex program want surface and light params passed to rendersystem?
+        passSurfaceAndLightParams = pass->getVertexProgram()->getPassSurfaceAndLightStates();
+    }
+    else
+    {
+        // Unbind program?
+        if (lastUsedVertexProgram)
+        {
+			//matt: remove later
+			//OutputDebugString("unbinding vertex program\n");
+
+            mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+            lastUsedVertexProgram = false;
+        }
+        // Set fixed-function vertex parameters
+    }
+
+    if (passSurfaceAndLightParams)
+    {
+        // Set surface reflectance properties, only valid if lighting is enabled
+        if (pass->getLightingEnabled())
+        {
+            mDestRenderSystem->_setSurfaceParams( 
+                pass->getAmbient(), 
+                pass->getDiffuse(), 
+                pass->getSpecular(), 
+                pass->getSelfIllumination(), 
+                pass->getShininess(),
+		pass->getVertexColourTracking() );
+        }
+
+        // Dynamic lighting enabled?
+        mDestRenderSystem->setLightingEnabled(pass->getLightingEnabled());
+    }
+
+    // Using a fragment program?
+    if (pass->hasFragmentProgram())
+    {
+        mDestRenderSystem->bindGpuProgram(
+            pass->getFragmentProgram()->_getBindingDelegate());
+        // bind parameters later since they can be per-object
+        lastUsedFragmentProgram = true;
+    }
+    else
+    {
+        // Unbind program?
+        if (lastUsedFragmentProgram)
+        {
+            mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+            lastUsedFragmentProgram = false;
+        }
+
+        // Set fixed-function fragment settings
+
+        // Fog (assumes we want pixel fog which is the usual)
+        // New fog params can either be from scene or from material
+        FogMode newFogMode;
+        ColourValue newFogColour;
+        Real newFogStart, newFogEnd, newFogDensity;
+        if (pass->getFogOverride())
+        {
+            // New fog params from material
+            newFogMode = pass->getFogMode();
+            newFogColour = pass->getFogColour();
+            newFogStart = pass->getFogStart();
+            newFogEnd = pass->getFogEnd();
+            newFogDensity = pass->getFogDensity();
+        }
+        else
+        {
+            // New fog params from scene
+            newFogMode = mFogMode;
+            newFogColour = mFogColour;
+            newFogStart = mFogStart;
+            newFogEnd = mFogEnd;
+            newFogDensity = mFogDensity;
+        }
+        mDestRenderSystem->_setFog(
+            newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
+
+    }
+
+    // The rest of the settings are the same no matter whether we use programs or not
+
+    // Set scene blending
+    mDestRenderSystem->_setSceneBlending(
+        pass->getSourceBlendFactor(), pass->getDestBlendFactor());
+
+
+    // Texture unit settings
+
+    Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
+    size_t unit = 0;
+    while(texIter.hasMoreElements())
+    {
+        TextureUnitState* pTex = texIter.getNext();
+        mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
+        ++unit;
+    }
+    // Disable remaining texture units
+    mDestRenderSystem->_disableTextureUnitsFrom(pass->getNumTextureUnitStates());
+
+    // Set up non-texture related material settings
+    // Depth buffer settings
+    mDestRenderSystem->_setDepthBufferFunction(pass->getDepthFunction());
+    mDestRenderSystem->_setDepthBufferCheckEnabled(pass->getDepthCheckEnabled());
+    mDestRenderSystem->_setDepthBufferWriteEnabled(pass->getDepthWriteEnabled());
+    mDestRenderSystem->_setDepthBias(pass->getDepthBias());
+	// Alpha-reject settings
+	mDestRenderSystem->_setAlphaRejectSettings(
+		pass->getAlphaRejectFunction(), pass->getAlphaRejectValue());
+    // Set colour write mode
+    // Right now we only use on/off, not per-channel
+    bool colWrite = pass->getColourWriteEnabled();
+    mDestRenderSystem->_setColourBufferWriteEnabled(colWrite, colWrite, colWrite, colWrite);
+    // Culling mode
+    mDestRenderSystem->_setCullingMode(pass->getCullingMode());
+    // Shading
+    mDestRenderSystem->setShadingType(pass->getShadingMode());
+
+    return pass;
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
+{
+    Root::getSingleton()._setCurrentSceneManager(this);
+    // Prep Pass for use in debug shadows
+    initShadowVolumeMaterials();
+    // Perform a quick pre-check to see whether we should override far distance
+    // When using stencil volumes we have to use infinite far distance
+    // to prevent dark caps getting clipped
+    if ((mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE ||
+        mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE) && 
+        camera->getFarClipDistance() != 0 && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE) && 
+        mShadowUseInfiniteFarPlane)
+    {
+        // infinite far distance
+        camera->setFarClipDistance(0);
+    }
+
+    mCameraInProgress = camera;
+    mCamChanged = true;
+
+
+    // Update the scene, only do this once per frame
+    static unsigned long lastFrameNumber = 0;
+    unsigned long thisFrameNumber = Root::getSingleton().getCurrentFrameNumber();
+    if (thisFrameNumber != lastFrameNumber)
+    {
+        // Update animations
+        _applySceneAnimations();
+        // Update controllers 
+        ControllerManager::getSingleton().updateAllControllers();
+        lastFrameNumber = thisFrameNumber;
+    }
+
+    // Update scene graph for this camera (can happen multiple times per frame)
+    _updateSceneGraph(camera);
+
+    // Auto-track nodes
+    AutoTrackingSceneNodes::iterator atsni, atsniend;
+    atsniend = mAutoTrackingSceneNodes.end();
+    for (atsni = mAutoTrackingSceneNodes.begin(); atsni != atsniend; ++atsni)
+    {
+        (*atsni)->_autoTrack();
+    }
+    // Auto-track camera if required
+    camera->_autoTrack();
+
+
+    // Are we using any shadows at all?
+    if (mShadowTechnique != SHADOWTYPE_NONE && 
+        mIlluminationStage != IRS_RENDER_TO_TEXTURE)
+    {
+        // Locate any lights which could be affecting the frustum
+        findLightsAffectingFrustum(camera);
+        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+        {
+            // *******
+            // WARNING
+            // *******
+            // This call will result in re-entrant calls to this method
+            // therefore anything which comes before this is NOT 
+            // guaranteed persistent. Make sure that anything which 
+            // MUST be specific to this camera / target is done 
+            // AFTER THIS POINT
+            prepareShadowTextures(camera, vp);
+            // reset the cameras because of the re-entrant call
+            mCameraInProgress = camera;
+            mCamChanged = true;
+        }
+    }
+
+    // Invert vertex winding?
+    if (camera->isReflected())
+    {
+        mDestRenderSystem->setInvertVertexWinding(true);
+    }
+    else
+    {
+        mDestRenderSystem->setInvertVertexWinding(false);
+    }
+
+    // Set the viewport
+    setViewport(vp);
+
+    // Tell params about camera
+    mAutoParamDataSource.setCurrentCamera(camera);
+    // Set autoparams for finite dir light extrusion
+    mAutoParamDataSource.setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist);
+
+    // Tell params about current ambient light
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+
+    // Tell params about render target
+    mAutoParamDataSource.setCurrentRenderTarget(vp->getTarget());
+
+
+    // Set camera window clipping planes (if any)
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES))
+    {
+        if (camera->isWindowSet())  
+        {
+            const std::vector<Plane>& planeList = 
+                camera->getWindowPlanes();
+            for (ushort i = 0; i < 4; ++i)
+            {
+                mDestRenderSystem->enableClipPlane(i, true);
+                mDestRenderSystem->setClipPlane(i, planeList[i]);
+            }
+        }
+        else
+        {
+            for (ushort i = 0; i < 4; ++i)
+            {
+                mDestRenderSystem->enableClipPlane(i, false);
+            }
+        }
+    }
+
+    // Clear the render queue
+    getRenderQueue()->clear();
+
+    // Parse the scene and tag visibles
+    _findVisibleObjects(camera, 
+        mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
+    // Add overlays, if viewport deems it
+    if (vp->getOverlaysEnabled())
+    {
+        OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp);
+    }
+    // Queue skies
+    _queueSkiesForRendering(camera);
+
+
+    // Don't do view / proj here anymore
+    // Checked per renderable now, although only changed when required
+    //mDestRenderSystem->_setViewMatrix(camera->getViewMatrix());
+    //mDestRenderSystem->_setProjectionMatrix(camera->getProjectionMatrix());
+
+    mDestRenderSystem->_beginGeometryCount();
+    // Begin the frame
+    mDestRenderSystem->_beginFrame();
+
+    // Set rasterisation mode
+    mDestRenderSystem->_setRasterisationMode(camera->getDetailLevel());
+
+    // Render scene content 
+    _renderVisibleObjects();
+
+    // End frame
+    mDestRenderSystem->_endFrame();
+
+    // Notify camera or vis faces
+    camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
+
+
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::_setDestinationRenderSystem(RenderSystem* sys)
+{
+    mDestRenderSystem = sys;
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::setWorldGeometry(const String& filename)
+{
+    // This default implementation cannot handle world geometry
+    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+        "World geometry is not supported by the generic SceneManager.",
+        "SceneManager::setWorldGeometry");
+}
+
+//-----------------------------------------------------------------------
+bool SceneManager::materialLess::operator() (const Material* x, const Material* y) const
+{
+    // If x transparent and y not, x > y (since x has to overlap y)
+    if (x->isTransparent() && !y->isTransparent())
+    {
+        return false;
+    }
+    // If y is transparent and x not, x < y
+    else if (!x->isTransparent() && y->isTransparent())
+    {
+        return true;
+    }
+    else
+    {
+        // Otherwise don't care (both transparent or both solid)
+        // Just arbitrarily use pointer
+        return x < y;
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::setSkyPlane(
+                               bool enable,
+                               const Plane& plane,
+                               const String& materialName,
+                               Real gscale,
+                               Real tiling,
+                               bool drawFirst,
+                               Real bow, 
+                               int xsegments, int ysegments, 
+                               const String& groupName)
+{
+    mSkyPlaneEnabled = enable;
+    if (enable)
+    {
+        String meshName = "SkyPlane";
+        mSkyPlane = plane;
+
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky plane material '" + materialName + "' not found.",
+                "SceneManager::setSkyPlane");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+
+        mSkyPlaneDrawFirst = drawFirst;
+
+        // Set up the plane
+        MeshPtr planeMesh = MeshManager::getSingleton().getByName(meshName);
+        if (!planeMesh.isNull())
+        {
+            // Destroy the old one
+            MeshManager::getSingleton().remove(planeMesh->getHandle());
+        }
+
+        // Create up vector
+        Vector3 up = plane.normal.crossProduct(Vector3::UNIT_X);
+        if (up == Vector3::ZERO)
+            up = plane.normal.crossProduct(-Vector3::UNIT_Z);
+
+        // Create skyplane
+        if( bow > 0 )
+        {
+            // Build a curved skyplane
+            planeMesh = MeshManager::getSingleton().createCurvedPlane(
+                meshName, groupName, plane, gscale * 100, gscale * 100, gscale * bow * 100, 
+                xsegments, ysegments, false, 1, tiling, tiling, up);
+        }
+        else
+        {
+            planeMesh = MeshManager::getSingleton().createPlane(
+                meshName, groupName, plane, gscale * 100, gscale * 100, xsegments, ysegments, false, 
+                1, tiling, tiling, up);
+        }
+
+        // Create entity 
+        if (mSkyPlaneEntity)
+        {
+            // destroy old one, do it by name for speed
+            removeEntity(meshName);
+        }
+        // Create, use the same name for mesh and entity
+        mSkyPlaneEntity = createEntity(meshName, meshName);
+        mSkyPlaneEntity->setMaterialName(materialName);
+        mSkyPlaneEntity->setCastShadows(false);
+
+        // Create node and attach
+        if (!mSkyPlaneNode)
+        {
+            mSkyPlaneNode = createSceneNode(meshName + "Node");
+        }
+        else
+        {
+            mSkyPlaneNode->detachAllObjects();
+        }
+        mSkyPlaneNode->attachObject(mSkyPlaneEntity);
+
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSkyBox(
+                             bool enable,
+                             const String& materialName,
+                             Real distance,
+                             bool drawFirst,
+                             const Quaternion& orientation,
+                             const String& groupName)
+{
+    mSkyBoxEnabled = enable;
+    if (enable)
+    {
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky box material '" + materialName + "' not found.",
+                "SceneManager::setSkyBox");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+        // Also clamp texture, don't wrap (otherwise edges can get filtered)
+        m->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+
+
+        mSkyBoxDrawFirst = drawFirst;
+
+        // Create node 
+        if (!mSkyBoxNode)
+        {
+            mSkyBoxNode = createSceneNode("SkyBoxNode");
+        }
+        else
+        {
+            mSkyBoxNode->detachAllObjects();
+        }
+
+        MaterialManager& matMgr = MaterialManager::getSingleton();
+        // Set up the box (6 planes)
+        for (int i = 0; i < 6; ++i)
+        {
+            MeshPtr planeMesh = createSkyboxPlane((BoxPlane)i, distance, orientation, groupName);
+            String entName = "SkyBoxPlane" + StringConverter::toString(i);
+
+            // Create entity 
+            if (mSkyBoxEntity[i])
+            {
+                // destroy old one, do it by name for speed
+                removeEntity(entName);
+            }
+            mSkyBoxEntity[i] = createEntity(entName, planeMesh->getName());
+            mSkyBoxEntity[i]->setCastShadows(false);
+            // Have to create 6 materials, one for each frame
+            // Used to use combined material but now we're using queue we can't split to change frame
+            // This doesn't use much memory because textures aren't duplicated
+            MaterialPtr boxMat = matMgr.getByName(entName);
+            if (boxMat.isNull())
+            {
+                // Create new by clone
+                boxMat = m->clone(entName);
+                boxMat->load();
+            }
+            else
+            {
+                // Copy over existing
+                m->copyDetailsTo(boxMat);
+                boxMat->load();
+            }
+            // Set active frame
+            boxMat->getBestTechnique()->getPass(0)->getTextureUnitState(0)
+                ->setCurrentFrame(i);
+
+            mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
+
+            // Attach to node
+            mSkyBoxNode->attachObject(mSkyBoxEntity[i]);
+        } // for each plane
+
+    }
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSkyDome(
+                              bool enable,
+                              const String& materialName,
+                              Real curvature,
+                              Real tiling,
+                              Real distance,
+                              bool drawFirst,
+                              const Quaternion& orientation,
+                              int xsegments, int ysegments, int ySegmentsToKeep,
+                              const String& groupName)
+{
+    mSkyDomeEnabled = enable;
+    if (enable)
+    {
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky dome material '" + materialName + " not found.",
+                "SceneManager::setSkyDome");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+
+        mSkyDomeDrawFirst = drawFirst;
+
+        // Create node 
+        if (!mSkyDomeNode)
+        {
+            mSkyDomeNode = createSceneNode("SkyDomeNode");
+        }
+        else
+        {
+            mSkyDomeNode->detachAllObjects();
+        }
+
+        // Set up the dome (5 planes)
+        for (int i = 0; i < 5; ++i)
+        {
+            MeshPtr planeMesh = createSkydomePlane((BoxPlane)i, curvature, 
+                tiling, distance, orientation, xsegments, ysegments, 
+                i!=BP_UP ? ySegmentsToKeep : -1, groupName);
+
+            String entName = "SkyDomePlane" + StringConverter::toString(i);
+
+            // Create entity 
+            if (mSkyDomeEntity[i])
+            {
+                // destroy old one, do it by name for speed
+                removeEntity(entName);
+            }
+            mSkyDomeEntity[i] = createEntity(entName, planeMesh->getName());
+            mSkyDomeEntity[i]->setMaterialName(m->getName());
+            mSkyDomeEntity[i]->setCastShadows(false);
+
+            // Attach to node
+            mSkyDomeNode->attachObject(mSkyDomeEntity[i]);
+        } // for each plane
+
+    }
+}
+//-----------------------------------------------------------------------
+MeshPtr SceneManager::createSkyboxPlane(
+                                      BoxPlane bp,
+                                      Real distance,
+                                      const Quaternion& orientation,
+                                      const String& groupName)
+{
+    Plane plane;
+    String meshName;
+    Vector3 up;
+
+    meshName = "SkyBoxPlane_";
+    // Set up plane equation
+    plane.d = distance;
+    switch(bp)
+    {
+    case BP_FRONT:
+        plane.normal = Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Front";
+        break;
+    case BP_BACK:
+        plane.normal = -Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Back";
+        break;
+    case BP_LEFT:
+        plane.normal = Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Left";
+        break;
+    case BP_RIGHT:
+        plane.normal = -Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Right";
+        break;
+    case BP_UP:
+        plane.normal = -Vector3::UNIT_Y;
+        up = Vector3::UNIT_Z;
+        meshName += "Up";
+        break;
+    case BP_DOWN:
+        plane.normal = Vector3::UNIT_Y;
+        up = -Vector3::UNIT_Z;
+        meshName += "Down";
+        break;
+    }
+    // Modify by orientation
+    plane.normal = orientation * plane.normal;
+    up = orientation * up;
+
+
+    // Check to see if existing plane
+    MeshManager& mm = MeshManager::getSingleton();
+    MeshPtr planeMesh = mm.getByName(meshName);
+    if(!planeMesh.isNull())
+    {
+        // destroy existing
+        mm.remove(planeMesh->getHandle());
+    }
+    // Create new
+    Real planeSize = distance * 2;
+    const int BOX_SEGMENTS = 1;
+    planeMesh = mm.createPlane(meshName, groupName, plane, planeSize, planeSize, 
+        BOX_SEGMENTS, BOX_SEGMENTS, false, 1, 1, 1, up);
+
+    //planeMesh->_dumpContents(meshName);
+
+    return planeMesh;
+
+}
+//-----------------------------------------------------------------------
+MeshPtr SceneManager::createSkydomePlane(
+                                       BoxPlane bp,
+                                       Real curvature,
+                                       Real tiling,
+                                       Real distance,
+                                       const Quaternion& orientation,
+                                       int xsegments, int ysegments, int ysegments_keep, 
+                                       const String& groupName)
+{
+
+    Plane plane;
+    String meshName;
+    Vector3 up;
+
+    meshName = "SkyDomePlane_";
+    // Set up plane equation
+    plane.d = distance;
+    switch(bp)
+    {
+    case BP_FRONT:
+        plane.normal = Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Front";
+        break;
+    case BP_BACK:
+        plane.normal = -Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Back";
+        break;
+    case BP_LEFT:
+        plane.normal = Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Left";
+        break;
+    case BP_RIGHT:
+        plane.normal = -Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Right";
+        break;
+    case BP_UP:
+        plane.normal = -Vector3::UNIT_Y;
+        up = Vector3::UNIT_Z;
+        meshName += "Up";
+        break;
+    case BP_DOWN:
+        // no down
+        return MeshPtr();
+    }
+    // Modify by orientation
+    plane.normal = orientation * plane.normal;
+    up = orientation * up;
+
+    // Check to see if existing plane
+    MeshManager& mm = MeshManager::getSingleton();
+    MeshPtr planeMesh = mm.getByName(meshName);
+    if(!planeMesh.isNull())
+    {
+        // destroy existing
+        mm.remove(planeMesh->getHandle());
+    }
+    // Create new
+    Real planeSize = distance * 2;
+    planeMesh = mm.createCurvedIllusionPlane(meshName, groupName, plane, 
+        planeSize, planeSize, curvature, 
+        xsegments, ysegments, false, 1, tiling, tiling, up, 
+        orientation, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
+        false, false, ysegments_keep);
+
+    //planeMesh->_dumpContents(meshName);
+
+    return planeMesh;
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::_updateSceneGraph(Camera* cam)
+{
+    // Cascade down the graph updating transforms & world bounds
+    // In this implementation, just update from the root
+    // Smarter SceneManager subclasses may choose to update only
+    //   certain scene graph branches
+    mSceneRoot->_update(true, false);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
+{
+    // Tell nodes to find, cascade down all nodes
+    mSceneRoot->_findVisibleObjects(cam, getRenderQueue(), true, 
+        mDisplayNodes, onlyShadowCasters);
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderVisibleObjects(void)
+{
+    // Render each separate queue
+    RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
+
+    // NB only queues which have been created are rendered, no time is wasted
+    //   parsing through non-existent queues (even though there are 10 available)
+
+    while (queueIt.hasMoreElements())
+    {
+        // Get queue group id
+        RenderQueueGroupID qId = queueIt.peekNextKey();
+		RenderQueueGroup* pGroup = queueIt.getNext();
+		// Skip this one if not to be processed
+		if (!isRenderQueueToBeProcessed(qId))
+			continue;
+
+
+        bool repeatQueue = false;
+        do // for repeating queues
+        {
+            // Fire queue started event
+            if (fireRenderQueueStarted(qId))
+            {
+                // Someone requested we skip this queue
+                continue;
+            }
+
+            renderQueueGroupObjects(pGroup);
+
+            // Fire queue ended event
+            if (fireRenderQueueEnded(qId))
+            {
+                // Someone requested we repeat this queue
+                repeatQueue = true;
+            }
+            else
+            {
+                repeatQueue = false;
+            }
+        } while (repeatQueue);
+
+    } // for each queue group
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+    LightList lightList;
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Clear light list
+        lightList.clear();
+
+        // Render all the ambient passes first, no light iteration, no lights
+        mIlluminationStage = IRS_AMBIENT;
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &lightList);
+        // Also render any objects which have receive shadows disabled
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+
+
+        // Now iterate per light
+        mIlluminationStage = IRS_PER_LIGHT;
+
+        // Iterate over lights, render all volumes to stencil
+        LightList::const_iterator li, liend;
+        liend = mLightsAffectingFrustum.end();
+
+        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
+        {
+            Light* l = *li;
+            // Set light state
+
+            if (l->getCastShadows())
+            {
+                // Clear stencil
+                mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
+                renderShadowVolumesToStencil(l, mCameraInProgress);
+                // turn stencil check on
+                mDestRenderSystem->setStencilCheckEnabled(true);
+                // NB we render where the stencil is equal to zero to render lit areas
+                mDestRenderSystem->setStencilBufferParams(CMPF_EQUAL, 0);
+            }
+
+            // render lighting passes for this light
+            if (lightList.empty())
+                lightList.push_back(l);
+            else
+                lightList[0] = l;
+            renderObjects(pPriorityGrp->_getSolidPassesDiffuseSpecular(), false, &lightList);
+
+            // Reset stencil params
+            mDestRenderSystem->setStencilBufferParams();
+            mDestRenderSystem->setStencilCheckEnabled(false);
+            mDestRenderSystem->_setDepthBufferParams();
+
+        }// for each light
+
+
+        // Now render decal passes, no need to set lights as lighting will be disabled
+        mIlluminationStage = IRS_DECAL;
+        renderObjects(pPriorityGrp->_getSolidPassesDecal(), false);
+
+
+    }// for each priority
+
+    // reset lighting stage
+    mIlluminationStage = IRS_NONE;
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
+    while (groupIt2.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderModulativeStencilShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    /* For each light, we need to render all the solids from each group, 
+    then do the modulative shadows, then render the transparents from
+    each group.
+    Now, this means we are going to reorder things more, but that it required
+    if the shadows are to look correct. The overall order is preserved anyway,
+    it's just that all the transparents are at the end instead of them being
+    interleaved as in the normal rendering loop. 
+    */
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do (shadowable) solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+    }
+
+
+    // Iterate over lights, render all volumes to stencil
+    LightList::const_iterator li, liend;
+    liend = mLightsAffectingFrustum.end();
+
+    for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
+    {
+        Light* l = *li;
+        if (l->getCastShadows())
+        {
+            // Clear stencil
+            mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
+            renderShadowVolumesToStencil(l, mCameraInProgress);
+            // render full-screen shadow modulator for all lights
+            setPass(mShadowModulativePass);
+            // turn stencil check on
+            mDestRenderSystem->setStencilCheckEnabled(true);
+            // NB we render where the stencil is not equal to zero to render shadows, not lit areas
+            mDestRenderSystem->setStencilBufferParams(CMPF_NOT_EQUAL, 0);
+            renderSingleObject(mFullScreenQuad, mShadowModulativePass, false);
+            // Reset stencil params
+            mDestRenderSystem->setStencilBufferParams();
+            mDestRenderSystem->setStencilCheckEnabled(false);
+            mDestRenderSystem->_setDepthBufferParams();
+        }
+
+    }// for each light
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
+    while (groupIt2.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
+
+        // Do non-shadowable solids
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+
+    }// for each priority
+
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
+    while (groupIt3.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTextureShadowCasterQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    static LightList nullLightList;
+    // This is like the basic group render, except we skip all transparents
+    // and we also render any non-shadowed objects
+    // Note that non-shadow casters will have already been eliminated during
+    // _findVisibleObjects
+
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    // Override auto param ambient to force vertex programs and fixed function to 
+    // use shadow colour
+    mAutoParamDataSource.setAmbientLightColour(mShadowColour);
+    mDestRenderSystem->setAmbientLight(mShadowColour.r, mShadowColour.g, mShadowColour.b);
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids, override light list incase any vertex programs use them
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &nullLightList);
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), false, &nullLightList);
+		// Do transparents that cast shadows
+		renderTransparentShadowCasterObjects(
+				pPriorityGrp->_getTransparentPasses(), false, &nullLightList);
+
+
+    }// for each priority
+
+    // reset ambient light
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    /* For each light, we need to render all the solids from each group, 
+    then do the modulative shadows, then render the transparents from
+    each group.
+    Now, this means we are going to reorder things more, but that it required
+    if the shadows are to look correct. The overall order is preserved anyway,
+    it's just that all the transparents are at the end instead of them being
+    interleaved as in the normal rendering loop. 
+    */
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+    }
+
+
+    // Iterate over lights, render received shadows
+    // only perform this if we're in the 'normal' render stage, to avoid
+    // doing it during the render to texture
+    if (mIlluminationStage == IRS_NONE)
+    {
+        mIlluminationStage = IRS_RENDER_MODULATIVE_PASS;
+
+        LightList::iterator i, iend;
+        ShadowTextureList::iterator si, siend;
+        iend = mLightsAffectingFrustum.end();
+        siend = mShadowTextures.end();
+        for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
+            i != iend && si != siend; ++i)
+        {
+            Light* l = *i;
+
+            if (!l->getCastShadows())
+                continue;
+
+            mCurrentShadowTexture = *si;
+            // Hook up receiver texture
+            mShadowReceiverPass->getTextureUnitState(0)->setTextureName(
+                mCurrentShadowTexture->getName());
+            // Hook up projection frustum
+            mShadowReceiverPass->getTextureUnitState(0)->setProjectiveTexturing(
+                true, mCurrentShadowTexture->getViewport(0)->getCamera());
+            mAutoParamDataSource.setTextureProjector(
+                mCurrentShadowTexture->getViewport(0)->getCamera());
+            // if this light is a spotlight, we need to add the spot fader layer
+            if (l->getType() == Light::LT_SPOTLIGHT)
+            {
+                // Add spot fader if not present already
+                if (mShadowReceiverPass->getNumTextureUnitStates() == 1)
+                {
+                    TextureUnitState* t = 
+                        mShadowReceiverPass->createTextureUnitState("spot_shadow_fade.png");
+                    t->setProjectiveTexturing(
+                        true, mCurrentShadowTexture->getViewport(0)->getCamera());
+                    t->setColourOperation(LBO_ADD);
+                    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+                }
+                else
+                {
+                    // Just set projector
+                    TextureUnitState* t = 
+                        mShadowReceiverPass->getTextureUnitState(1);
+                    t->setProjectiveTexturing(
+                        true, mCurrentShadowTexture->getViewport(0)->getCamera());
+                }
+            }
+            else if (mShadowReceiverPass->getNumTextureUnitStates() > 1)
+            {
+                // remove spot fader layer
+                mShadowReceiverPass->removeTextureUnitState(1);
+
+            }
+            mShadowReceiverPass->_load();
+
+            if (l->getCastShadows() && pGroup->getShadowsEnabled())
+            {
+                renderTextureShadowReceiverQueueGroupObjects(pGroup);
+            }
+
+            ++si;
+
+        }// for each light
+
+        mIlluminationStage = IRS_NONE;
+
+    }
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
+    while (groupIt3.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    static LightList nullLightList;
+
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    // Override auto param ambient to force vertex programs to go full-bright
+    mAutoParamDataSource.setAmbientLightColour(ColourValue::White);
+    mDestRenderSystem->setAmbientLight(1, 1, 1);
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Do solids, override light list incase any vertex programs use them
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &nullLightList);
+
+        // Don't render transparents or passes which have shadow receipt disabled
+
+    }// for each priority
+
+    // reset ambient
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
+
+}
+//-----------------------------------------------------------------------
+bool SceneManager::validatePassForRendering(Pass* pass)
+{
+    // Bypass if we're doing a texture shadow render and 
+    // this pass is after the first (only 1 pass needed for shadow texture)
+    if ((mIlluminationStage == IRS_RENDER_TO_TEXTURE ||
+        mIlluminationStage == IRS_RENDER_MODULATIVE_PASS) && 
+        pass->getIndex() > 0)
+    {
+        return false;
+    }
+
+    return true;
+}
+//-----------------------------------------------------------------------
+bool SceneManager::validateRenderableForRendering(Pass* pass, Renderable* rend)
+{
+    // Skip this renderable if we're doing texture shadows, it casts shadows
+    // and we're doing the render receivers pass and we're not self-shadowing
+    if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE && 
+        mIlluminationStage == IRS_RENDER_MODULATIVE_PASS && 
+        rend->getCastsShadows() && !mShadowTextureSelfShadow)
+    {
+        return false;
+    }
+
+    return true;
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderObjects(
+                                 const RenderPriorityGroup::SolidRenderablePassMap& objs, bool doLightIteration, 
+                                 const LightList* manualLightList)
+{
+    // ----- SOLIDS LOOP -----
+    RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
+    ipassend = objs.end();
+    for (ipass = objs.begin(); ipass != ipassend; ++ipass)
+    {
+        // Fast bypass if this group is now empty
+        if (ipass->second->empty()) continue;
+
+        // Give SM a chance to eliminate this pass
+        if (!validatePassForRendering(ipass->first))
+            continue;
+
+        // For solids, we try to do each pass in turn
+        Pass* usedPass = setPass(ipass->first);
+        RenderPriorityGroup::RenderableList* rendList = ipass->second;
+        RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
+        irendend = rendList->end();
+        for (irend = rendList->begin(); irend != irendend; ++irend)
+        {
+            // Give SM a chance to eliminate
+            if (!validateRenderableForRendering(ipass->first, *irend))
+                continue;
+            // Render a single object, this will set up auto params if required
+            renderSingleObject(*irend, usedPass, doLightIteration, manualLightList);
+        }
+    } 
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderObjects(
+                                 const RenderPriorityGroup::TransparentRenderablePassList& objs, bool doLightIteration,
+                                 const LightList* manualLightList)
+{
+    // ----- TRANSPARENT LOOP -----
+    // This time we render by Z, not by pass
+    // The mTransparentObjects set needs to be ordered first
+    // Render each non-transparent entity in turn, grouped by material
+    RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
+
+    itransend = objs.end();
+    for (itrans = objs.begin(); 
+        itrans != itransend; ++itrans)
+    {
+        // For transparents, we have to accept that we can't sort entirely by pass
+        setPass(itrans->pass);
+        renderSingleObject(itrans->renderable, itrans->pass, doLightIteration, 
+            manualLightList);
+    }
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    if (pGroup->getShadowsEnabled() && 
+        mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
+    {
+        // Additive stencil shadows in use
+        renderAdditiveStencilShadowedQueueGroupObjects(pGroup);
+    }
+    else if (pGroup->getShadowsEnabled() && 
+        mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
+    {
+        // Modulative stencil shadows in use
+        renderModulativeStencilShadowedQueueGroupObjects(pGroup);
+    }
+    else if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+    {
+        // Modulative texture shadows in use
+        if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
+        {
+            // Shadow caster pass
+            if (pGroup->getShadowsEnabled())
+                renderTextureShadowCasterQueueGroupObjects(pGroup);
+        }
+        else
+        {
+            // Ordinary pass
+            renderModulativeTextureShadowedQueueGroupObjects(pGroup);
+        }
+    }
+    else
+    {
+        // No shadows, ordinary pass
+        renderBasicQueueGroupObjects(pGroup);
+    }
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    // Basic render loop
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+
+    }// for each priority
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTransparentShadowCasterObjects(
+	const RenderPriorityGroup::TransparentRenderablePassList& objs, bool doLightIteration,
+	const LightList* manualLightList)
+{
+	// ----- TRANSPARENT LOOP as in renderObjects above, but changed a bit -----
+	RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
+
+	itransend = objs.end();
+	for (itrans = objs.begin(); 
+		itrans != itransend; ++itrans)
+	{
+		Renderable *r = itrans->renderable;
+		Pass *p = itrans->pass;
+
+		// only render this pass if it's being forced to cast shadows
+		if (p->getParent()->getParent()->getTransparencyCastsShadows())
+		{
+			setPass(p);
+			renderSingleObject(itrans->renderable, p, doLightIteration, manualLightList);
+		}
+	}
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderSingleObject(Renderable* rend, Pass* pass, 
+                                      bool doLightIteration, const LightList* manualLightList)
+{
+    static Matrix4 xform[256];
+    unsigned short numMatrices;
+    static bool normalisedNormals = false;
+    static SceneDetailLevel camDetailLevel = mCameraInProgress->getDetailLevel();
+    static SceneDetailLevel lastDetailLevel = camDetailLevel;
+    static RenderOperation ro;
+    static LightList localLightList;
+
+    if (pass->isProgrammable())
+    {
+        // Tell auto params object about the renderable change
+        mAutoParamDataSource.setCurrentRenderable(rend);
+        pass->_updateAutoParamsNoLights(mAutoParamDataSource);
+    }
+
+    // Set world transformation
+    rend->getWorldTransforms(xform);
+    numMatrices = rend->getNumWorldTransforms();
+    if (numMatrices > 1)
+    {
+        mDestRenderSystem->_setWorldMatrices(xform, numMatrices);
+    }
+    else
+    {
+        mDestRenderSystem->_setWorldMatrix(*xform);
+    }
+
+    // Issue view / projection changes if any
+    useRenderableViewProjMode(rend);
+
+    // Reissue any texture gen settings which are dependent on view matrix
+    Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
+    size_t unit = 0;
+    while(texIter.hasMoreElements())
+    {
+        TextureUnitState* pTex = texIter.getNext();
+        if (pTex->hasViewRelativeTextureCoordinateGeneration())
+        {
+            mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
+        }
+        ++unit;
+    }
+
+
+    // Sort out normalisation
+    bool thisNormalise = rend->getNormaliseNormals();
+    if (thisNormalise != normalisedNormals)
+    {
+        mDestRenderSystem->setNormaliseNormals(thisNormalise);
+        normalisedNormals = thisNormalise;
+    }
+
+    // Set up the solid / wireframe override
+    SceneDetailLevel reqDetail = rend->getRenderDetail();
+    if (reqDetail != lastDetailLevel || reqDetail != camDetailLevel)
+    {
+        if (reqDetail > camDetailLevel)
+        {
+            // only downgrade detail; if cam says wireframe we don't go up to solid
+            reqDetail = camDetailLevel;
+        }
+        mDestRenderSystem->_setRasterisationMode(reqDetail);
+        lastDetailLevel = reqDetail;
+
+    }
+
+    mDestRenderSystem->setClipPlanes(rend->getClipPlanes());
+
+    // Set up rendering operation
+    rend->getRenderOperation(ro);
+    ro.srcRenderable = rend;
+
+    if (doLightIteration)
+    {
+        // Here's where we issue the rendering operation to the render system
+        // Note that we may do this once per light, therefore it's in a loop
+        // and the light parameters are updated once per traversal through the
+        // loop
+        const LightList& rendLightList = rend->getLights();
+        bool iteratePerLight = pass->getRunOncePerLight();
+        size_t numIterations = iteratePerLight ? rendLightList.size() : 1;
+        const LightList* pLightListToUse;
+        for (size_t i = 0; i < numIterations; ++i)
+        {
+            // Determine light list to use
+            if (iteratePerLight)
+            {
+                // Change the only element of local light list to be
+                // the light at index i
+                localLightList.clear();
+                // Check whether we need to filter this one out
+                if (pass->getRunOnlyForOneLightType() && 
+                    pass->getOnlyLightType() != rendLightList[i]->getType())
+                {
+                    // Skip
+                    continue;
+                }
+
+                localLightList.push_back(rendLightList[i]);
+                pLightListToUse = &localLightList;
+            }
+            else
+            {
+                // Use complete light list
+                pLightListToUse = &rendLightList;
+            }
+
+            // Do we need to update GPU program parameters?
+            if (pass->isProgrammable())
+            {
+                // Update any automatic gpu params for lights
+                // Other bits of information will have to be looked up
+                mAutoParamDataSource.setCurrentLightList(pLightListToUse);
+                pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
+                // NOTE: We MUST bind parameters AFTER updating the autos
+                // TEST
+                if (pass->hasVertexProgram())
+                {
+                    mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
+                        pass->getVertexProgramParameters());
+                }
+                if (pass->hasFragmentProgram())
+                {
+                    mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, 
+                        pass->getFragmentProgramParameters());
+                }
+            }
+            // Do we need to update light states? 
+            // Only do this if fixed-function vertex lighting applies
+            if (pass->getLightingEnabled() &&
+                (!pass->hasVertexProgram() || pass->getVertexProgram()->getPassSurfaceAndLightStates()))
+            {
+                mDestRenderSystem->_useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
+            }
+            // issue the render op		
+            mDestRenderSystem->_render(ro);
+        } // possibly iterate per light
+    }
+    else // no automatic light processing
+    {
+        // Do we need to update GPU program parameters?
+        if (pass->isProgrammable())
+        {
+            // Do we have a manual light list?
+            if (manualLightList)
+            {
+                // Update any automatic gpu params for lights
+                mAutoParamDataSource.setCurrentLightList(manualLightList);
+                pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
+            }
+
+            if (pass->hasVertexProgram())
+            {
+                mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
+                    pass->getVertexProgramParameters());
+            }
+            if (pass->hasFragmentProgram())
+            {
+                mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, 
+                    pass->getFragmentProgramParameters());
+            }
+        }
+
+        // Use manual lights if present, and fixed-function vertex lighting applies
+        if (manualLightList && 
+            pass->getLightingEnabled() &&
+            (!pass->hasVertexProgram() || pass->getVertexProgram()->getPassSurfaceAndLightStates()))
+        {
+            mDestRenderSystem->_useLights(*manualLightList, pass->getMaxSimultaneousLights());
+        }
+        // issue the render op		
+        mDestRenderSystem->_render(ro);
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::setAmbientLight(const ColourValue& colour)
+{
+    mAmbientLight = colour;
+    mDestRenderSystem->setAmbientLight(colour.r, colour.g, colour.b);
+}
+//-----------------------------------------------------------------------
+const ColourValue& SceneManager::getAmbientLight(void) const
+{
+    return mAmbientLight;
+}
+//-----------------------------------------------------------------------
+ViewPoint SceneManager::getSuggestedViewpoint(bool random)
+{
+    // By default return the origin
+    ViewPoint vp;
+    vp.position = Vector3::ZERO;
+    vp.orientation = Quaternion::IDENTITY;
+    return vp;
+}
+//-----------------------------------------------------------------------
+void SceneManager::setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
+{
+    mFogMode = mode;
+    mFogColour = colour;
+    mFogStart = start;
+    mFogEnd = end;
+    mFogDensity = density;
+}
+//-----------------------------------------------------------------------
+FogMode SceneManager::getFogMode(void) const
+{
+    return mFogMode;
+}
+//-----------------------------------------------------------------------
+const ColourValue& SceneManager::getFogColour(void) const
+{
+    return mFogColour;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogStart(void) const
+{
+    return mFogStart;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogEnd(void) const
+{
+    return mFogEnd;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogDensity(void) const
+{
+    return mFogDensity;
+}
+//-----------------------------------------------------------------------
+BillboardSet* SceneManager::createBillboardSet(const String& name, unsigned int poolSize)
+{
+    // Check name not used
+    if (mBillboardSets.find(name) != mBillboardSets.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A billboard set with the name " + name + " already exists",
+            "SceneManager::createBillboardSet" );
+    }
+
+    BillboardSet* set = new BillboardSet( name, poolSize );
+    mBillboardSets[name] = set;//.insert(BillboardSetList::value_type(name, set));
+
+    return set;
+}
+//-----------------------------------------------------------------------
+BillboardSet* SceneManager::getBillboardSet(const String& name)
+{
+    BillboardSetList::iterator i = mBillboardSets.find(name);
+    if (i == mBillboardSets.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find BillboardSet with name " + name,
+            "SceneManager::getBillboardSet");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeBillboardSet(BillboardSet* set)
+{
+    // Find in list
+    BillboardSetList::iterator i = mBillboardSets.begin();
+    for (; i != mBillboardSets.end(); ++i)
+    {
+        if (i->second == set)
+        {
+            mBillboardSets.erase(i);
+            delete set;
+            break;
+        }
+    }
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeBillboardSet(const String& name)
+{
+    // Find in list
+    BillboardSetList::iterator i = mBillboardSets.find(name);
+    if (i != mBillboardSets.end())
+    {
+        delete i->second;
+        mBillboardSets.erase(i);
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::setDisplaySceneNodes(bool display)
+{
+    mDisplayNodes = display;
+}
+//-----------------------------------------------------------------------
+Animation* SceneManager::createAnimation(const String& name, Real length)
+{
+    // Check name not used
+    if (mAnimationsList.find(name) != mAnimationsList.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "An animation with the name " + name + " already exists",
+            "SceneManager::createAnimation" );
+    }
+
+    Animation* pAnim = new Animation(name, length);
+    mAnimationsList[name] = pAnim;
+    return pAnim;
+}
+//-----------------------------------------------------------------------
+Animation* SceneManager::getAnimation(const String& name) const
+{
+    AnimationList::const_iterator i = mAnimationsList.find(name);
+    if (i == mAnimationsList.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find animation with name " + name, 
+            "SceneManager::getAnimation");
+    }
+    return i->second;
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAnimation(const String& name)
+{
+    // Also destroy any animation states referencing this animation
+    AnimationStateSet::iterator si, siend;
+    siend = mAnimationStates.end();
+    for (si = mAnimationStates.begin(); si != siend; )
+    {
+        if (si->second.getAnimationName() == name)
+        {
+            // erase, post increment to avoid the invalidated iterator
+            mAnimationStates.erase(si++);
+        }
+        else
+        {
+            ++si;
+        }
+    }
+
+    AnimationList::iterator i = mAnimationsList.find(name);
+    if (i == mAnimationsList.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find animation with name " + name, 
+            "SceneManager::getAnimation");
+    }
+
+    // Free memory
+    delete i->second;
+
+    mAnimationsList.erase(i);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAllAnimations(void)
+{
+    // Destroy all states too, since they cannot reference destroyed animations
+    destroyAllAnimationStates();
+
+    AnimationList::iterator i;
+    for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
+    {
+        // destroy
+        delete i->second;
+    }
+    mAnimationsList.clear();
+}
+//-----------------------------------------------------------------------
+AnimationState* SceneManager::createAnimationState(const String& animName)
+{
+    if (mAnimationStates.find(animName) != mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
+            "Cannot create, AnimationState already exists: "+animName, 
+            "SceneManager::createAnimationState");
+    }
+
+    // Get animation, this will throw an exception if not found
+    Animation* anim = getAnimation(animName);
+
+    // Create new state
+    AnimationState newState(animName, 0, anim->getLength());
+
+    // Record it
+    std::pair<AnimationStateSet::iterator, bool> retPair = 
+        mAnimationStates.insert(AnimationStateSet::value_type(animName, newState));
+
+    // Check boolean return
+    if (retPair.second)
+    {
+        // insert was OK
+        // Get pointer from iterator in pair
+        return &(retPair.first->second);
+    }
+    else
+    {
+        // Problem
+        // Not because of duplicate item, that's checked for above
+        OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Unexpected error creating new animation state.",
+            "SceneManager::createAnimationState");
+    }
+
+
+}
+//-----------------------------------------------------------------------
+AnimationState* SceneManager::getAnimationState(const String& animName) 
+{
+    AnimationStateSet::iterator i = mAnimationStates.find(animName);
+
+    if (i == mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot locate animation state for animation " + animName,
+            "SceneManager::getAnimationState");
+    }
+
+    return &(i->second);
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAnimationState(const String& name)
+{
+    AnimationStateSet::iterator i = mAnimationStates.find(name);
+
+    if (i == mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot locate animation state for animation " + name,
+            "SceneManager::destroyAnimationState");
+    }
+
+    mAnimationStates.erase(i);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAllAnimationStates(void)
+{
+    mAnimationStates.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::_applySceneAnimations(void)
+{
+    AnimationStateSet::const_iterator i, iend;
+
+    i = mAnimationStates.begin();
+    iend = mAnimationStates.end();
+
+    for (;i != iend; ++i)
+    {
+        if (i->second.getEnabled())
+        {
+            Animation* anim = getAnimation(i->second.getAnimationName());
+
+            // Reset any nodes involved
+            // NB this excludes blended animations
+            const Animation::TrackList& trackList = anim->_getTrackList();
+            Animation::TrackList::const_iterator ti, tend;
+            ti = trackList.begin();
+            tend = trackList.end();
+            for (;ti != tend; ++ti)
+            {
+                Node* nd = ti->second->getAssociatedNode();
+                nd->resetToInitialState();
+            }
+
+
+            // Apply the animation
+            anim->apply(i->second.getTimePosition(), i->second.getWeight());
+        }
+    }
+
+
+}
+//---------------------------------------------------------------------
+void SceneManager::manualRender(RenderOperation* rend, 
+                                Pass* pass, Viewport* vp, const Matrix4& worldMatrix, 
+                                const Matrix4& viewMatrix, const Matrix4& projMatrix, 
+                                bool doBeginEndFrame) 
+{
+    mDestRenderSystem->_setViewport(vp);
+    mDestRenderSystem->_setWorldMatrix(worldMatrix);
+    mDestRenderSystem->_setViewMatrix(viewMatrix);
+    mDestRenderSystem->_setProjectionMatrix(projMatrix);
+
+    if (doBeginEndFrame)
+        mDestRenderSystem->_beginFrame();
+
+    setPass(pass);
+    mDestRenderSystem->_render(*rend);
+
+    if (doBeginEndFrame)
+        mDestRenderSystem->_endFrame();
+
+}
+//---------------------------------------------------------------------
+void SceneManager::useRenderableViewProjMode(Renderable* pRend)
+{
+    // Check view matrix
+    static bool lastViewWasIdentity = false;
+    bool useIdentityView = pRend->useIdentityView();
+    if (useIdentityView && (mCamChanged || !lastViewWasIdentity))
+    {
+        // Using identity view now, change it
+        mDestRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
+        lastViewWasIdentity = true;
+    }
+    else if (!useIdentityView && (mCamChanged || lastViewWasIdentity))
+    {
+        // Coming back to normal from identity view
+        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix());
+        lastViewWasIdentity = false;
+    }
+
+    static bool lastProjWasIdentity = false;
+    bool useIdentityProj = pRend->useIdentityProjection();
+
+    if (useIdentityProj && (mCamChanged || !lastProjWasIdentity))
+    {
+        mDestRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY);
+
+        lastProjWasIdentity = true;
+    }
+    else if (!useIdentityProj && (mCamChanged || lastProjWasIdentity))
+    {
+        // Coming back from flat projection
+        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrix());
+        lastProjWasIdentity = false;
+    }
+
+    mCamChanged = false;
+
+}
+
+//---------------------------------------------------------------------
+void SceneManager::_queueSkiesForRendering(Camera* cam)
+{
+    // Update nodes
+    // Translate the box by the camera position (constant distance)
+    if (mSkyPlaneNode)
+    {
+        // The plane position relative to the camera has already been set up
+        mSkyPlaneNode->setPosition(cam->getDerivedPosition());
+    }
+
+    if (mSkyBoxNode)
+    {
+        mSkyBoxNode->setPosition(cam->getDerivedPosition());
+    }
+
+    if (mSkyDomeNode)
+    {
+        mSkyDomeNode->setPosition(cam->getDerivedPosition());
+    }
+
+    RenderQueueGroupID qid;
+    if (mSkyPlaneEnabled)
+    {
+        qid = mSkyPlaneDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+        getRenderQueue()->addRenderable(mSkyPlaneEntity->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+    }
+
+    uint plane;
+    if (mSkyBoxEnabled)
+    {
+        qid = mSkyBoxDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+
+        for (plane = 0; plane < 6; ++plane)
+        {
+            getRenderQueue()->addRenderable(
+                mSkyBoxEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+        }
+    }
+
+    if (mSkyDomeEnabled)
+    {
+        qid = mSkyDomeDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+
+        for (plane = 0; plane < 5; ++plane)
+        {
+            getRenderQueue()->addRenderable(
+                mSkyDomeEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+        }
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::addRenderQueueListener(RenderQueueListener* newListener)
+{
+    mRenderQueueListeners.push_back(newListener);
+}
+//---------------------------------------------------------------------
+void SceneManager::removeRenderQueueListener(RenderQueueListener* delListener)
+{
+    RenderQueueListenerList::iterator i, iend;
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        if (*i == delListener)
+        {
+            mRenderQueueListeners.erase(i);
+            break;
+        }
+    }
+
+}
+//---------------------------------------------------------------------
+bool SceneManager::fireRenderQueueStarted(RenderQueueGroupID id)
+{
+    RenderQueueListenerList::iterator i, iend;
+    bool skip = false;
+
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        (*i)->renderQueueStarted(id, skip);
+    }
+    return skip;
+}
+//---------------------------------------------------------------------
+bool SceneManager::fireRenderQueueEnded(RenderQueueGroupID id)
+{
+    RenderQueueListenerList::iterator i, iend;
+    bool repeat = false;
+
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        (*i)->renderQueueEnded(id, repeat);
+    }
+    return repeat;
+}
+//---------------------------------------------------------------------
+void SceneManager::setViewport(Viewport* vp)
+{
+    mCurrentViewport = vp;
+    // Set viewport in render system
+    mDestRenderSystem->_setViewport(vp);
+}
+//---------------------------------------------------------------------
+void SceneManager::showBoundingBoxes(bool bShow) 
+{
+    mShowBoundingBoxes = bShow;
+}
+//---------------------------------------------------------------------
+bool SceneManager::getShowBoundingBoxes() const
+{
+    return mShowBoundingBoxes;
+}
+//---------------------------------------------------------------------
+void SceneManager::_notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack)
+{
+    if (autoTrack)
+    {
+        mAutoTrackingSceneNodes.insert(node);
+    }
+    else
+    {
+        mAutoTrackingSceneNodes.erase(node);
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTechnique(ShadowTechnique technique)
+{
+    mShadowTechnique = technique;
+    if (technique == SHADOWTYPE_STENCIL_ADDITIVE || 
+        technique == SHADOWTYPE_STENCIL_MODULATIVE)
+    {
+        // Firstly check that we  have a stencil
+        // Otherwise forget it
+        if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_HWSTENCIL))
+        {
+            LogManager::getSingleton().logMessage(
+                "WARNING: Stencil shadows were requested, but this device does not "
+                "have a hardware stencil. Shadows disabled.");
+            mShadowTechnique = SHADOWTYPE_NONE;
+        }
+        else if (mShadowIndexBuffer.isNull())
+        {
+            // Create an estimated sized shadow index buffer
+            mShadowIndexBuffer = HardwareBufferManager::getSingleton().
+                createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 
+                mShadowIndexBufferSize, 
+                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
+                false);
+            // tell all meshes to prepare shadow volumes
+            MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(true);
+        }
+    }
+
+    if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
+    {
+        // Additive stencil, we need to split everything by illumination stage
+        getRenderQueue()->setSplitPassesByLightingType(true);
+    }
+    else
+    {
+        getRenderQueue()->setSplitPassesByLightingType(false);
+    }
+
+    if (mShadowTechnique != SHADOWTYPE_NONE)
+    {
+        // Tell render queue to split off non-shadowable materials
+        getRenderQueue()->setSplitNoShadowPasses(true);
+    }
+    else
+    {
+        getRenderQueue()->setSplitNoShadowPasses(false);
+    }
+
+    if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+    {
+        createShadowTextures(mShadowTextureSize, mShadowTextureCount, mShadowTextureFormat);
+    }
+
+}
+//---------------------------------------------------------------------
+void SceneManager::findLightsAffectingFrustum(const Camera* camera)
+{
+    // Basic iteration for this SM
+    mLightsAffectingFrustum.clear();
+    SceneLightList::iterator i, iend;
+    iend = mLights.end();
+    Sphere sphere;
+    for (i = mLights.begin(); i != iend; ++i)
+    {
+        Light* l = i->second;
+        if (l->getType() == Light::LT_DIRECTIONAL)
+        {
+            // Always visible
+            mLightsAffectingFrustum.push_back(l);
+        }
+        else
+        {
+            // NB treating spotlight as point for simplicity
+            // Just see if the lights attenuation range is within the frustum
+            sphere.setCenter(l->getDerivedPosition());
+            sphere.setRadius(l->getAttenuationRange());
+            if (camera->isVisible(sphere))
+            {
+                mLightsAffectingFrustum.push_back(l);
+            }
+
+        }
+    }
+
+}
+//---------------------------------------------------------------------
+bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
+    MovableObject* object)
+{
+    if (object->getCastShadows() && object->isVisible() && 
+		mSceneMgr->isRenderQueueToBeProcessed(object->getRenderQueueGroup()))
+    {
+        if (mFarDistSquared)
+        {
+            // Check object is within the shadow far distance
+            Vector3 toObj = object->getParentNode()->_getDerivedPosition() 
+                - mCamera->getDerivedPosition();
+            Real radius = object->getWorldBoundingSphere().getRadius();
+            Real dist =  toObj.squaredLength();               
+            if (dist - (radius * radius) > mFarDistSquared)
+            {
+                // skip, beyond max range
+                return true;
+            }
+        }
+
+        // If the object is in the frustum, we can always see the shadow
+        if (mCamera->isVisible(object->getWorldBoundingBox()))
+        {
+            mCasterList->push_back(object);
+            return true;
+        }
+
+        // Otherwise, object can only be casting a shadow into our view if
+        // the light is outside the frustum (or it's a directional light, 
+        // which are always outside), and the object is intersecting
+        // on of the volumes formed between the edges of the frustum and the
+        // light
+        if (!mIsLightInFrustum || mLight->getType() == Light::LT_DIRECTIONAL)
+        {
+            // Iterate over volumes
+            PlaneBoundedVolumeList::const_iterator i, iend;
+            iend = mLightClipVolumeList->end();
+            for (i = mLightClipVolumeList->begin(); i != iend; ++i)
+            {
+                if (i->intersects(object->getWorldBoundingBox()))
+                {
+                    mCasterList->push_back(object);
+                    return true;
+                }
+
+            }
+
+        }
+    }
+    return true;
+}
+//---------------------------------------------------------------------
+bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
+    SceneQuery::WorldFragment* fragment)
+{
+    // don't deal with world geometry
+    return true;
+}
+//---------------------------------------------------------------------
+const SceneManager::ShadowCasterList& SceneManager::findShadowCastersForLight(
+    const Light* light, const Camera* camera)
+{
+    mShadowCasterList.clear();
+
+    if (light->getType() == Light::LT_DIRECTIONAL)
+    {
+        // Basic AABB query encompassing the frustum and the extrusion of it
+        AxisAlignedBox aabb;
+        const Vector3* corners = camera->getWorldSpaceCorners();
+        Vector3 min, max;
+        Vector3 extrude = light->getDirection() * -mShadowDirLightExtrudeDist;
+        // do first corner
+        min = max = corners[0];
+        min.makeFloor(corners[0] + extrude);
+        max.makeCeil(corners[0] + extrude);
+        for (size_t c = 1; c < 8; ++c)
+        {
+            min.makeFloor(corners[c]);
+            max.makeCeil(corners[c]);
+            min.makeFloor(corners[c] + extrude);
+            max.makeCeil(corners[c] + extrude);
+        }
+        aabb.setExtents(min, max);
+
+        if (!mShadowCasterAABBQuery)
+            mShadowCasterAABBQuery = createAABBQuery(aabb);
+        else
+            mShadowCasterAABBQuery->setBox(aabb);
+        // Execute, use callback
+        mShadowCasterQueryListener->prepare(false, 
+            &(light->_getFrustumClipVolumes(camera)), 
+            light, camera, &mShadowCasterList, mShadowFarDistSquared);
+        mShadowCasterAABBQuery->execute(mShadowCasterQueryListener);
+
+
+    }
+    else
+    {
+        Sphere s(light->getPosition(), light->getAttenuationRange());
+        // eliminate early if camera cannot see light sphere
+        if (camera->isVisible(s))
+        {
+            if (!mShadowCasterSphereQuery)
+                mShadowCasterSphereQuery = createSphereQuery(s);
+            else
+                mShadowCasterSphereQuery->setSphere(s);
+
+            // Determine if light is inside or outside the frustum
+            bool lightInFrustum = camera->isVisible(light->getDerivedPosition());
+            const PlaneBoundedVolumeList* volList = 0;
+            if (!lightInFrustum)
+            {
+                // Only worth building an external volume list if
+                // light is outside the frustum
+                volList = &(light->_getFrustumClipVolumes(camera));
+            }
+
+            // Execute, use callback
+            mShadowCasterQueryListener->prepare(lightInFrustum, 
+                volList, light, camera, &mShadowCasterList, mShadowFarDistSquared);
+            mShadowCasterSphereQuery->execute(mShadowCasterQueryListener);
+
+        }
+
+    }
+
+
+    return mShadowCasterList;
+}
+//---------------------------------------------------------------------
+void SceneManager::initShadowVolumeMaterials(void)
+{
+
+    if (mShadowMaterialInitDone)
+        return;
+
+    if (!mShadowDebugPass)
+    {
+        MaterialPtr matDebug = 
+            MaterialManager::getSingleton().getByName("Ogre/Debug/ShadowVolumes");
+        if (matDebug.isNull())
+        {
+            // Create
+            matDebug = MaterialManager::getSingleton().create(
+                "Ogre/Debug/ShadowVolumes", 
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
+            mShadowDebugPass->setSceneBlending(SBT_ADD); 
+            mShadowDebugPass->setLightingEnabled(false);
+            mShadowDebugPass->setDepthWriteEnabled(false);
+            TextureUnitState* t = mShadowDebugPass->createTextureUnitState();
+            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, 
+                ColourValue(0.7, 0.0, 0.2));
+            mShadowDebugPass->setCullingMode(CULL_NONE);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(
+                RSC_VERTEX_PROGRAM))
+            {
+                ShadowVolumeExtrudeProgram::initialise();
+
+                // Enable the (infinite) point light extruder for now, just to get some params
+                mShadowDebugPass->setVertexProgram(
+                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT]);
+                mInfiniteExtrusionParams = 
+                    mShadowDebugPass->getVertexProgramParameters();
+                mInfiniteExtrusionParams->setAutoConstant(0, 
+                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+                mInfiniteExtrusionParams->setAutoConstant(4, 
+                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
+            }	
+            matDebug->compile();
+
+        }
+        else
+        {
+            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
+        }
+    }
+
+    if (!mShadowStencilPass)
+    {
+
+        MaterialPtr matStencil = MaterialManager::getSingleton().getByName(
+            "Ogre/StencilShadowVolumes");
+        if (matStencil.isNull())
+        {
+            // Init
+            matStencil = MaterialManager::getSingleton().create(
+                "Ogre/StencilShadowVolumes",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(
+                RSC_VERTEX_PROGRAM))
+            {
+
+                // Enable the finite point light extruder for now, just to get some params
+                mShadowStencilPass->setVertexProgram(
+                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT_FINITE]);
+                mFiniteExtrusionParams = 
+                    mShadowStencilPass->getVertexProgramParameters();
+                mFiniteExtrusionParams->setAutoConstant(0, 
+                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+                mFiniteExtrusionParams->setAutoConstant(4, 
+                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
+                // Note extra parameter
+                mFiniteExtrusionParams->setAutoConstant(5, 
+                    GpuProgramParameters::ACT_SHADOW_EXTRUSION_DISTANCE);
+            }
+            matStencil->compile();
+            // Nothing else, we don't use this like a 'real' pass anyway,
+            // it's more of a placeholder
+        }
+        else
+        {
+            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
+        }
+    }
+
+
+
+
+    if (!mShadowModulativePass)
+    {
+
+        MaterialPtr matModStencil = MaterialManager::getSingleton().getByName(
+            "Ogre/StencilShadowModulationPass");
+        if (matModStencil.isNull())
+        {
+            // Init
+            matModStencil = MaterialManager::getSingleton().create(
+                "Ogre/StencilShadowModulationPass",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
+            mShadowModulativePass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO); 
+            mShadowModulativePass->setLightingEnabled(false);
+            mShadowModulativePass->setDepthWriteEnabled(false);
+            mShadowModulativePass->setDepthCheckEnabled(false);
+            TextureUnitState* t = mShadowModulativePass->createTextureUnitState();
+            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, 
+                mShadowColour);
+            mShadowModulativePass->setCullingMode(CULL_NONE);
+        }
+        else
+        {
+            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
+        }
+    }
+
+    // Also init full screen quad while we're at it
+    if (!mFullScreenQuad)
+    {
+        mFullScreenQuad = new Rectangle2D();
+        mFullScreenQuad->setCorners(-1,1,1,-1);
+    }
+
+    // Also init shadow caster material for texture shadows
+    if (!mShadowCasterPlainBlackPass)
+    {
+        MaterialPtr matPlainBlack = MaterialManager::getSingleton().getByName(
+            "Ogre/TextureShadowCaster");
+        if (matPlainBlack.isNull())
+        {
+            matPlainBlack = MaterialManager::getSingleton().create(
+                "Ogre/TextureShadowCaster",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
+            // Lighting has to be on, because we need shadow coloured objects
+            // Note that because we can't predict vertex programs, we'll have to
+            // bind light values to those, and so we bind White to ambient
+            // reflectance, and we'll set the ambient colour to the shadow colour
+            mShadowCasterPlainBlackPass->setAmbient(ColourValue::White);
+            mShadowCasterPlainBlackPass->setDiffuse(ColourValue::Black);
+            mShadowCasterPlainBlackPass->setSelfIllumination(ColourValue::Black);
+            mShadowCasterPlainBlackPass->setSpecular(ColourValue::Black);
+			// Override fog
+			mShadowCasterPlainBlackPass->setFog(true, FOG_NONE);
+            // no textures or anything else, we will bind vertex programs
+            // every so often though
+        }
+        else
+        {
+            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
+        }
+    }
+
+    if (!mShadowReceiverPass)
+    {
+        MaterialPtr matShadRec = MaterialManager::getSingleton().getByName(
+            "Ogre/TextureShadowReceiver");
+        if (matShadRec.isNull())			
+        {
+            matShadRec = MaterialManager::getSingleton().create(
+                "Ogre/TextureShadowReceiver",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
+            mShadowReceiverPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
+            // No lighting, one texture unit 
+            // everything else will be bound as needed during the receiver pass
+            mShadowReceiverPass->setLightingEnabled(false);
+            TextureUnitState* t = mShadowReceiverPass->createTextureUnitState();
+            t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+        }
+        else
+        {
+            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
+        }
+    }
+
+    // Set up spot shadow fade texture (loaded from code data block)
+    TexturePtr spotShadowFadeTex = 
+        TextureManager::getSingleton().getByName("spot_shadow_fade.png");
+    if (spotShadowFadeTex.isNull())
+    {
+        // Load the manual buffer into an image (don't destroy memory!
+        DataStreamPtr stream(
+			new MemoryDataStream(SPOT_SHADOW_FADE_PNG, SPOT_SHADOW_FADE_PNG_SIZE, false));
+        Image img;
+        img.load(stream, "png");
+        spotShadowFadeTex = 
+            TextureManager::getSingleton().loadImage(
+			"spot_shadow_fade.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
+			img, TEX_TYPE_2D);
+    }
+
+    mShadowMaterialInitDone = true;
+}
+//---------------------------------------------------------------------
+Pass* SceneManager::deriveShadowCasterPass(Pass* pass)
+{
+    switch (mShadowTechnique)
+    {
+    case SHADOWTYPE_TEXTURE_MODULATIVE:
+		if (mShadowTextureCustomCasterPass)
+		{
+			// Caster pass has been customised
+
+			if (!pass->getShadowCasterVertexProgramName().empty())
+			{
+				// Have to merge the shadow caster vertex program in
+				mShadowTextureCustomCasterPass->setVertexProgram(
+					pass->getShadowCasterVertexProgramName());
+				const GpuProgramPtr& prg = mShadowTextureCustomCasterPass->getVertexProgram();
+				// Load this program if not done already
+				if (!prg->isLoaded())
+					prg->load();
+				// Copy params
+				mShadowTextureCustomCasterPass->setVertexProgramParameters(
+					pass->getShadowCasterVertexProgramParameters());
+				// mark that we've overridden the standard
+				mShadowTextureCasterVPDirty = true;
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowTextureCasterVPDirty)
+			{
+				// reset
+				mShadowTextureCustomCasterPass->setVertexProgram(
+					mShadowTextureCustomCasterVertexProgram);
+				if(mShadowTextureCustomCasterPass->hasVertexProgram())
+				{
+					mShadowTextureCustomCasterPass->setVertexProgramParameters(
+						mShadowTextureCustomCasterVPParams);
+
+				}
+				mShadowTextureCasterVPDirty = false;
+			}
+			return mShadowTextureCustomCasterPass;
+		}
+		else
+		{
+			// Standard pass
+			if (pass->hasVertexProgram())
+			{
+				// Have to merge the shadow caster vertex program in
+				// This may in fact be blank, in which case it falls back on 
+				// fixed function
+				mShadowCasterPlainBlackPass->setVertexProgram(
+					pass->getShadowCasterVertexProgramName());
+				// Did this result in a new vertex program?
+				if (mShadowCasterPlainBlackPass->hasVertexProgram())
+				{
+					const GpuProgramPtr& prg = mShadowCasterPlainBlackPass->getVertexProgram();
+					// Load this program if not done already
+					if (!prg->isLoaded())
+						prg->load();
+					// Copy params
+					mShadowCasterPlainBlackPass->setVertexProgramParameters(
+						pass->getShadowCasterVertexProgramParameters());
+				}
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowCasterPlainBlackPass->hasVertexProgram())
+			{
+				// reset
+				mShadowCasterPlainBlackPass->setVertexProgram("");
+			}
+			return mShadowCasterPlainBlackPass;
+		}
+    default:
+        return pass;
+    };
+
+}
+//---------------------------------------------------------------------
+Pass* SceneManager::deriveShadowReceiverPass(Pass* pass)
+{
+
+    switch (mShadowTechnique)
+    {
+    case SHADOWTYPE_TEXTURE_MODULATIVE:
+		if (mShadowTextureCustomReceiverPass)
+		{
+			// Receiver pass has been customised
+
+			if (!pass->getShadowReceiverVertexProgramName().empty())
+			{
+				// Have to merge the shadow Receiver vertex program in
+				mShadowTextureCustomReceiverPass->setVertexProgram(
+					pass->getShadowReceiverVertexProgramName());
+				const GpuProgramPtr& prg = mShadowTextureCustomReceiverPass->getVertexProgram();
+				// Load this program if not done already
+				if (!prg->isLoaded())
+					prg->load();
+				// Copy params
+				mShadowTextureCustomReceiverPass->setVertexProgramParameters(
+					pass->getShadowReceiverVertexProgramParameters());
+				// mark that we've overridden the standard
+				mShadowTextureReceiverVPDirty = true;
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowTextureReceiverVPDirty)
+			{
+				// reset
+				mShadowTextureCustomReceiverPass->setVertexProgram(
+					mShadowTextureCustomReceiverVertexProgram);
+				if(mShadowTextureCustomReceiverPass->hasVertexProgram())
+				{
+					mShadowTextureCustomReceiverPass->setVertexProgramParameters(
+						mShadowTextureCustomReceiverVPParams);
+
+				}
+				mShadowTextureReceiverVPDirty = false;
+			}
+			return mShadowTextureCustomReceiverPass;
+		}
+		else
+		{
+			if (pass->hasVertexProgram())
+			{
+				// Have to merge the receiver vertex program in
+				// This may return "" which means fixed function will be used
+				mShadowReceiverPass->setVertexProgram(
+					pass->getShadowReceiverVertexProgramName());
+				// Did this result in a new vertex program?
+				if (mShadowReceiverPass->hasVertexProgram())
+				{
+					const GpuProgramPtr& prg = mShadowReceiverPass->getVertexProgram();
+					// Load this program if required
+					if (!prg->isLoaded())
+						prg->load();
+					// Copy params
+					mShadowReceiverPass->setVertexProgramParameters(
+						pass->getShadowReceiverVertexProgramParameters());
+				}
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowReceiverPass->hasVertexProgram())
+			{
+				// reset
+				mShadowReceiverPass->setVertexProgram("");
+
+			}
+		}
+
+        return mShadowReceiverPass;
+    default:
+        return pass;
+    };
+
+}
+//---------------------------------------------------------------------
+void SceneManager::renderShadowVolumesToStencil(const Light* light, const Camera* camera)
+{
+    // Get the shadow caster list
+    const ShadowCasterList& casters = findShadowCastersForLight(light, camera);
+    // Check there are some shadow casters to render
+    if (casters.empty())
+    {
+        // No casters, just do nothing
+        return;
+    }
+
+    // Set up scissor test (point & spot lights only)
+    bool scissored = false;
+    if (light->getType() != Light::LT_DIRECTIONAL && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_SCISSOR_TEST))
+    {
+        // Project the sphere onto the camera
+        Real left, right, top, bottom;
+        Sphere sphere(light->getDerivedPosition(), light->getAttenuationRange());
+        if (camera->projectSphere(sphere, &left, &top, &right, &bottom))
+        {
+            scissored = true;
+            // Turn normalised device coordinates into pixels
+            int iLeft, iTop, iWidth, iHeight;
+            mCurrentViewport->getActualDimensions(iLeft, iTop, iWidth, iHeight);
+            size_t szLeft, szRight, szTop, szBottom;
+
+            szLeft = (size_t)(iLeft + ((left + 1) * 0.5 * iWidth));
+            szRight = (size_t)(iLeft + ((right + 1) * 0.5 * iWidth));
+            szTop = (size_t)(iTop + ((-top + 1) * 0.5 * iHeight));
+            szBottom = (size_t)(iTop + ((-bottom + 1) * 0.5 * iHeight));
+
+            mDestRenderSystem->setScissorTest(true, szLeft, szTop, szRight, szBottom);
+        }
+    }
+
+    mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+
+    // Can we do a 2-sided stencil?
+    bool stencil2sided = false;
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_TWO_SIDED_STENCIL) && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
+    {
+        // enable
+        stencil2sided = true;
+    }
+
+    // Do we have access to vertex programs?
+    bool extrudeInSoftware = true;
+    bool finiteExtrude = !mShadowUseInfiniteFarPlane || 
+        !mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE);
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
+    {
+        extrudeInSoftware = false;
+        // attach the appropriate extrusion vertex program
+        // Note we never unset it because support for vertex programs is constant
+        mShadowStencilPass->setVertexProgram(
+            ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, false)
+            , false);
+        // Set params
+        if (finiteExtrude)
+        {
+            mShadowStencilPass->setVertexProgramParameters(mFiniteExtrusionParams);
+        }
+        else
+        {
+            mShadowStencilPass->setVertexProgramParameters(mInfiniteExtrusionParams);
+        }
+        if (mDebugShadows)
+        {
+            mShadowDebugPass->setVertexProgram(
+                ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, true)
+                , false);
+            // Set params
+            if (finiteExtrude)
+            {
+                mShadowDebugPass->setVertexProgramParameters(mFiniteExtrusionParams);
+            }
+            else
+            {
+                mShadowDebugPass->setVertexProgramParameters(mInfiniteExtrusionParams);
+            }
+        }
+
+        mDestRenderSystem->bindGpuProgram(mShadowStencilPass->getVertexProgram()->_getBindingDelegate());
+
+    }
+    else
+    {
+        mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+    }
+
+    // Add light to internal list for use in render call
+    LightList lightList;
+    // const_cast is forgiveable here since we pass this const
+    lightList.push_back(const_cast<Light*>(light));
+
+    // Turn off colour writing and depth writing
+    mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
+	mDestRenderSystem->_disableTextureUnitsFrom(0);
+    mDestRenderSystem->_setDepthBufferParams(true, false, CMPF_LESS);
+    mDestRenderSystem->setStencilCheckEnabled(true);
+
+    // Calculate extrusion distance
+    // Use direction light extrusion distance now, just form optimize code
+    // generate a little, point/spot light will up to date later
+    Real extrudeDist = mShadowDirLightExtrudeDist;
+
+    // Figure out the near clip volume
+    const PlaneBoundedVolume& nearClipVol = 
+        light->_getNearClipVolume(camera);
+
+    // Now iterate over the casters and render
+    ShadowCasterList::const_iterator si, siend;
+    siend = casters.end();
+
+
+	// Now iterate over the casters and render
+	for (si = casters.begin(); si != siend; ++si)
+	{
+        ShadowCaster* caster = *si;
+		bool zfailAlgo = false;
+		unsigned long flags = 0;
+
+        if (light->getType() != Light::LT_DIRECTIONAL)
+        {
+            extrudeDist = caster->getPointExtrusionDistance(light); 
+        }
+
+        if (!extrudeInSoftware && !finiteExtrude)
+        {
+            // hardware extrusion, to infinity (and beyond!)
+            flags |= SRF_EXTRUDE_TO_INFINITY;
+        }
+
+		// Determine whether zfail is required
+        if (nearClipVol.intersects(caster->getWorldBoundingBox()))
+        {
+            // We use zfail for this object only because zfail
+	        // compatible with zpass algorithm
+			zfailAlgo = true;
+            // We need to include the light and / or dark cap
+            // But only if they will be visible
+            if(camera->isVisible(caster->getLightCapBounds()))
+            {
+                flags |= SRF_INCLUDE_LIGHT_CAP;
+            }
+			// zfail needs dark cap 
+			// UNLESS directional lights using hardware extrusion to infinity
+			// since that extrudes to a single point
+			if(!((flags & SRF_EXTRUDE_TO_INFINITY) && 
+				light->getType() == Light::LT_DIRECTIONAL) &&
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+        }
+		else
+		{
+			// In zpass we need a dark cap if
+			// 1: infinite extrusion on point/spotlight sources in modulative shadows
+			//    mode, since otherwise in areas where there is no depth (skybox)
+			//    the infinitely projected volume will leave a dark band
+			// 2: finite extrusion on any light source since glancing angles
+			//    can peek through the end and shadow objects behind incorrectly
+			if ((flags & SRF_EXTRUDE_TO_INFINITY) && 
+				light->getType() != Light::LT_DIRECTIONAL && 
+				mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE && 
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+			else if (!(flags & SRF_EXTRUDE_TO_INFINITY) && 
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+
+		}
+
+        // Get shadow renderables			
+        ShadowCaster::ShadowRenderableListIterator iShadowRenderables =
+            caster->getShadowVolumeRenderableIterator(mShadowTechnique,
+            light, &mShadowIndexBuffer, extrudeInSoftware, 
+            extrudeDist, flags);
+
+        // Render a shadow volume here
+        //  - if we have 2-sided stencil, one render with no culling
+        //  - otherwise, 2 renders, one with each culling method and invert the ops
+        setShadowVolumeStencilState(false, zfailAlgo, stencil2sided);
+        renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
+            false, zfailAlgo, stencil2sided);
+        if (!stencil2sided)
+        {
+            // Second pass
+            setShadowVolumeStencilState(true, zfailAlgo, false);
+            renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
+                true, zfailAlgo, false);
+        }
+
+        // Do we need to render a debug shadow marker?
+        if (mDebugShadows)
+        {
+            // reset stencil & colour ops
+            mDestRenderSystem->setStencilBufferParams();
+            mShadowDebugPass->getTextureUnitState(0)->
+                setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
+                zfailAlgo ? ColourValue(0.7, 0.0, 0.2) : ColourValue(0.0, 0.7, 0.2));
+            setPass(mShadowDebugPass);
+            renderShadowVolumeObjects(iShadowRenderables, mShadowDebugPass, &lightList, flags,
+                true, false, false);
+            mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
+            mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+        }
+    }
+
+    // revert colour write state
+    mDestRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
+    // revert depth state
+    mDestRenderSystem->_setDepthBufferParams();
+
+    mDestRenderSystem->setStencilCheckEnabled(false);
+
+    mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+
+    if (scissored)
+    {
+        // disable scissor test
+        mDestRenderSystem->setScissorTest(false);
+    }
+
+}
+//---------------------------------------------------------------------
+void SceneManager::renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
+                                             Pass* pass,
+                                             const LightList *manualLightList,
+                                             unsigned long flags,
+                                             bool secondpass, bool zfail, bool twosided)
+{
+    // ----- SHADOW VOLUME LOOP -----
+    // Render all shadow renderables with same stencil operations
+    while (iShadowRenderables.hasMoreElements())
+    {
+        ShadowRenderable* sr = iShadowRenderables.getNext();
+
+        // omit hidden renderables
+        if (sr->isVisible())
+        {
+            // render volume, including dark and (maybe) light caps
+            renderSingleObject(sr, pass, false, manualLightList);
+
+            // optionally render separate light cap
+            if (sr->isLightCapSeparate() && (flags & SRF_INCLUDE_LIGHT_CAP))
+            {
+                ShadowRenderable* lightCap = sr->getLightCapRenderable();
+                assert(lightCap && "Shadow renderable is missing a separate light cap renderable!");
+
+                // We must take care with light caps when we could 'see' the back facing
+                // triangles directly:
+                //   1. The front facing light caps must render as always fail depth
+                //      check to avoid 'depth fighting'.
+                //   2. The back facing light caps must use normal depth function to
+                //      avoid break the standard depth check
+                //
+                // TODO:
+                //   1. Separate light caps rendering doesn't need for the 'closed'
+                //      mesh that never touch the near plane, because in this instance,
+                //      we couldn't 'see' any back facing triangles directly. The
+                //      'closed' mesh must determinate by edge list builder.
+                //   2. There still exists 'depth fighting' bug with coplane triangles
+                //      that has opposite facing. This usually occur when use two side
+                //      material in the modeling tools and the model exporting tools
+                //      exporting double triangles to represent this model. This bug
+                //      can't fixed in GPU only, there must has extra work on edge list
+                //      builder and shadow volume generater to fix it.
+                //
+                if (twosided)
+                {
+                    // select back facing light caps to render
+                    mDestRenderSystem->_setCullingMode(CULL_ANTICLOCKWISE);
+                    // use normal depth function for back facing light caps
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // select front facing light caps to render
+                    mDestRenderSystem->_setCullingMode(CULL_CLOCKWISE);
+                    // must always fail depth check for front facing light caps
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // reset depth function
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+                    // reset culling mode
+                    mDestRenderSystem->_setCullingMode(CULL_NONE);
+                }
+                else if ((secondpass || zfail) && !(secondpass && zfail))
+                {
+                    // use normal depth function for back facing light caps
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+                }
+                else
+                {
+                    // must always fail depth check for front facing light caps
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // reset depth function
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+                }
+            }
+        }
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided)
+{
+    // Determinate the best stencil operation
+    StencilOperation incrOp, decrOp;
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
+    {
+        incrOp = SOP_INCREMENT_WRAP;
+        decrOp = SOP_DECREMENT_WRAP;
+    }
+    else
+    {
+        incrOp = SOP_INCREMENT;
+        decrOp = SOP_DECREMENT;
+    }
+
+    // First pass, do front faces if zpass
+    // Second pass, do back faces if zpass
+    // Invert if zfail
+    // this is to ensure we always increment before decrement
+    // When two-sided stencil, always pass front face stencil
+    // operation parameters and the inverse of them will happen
+    // for back faces
+    if ( !twosided && ((secondpass || zfail) && !(secondpass && zfail)) )
+    {
+        mDestRenderSystem->_setCullingMode(
+            twosided? CULL_NONE : CULL_ANTICLOCKWISE);
+        mDestRenderSystem->setStencilBufferParams(
+            CMPF_ALWAYS_PASS, // always pass stencil check
+            0, // no ref value (no compare)
+            0xFFFFFFFF, // no mask
+            SOP_KEEP, // stencil test will never fail
+            zfail ? incrOp : SOP_KEEP, // back face depth fail
+            zfail ? SOP_KEEP : decrOp, // back face pass
+            twosided
+            );
+    }
+    else
+    {
+        mDestRenderSystem->_setCullingMode(
+            twosided? CULL_NONE : CULL_CLOCKWISE);
+        mDestRenderSystem->setStencilBufferParams(
+            CMPF_ALWAYS_PASS, // always pass stencil check
+            0, // no ref value (no compare)
+            0xFFFFFFFF, // no mask
+            SOP_KEEP, // stencil test will never fail
+            zfail ? decrOp : SOP_KEEP, // front face depth fail
+            zfail ? SOP_KEEP : incrOp, // front face pass
+            twosided
+            );
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowColour(const ColourValue& colour)
+{
+    mShadowColour = colour;
+
+    // Prep materials first
+    initShadowVolumeMaterials();
+
+    mShadowModulativePass->getTextureUnitState(0)->setColourOperationEx(
+        LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, colour);
+}
+//---------------------------------------------------------------------
+const ColourValue& SceneManager::getShadowColour(void) const
+{
+    return mShadowColour;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowFarDistance(Real distance)
+{
+    mShadowFarDist = distance;
+    mShadowFarDistSquared = distance * distance;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowDirectionalLightExtrusionDistance(Real dist)
+{
+    mShadowDirLightExtrudeDist = dist;
+}
+//---------------------------------------------------------------------
+Real SceneManager::getShadowDirectionalLightExtrusionDistance(void) const
+{
+    return mShadowDirLightExtrudeDist;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowIndexBufferSize(size_t size)
+{
+    if (!mShadowIndexBuffer.isNull() && size != mShadowIndexBufferSize)
+    {
+        // re-create shadow buffer with new size
+        mShadowIndexBuffer = HardwareBufferManager::getSingleton().
+            createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 
+            mShadowIndexBufferSize, 
+            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
+            false);
+    }
+    mShadowIndexBufferSize = size;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureSize(unsigned short size)
+{
+    // possibly recreate
+    createShadowTextures(size, mShadowTextureCount, mShadowTextureFormat);
+    mShadowTextureSize = size;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureCount(unsigned short count)
+{
+    // possibly recreate
+    createShadowTextures(mShadowTextureSize, count, mShadowTextureFormat);
+    mShadowTextureCount = count;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTexturePixelFormat(PixelFormat fmt)
+{
+	// possibly recreate
+	createShadowTextures(mShadowTextureSize, mShadowTextureCount, fmt);
+	mShadowTextureFormat = fmt;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureSettings(unsigned short size, 
+	unsigned short count, PixelFormat fmt)
+{
+    if (!mShadowTextures.empty() && 
+        (count != mShadowTextureCount ||
+        size != mShadowTextureSize ||
+		fmt != mShadowTextureFormat))
+    {
+        // recreate
+        createShadowTextures(size, count, fmt);
+    }
+    mShadowTextureCount = count;
+    mShadowTextureSize = size;
+	mShadowTextureFormat = fmt;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureCasterMaterial(const String& name)
+{
+	if (name.empty())
+	{
+		mShadowTextureCustomCasterPass = 0;
+	}
+	else
+	{
+		MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
+		if (mat.isNull())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+				"Cannot locate material called '" + name + "'", 
+				"SceneManager::setShadowTextureCasterMaterial");
+		}
+		mat->load();
+		mShadowTextureCustomCasterPass = mat->getBestTechnique()->getPass(0);
+		if (mShadowTextureCustomCasterPass->hasVertexProgram())
+		{
+			// Save vertex program and params in case we have to swap them out
+			mShadowTextureCustomCasterVertexProgram = 
+				mShadowTextureCustomCasterPass->getVertexProgramName();
+			mShadowTextureCustomCasterVPParams = 
+				mShadowTextureCustomCasterPass->getVertexProgramParameters();
+			mShadowTextureCasterVPDirty = false;
+
+		}
+	}
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureReceiverMaterial(const String& name)
+{
+	if (name.empty())
+	{
+		mShadowTextureCustomReceiverPass = 0;
+	}
+	else
+	{
+		MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
+		if (mat.isNull())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+				"Cannot locate material called '" + name + "'", 
+				"SceneManager::setShadowTextureReceiverMaterial");
+		}
+		mat->load();
+		mShadowTextureCustomReceiverPass = mat->getBestTechnique()->getPass(0);
+		if (mShadowTextureCustomReceiverPass->hasVertexProgram())
+		{
+			// Save vertex program and params in case we have to swap them out
+			mShadowTextureCustomReceiverVertexProgram = 
+				mShadowTextureCustomReceiverPass->getVertexProgramName();
+			mShadowTextureCustomReceiverVPParams = 
+				mShadowTextureCustomReceiverPass->getVertexProgramParameters();
+			mShadowTextureReceiverVPDirty = false;
+
+		}
+	}
+}
+//---------------------------------------------------------------------
+void SceneManager::createShadowTextures(unsigned short size,
+	unsigned short count, PixelFormat fmt)
+{
+    static const String baseName = "Ogre/ShadowTexture";
+
+    if (mShadowTechnique != SHADOWTYPE_TEXTURE_MODULATIVE ||
+        !mShadowTextures.empty() && 
+        count == mShadowTextureCount &&
+        size == mShadowTextureSize && 
+		fmt == mShadowTextureFormat)
+    {
+        // no change
+        return;
+    }
+
+
+    // destroy existing
+    ShadowTextureList::iterator i, iend;
+    iend = mShadowTextures.end();
+    for (i = mShadowTextures.begin(); i != iend; ++i)
+    {
+        RenderTexture* r = *i;
+        // remove camera and destroy texture
+        removeCamera(r->getViewport(0)->getCamera());
+        mDestRenderSystem->destroyRenderTexture(r->getName());
+    }
+    mShadowTextures.clear();
+
+    // Recreate shadow textures
+    for (unsigned short t = 0; t < count; ++t)
+    {
+        String targName = baseName + StringConverter::toString(t);
+        String matName = baseName + "Mat" + StringConverter::toString(t);
+        String camName = baseName + "Cam" + StringConverter::toString(t);
+
+        RenderTexture* shadowTex;
+        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+        {
+            shadowTex = mDestRenderSystem->createRenderTexture( 
+                targName, size, size, TEX_TYPE_2D, mShadowTextureFormat);
+        }
+
+        // Create a camera to go with this texture
+        Camera* cam = createCamera(camName);
+        cam->setAspectRatio(1.0f);
+        // Create a viewport
+        Viewport *v = shadowTex->addViewport(cam);
+        v->setClearEveryFrame(true);
+        // remove overlays
+        v->setOverlaysEnabled(false);
+        // Don't update automatically - we'll do it when required
+        shadowTex->setAutoUpdated(false);
+        mShadowTextures.push_back(shadowTex);
+
+        // Also create corresponding Material used for rendering this shadow
+        MaterialPtr mat = MaterialManager::getSingleton().getByName(matName);
+        if (mat.isNull())
+        {
+            mat = MaterialManager::getSingleton().create(
+                matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+        }
+        else
+        {
+            mat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
+        }
+        // create texture unit referring to render target texture
+        TextureUnitState* texUnit = 
+            mat->getTechnique(0)->getPass(0)->createTextureUnitState(targName);
+        // set projective based on camera
+        texUnit->setProjectiveTexturing(true, cam);
+        texUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+        mat->touch();
+
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::prepareShadowTextures(Camera* cam, Viewport* vp)
+{
+    // Set the illumination stage, prevents recursive calls
+    IlluminationRenderStage savedStage = mIlluminationStage;
+    mIlluminationStage = IRS_RENDER_TO_TEXTURE;
+
+    // Determine far shadow distance
+    Real shadowDist = mShadowFarDist;
+    if (!shadowDist)
+    {
+        // need a shadow distance, make one up
+        shadowDist = cam->getNearClipDistance() * 300;
+    }
+    // set fogging to hide the shadow edge
+    Real shadowOffset = shadowDist * mShadowTextureOffset;
+    Real shadowEnd = shadowDist + shadowOffset;
+    mShadowReceiverPass->setFog(true, FOG_LINEAR, ColourValue::White, 
+        0, shadowEnd * mShadowTextureFadeStart, shadowEnd * mShadowTextureFadeEnd);
+
+    // Iterate over the lights we've found, max out at the limit of light textures
+
+    LightList::iterator i, iend;
+    ShadowTextureList::iterator si, siend;
+    iend = mLightsAffectingFrustum.end();
+    siend = mShadowTextures.end();
+    for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
+        i != iend && si != siend; ++i)
+    {
+        Light* light = *i;
+        RenderTexture* shadowTex = *si;
+        // Skip non-shadowing lights
+        if (!light->getCastShadows())
+            continue;
+
+        // Directional lights 
+        if (light->getType() == Light::LT_DIRECTIONAL)
+        {
+
+            // set up the shadow texture
+            Camera* texCam = shadowTex->getViewport(0)->getCamera();
+            // Set ortho projection
+            texCam->setProjectionType(PT_ORTHOGRAPHIC);
+            // set easy FOV and near dist so that texture covers far dist
+            texCam->setFOVy(Degree(90));
+            texCam->setNearClipDistance(shadowDist);
+
+            // Set size of projection
+
+            // Calculate look at position
+            // We want to look at a spot shadowOffset away from near plane
+            // 0.5 is a litle too close for angles
+            Vector3 target = cam->getDerivedPosition() + 
+                (cam->getDerivedDirection() * shadowOffset);
+
+            // Calculate position
+            // We want to be in the -ve direction of the light direction
+            // far enough to project for the dir light extrusion distance
+            Vector3 pos = target + 
+                (light->getDerivedDirection() * -mShadowDirLightExtrudeDist);
+
+            // Calculate orientation
+            Vector3 dir = (pos - target); // backwards since point down -z
+            dir.normalise();
+            /*
+            // Next section (camera oriented shadow map) abandoned
+            // Always point in the same direction, if we don't do this then
+            // we get 'shadow swimming' as camera rotates
+            // As it is, we get swimming on moving but this is less noticeable
+
+            // calculate up vector, we want it aligned with cam direction
+            Vector3 up = cam->getDerivedDirection();
+            // Check it's not coincident with dir
+            if (up.dotProduct(dir) >= 1.0f)
+            {
+            // Use camera up
+            up = cam->getUp();
+            }
+            */
+            Vector3 up = Vector3::UNIT_Y;
+            // Check it's not coincident with dir
+            if (up.dotProduct(dir) >= 1.0f)
+            {
+                // Use camera up
+                up = Vector3::UNIT_Z;
+            }
+            // cross twice to rederive, only direction is unaltered
+            Vector3 left = dir.crossProduct(up);
+            left.normalise();
+            up = dir.crossProduct(left);
+            up.normalise();
+            // Derive quaternion from axes
+            Quaternion q;
+            q.FromAxes(left, up, dir);
+            texCam->setOrientation(q);
+
+            // Round local x/y position based on a world-space texel; this helps to reduce
+            // jittering caused by the projection moving with the camera
+            // Viewport is 2 * near clip distance across (90 degree fov)
+            Real worldTexelSize = (texCam->getNearClipDistance() * 20) / mShadowTextureSize;
+            pos.x -= fmod(pos.x, worldTexelSize);
+            pos.y -= fmod(pos.y, worldTexelSize);
+            pos.z -= fmod(pos.z, worldTexelSize);
+            // Finally set position
+            texCam->setPosition(pos);
+
+            if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+                shadowTex->getViewport(0)->setBackgroundColour(ColourValue::White);
+
+            // Update target
+            shadowTex->update();
+
+            ++si;
+        }
+        // Spotlight
+        else if (light->getType() == Light::LT_SPOTLIGHT)
+        {
+
+            // set up the shadow texture
+            Camera* texCam = shadowTex->getViewport(0)->getCamera();
+            // Set perspective projection
+            texCam->setProjectionType(PT_PERSPECTIVE);
+            // set FOV slightly larger than the spotlight range to ensure coverage
+            texCam->setFOVy(light->getSpotlightOuterAngle()*1.2);
+            texCam->setPosition(light->getDerivedPosition());
+            texCam->setDirection(light->getDerivedDirection());
+            // set near clip the same as main camera, since they are likely
+            // to both reflect the nature of the scene
+            texCam->setNearClipDistance(cam->getNearClipDistance());
+
+            if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+                shadowTex->getViewport(0)->setBackgroundColour(ColourValue::White);
+
+            // Update target
+            shadowTex->update();
+
+            ++si;
+        }
+    }
+    // Set the illumination stage, prevents recursive calls
+    mIlluminationStage = savedStage;
+}
+//---------------------------------------------------------------------
+StaticGeometry* SceneManager::createStaticGeometry(const String& name)
+{
+	// Check not existing
+	if (mStaticGeometryList.find(name) != mStaticGeometryList.end())
+	{
+		OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
+			"StaticGeometry with name '" + name + "' already exists!", 
+			"SceneManager::createStaticGeometry");
+	}
+	StaticGeometry* ret = new StaticGeometry(this, name);
+	mStaticGeometryList[name] = ret;
+	return ret;
+}
+//---------------------------------------------------------------------
+StaticGeometry* SceneManager::getStaticGeometry(const String& name) const
+{
+	StaticGeometryList::const_iterator i = mStaticGeometryList.find(name);
+	if (i == mStaticGeometryList.end())
+	{
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+			"StaticGeometry with name '" + name + "' not found", 
+			"SceneManager::createStaticGeometry");
+	}
+	return i->second;
+}
+//---------------------------------------------------------------------
+void SceneManager::removeStaticGeometry(StaticGeometry* geom)
+{
+	removeStaticGeometry(geom->getName());
+}
+//---------------------------------------------------------------------
+void SceneManager::removeStaticGeometry(const String& name)
+{
+	StaticGeometryList::iterator i = mStaticGeometryList.find(name);
+	if (i != mStaticGeometryList.end())
+	{
+		delete i->second;
+		mStaticGeometryList.erase(i);
+	}
+
+}
+//---------------------------------------------------------------------
+void SceneManager::removeAllStaticGeometry(void)
+{
+	StaticGeometryList::iterator i, iend;
+	iend = mStaticGeometryList.end();
+	for (i = mStaticGeometryList.begin(); i != iend; ++i)
+	{
+		delete i->second;
+	}
+	mStaticGeometryList.clear();
+}
+//---------------------------------------------------------------------
+AxisAlignedBoxSceneQuery* 
+SceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
+{
+    DefaultAxisAlignedBoxSceneQuery* q = new DefaultAxisAlignedBoxSceneQuery(this);
+    q->setBox(box);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+SphereSceneQuery* 
+SceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
+{
+    DefaultSphereSceneQuery* q = new DefaultSphereSceneQuery(this);
+    q->setSphere(sphere);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+PlaneBoundedVolumeListSceneQuery* 
+SceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, 
+                                            unsigned long mask)
+{
+    DefaultPlaneBoundedVolumeListSceneQuery* q = new DefaultPlaneBoundedVolumeListSceneQuery(this);
+    q->setVolumes(volumes);
+    q->setQueryMask(mask);
+    return q;
+}
+
+//---------------------------------------------------------------------
+RaySceneQuery* 
+SceneManager::createRayQuery(const Ray& ray, unsigned long mask)
+{
+    DefaultRaySceneQuery* q = new DefaultRaySceneQuery(this);
+    q->setRay(ray);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+IntersectionSceneQuery* 
+SceneManager::createIntersectionQuery(unsigned long mask)
+{
+
+    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+void SceneManager::destroyQuery(SceneQuery* query)
+{
+    delete query;
+}
+//---------------------------------------------------------------------
+DefaultIntersectionSceneQuery::DefaultIntersectionSceneQuery(SceneManager* creator)
+: IntersectionSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultIntersectionSceneQuery::~DefaultIntersectionSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator a, b, theEnd;
+    theEnd = mParentSceneMgr->mEntities.end();
+    int numEntities;
+    // Loop a from first to last-1
+    a = mParentSceneMgr->mEntities.begin();
+    numEntities = (uint)mParentSceneMgr->mEntities.size();
+    for (int i = 0; i < (numEntities - 1); ++i, ++a)
+    {
+        // Skip if a does not pass the mask
+        if (!(a->second->getQueryFlags() & mQueryMask) ||
+			!a->second->isInScene())
+            continue;
+
+        // Loop b from a+1 to last
+        b = a;
+        for (++b; b != theEnd; ++b)
+        {
+            // Apply mask to b (both must pass)
+            if ((b->second->getQueryFlags() & mQueryMask) && b->second->isInScene())
+            {
+                const AxisAlignedBox& box1 = a->second->getWorldBoundingBox();
+                const AxisAlignedBox& box2 = b->second->getWorldBoundingBox();
+
+                if (box1.intersects(box2))
+                {
+                    if (!listener->queryResult(a->second, b->second)) return;
+                }
+            }
+
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultAxisAlignedBoxSceneQuery::
+DefaultAxisAlignedBoxSceneQuery(SceneManager* creator)
+: AxisAlignedBoxSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultAxisAlignedBoxSceneQuery::~DefaultAxisAlignedBoxSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultAxisAlignedBoxSceneQuery::execute(SceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        if ((i->second->getQueryFlags() & mQueryMask) && 
+			i->second->isInScene() &&
+			mAABB.intersects(i->second->getWorldBoundingBox()))
+        {
+            if (!listener->queryResult(i->second)) return;
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultRaySceneQuery::
+DefaultRaySceneQuery(SceneManager* creator) : RaySceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultRaySceneQuery::~DefaultRaySceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultRaySceneQuery::execute(RaySceneQueryListener* listener)
+{
+    // Note that becuase we have no scene partitioning, we actually
+    // perform a complete scene search even if restricted results are
+    // requested; smarter scene manager queries can utilise the paritioning 
+    // of the scene in order to reduce the number of intersection tests 
+    // required to fulfil the query
+
+    // TODO: BillboardSets? Will need per-billboard collision most likely
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        if( (i->second->getQueryFlags() & mQueryMask) &&
+			i->second->isInScene())
+        {
+            // Do ray / box test
+            std::pair<bool, Real> result =
+                mRay.intersects(i->second->getWorldBoundingBox());
+
+            if (result.first)
+            {
+                if (!listener->queryResult(i->second, result.second)) return;
+            }
+        }
+    }
+
+}
+//---------------------------------------------------------------------
+DefaultSphereSceneQuery::
+DefaultSphereSceneQuery(SceneManager* creator) : SphereSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultSphereSceneQuery::~DefaultSphereSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultSphereSceneQuery::execute(SceneQueryListener* listener)
+{
+    // TODO: BillboardSets? Will need per-billboard collision most likely
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    Sphere testSphere;
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        // Skip unattached
+        if (!i->second->isInScene() || 
+			!(i->second->getQueryFlags() & mQueryMask))
+            continue;
+
+        // Do sphere / sphere test
+        testSphere.setCenter(i->second->getParentNode()->_getDerivedPosition());
+        testSphere.setRadius(i->second->getBoundingRadius());
+        if (mSphere.intersects(testSphere))
+        {
+            if (!listener->queryResult(i->second)) return;
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultPlaneBoundedVolumeListSceneQuery::
+DefaultPlaneBoundedVolumeListSceneQuery(SceneManager* creator) 
+: PlaneBoundedVolumeListSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultPlaneBoundedVolumeListSceneQuery::~DefaultPlaneBoundedVolumeListSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultPlaneBoundedVolumeListSceneQuery::execute(SceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    Sphere testSphere;
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        PlaneBoundedVolumeList::iterator pi, piend;
+        piend = mVolumes.end();
+        for (pi = mVolumes.begin(); pi != piend; ++pi)
+        {
+            PlaneBoundedVolume& vol = *pi;
+            // Do AABB / plane volume test
+            if ((i->second->getQueryFlags() & mQueryMask) && 
+				i->second->isInScene() && 
+				vol.intersects(i->second->getWorldBoundingBox()))
+            {
+                if (!listener->queryResult(i->second)) return;
+                break;
+            }
+        }
+    }
+}
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+//-----------------------------------------------------------------------
+void SceneManager::_renderSceneNode( Camera *cam, SceneNode *node )
+{
+	node->_findVisibleObjects(cam, getRenderQueue(), false, mDisplayNodes, false);
+	SceneManager::_renderVisibleObjects();
+	
+	// delete all rendered objects from renderqueue
+	_deleteRenderedQueueGroups();
+}
+//-----------------------------------------------------------------------
+void SceneManager::_deleteRenderedQueueGroups()
+{
+	RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
+
+	while (queueIt.hasMoreElements())
+	{
+		RenderQueueGroupID qId = queueIt.peekNextKey();
+		RenderQueueGroup* pGroup = queueIt.getNext();
+
+		// delete this queue group if already processed
+		if (isRenderQueueToBeProcessed(qId))
+			pGroup->clear();
+	}
+	
+	// Now trigger the pending pass updates
+	// Pass::processPendingPassUpdates();
+}
+#endif //OGRE_COHERENT_OCCLUSION_CULLING
+}
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h	(revision 61)
@@ -0,0 +1,203 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octree.h  -  description
+-------------------
+begin                : Mon Sep 30 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+***************************************************************************/
+
+#ifndef OCTREE_H
+#define OCTREE_H
+
+#include "OgreTerrainPrerequisites.h"
+#include <OgreAxisAlignedBox.h>
+#include <OgreWireBoundingBox.h>
+
+#include <list>
+
+namespace Ogre
+{
+
+class OctreeNode;
+
+typedef std::list < OctreeNode * > NodeList;
+
+
+/** Octree datastructure for managing scene nodes.
+@remarks
+This is a loose octree implementation, meaning that each
+octant child of the octree actually overlaps it's siblings by a factor
+of .5.  This guarantees that any thing that is half the size of the parent will
+fit completely into a child, with no splitting necessary.
+*/
+
+class _OgreTerrainExport Octree
+{
+public:
+    Octree( Octree * p );
+    ~Octree();
+
+    /** Adds an Octree scene node to this octree level.
+    @remarks
+    This is called by the OctreeSceneManager after
+    it has determined the correct Octree to insert the node into.
+    */
+    void _addNode( OctreeNode * );
+
+    /** Removes an Octree scene node to this octree level.
+    */
+    void _removeNode( OctreeNode * );
+
+    /** Returns the number of scene nodes attached to this octree
+    */
+    int numNodes()
+    {
+        return mNumNodes;
+    };
+
+    /** The bounding box of the octree
+    @remarks
+    This is used for octant index determination and rendering, but not culling
+    */
+    AxisAlignedBox mBox;
+    WireBoundingBox* mWireBoundingBox;
+    
+    /** Creats the wire frame bounding box for this octant
+    */
+    WireBoundingBox* getWireBoundingBox();
+
+    /** Vector containing the dimensions of this octree / 2
+    */
+    Vector3 mHalfSize;
+
+    /** 3D array of children of this octree.
+    @remarks
+    Children are dynamically created as needed when nodes are inserted in the Octree.
+    If, later, the all the nodes are removed from the child, it is still kept arround.
+    */
+    Octree * mChildren[ 2 ][ 2 ][ 2 ];
+
+    /** Determines if this octree is twice as big as the given box.
+    @remarks
+    This method is used by the OctreeSceneManager to determine if the given
+    box will fit into a child of this octree.
+    */
+    bool _isTwiceSize( AxisAlignedBox &box );
+
+    /**  Returns the appropriate indexes for the child of this octree into which the box will fit.
+    @remarks
+    This is used by the OCtreeSceneManager to determine which child to traverse next when
+    finding the appropriate octree to insert the box.  Since it is a loose octree, only the
+    center of the box is checked to determine the octant.
+    */
+    void _getChildIndexes( AxisAlignedBox &, int *x, int *y, int *z );
+
+    /** Creates the AxisAlignedBox used for culling this octree.
+    @remarks
+    Since it's a loose octree, the culling bounds can be different than the actual bounds of the octree.
+    */
+    void _getCullBounds( AxisAlignedBox * );
+
+
+    /** Public list of SceneNodes attached to this particular octree
+    */
+    NodeList mNodes;
+
+protected:
+
+    /** Increments the overall node count of this octree and all it's parents
+    */
+    inline void _ref()
+    {
+        mNumNodes++;
+
+        if ( mParent != 0 ) mParent -> _ref();
+    };
+
+    /** Decrements the overall node count of this octree and all it's parents
+    */
+    inline void _unref()
+    {
+        mNumNodes--;
+
+        if ( mParent != 0 ) mParent -> _unref();
+    };
+
+    ///number of SceneNodes in this octree and all it's children.
+    int mNumNodes;
+
+    ///parent octree
+    Octree * mParent;
+
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+	public:
+		/** Returns last visited frame id. */
+		int lastVisited(void);
+		/** Set to current frame id.
+        @param current frame id.
+        */
+		void setLastVisited(int frameid);
+		/** Makes this octree become visible / invisble.
+        @param visible Whether this node is to be made visible or invisible
+        */
+		void setOctreeVisible(bool visible);
+		/** Returns true if this node is marked visible, false otherwise. 
+		*/
+		bool isOctreeVisible(void);
+		/** Gets this node's parent (NULL if this is the root).
+		*/
+		Octree *getParent();
+		/** Frame id when this octree was last rendered. 
+		@return last rendered frame id
+		*/	
+		int lastRendered(void);
+		/** Sets frame id when this octree was last rendered. 
+		@param last rendered frame id
+		*/
+		void setLastRendered(int frameid);
+		/** Returns current depth of octree 
+		@return current depth
+		*/
+		int getDepth();
+
+	protected:
+
+		int mLastRendered;
+		int mLastVisited;
+		bool mVisible;
+		int mDepth;
+
+#endif //OGRE_COHERENT_OCCLUSION_CULLING
+};
+
+}
+
+#endif
+
+
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 61)
@@ -0,0 +1,90 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreecamera.h  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+***************************************************************************/
+
+#ifndef OCTREECAMERA_H
+#define OCTREECAMERA_H
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+#include "OgreTerrainPrerequisites.h"
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+#include <OgreCamera.h>
+#include <OgreHardwareBufferManager.h>
+#include <OgreSimpleRenderable.h>
+
+/**
+*@author Jon Anderson
+*/
+
+namespace Ogre
+{
+
+class Octree;
+
+
+/** Specialized viewpoint from which an Octree can be rendered.
+@remarks
+This class contains several speciliazations of the Ogre::Camera class. It
+implements the getRenderOperation method inorder to return displayable geometry
+for debuggin purposes. It also implements a visibility function that is more granular
+than the default.
+*/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+class _OgreTerrainExport OctreeCamera : public Camera
+#else
+class OctreeCamera : public Camera
+#endif
+{
+public:
+
+    /** Visibility types */
+    enum Visibility
+    {
+        NONE,
+        PARTIAL,
+        FULL
+    };
+
+    /* Standard Constructor */
+    OctreeCamera( const String& name, SceneManager* sm );
+    /* Standard destructor */
+    ~OctreeCamera();
+
+    /** Returns the visiblity of the box
+    */
+    OctreeCamera::Visibility getVisibility( const AxisAlignedBox &bound );
+
+};
+
+}
+
+#endif
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 61)
@@ -0,0 +1,260 @@
+/***************************************************************************
+octreescenemanager.h  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+***************************************************************************/
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef OCTREESCENEMANAGER_H
+#define OCTREESCENEMANAGER_H
+
+#include "OgreTerrainPrerequisites.h"
+#include "OgreSceneManager.h"
+#include "OgreRenderOperation.h"
+#include "OgreSphere.h"
+
+#include <list>
+#include <algorithm>
+
+#include <OgreOctree.h>
+
+
+namespace Ogre
+{
+
+class OctreeNode;
+
+class OctreeCamera;
+class OctreeIntersectionSceneQuery;
+class OctreeRaySceneQuery;
+class OctreeSphereSceneQuery;
+class OctreeAxisAlignedBoxSceneQuery;
+class OctreePlaneBoundedVolumeListSceneQuery;
+
+
+typedef std::list < WireBoundingBox * > BoxList;
+typedef std::list < unsigned long > ColorList;
+//typedef std::list < SceneNode * > SceneNodeList;
+
+
+/** Specialized SceneManager that divides the geometry into an octree in order to faciliate spatial queries.
+@remarks
+For debugging purposes, a special "CullCamera" can be defined.  To use it, call setUseCallCamera( true ),
+and create a camera named "CullCamera".  All culling will be performed using that camera, instead of the viewport
+camera, allowing you to fly around and examine culling.
+*/
+
+class _OgreTerrainExport OctreeSceneManager : public SceneManager
+{
+    friend class OctreeIntersectionSceneQuery;
+    friend class OctreeRaySceneQuery;
+    friend class OctreeSphereSceneQuery;
+    friend class OctreeAxisAlignedBoxSceneQuery;
+    friend class OctreePlaneBoundedVolumeListSceneQuery;
+
+public:
+    static int intersect_call;
+    /** Standard Constructor.  Initializes the octree to -500,-500,-500 to 500,500,500 with unlimited depth. */
+    OctreeSceneManager( );
+    /** Standard Constructor */
+    OctreeSceneManager( AxisAlignedBox &box, int max_depth );
+    /** Standard desctructor */
+    ~OctreeSceneManager();
+
+    /** Initializeds the manager to the given box and depth.
+    */
+    void init( AxisAlignedBox &box, int d );
+
+    /** Creates a specialized OctreeNode */
+    virtual	SceneNode * createSceneNode ( void );
+    /** Creates a specialized OctreeNode */
+    virtual SceneNode * createSceneNode ( const String &name );
+    /** Creates a specialized OctreeCamera */
+    virtual Camera * createCamera( const String &name );
+
+    /** Deletes a scene node */
+    virtual void destroySceneNode( const String &name );
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/** Renders one octant of an octree, i.e., renders current octant
+		node and does not traverse deeper into the tree.
+		@remark Note that OctreeNode instances are NOT part of the octree 
+		hierarchy, instead one octant of an Octree contains many OctreeNode instances.
+		@param octree the octree to be rendered
+		@param cam current camera
+	*/
+	void _renderOctant(Camera* cam, Octree *octree);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+
+    /** Does nothing more */
+    virtual void _updateSceneGraph( Camera * cam );
+    /** Recurses through the octree determining which nodes are visible. */
+    virtual void _findVisibleObjects ( Camera * cam, bool onlyShadowCasters );
+
+    /** Alerts each unculled object, notifying it that it will be drawn.
+     * Useful for doing calculations only on nodes that will be drawn, prior
+     * to drawing them...
+     */
+    virtual void _alertVisibleObjects( void );
+
+    /** Walks through the octree, adding any visible objects to the render queue.
+    @remarks
+    If any octant in the octree if completely within the the view frustum,
+    all subchildren are automatically added with no visibility tests.
+    */
+    void walkOctree( OctreeCamera *, RenderQueue *, Octree *, bool foundvisible,
+                     bool onlyShadowCasters);
+
+    /** Checks the given OctreeNode, and determines if it needs to be moved
+    * to a different octant.
+    */
+    void _updateOctreeNode( OctreeNode * );
+    /** Removes the given octree node */
+    void _removeOctreeNode( OctreeNode * );
+    /** Adds the Octree Node, starting at the given octree, and recursing at max to the specified depth.
+    */
+    void _addOctreeNode( OctreeNode *, Octree *octree, int depth = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the box into the given list.
+    It ignores the exclude scene node.
+    */
+    void findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the sphere into the given list.
+    It ignores the exclude scene node.
+    */
+    void findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the volume into the given list.
+      It ignores the exclude scene node.
+      */
+    void findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude=0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the ray into the given list.
+      It ignores the exclude scene node.
+      */
+    void findNodesIn( const Ray &ray, std::list < SceneNode * > &list, SceneNode *exclude=0 );
+
+    /** Sets the box visibility flag */
+    void setShowBoxes( bool b )
+    {
+        mShowBoxes = b;
+    };
+
+    /** Sets the cull camera flag */
+    void setUseCullCamera( bool b )
+    {
+        mCullCamera = b;
+    };
+
+    void setLooseOctree( bool b )
+    {
+        mLoose = b;
+    };
+
+
+    /** Resizes the octree to the given size */
+    void resize( const AxisAlignedBox &box );
+
+    /** Sets the given option for the SceneManager
+               @remarks
+        Options are:
+        "Size", AxisAlignedBox *;
+        "CullCamera", bool *;
+        "Depth", int *;
+        "ShowOctree", bool *;
+    */
+
+    virtual bool setOption( const String &, const void * );
+    /** Gets the given option for the Scene Manager.
+        @remarks
+        See setOption
+    */
+    virtual bool getOption( const String &, void * );
+
+    bool getOptionValues( const String & key, StringVector &refValueList );
+    bool getOptionKeys( StringVector &refKeys );
+    /** Overridden from SceneManager */
+    void clearScene(void);
+
+    AxisAlignedBoxSceneQuery* OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask);
+    SphereSceneQuery* OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask);
+    PlaneBoundedVolumeListSceneQuery* createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, unsigned long mask);
+    RaySceneQuery* createRayQuery(const Ray& ray, unsigned long mask);
+    IntersectionSceneQuery* createIntersectionQuery(unsigned long mask);
+
+protected:
+
+
+    NodeList mVisible;
+
+    /// The root octree
+    Octree *mOctree;
+
+    /// list of boxes to be rendered
+    BoxList mBoxes;
+
+    /// number of rendered objs
+    int mNumObjects;
+
+    /// max depth for the tree.
+    int mMaxDepth;
+    /// Size of the octree
+    AxisAlignedBox mBox;
+
+    /// box visibility flag
+    bool mShowBoxes;
+
+    /// cull camera flag
+    bool mCullCamera;
+
+
+    bool mLoose;
+
+    Real mCorners[ 24 ];
+    static unsigned long mColors[ 8 ];
+    static unsigned short mIndexes[ 24 ];
+
+    Matrix4 mScaleFactor;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/* the number of nodes in the octree. do not confuse this with the OctreeNode
+	class with is derived from SceneNode.
+	*/
+	int mNumOctreeNodes;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+};
+
+
+}
+
+#endif
+
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp	(revision 61)
@@ -0,0 +1,223 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octree.cpp  -  description
+-------------------
+begin                : Mon Sep 30 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+
+#include <OgreOctree.h>
+#include <OgreOctreeNode.h>
+
+namespace Ogre
+{
+
+/** Returns true is the box will fit in a child.
+*/
+bool Octree::_isTwiceSize( AxisAlignedBox &box )
+{
+    const Vector3 * pts1 = mBox.getAllCorners();
+    const Vector3 * pts2 = box.getAllCorners();
+
+    return ( ( pts2[ 4 ].x -pts2[ 0 ].x ) <= ( pts1[ 4 ].x - pts1[ 0 ].x ) / 2 ) &&
+           ( ( pts2[ 4 ].y - pts2[ 0 ].y ) <= ( pts1[ 4 ].y - pts1[ 0 ].y ) / 2 ) &&
+           ( ( pts2[ 4 ].z - pts2[ 0 ].z ) <= ( pts1[ 4 ].z - pts1[ 0 ].z ) / 2 ) ;
+
+}
+
+/** It's assumed the the given box has already been proven to fit into
+* a child.  Since it's a loose octree, only the centers need to be
+* compared to find the appropriate node.
+*/
+void Octree::_getChildIndexes( AxisAlignedBox &box, int *x, int *y, int *z )
+{
+    Vector3 max = mBox.getMaximum();
+    Vector3 min = box.getMinimum();
+
+    Vector3 center = mBox.getMaximum().midPoint( mBox.getMinimum() );
+
+    Vector3 ncenter = box.getMaximum().midPoint( box.getMinimum() );
+
+    if ( ncenter.x > center.x )
+        * x = 1;
+    else
+        *x = 0;
+
+    if ( ncenter.y > center.y )
+        * y = 1;
+    else
+        *y = 0;
+
+    if ( ncenter.z > center.z )
+        * z = 1;
+    else
+        *z = 0;
+
+}
+
+Octree::Octree( Octree * parent ) 
+    : mWireBoundingBox(0),
+      mHalfSize( 0, 0, 0 )
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false), mLastRendered(-1)
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+{
+    //initialize all children to null.
+    for ( int i = 0; i < 2; i++ )
+    {
+        for ( int j = 0; j < 2; j++ )
+        {
+            for ( int k = 0; k < 2; k++ )
+            {
+                mChildren[ i ][ j ][ k ] = 0;
+            }
+        }
+    }
+
+    mParent = parent;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	if (mParent) 
+		mDepth = parent->getDepth() + 1;
+	else
+		mDepth = 0;
+
+	//matt: remove later
+	//char msg[100];
+	//sprintf(msg, "creating new octant in depth %d", mDepth);
+	//OutputDebugString(msg);
+
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    mNumNodes = 0;
+}
+
+Octree::~Octree()
+{
+    //initialize all children to null.
+    for ( int i = 0; i < 2; i++ )
+    {
+        for ( int j = 0; j < 2; j++ )
+        {
+            for ( int k = 0; k < 2; k++ )
+            {
+                if ( mChildren[ i ][ j ][ k ] != 0 )
+                    delete mChildren[ i ][ j ][ k ];
+            }
+        }
+    }
+
+    if(mWireBoundingBox)
+        delete mWireBoundingBox;
+
+    mParent = 0;
+}
+
+void Octree::_addNode( OctreeNode * n )
+{
+    mNodes.push_back( n );
+    n -> setOctant( this );
+
+    //update total counts.
+    _ref();
+
+}
+
+void Octree::_removeNode( OctreeNode * n )
+{
+    mNodes.erase( std::find( mNodes.begin(), mNodes.end(), n ) );
+    n -> setOctant( 0 );
+
+    //update total counts.
+    _unref();
+}
+
+void Octree::_getCullBounds( AxisAlignedBox *b )
+{
+    const Vector3 * corners = mBox.getAllCorners();
+    b -> setExtents( corners[ 0 ] - mHalfSize, corners[ 4 ] + mHalfSize );
+}
+
+WireBoundingBox* Octree::getWireBoundingBox()
+{
+	// Create a WireBoundingBox if needed
+    if(mWireBoundingBox == 0)
+        mWireBoundingBox = new WireBoundingBox();
+
+	mWireBoundingBox->setupBoundingBox(mBox);
+
+	// matt: change this back
+	//AxisAlignedBox box; _getCullBounds(&box); 
+	//mWireBoundingBox->setupBoundingBox(box);
+
+    return mWireBoundingBox;
+}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//-----------------------------------------------------------------------	
+int Octree::lastVisited(void)
+{
+	return mLastVisited;
+}
+//-----------------------------------------------------------------------
+void Octree::setLastVisited(int frameid)
+{
+	mLastVisited = frameid;
+}
+//-----------------------------------------------------------------------	
+int Octree::lastRendered(void)
+{
+	return mLastRendered;
+}
+//-----------------------------------------------------------------------
+void Octree::setLastRendered(int frameid)
+{
+	mLastRendered = frameid;
+}
+//-----------------------------------------------------------------------	
+void Octree::setOctreeVisible(bool visible)
+{
+	mVisible = visible;
+}
+//-----------------------------------------------------------------------	
+bool Octree::isOctreeVisible(void)
+{
+	return mVisible;
+}
+//-----------------------------------------------------------------------	
+Octree *Octree::getParent()
+{
+	return mParent;
+}
+//-----------------------------------------------------------------------	
+int Octree::getDepth()
+{
+	return mDepth;
+}
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp	(revision 61)
@@ -0,0 +1,114 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreecamera.cpp  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+#include <OgreMath.h>
+#include <OgreAxisAlignedBox.h>
+#include <OgreRoot.h>
+
+#include <OgreOctreeCamera.h>
+
+namespace Ogre
+{
+OctreeCamera::OctreeCamera( const String& name, SceneManager* sm ) : Camera( name, sm )
+{
+                                                                      
+}
+
+OctreeCamera::~OctreeCamera()
+{
+}
+
+OctreeCamera::Visibility OctreeCamera::getVisibility( const AxisAlignedBox &bound )
+{
+
+    // Null boxes always invisible
+    if ( bound.isNull() )
+        return NONE;
+
+    // Make any pending updates to the calculated frustum
+    updateView();
+
+    // Get corners of the box
+    const Vector3* pCorners = bound.getAllCorners();
+
+    // For each plane, see if all points are on the negative side
+    // If so, object is not visible.
+    // If one or more are, it's partial.
+    // If all aren't, full
+
+    int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
+
+    int planes[ 6 ] = {FRUSTUM_PLANE_TOP, FRUSTUM_PLANE_BOTTOM,
+                       FRUSTUM_PLANE_LEFT, FRUSTUM_PLANE_RIGHT,
+                       FRUSTUM_PLANE_FAR, FRUSTUM_PLANE_NEAR };
+
+    bool all_inside = true;
+
+    for ( int plane = 0; plane < 6; ++plane )
+    {
+
+        // Skip far plane if infinite view frustum
+        if (mFarDist == 0 && planes[ plane ] == FRUSTUM_PLANE_FAR)
+            continue;
+
+        bool all_outside = true;
+
+        float distance = 0;
+
+        for ( int corner = 0; corner < 8; ++corner )
+        {
+            distance = mFrustumPlanes[ planes[ plane ] ].getDistance( pCorners[ corners[ corner ] ] );
+            all_outside = all_outside && ( distance < 0 );
+            all_inside = all_inside && ( distance >= 0 );
+
+            if ( !all_outside && !all_inside )
+                break;
+        }
+
+        if ( all_outside )
+            return NONE;
+    }
+
+    if ( all_inside )
+        return FULL;
+    else
+        return PARTIAL;
+
+}
+
+}
+
+
+
+
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 61)
@@ -0,0 +1,1207 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreescenemanager.cpp  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+ 
+Enhancements 2003 - 2004 (C) The OGRE Team
+ 
+***************************************************************************/
+
+#include <OgreOctreeSceneManager.h>
+#include <OgreOctreeSceneQuery.h>
+#include <OgreOctreeNode.h>
+#include <OgreOctreeCamera.h>
+#include <OgreRenderSystem.h>
+#include <windows.h>
+
+extern "C"
+{
+    void findNodesInBox( Ogre::SceneManager *sm,
+                         const Ogre::AxisAlignedBox &box,
+                         std::list < Ogre::SceneNode * > &list,
+                         Ogre::SceneNode *exclude )
+    {
+        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( box, list, exclude );
+    }
+    void findNodesInSphere( Ogre::SceneManager *sm,
+                            const Ogre::Sphere &sphere,
+                            std::list < Ogre::SceneNode * > &list,
+                            Ogre::SceneNode *exclude )
+    {
+        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( sphere, list, exclude );
+    }
+}
+
+namespace Ogre
+{
+enum Intersection
+{
+    OUTSIDE=0,
+    INSIDE=1,
+    INTERSECT=2
+};
+int OctreeSceneManager::intersect_call = 0;
+
+Intersection intersect( const Ray &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    bool inside = true;
+    const Vector3* pCorners = two.getAllCorners();
+    Vector3 origin = one.getOrigin();
+    Vector3 dir = one.getDirection();
+
+    Vector3 maxT(-1, -1, -1);
+
+    int i = 0;
+    for(i=0; i<3; i++ )
+    {
+        if( origin[i] < pCorners[0][i] )
+        {
+            inside = false;
+            if( dir[i] > 0 )
+            {
+                maxT[i] = (pCorners[0][i] - origin[i])/ dir[i];
+            }
+        }
+        else if( origin[i] > pCorners[4][i] )
+        {
+            inside = false;
+            if( dir[i] < 0 )
+            {
+                maxT[i] = (pCorners[4][i] - origin[i]) / dir[i];
+            }
+        }
+    }
+
+    if( inside )
+    {
+        return INTERSECT;
+    }
+    int whichPlane = 0;
+    if( maxT[1] > maxT[whichPlane])
+        whichPlane = 1;
+    if( maxT[2] > maxT[whichPlane])
+        whichPlane = 2;
+
+    if( ((int)maxT[whichPlane]) & 0x80000000 )
+    {
+        return OUTSIDE;
+    }
+    for(i=0; i<3; i++ )
+    {
+        if( i!= whichPlane )
+        {
+            float f = origin[i] + maxT[whichPlane] * dir[i];
+            if ( f < (pCorners[0][i] - 0.00001f) ||
+                    f > (pCorners[4][i] +0.00001f ) )
+            {
+                return OUTSIDE;
+            }
+        }
+    }
+
+    return INTERSECT;
+
+}
+
+
+/** Checks how the second box intersects with the first.
+*/
+Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    // Get corners of the box
+    const Vector3* pCorners = two.getAllCorners();
+
+    // For each plane, see if all points are on the negative side
+    // If so, object is not visible.
+    // If one or more are, it's partial.
+    // If all aren't, full
+    int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
+    bool all_inside = true;
+    PlaneList::const_iterator i, iend;
+    iend = one.planes.end();
+    for (i = one.planes.begin(); i != iend; ++i)
+    {
+        const Plane& plane = *i;
+        bool all_outside = true;
+
+        float distance = 0;
+
+        for ( int corner = 0; corner < 8; ++corner )
+        {
+            distance = plane.getDistance( pCorners[ corners[ corner ] ] );
+            all_outside = all_outside && ( distance < 0 );
+            all_inside = all_inside && ( distance >= 0 );
+
+            if ( !all_outside && !all_inside )
+                break;
+        }
+
+        if ( all_outside )
+            return OUTSIDE;
+    }
+
+    if ( all_inside )
+        return INSIDE;
+    else
+        return INTERSECT;
+
+}
+
+
+/** Checks how the second box intersects with the first.
+*/
+Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (one.isNull() || two.isNull()) return OUTSIDE;
+
+    const Vector3 * outside = one.getAllCorners();
+    const Vector3 *inside = two.getAllCorners();
+
+    if ( inside[ 4 ].x < outside[ 0 ].x ||
+            inside[ 4 ].y < outside[ 0 ].y ||
+            inside[ 4 ].z < outside[ 0 ].z ||
+            inside[ 0 ].x > outside[ 4 ].x ||
+            inside[ 0 ].y > outside[ 4 ].y ||
+            inside[ 0 ].z > outside[ 4 ].z )
+    {
+        return OUTSIDE;
+    }
+
+    bool full = ( inside[ 0 ].x > outside[ 0 ].x &&
+                  inside[ 0 ].y > outside[ 0 ].y &&
+                  inside[ 0 ].z > outside[ 0 ].z &&
+                  inside[ 4 ].x < outside[ 4 ].x &&
+                  inside[ 4 ].y < outside[ 4 ].y &&
+                  inside[ 4 ].z < outside[ 4 ].z );
+
+    if ( full )
+        return INSIDE;
+    else
+        return INTERSECT;
+
+}
+
+/** Checks how the box intersects with the sphere.
+*/
+Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    float sradius = one.getRadius();
+
+    sradius *= sradius;
+
+    Vector3 scenter = one.getCenter();
+
+    const Vector3 *corners = two.getAllCorners();
+
+    float s, d = 0;
+
+    Vector3 mndistance = ( corners[ 0 ] - scenter );
+    Vector3 mxdistance = ( corners[ 4 ] - scenter );
+
+    if ( mndistance.squaredLength() < sradius &&
+            mxdistance.squaredLength() < sradius )
+    {
+        return INSIDE;
+    }
+
+    //find the square of the distance
+    //from the sphere to the box
+    for ( int i = 0 ; i < 3 ; i++ )
+    {
+        if ( scenter[ i ] < corners[ 0 ][ i ] )
+        {
+            s = scenter[ i ] - corners[ 0 ][ i ];
+            d += s * s;
+        }
+
+        else if ( scenter[ i ] > corners[ 4 ][ i ] )
+        {
+            s = scenter[ i ] - corners[ 4 ][ i ];
+            d += s * s;
+        }
+
+    }
+
+    bool partial = ( d <= sradius );
+
+    if ( !partial )
+    {
+        return OUTSIDE;
+    }
+
+    else
+    {
+        return INTERSECT;
+    }
+
+
+}
+
+unsigned long white = 0xFFFFFFFF;
+
+unsigned short OctreeSceneManager::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
+        0, 6, 6, 5, 5, 1,             //left
+        3, 7, 7, 4, 4, 2,             //right
+        6, 7, 5, 4 };          //front
+unsigned long OctreeSceneManager::mColors[ 8 ] = {white, white, white, white, white, white, white, white };
+
+
+OctreeSceneManager::OctreeSceneManager( ) : SceneManager()
+{
+    AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
+    int depth = 8; 
+    mOctree = 0;
+    init( b, depth );
+}
+
+OctreeSceneManager::OctreeSceneManager( AxisAlignedBox &box, int max_depth ) : SceneManager()
+{
+    mOctree = 0;
+    init( box, max_depth );
+}
+
+void OctreeSceneManager::init( AxisAlignedBox &box, int depth )
+{
+    delete mSceneRoot; //get rid of old root.
+
+    // -- Changes by Steve
+    // Don't do it this way, it will add it to the mSceneNodes which we don't want
+    //mSceneRoot = createSceneNode( "SceneRoot" );
+    mSceneRoot = new OctreeNode( this, "SceneRoot" );
+	mSceneRoot->_notifyRootNode();
+    // -- End changes by Steve
+
+    if ( mOctree != 0 )
+        delete mOctree;
+
+    mOctree = new Octree( 0 );
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+	mNumOctreeNodes = 1;
+#endif // OGRE_COHERENT_OCCLUSION_CULLING
+    mMaxDepth = depth;
+    mBox = box;
+
+    mOctree -> mBox = box;
+
+    Vector3 min = box.getMinimum();
+
+    Vector3 max = box.getMaximum();
+
+    mOctree -> mHalfSize = ( max - min ) / 2;
+
+
+    mShowBoxes = false;
+
+    mCullCamera = false;
+
+    mNumObjects = 0;
+
+    Vector3 v( 1.5, 1.5, 1.5 );
+
+    mScaleFactor.setScale( v );
+
+
+
+    // setDisplaySceneNodes( true );
+    // setShowBoxes( true );
+
+    //
+    //setUseCullCamera( true );
+    //mSceneRoot isn't put into the octree since it has no volume.
+
+}
+
+OctreeSceneManager::~OctreeSceneManager()
+{
+    // -- Changed by Steve
+    // Don't do this here, SceneManager will do it
+    /*
+    if( mSceneRoot )
+    delete mSceneRoot;
+    */ 
+    // --End Changes by Steve
+
+    if ( mOctree )
+        delete mOctree;
+}
+
+Camera * OctreeSceneManager::createCamera( const String &name )
+{
+    Camera * c = new OctreeCamera( name, this );
+    mCameras.insert( CameraList::value_type( name, c ) );
+    return c;
+}
+
+void OctreeSceneManager::destroySceneNode( const String &name )
+{
+    OctreeNode * on = static_cast < OctreeNode* > ( getSceneNode( name ) );
+
+    if ( on != 0 )
+        _removeOctreeNode( on );
+
+    SceneManager::destroySceneNode( name );
+}
+
+bool OctreeSceneManager::getOptionValues( const String & key, StringVector  &refValueList )
+{
+    return SceneManager::getOptionValues( key, refValueList );
+}
+
+bool OctreeSceneManager::getOptionKeys( StringVector & refKeys )
+{
+    SceneManager::getOptionKeys( refKeys );
+    refKeys.push_back( "CullCamera" );
+    refKeys.push_back( "Size" );
+    refKeys.push_back( "ShowOctree" );
+    refKeys.push_back( "Depth" );
+
+    return true;
+}
+
+
+void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
+{
+    AxisAlignedBox box = onode -> _getWorldAABB();
+
+    if ( box.isNull() )
+        return ;
+
+
+    if ( onode -> getOctant() == 0 )
+    {
+        //if outside the octree, force into the root node.
+        if ( ! onode -> _isIn( mOctree -> mBox ) )
+            mOctree->_addNode( onode );
+        else
+            _addOctreeNode( onode, mOctree );
+        return ;
+    }
+
+    if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
+    {
+        _removeOctreeNode( onode );
+
+        //if outside the octree, force into the root node.
+        if ( ! onode -> _isIn( mOctree -> mBox ) )
+            mOctree->_addNode( onode );
+        else
+            _addOctreeNode( onode, mOctree );
+    }
+}
+
+/** Only removes the node from the octree.  It leaves the octree, even if it's empty.
+*/
+void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
+{
+    Octree * oct = n -> getOctant();
+
+    if ( oct )
+    {
+        oct -> _removeNode( n );
+    }
+
+    n->setOctant(0);
+}
+
+
+void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
+{
+
+    AxisAlignedBox bx = n -> _getWorldAABB();
+
+
+    //if the octree is twice as big as the scene node,
+    //we will add it to a child.
+    if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
+    {
+        int x, y, z;
+        octant -> _getChildIndexes( bx, &x, &y, &z );
+
+        if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
+        {
+            octant -> mChildren[ x ][ y ][ z ] = new Octree( octant );
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+	mNumOctreeNodes ++;
+#endif // OGRE_COHERENT_OCCLUSION_CULLING
+
+            const Vector3 *corners = octant -> mBox.getAllCorners();
+            Vector3 min, max;
+
+            if ( x == 0 )
+            {
+                min.x = corners[ 0 ].x;
+                max.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
+            }
+
+            else
+            {
+                min.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
+                max.x = corners[ 4 ].x;
+            }
+
+            if ( y == 0 )
+            {
+                min.y = corners[ 0 ].y;
+                max.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
+            }
+
+            else
+            {
+                min.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
+                max.y = corners[ 4 ].y;
+            }
+
+            if ( z == 0 )
+            {
+                min.z = corners[ 0 ].z;
+                max.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
+            }
+
+            else
+            {
+                min.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
+                max.z = corners[ 4 ].z;
+            }
+
+            octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
+            octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
+        }
+
+		//matt: remove later
+		//OutputDebugString("adding octree node\n");
+		
+
+        _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
+
+    }
+
+    else
+    {
+        octant -> _addNode( n );
+    }
+}
+
+
+SceneNode * OctreeSceneManager::createSceneNode( void )
+{
+    OctreeNode * on = new OctreeNode( this );
+    mSceneNodes[ on->getName() ] = on;
+    return on;
+}
+
+SceneNode * OctreeSceneManager::createSceneNode( const String &name )
+{
+    OctreeNode * on = new OctreeNode( this, name );
+    mSceneNodes[ on->getName() ] = on;
+    return on;
+}
+
+void OctreeSceneManager::_updateSceneGraph( Camera * cam )
+{
+    SceneManager::_updateSceneGraph( cam );
+}
+
+void OctreeSceneManager::_alertVisibleObjects( void )
+{
+    NodeList::iterator it = mVisible.begin();
+
+    while ( it != mVisible.end() )
+    {
+        OctreeNode * node = *it;
+
+        ++it;
+    }
+}
+
+void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
+{
+
+    getRenderQueue()->clear();
+    mBoxes.clear();
+    mVisible.clear();
+
+    if ( mCullCamera )
+    {
+        Camera * c = getCamera( "CullCamera" );
+
+        if ( c != 0 )
+            cam = getCamera( "CullCamera" );
+    }
+
+    mNumObjects = 0;
+
+    //walk the octree, adding all visible Octreenodes nodes to the render queue.
+    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
+
+
+    // Show the octree boxes & cull camera if required
+    if ( mShowBoxes || mCullCamera )
+    {
+
+
+
+        if ( mShowBoxes )
+        {
+            for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
+            {
+                getRenderQueue()->addRenderable(*it);
+            }
+        }
+
+        if ( mCullCamera )
+        {
+            OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
+
+            if ( c != 0 )
+            {
+                getRenderQueue()->addRenderable(c);
+            }
+        }
+
+    }
+
+
+
+}
+
+void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
+                                     Octree *octant, bool foundvisible, bool onlyShadowCasters )
+{
+
+    //return immediately if nothing is in the node.
+    if ( octant -> numNodes() == 0 )
+        return ;
+
+    OctreeCamera::Visibility v = OctreeCamera::NONE;
+
+    if ( foundvisible )
+    {
+        v = OctreeCamera::FULL;
+    }
+
+    else if ( octant == mOctree )
+    {
+        v = OctreeCamera::PARTIAL;
+    }
+
+    else
+    {
+        AxisAlignedBox box;
+        octant -> _getCullBounds( &box );
+        v = camera -> getVisibility( box );
+    }
+
+
+    // if the octant is visible, or if it's the root node...
+    if ( v != OctreeCamera::NONE )
+    {
+
+        //Add stuff to be rendered;
+        NodeList::iterator it = octant -> mNodes.begin();
+
+        if ( mShowBoxes )
+        {
+            mBoxes.push_back( octant->getWireBoundingBox() );
+        }
+
+        bool vis = true;
+
+        while ( it != octant -> mNodes.end() )
+        {
+            OctreeNode * sn = *it;
+
+            // if this octree is partially visible, manually cull all
+            // scene nodes attached directly to this level.
+
+            if ( v == OctreeCamera::PARTIAL )
+                vis = camera -> isVisible( sn -> _getWorldAABB() );
+
+            if ( vis )
+            {
+
+                mNumObjects++;
+                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
+
+                mVisible.push_back( sn );
+
+                if ( mDisplayNodes )
+                    queue -> addRenderable( sn );
+
+                // check if the scene manager or this node wants the bounding box shown.
+                if (sn->getShowBoundingBox() || mShowBoundingBoxes)
+                    sn->_addBoundingBoxToQueue(queue);
+            }
+
+            ++it;
+        }
+
+        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+    }
+
+}
+
+// --- non template versions
+void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+
+void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( box, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( sphere, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( volume, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( r, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::resize( const AxisAlignedBox &box )
+{
+    std::list < SceneNode * > nodes;
+    std::list < SceneNode * > ::iterator it;
+
+    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
+
+    delete mOctree;
+
+    mOctree = new Octree( 0 );
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+	mNumOctreeNodes = 1;
+#endif // OGRE_COHERENT_OCCLUSION_CULLING
+    mOctree->mBox = box;
+
+    it = nodes.begin();
+
+    while ( it != nodes.end() )
+    {
+        OctreeNode * on = static_cast < OctreeNode * > ( *it );
+        on -> setOctant( 0 );
+        _updateOctreeNode( on );
+        ++it;
+    }
+
+}
+
+bool OctreeSceneManager::setOption( const String & key, const void * val )
+{
+    if ( key == "Size" )
+    {
+        resize( * static_cast < const AxisAlignedBox * > ( val ) );
+        return true;
+    }
+
+    else if ( key == "Depth" )
+    {
+        mMaxDepth = * static_cast < const int * > ( val );
+        resize( mOctree->mBox );
+        return true;
+    }
+
+    else if ( key == "ShowOctree" )
+    {
+        mShowBoxes = * static_cast < const bool * > ( val );
+        return true;
+    }
+
+    else if ( key == "CullCamera" )
+    {
+        mCullCamera = * static_cast < const bool * > ( val );
+        return true;
+    }
+
+    return SceneManager::setOption( key, val );
+
+
+}
+
+bool OctreeSceneManager::getOption( const String & key, void *val )
+{
+    if ( key == "Size" )
+    {
+        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
+        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
+        return true;
+    }
+
+    else if ( key == "Depth" )
+    {
+        * static_cast < int * > ( val ) = mMaxDepth;
+        return true;
+    }
+
+    else if ( key == "ShowOctree" )
+    {
+
+        * static_cast < bool * > ( val ) = mShowBoxes;
+        return true;
+    }
+
+    else if ( key == "CullCamera" )
+    {
+        * static_cast < bool * > ( val ) = mCullCamera;
+        return true;
+    }
+
+    return SceneManager::getOption( key, val );
+
+}
+
+void OctreeSceneManager::clearScene(void)
+{
+    SceneManager::clearScene();
+    init(mBox, mMaxDepth);
+
+}
+
+//---------------------------------------------------------------------
+AxisAlignedBoxSceneQuery*
+OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
+{
+    OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
+    q->setBox(box);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+SphereSceneQuery*
+OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
+{
+    OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
+    q->setSphere(sphere);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+PlaneBoundedVolumeListSceneQuery*
+OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
+        unsigned long mask)
+{
+    OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
+    q->setVolumes(volumes);
+    q->setQueryMask(mask);
+    return q;
+}
+
+//---------------------------------------------------------------------
+RaySceneQuery*
+OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
+{
+    OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
+    q->setRay(ray);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+IntersectionSceneQuery*
+OctreeSceneManager::createIntersectionQuery(unsigned long mask)
+{
+
+    // Octree implementation performs WORSE for < 500 objects
+    // TODO: optimise it so it's better in all cases
+    //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
+    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
+    q->setQueryMask(mask);
+    return q;
+}
+#ifdef OGRE_COHERENT_OCCLUSION_CULLING
+//-----------------------------------------------------------------------
+void OctreeSceneManager::_renderOctant(Camera *cam, Octree *octant)
+{
+	//Add stuff to be rendered;
+    NodeList::iterator it = octant->mNodes.begin();
+         
+    while(it != octant->mNodes.end())
+    {
+		OctreeNode *sn = *it;
+
+        mNumObjects++;
+
+		// check bounding box visibility of scene nodes
+		if (cam->isVisible(sn->_getWorldAABB()))
+		{
+			sn->_addToRenderQueue(cam, getRenderQueue(), false);
+			//node->_findVisibleObjects(cam, getRenderQueue(), false, mDisplayNodes, false);
+			mVisible.push_back(sn);
+
+			if (mDisplayNodes)
+				getRenderQueue()->addRenderable(sn);
+
+			// check if the scene manager or this node wants the bounding box shown.
+			if (sn->getShowBoundingBox() || mShowBoundingBoxes)
+				sn->_addBoundingBoxToQueue(getRenderQueue());
+
+			if (mShowBoxes)
+				getRenderQueue()->addRenderable(octant->getWireBoundingBox());
+		}
+        ++it;
+	}
+
+	SceneManager::_renderVisibleObjects();
+
+	// delete all rendered objects from renderqueue
+	_deleteRenderedQueueGroups();
+}
+#endif // OGRE_COHERENT_OCCLUSION_CULLING
+}
Index: trunk/VUT/work/ogre_changes/RenderSystem/GL/include/OgreGLHardwareOcclusionQuery.h
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystem/GL/include/OgreGLHardwareOcclusionQuery.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/RenderSystem/GL/include/OgreGLHardwareOcclusionQuery.h	(revision 61)
@@ -0,0 +1,133 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+/*
+The nVidia occlusion query extension is defined in glext.h so you don't 
+need anything else. You do need to look up the function, we provide a 
+GLSupport class to do this, which has platform implementations for 
+getProcAddress. Check the way that extensions like glActiveTextureARB are 
+initialised and used in glRenderSystem and copy what is done there.
+
+
+
+  To do: fix so dx7 and DX9 checks and flags if HW Occlusion is supported
+  See the openGl dito for ideas what to do.
+
+*/
+
+
+
+//GL_ActiveTextureARB_Func* glActiveTextureARB_ptr = (GL_ActiveTextureARB_Func)mGLSupport->getProcAddress("glActiveTextureARB");
+
+#ifndef __GLHARDWAREOCCLUSIONQUERY_H__
+#define __GLHARDWAREOCCLUSIONQUERY_H__
+
+#include "OgreGLPrerequisites.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+
+namespace Ogre { 
+
+
+// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
+// if the first pass resultet has too few pixels visable.
+
+// Be sure to render all occlluder first and whats out so the RenderQue don't switch places on 
+// the occluding objects and the tested objects because it thinks it's more effective..
+
+
+/**
+  * This is a class that is the base class of the query class for 
+  * hardware occlusion.
+  *
+  * @author Lee Sandberg email: lee@abcmedia.se
+  */
+
+class GLHardwareOcclusionQuery : public HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	GLHardwareOcclusionQuery();
+	/**
+	  * Object destructor
+	  */
+	~GLHardwareOcclusionQuery();
+
+	//------------------------------------------------------------------
+	// Occlusion query functions (see base class documentation for this)
+	//--
+
+	void beginOcclusionQuery();
+	void endOcclusionQuery();
+	bool pullOcclusionQuery( unsigned int* NumOfFragments);
+	bool pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ); 
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool resultAvailable();
+#endif
+	unsigned int getLastQuerysPixelcount() { return m_uintPixelCount; }
+
+	// This functions are optional, it's a simple filter that simply skipps some hardware occlusion tests on visable objects only
+	// It's easy to use if you don't have to keep track on which objects are visable (can be skipped) and what objects arn't visable..
+	// (None visable objects and object you introduce for the first time have allways to be tested allthough the cheepest possible 
+	// LOD (Level Of Detail) mesh and material wize). 
+
+	/**
+	  *   
+	  * Remarks This function allows you to set how often the hardware occlusion really sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 2 only 50% of your queries are sent. 
+	  * for all visable objects. 3 will result in 33% of all queries to acctualy be sent and so on. 
+	  * New and none visable objects will be tested all the time.
+	  * This functionality is here because this class can keep track on visable and none visable objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+	void setSkipRate( int skip ) { m_Skip = skip; }		// Using 2 only 50 % of the tests are actully made and 3 results in only 33% of the tests. So on.
+	int	 getSkipRate() { return m_Skip; } 
+
+
+//----------------------------------------------------------------------
+// Protected members
+//--
+protected:
+
+	unsigned int	m_uintPixelCount;
+	unsigned int	m_uintQuery[1];
+	bool			m_bOcclusionQuery;
+	int				m_SkipCounter;		// m_SkipConter =  m_SkipConter % m_Skip; if ( m_SkipConter == 0 && m_uintPixelCount !=0 ) TestHWOcclusion else just return 
+	static int		m_Skip;				// This is shared by all instancies
+	bool			m_bHWOcclusionSupport;
+};
+
+
+}
+
+#endif 
+
Index: trunk/VUT/work/ogre_changes/RenderSystem/GL/src/OgreGLHardwareOcclusionQuery.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystem/GL/src/OgreGLHardwareOcclusionQuery.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/RenderSystem/GL/src/OgreGLHardwareOcclusionQuery.cpp	(revision 61)
@@ -0,0 +1,169 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreGLHardwareOcclusionQuery.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+int GLHardwareOcclusionQuery::m_Skip = 0;
+
+/**
+  * This is a class that is the base class of the query class for 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg email: lee@abcmedia.se
+  */
+
+/* Functions used;
+
+glGenOcclusionQueriesNV_ptr( 1, m_uintQuery );
+glDeleteOcclusionQueriesNV_ptr( 1, &m_uintQuery[0] );
+glBeginOcclusionQueryNV_ptr( m_uintQuery[0] );
+glEndOcclusionQueryNV_ptr();
+glGetOcclusionQueryuivNV_ptr( m_uintQuery[0], GL_PIXEL_COUNT_NV, NumOfFragments );
+
+  TO DO: change this to the new ARB functions...
+
+*/
+
+
+/**
+  * Default object constructor
+  * 
+  */
+GLHardwareOcclusionQuery::GLHardwareOcclusionQuery() 
+{ 
+	m_uintPixelCount = 0; 
+	m_SkipCounter = 0;
+
+	// Check for hardware occlusion support
+    if( glDeleteOcclusionQueriesNV_ptr != 0 )	// This is a hack to see if hw occlusion is supported. pointer is 0 if it's not supported.
+    {
+		m_bHWOcclusionSupport = true;
+	}
+	else
+	{
+		m_bHWOcclusionSupport = false;
+	}
+
+	if( m_bHWOcclusionSupport )
+	{
+		glGenOcclusionQueriesNV_ptr( 1, m_uintQuery );	
+	}
+}
+
+
+/**
+  * Object destructor
+  */
+GLHardwareOcclusionQuery::~GLHardwareOcclusionQuery() 
+{ 
+	if( m_bHWOcclusionSupport )
+	{
+		glDeleteOcclusionQueriesNV_ptr( 1, &m_uintQuery[0] );  
+	}	
+}
+
+//------------------------------------------------------------------
+// Occlusion query functions (see base class documentation for this)
+//--
+void GLHardwareOcclusionQuery::beginOcclusionQuery() 
+{ 
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		//if  ( m_SkipCounter ==  m_Skip ) { m_SkipCounter = 0; };		// Counter starts at 0 again at m_Skip 
+		//if ( m_SkipCounter == 0 && m_uintPixelCount != 0 ) // New or none visable objects must allways be tested but visable objects can be skiped
+		//{
+			glBeginOcclusionQueryNV_ptr( m_uintQuery[0] );
+		//}
+	}
+}
+	
+void GLHardwareOcclusionQuery::endOcclusionQuery() 
+{ 
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		//if( m_SkipCounter == 0 && m_uintPixelCount != 0 ) // New or none visable objects must allways be tested but visable objects can be skiped
+		//{
+			glEndOcclusionQueryNV_ptr();
+		//}
+		//m_SkipCounter++;
+	}
+}
+
+bool GLHardwareOcclusionQuery::pullOcclusionQuery( unsigned int * NumOfFragments) 
+{
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		glGetOcclusionQueryuivNV_ptr( m_uintQuery[0], GL_PIXEL_COUNT_NV, NumOfFragments );
+	} 
+	else
+	{
+		*NumOfFragments = 100000;		// Fails quitlly -> every object tested is visable.
+	}
+
+	m_uintPixelCount = *NumOfFragments; 
+
+	return true;
+}
+
+//------------------------------------------------------------------
+// OpenGL dosn't use the flag, but to fulfil the abstract interface we need to include this function.
+// Using this function in OpenGL mode simple works the same way as calling the other function without the flag parameter,
+// but in DX9 it works differentlly, see notes in the DX9 implementation.
+//--
+bool GLHardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ) 
+{
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		glGetOcclusionQueryuivNV_ptr( m_uintQuery[0], GL_PIXEL_COUNT_NV, NumOfFragments );
+	}
+	else
+	{
+		*NumOfFragments = 100000;		// Fails quitlly -> every object tested is visable.
+	}
+
+	m_uintPixelCount = *NumOfFragments; 
+	
+	return true;
+}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+bool GLHardwareOcclusionQuery::resultAvailable()
+{
+	unsigned int result = GL_TRUE;
+
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		glGetOcclusionQueryuivNV_ptr( m_uintQuery[0], GL_PIXEL_COUNT_NV, &result );
+	}
+
+	return result == GL_TRUE;
+}
+#endif
+}
+
+
Index: trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h	(revision 61)
+++ trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h	(revision 61)
@@ -0,0 +1,116 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _D3D9HARWAREOCCLUSIONQUERY_H__
+#define _D3D9HARWAREOCCLUSIONQUERY_H__
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+
+namespace Ogre {
+
+
+
+// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
+// if the first pass resultet has too few pixels visable.
+
+// Be sure to render all occlluder first and whats out so the RenderQue don't switch places on 
+// the occluding objects and the tested objects because it thinks it's more effective..
+
+/**
+  * This is a class that is the DirectX9 implementation of 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg, email lee@abcmedia.se
+  */
+class D3D9HardwareOcclusionQuery : public HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	D3D9HardwareOcclusionQuery( IDirect3DDevice9* pD3DDevice );
+
+	/**
+	  * Object destructor
+	  */
+	~D3D9HardwareOcclusionQuery();
+
+	//------------------------------------------------------------------
+	// Occlusion query functions (see base class documentation for this)
+	//--
+
+	void beginOcclusionQuery();	
+	void endOcclusionQuery();
+	bool pullOcclusionQuery( unsigned int* NumOfFragments);
+	bool pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  );
+	unsigned int getLastQuerysPixelcount() { return m_uintPixelCount; }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool resultAvailable();
+#endif
+	// This functions are optional, it's a simple filter that simply skipps some hardware occlusion tests on visable objects only
+	// It's easy to use if you don't have to keep track on which objects are visable (can be skipped) and what objects arn't visable..
+	// (None visable objects and object you introduce for the first time have allways to be tested allthough the cheepest possible 
+	// LOD (Level Of Detail) mesh and material wize). 
+
+	/**
+	  *   
+	  * Remarks This function allows you to set how often the hardware occlusion really are sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 1 only the half of your queries are sent 
+	  * for all visable objects. 2 will result in 25% of all queries to acctualy be sent. 
+	  * New and none visable objects will be tested all the time.
+	  * This functionality is here because this class can keep track on visable and none visable objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+
+	void setSkipRate( int skip ) { m_Skip = skip; }			// Using 2 only 50 % of the tests are actully made and 3 results in only 33% of the tests. So on.
+	int	 getSkipRate() { return m_Skip; } 
+
+//----------------------------------------------------------------------
+// Protected members
+//--
+protected:
+
+	unsigned int		m_uintPixelCount;		
+	IDirect3DQuery9*	m_pD3DQuery;
+	IDirect3DDevice9*   m_pD3DDevice;       // d3d device
+	bool				m_bOcclusionQuery;
+	int					m_SkipCounter;		// m_SkipConter =  m_SkipConter % m_Skip; if ( m_SkipConter == 0 && m_uintPixelCount !=0 ) TestHWOcclusion else just return 
+	static int			m_Skip;				// This is shared by all instancies
+	bool				m_bHWOcclusionSupport;
+};
+
+
+}
+
+
+#endif
Index: trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp	(revision 61)
+++ trunk/VUT/work/ogre_changes/RenderSystem/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp	(revision 61)
@@ -0,0 +1,193 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreD3D9HardwareOcclusionQuery.h"
+#include "OgreRenderSystemCapabilities.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+int D3D9HardwareOcclusionQuery::m_Skip = 0;
+
+/**
+  * This is a class that is the DirectX9 implementation of 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg
+  */
+
+/**
+  * Default object constructor
+  * 
+  */
+D3D9HardwareOcclusionQuery::D3D9HardwareOcclusionQuery( IDirect3DDevice9* pD3DDevice ) 
+{ 
+	m_pD3DDevice = pD3DDevice;
+	m_uintPixelCount = 0; 
+	m_SkipCounter = 0;
+	m_bHWOcclusionSupport = false;
+
+	HRESULT hr = m_pD3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &m_pD3DQuery);
+	if ( hr != D3D_OK ) 
+	{
+		//OGRE_EXCEPT(hr, "D3D9HardwareOcclusionQuery couldn't create hardware occlusion query object.", 
+        //        "D3D9HardwareOcclusionQuery::D3D9HardwareOcclusionQuery");
+		m_bHWOcclusionSupport = false;
+	}
+	else 
+	{
+		m_bHWOcclusionSupport = true;
+	}
+}
+
+
+/**
+  * Object destructor
+  */
+D3D9HardwareOcclusionQuery::~D3D9HardwareOcclusionQuery() 
+{ 
+	SAFE_RELEASE( m_pD3DQuery ); 
+}
+
+//------------------------------------------------------------------
+// Occlusion query functions (see base class documentation for this)
+//--
+void D3D9HardwareOcclusionQuery::beginOcclusionQuery() 
+{ 
+	if( m_bHWOcclusionSupport )		// Make it fail silently if hardware occlusion isn't supported
+	{
+		if  ( m_SkipCounter ==  m_Skip ) { m_SkipCounter = 0; };		// Counter starts at 0 again at m_Skip 
+		
+		if ( m_SkipCounter == 0 && m_uintPixelCount != 0 )	// New or none visable objects must allways be tested but visable objects can be skiped
+		{
+			m_pD3DQuery->Issue(D3DISSUE_BEGIN); 
+		}
+	}
+}
+	
+void D3D9HardwareOcclusionQuery::endOcclusionQuery() 
+{ 
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		if (m_SkipCounter == 0 && m_uintPixelCount != 0 ) // New or none visable objects must allways be tested but visable objects can be skiped
+		{
+			m_pD3DQuery->Issue(D3DISSUE_END); 
+		}
+		m_SkipCounter++;								 // The skip counter is increased 
+	}
+}
+
+//------------------------------------------------------------------
+// This version of pullOcclusionQuery cases the DX9 API/Driver to flush all commands to the 3D card
+// to allow a fast result from the query, but at the cost of poorer batching of API calls to the card.
+// Note: OpenGL dosn't use this flag at all so the application running OpenGL won't display any different behaviour.
+//--
+bool D3D9HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments) 
+{
+	HRESULT hr;
+	
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+		hr = m_pD3DQuery->GetData( NumOfFragments, sizeof( NumOfFragments ), D3DGETDATA_FLUSH );
+
+		if ( hr != S_OK ) 
+			{
+				return false; 
+			}
+			else 
+			{ 
+				m_uintPixelCount = *NumOfFragments; 
+				return true; 
+			}
+	}
+	else
+	{
+		m_uintPixelCount = 100000; // Fails quitlly if hardware occlusion is not supported - every object is visable
+		return true;
+	}
+}
+
+//------------------------------------------------------------------
+// This version of pullOcclusionQuery cases the DX9 API/Driver to not flush all commands to the 3D card
+// to allow a fast result from the query, but the batching of API calls to the card will be normal. 
+// But the query wont be processed until the card recives the query in the nexr batch.
+// Note: OpenGL dosn't use this flag at all so the application running OpenGL won't display any different behaviour.
+//--
+bool D3D9HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ) 
+{
+	HRESULT hr;
+
+	// TO DO: USE lockOpts= D3D9Mappings::get(options); instead of RS_OCCLUSIONQUERY enum
+
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{
+	
+		switch( flag )
+		{
+			case HWOCCLUSIONQUERY_FLUSH : 	
+				hr = m_pD3DQuery->GetData( NumOfFragments, sizeof( NumOfFragments ), D3DGETDATA_FLUSH );
+			break;
+
+			case HWOCCLUSIONQUERY_NOFLUSH :	
+				hr = m_pD3DQuery->GetData( NumOfFragments, sizeof( NumOfFragments ), 0 );
+			break;
+		};
+
+
+
+		if ( hr != S_OK ) 
+			{
+				return false; 
+			}
+			else 
+			{ 
+				m_uintPixelCount = *NumOfFragments; 
+				return true; 
+			}
+	}
+	else 
+	{
+		m_uintPixelCount = 100000; // Fails quitlly if hardware occlusion is not supported - every object is visable
+		return true;
+	}
+}
+
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+
+bool D3D9HardwareOcclusionQuery::resultAvailable()
+{
+	bool result = true;
+
+	if( m_bHWOcclusionSupport )	// Make it fail silently if hardware occlusion isn't supported
+	{	//TODO: implement
+		//glGetOcclusionQueryuivNV_ptr( m_uintQuery[0], GL_PIXEL_COUNT_NV, &result );
+	}
+
+	return result;
+}
+
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+}
Index: trunk/VUT/work/tinyxml/tinyxmlerror.cpp
===================================================================
--- trunk/VUT/work/tinyxml/tinyxmlerror.cpp	(revision 61)
+++ trunk/VUT/work/tinyxml/tinyxmlerror.cpp	(revision 61)
@@ -0,0 +1,50 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// latin-1, but at least the error messages could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
+{
+	"No error",
+	"Error",
+	"Failed to open file",
+	"Memory allocation failed.",
+	"Error parsing Element.",
+	"Failed to read Element name",
+	"Error reading Element value.",
+	"Error reading Attributes.",
+	"Error: empty tag.",
+	"Error reading end tag.",
+	"Error parsing Unknown.",
+	"Error parsing Comment.",
+	"Error parsing Declaration.",
+	"Error document empty."
+};
Index: trunk/VUT/work/tinyxml/tinystr.h
===================================================================
--- trunk/VUT/work/tinyxml/tinystr.h	(revision 61)
+++ trunk/VUT/work/tinyxml/tinystr.h	(revision 61)
@@ -0,0 +1,228 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this 
+software in a product, an acknowledgment in the product documentation 
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+distribution.
+*/
+
+#include "tinyxml.h"
+
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#pragma warning( disable : 4514 )
+
+#include <assert.h>
+
+/**
+   TiXmlString is an emulation of the std::string template.
+   Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+   Only the member functions relevant to the TinyXML project have been implemented.
+   The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+   a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+  public :
+    // TiXmlString constructor, based on a string
+    TiXmlString (const char * instring);
+
+    // TiXmlString empty constructor
+    TiXmlString ()
+    {
+        allocated = 0;
+        cstring = NULL;
+    }
+
+    // TiXmlString copy constructor
+    TiXmlString (const TiXmlString& copy);
+
+    // TiXmlString destructor
+    ~ TiXmlString ()
+    {
+        empty_it ();
+    }
+
+    // Convert a TiXmlString into a classical char *
+    const char * c_str () const
+    {
+        if (allocated)
+            return cstring;
+        return "";
+    }
+
+    // Return the length of a TiXmlString
+    unsigned length () const;
+
+    // TiXmlString = operator
+    void operator = (const char * content);
+
+    // = operator
+    void operator = (const TiXmlString & copy);
+
+    // += operator. Maps to append
+    TiXmlString& operator += (const char * suffix)
+    {
+        append (suffix);
+		return *this;
+    }
+
+    // += operator. Maps to append
+    TiXmlString& operator += (char single)
+    {
+        append (single);
+		return *this;
+    }
+
+    // += operator. Maps to append
+    TiXmlString& operator += (TiXmlString & suffix)
+    {
+        append (suffix);
+		return *this;
+    }
+    bool operator == (const TiXmlString & compare) const;
+    bool operator < (const TiXmlString & compare) const;
+    bool operator > (const TiXmlString & compare) const;
+
+    // Checks if a TiXmlString is empty
+    bool empty () const
+    {
+        return length () ? false : true;
+    }
+
+    // Checks if a TiXmlString contains only whitespace (same rules as isspace)
+	// Not actually used in tinyxml. Conflicts with a C macro, "isblank",
+	// which is a problem. Commenting out. -lee
+//    bool isblank () const;
+
+    // single char extraction
+    const char& at (unsigned index) const
+    {
+        assert( index < length ());
+        return cstring [index];
+    }
+
+    // find a char in a string. Return TiXmlString::notfound if not found
+    unsigned find (char lookup) const
+    {
+        return find (lookup, 0);
+    }
+
+    // find a char in a string from an offset. Return TiXmlString::notfound if not found
+    unsigned find (char tofind, unsigned offset) const;
+
+    /*	Function to reserve a big amount of data when we know we'll need it. Be aware that this
+		function clears the content of the TiXmlString if any exists.
+    */
+    void reserve (unsigned size)
+    {
+        empty_it ();
+        if (size)
+        {
+            allocated = size;
+            cstring = new char [size];
+            cstring [0] = 0;
+        }
+    }
+
+    // [] operator 
+    char& operator [] (unsigned index) const
+    {
+        assert( index < length ());
+        return cstring [index];
+    }
+
+    // Error value for find primitive 
+    enum {	notfound = 0xffffffff,
+            npos = notfound };
+
+    void append (const char *str, int len );
+
+  protected :
+
+    // The base string
+    char * cstring;
+    // Number of chars allocated
+    unsigned allocated;
+
+    // New size computation. It is simplistic right now : it returns twice the amount
+    // we need
+    unsigned assign_new_size (unsigned minimum_to_allocate)
+    {
+        return minimum_to_allocate * 2;
+    }
+
+    // Internal function that clears the content of a TiXmlString
+    void empty_it ()
+    {
+        if (cstring)
+            delete [] cstring;
+        cstring = NULL;
+        allocated = 0;
+    }
+
+    void append (const char *suffix );
+
+    // append function for another TiXmlString
+    void append (const TiXmlString & suffix)
+    {
+        append (suffix . c_str ());
+    }
+
+    // append for a single char. This could be improved a lot if needed
+    void append (char single)
+    {
+        char smallstr [2];
+        smallstr [0] = single;
+        smallstr [1] = 0;
+        append (smallstr);
+    }
+
+} ;
+
+/** 
+   TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+   Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+    TiXmlOutStream () : TiXmlString () {}
+
+    // TiXmlOutStream << operator. Maps to TiXmlString::append
+    TiXmlOutStream & operator << (const char * in)
+    {
+        append (in);
+        return (* this);
+    }
+
+    // TiXmlOutStream << operator. Maps to TiXmlString::append
+    TiXmlOutStream & operator << (const TiXmlString & in)
+    {
+        append (in . c_str ());
+        return (* this);
+    }
+} ;
+
+#endif	// TIXML_STRING_INCLUDED
+#endif	// TIXML_USE_STL
Index: trunk/VUT/work/tinyxml/tinyxmlparser.cpp
===================================================================
--- trunk/VUT/work/tinyxml/tinyxmlparser.cpp	(revision 61)
+++ trunk/VUT/work/tinyxml/tinyxmlparser.cpp	(revision 61)
@@ -0,0 +1,939 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and 
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+distribution.
+*/
+
+#include "tinyxml.h"
+#include <ctype.h>
+
+//#define DEBUG_PARSER
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.	
+TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = 
+{
+	{ "&amp;",  5, '&' },
+	{ "&lt;",   4, '<' },
+	{ "&gt;",   4, '>' },
+	{ "&quot;", 6, '\"' },
+	{ "&apos;", 6, '\'' }
+};
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p )
+{
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+	while ( p && *p )
+	{
+		if ( isspace( *p ) || *p == '\n' || *p =='\r' )		// Still using old rules for white space.
+			++p;
+		else
+			break;
+	}
+
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	for( ;; )
+	{
+		if ( !in->good() ) return false;
+
+		int c = in->peek();
+		if ( !IsWhiteSpace( c ) )
+			return true;
+		*tag += in->get();
+	}
+}
+
+/*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->peek();
+		if ( c == character )
+			return true;
+
+		in->get();
+		*tag += c;
+	}
+	return false;
+}
+#endif
+
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name )
+{
+	*name = "";
+	assert( p );
+
+	// Names start with letters or underscores.
+	// After that, they can be letters, underscores, numbers,
+	// hyphens, or colons. (Colons are valid ony for namespaces,
+	// but tinyxml can't tell namespaces from names.)
+	if (    p && *p 
+		 && ( isalpha( (unsigned char) *p ) || *p == '_' ) )
+	{
+		while(		p && *p
+				&&	(		isalnum( (unsigned char ) *p ) 
+						 || *p == '_'
+						 || *p == '-'
+						 || *p == ':' ) )
+		{
+			(*name) += *p;
+			++p;
+		}
+		return p;
+	}
+	return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value )
+{
+	// Presume an entity, and pull it out.
+    TIXML_STRING ent;
+	int i;
+
+	// Ignore the &#x entities.
+	if (    strncmp( "&#x", p, 3 ) == 0 
+	     && *(p+3) 
+		 && *(p+4) )
+	{
+		*value = 0;
+		
+		if ( isalpha( *(p+3) ) ) *value += ( tolower( *(p+3) ) - 'a' + 10 ) * 16;
+		else				     *value += ( *(p+3) - '0' ) * 16;
+
+		if ( isalpha( *(p+4) ) ) *value += ( tolower( *(p+4) ) - 'a' + 10 );
+		else				     *value += ( *(p+4) - '0' );
+
+		return p+6;
+	}
+
+	// Now try to match it.
+	for( i=0; i<NUM_ENTITY; ++i )
+	{
+		if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+		{
+			assert( strlen( entity[i].str ) == entity[i].strLength );
+			*value = entity[i].chr;
+			return ( p + entity[i].strLength );
+		}
+	}
+
+	// So it wasn't an entity, its unrecognized, or something like that.
+	*value = *p;	// Don't put back the last one, since we return it!
+	return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+							 const char* tag,
+							 bool ignoreCase )
+{
+	assert( p );
+	if ( !p || !*p )
+	{
+		assert( 0 );
+		return false;
+	}
+
+    if ( tolower( *p ) == tolower( *tag ) )
+	{
+		const char* q = p;
+
+		if (ignoreCase)
+		{
+			while ( *q && *tag && *q == *tag )
+			{
+				++q;
+				++tag;
+			}
+
+			if ( *tag == 0 )		// Have we found the end of the tag, and everything equal?
+			{
+				return true;
+			}
+		}
+		else
+		{
+			while ( *q && *tag && tolower( *q ) == tolower( *tag ) )
+			{
+				++q;
+				++tag;
+			}
+
+			if ( *tag == 0 )
+			{
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+const char* TiXmlBase::ReadText(	const char* p, 
+									TIXML_STRING * text, 
+									bool trimWhiteSpace, 
+									const char* endTag, 
+									bool caseInsensitive )
+{
+    *text = "";
+	if (    !trimWhiteSpace			// certain tags always keep whitespace
+		 || !condenseWhiteSpace )	// if true, whitespace is always kept
+	{
+		// Keep all the white space.
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive )
+			  )
+		{
+			char c;
+			p = GetChar( p, &c );
+            (* text) += c;
+		}
+	}
+	else
+	{
+		bool whitespace = false;
+
+		// Remove leading white space:
+		p = SkipWhiteSpace( p );
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive ) )
+		{
+			if ( *p == '\r' || *p == '\n' )
+			{
+				whitespace = true;
+				++p;
+			}
+			else if ( isspace( *p ) )
+			{
+				whitespace = true;
+				++p;
+			}
+			else
+			{
+				// If we've found whitespace, add it before the
+				// new character. Any whitespace just becomes a space.
+				if ( whitespace )
+				{
+               (* text) += ' ';
+					whitespace = false;
+				}
+				char c;
+				p = GetChar( p, &c );
+            (* text) += c;
+			}
+		}
+	}
+	return p + strlen( endTag );
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	// The basic issue with a document is that we don't know what we're
+	// streaming. Read something presumed to be a tag (and hope), then
+	// identify it, and call the appropriate stream method on the tag.
+	//
+	// This "pre-streaming" will never read the closing ">" so the
+	// sub-tag can orient itself.
+
+	if ( !StreamTo( in, '<', tag ) ) 
+	{
+		SetError( TIXML_ERROR_PARSING_EMPTY );
+		return;
+	}
+
+	while ( in->good() )
+	{
+		size_t tagIndex = tag->length();
+		while ( in->good() && in->peek() != '>' )
+		{
+			int c = in->get();
+			(*tag) += (char) c;
+		}
+
+		if ( in->good() )
+		{
+			// We now have something we presume to be a node of 
+			// some sort. Identify it, and call the node to
+			// continue streaming.
+			TiXmlNode* node = Identify( tag->c_str() + tagIndex );
+
+			if ( node )
+			{
+				node->StreamIn( in, tag );
+				bool isElement = node->ToElement() != 0;
+				delete node;
+				node = 0;
+
+				// If this is the root element, we're done. Parsing will be
+				// done by the >> operator.
+				if ( isElement )
+				{
+					return;
+				}
+			}
+			else
+			{
+				SetError( TIXML_ERROR );
+				return;
+			}
+		}
+	}
+	// We should have returned sooner.
+	SetError( TIXML_ERROR );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p )
+{
+	// Parse away, at the document level. Since a document
+	// contains nothing but other tags, most of what happens
+	// here is skipping white space.
+	//
+	// In this variant (as opposed to stream and Parse) we
+	// read everything we can.
+
+
+	if ( !p || !*p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY );
+		return false;
+	}
+
+    p = SkipWhiteSpace( p );
+	if ( !p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY );
+		return false;
+	}
+
+	while ( p && *p )
+	{
+		TiXmlNode* node = Identify( p );
+		if ( node )
+		{
+			p = node->Parse( p );
+			LinkEndChild( node );
+		}
+		else
+		{
+			break;
+		}
+		p = SkipWhiteSpace( p );
+	}
+	// All is well.
+	return p;
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p )
+{
+	TiXmlNode* returnNode = 0;
+
+	p = SkipWhiteSpace( p );
+	if( !p || !*p || *p != '<' )
+	{
+		return 0;
+	}
+
+	TiXmlDocument* doc = GetDocument();
+	p = SkipWhiteSpace( p );
+
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+
+	// What is this thing? 
+	// - Elements start with a letter or underscore, but xml is reserved.
+	// - Comments: <!--
+	// - Decleration: <?xml
+	// - Everthing else is unknown to tinyxml.
+	//
+
+	const char* xmlHeader = { "<?xml" };
+	const char* commentHeader = { "<!--" };
+
+	if ( StringEqual( p, xmlHeader, true ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Declaration\n" );
+		#endif
+		returnNode = new TiXmlDeclaration();
+	}
+	else if (    isalpha( *(p+1) )
+			  || *(p+1) == '_' )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Element\n" );
+		#endif
+		returnNode = new TiXmlElement( "" );
+	}
+	else if ( StringEqual( p, commentHeader, false ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Comment\n" );
+		#endif
+		returnNode = new TiXmlComment();
+	}
+	else
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Unknown\n" );
+		#endif
+		returnNode = new TiXmlUnknown();
+	}
+
+	if ( returnNode )
+	{
+		// Set the parent, so it can report errors
+		returnNode->parent = this;
+		//p = returnNode->Parse( p );
+	}
+	else
+	{
+		if ( doc )
+			doc->SetError( TIXML_ERROR_OUT_OF_MEMORY );
+	}
+	return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
+{
+	// We're called with some amount of pre-parsing. That is, some of "this"
+	// element is in "tag". Go ahead and stream to the closing ">"
+	while( in->good() )
+	{
+		int c = in->get();
+		(*tag) += (char) c ;
+		
+		if ( c == '>' )
+			break;
+	}
+
+	if ( tag->length() < 3 ) return;
+
+	// Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+	// If not, identify and stream.
+
+	if (    tag->at( tag->length() - 1 ) == '>' 
+		 && tag->at( tag->length() - 2 ) == '/' )
+	{
+		// All good!
+		return;
+	}
+	else if ( tag->at( tag->length() - 1 ) == '>' )
+	{
+		// There is more. Could be:
+		//		text
+		//		closing tag
+		//		another node.
+		for ( ;; )
+		{
+			StreamWhiteSpace( in, tag );
+
+			// Do we have text?
+			if ( in->peek() != '<' )
+			{
+				// Yep, text.
+				TiXmlText text( "" );
+				text.StreamIn( in, tag );
+
+				// What follows text is a closing tag or another node.
+				// Go around again and figure it out.
+				continue;
+			}
+
+			// We now have either a closing tag...or another node.
+			// We should be at a "<", regardless.
+			if ( !in->good() ) return;
+			assert( in->peek() == '<' );
+			size_t tagIndex = tag->length();
+
+			bool closingTag = false;
+			bool firstCharFound = false;
+
+			for( ;; )
+			{
+				if ( !in->good() )
+					return;
+
+				int c = in->peek();
+				
+				if ( c == '>' )
+					break;
+
+				*tag += c;
+				in->get();
+
+				if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+				{
+					firstCharFound = true;
+					if ( c == '/' )
+						closingTag = true;
+				}
+			}
+			// If it was a closing tag, then read in the closing '>' to clean up the input stream.
+			// If it was not, the streaming will be done by the tag.
+			if ( closingTag )
+			{
+				int c = in->get();
+				assert( c == '>' );
+				*tag += c;
+
+				// We are done, once we've found our closing tag.
+				return;
+			}
+			else
+			{
+				// If not a closing tag, id it, and stream.
+				const char* tagloc = tag->c_str() + tagIndex;
+				TiXmlNode* node = Identify( tagloc );
+				if ( !node )
+					return;
+				node->StreamIn( in, tag );
+				delete node;
+				node = 0;
+
+				// No return: go around from the beginning: text, closing tag, or node.
+			}
+		}
+	}
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p )
+{
+	p = SkipWhiteSpace( p );
+	TiXmlDocument* document = GetDocument();
+
+	if ( !p || !*p || *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT );
+		return false;
+	}
+
+	p = SkipWhiteSpace( p+1 );
+
+	// Read the name.
+    p = ReadName( p, &value );
+	if ( !p || !*p )
+	{
+		if ( document )	document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME );
+		return false;
+	}
+
+    TIXML_STRING endTag ("</");
+	endTag += value;
+	endTag += ">";
+
+	// Check for and read attributes. Also look for an empty
+	// tag or an end tag.
+	while ( p && *p )
+	{
+		p = SkipWhiteSpace( p );
+		if ( !p || !*p )
+		{
+			if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
+			return 0;
+		}
+		if ( *p == '/' )
+		{
+			++p;
+			// Empty tag.
+			if ( *p  != '>' )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY );		
+				return 0;
+			}
+			return (p+1);
+		}
+		else if ( *p == '>' )
+		{
+			// Done with attributes (if there were any.)
+			// Read the value -- which can include other
+			// elements -- read the end tag, and return.
+			++p;
+			p = ReadValue( p );		// Note this is an Element method, and will set the error if one happens.
+			if ( !p || !*p )
+				return 0;
+
+			// We should find the end tag now
+			if ( StringEqual( p, endTag.c_str(), false ) )
+			{
+				p += endTag.length();
+				return p;
+			}
+			else
+			{
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG );
+				return 0;
+			}
+		}
+		else
+		{
+			// Try to read an element:
+			TiXmlAttribute attrib;
+			attrib.SetDocument( document );
+			p = attrib.Parse( p );
+
+			if ( !p || !*p )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT );
+				return 0;
+			}
+			SetAttribute( attrib.Name(), attrib.Value() );
+		}
+	}
+	return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p )
+{
+	TiXmlDocument* document = GetDocument();
+
+	// Read in text and elements in any order.
+	p = SkipWhiteSpace( p );
+	while ( p && *p )
+	{
+		if ( *p != '<' )
+		{
+			// Take what we have, make a text element.
+			TiXmlText* textNode = new TiXmlText( "" );
+
+			if ( !textNode )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
+				    return 0;
+			}
+
+			p = textNode->Parse( p );
+
+			if ( !textNode->Blank() )
+				LinkEndChild( textNode );
+			else
+				delete textNode;
+		} 
+		else 
+		{
+			// We hit a '<'
+			// Have we hit a new element or an end tag?
+			if ( StringEqual( p, "</", false ) )
+			{
+				return p;
+			}
+			else
+			{
+				TiXmlNode* node = Identify( p );
+				if ( node )
+				{
+					p = node->Parse( p );
+					LinkEndChild( node );
+				}				
+				else
+				{
+					return 0;
+				}
+			}
+		}
+		p = SkipWhiteSpace( p );
+	}
+
+	if ( !p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE );
+	}	
+	return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();	
+		(*tag) += c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;		
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p )
+{
+	TiXmlDocument* document = GetDocument();
+	p = SkipWhiteSpace( p );
+	if ( !p || !*p || *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN );
+		return 0;
+	}
+	++p;
+    value = "";
+
+	while ( p && *p && *p != '>' )
+	{
+		value += *p;
+		++p;
+	}
+
+	if ( !p )
+	{
+		if ( document )	document->SetError( TIXML_ERROR_PARSING_UNKNOWN );
+	}
+	if ( *p == '>' )
+		return p+1;
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();	
+		(*tag) += c;
+
+		if ( c == '>' 
+			 && tag->at( tag->length() - 2 ) == '-'
+			 && tag->at( tag->length() - 3 ) == '-' )
+		{
+			// All is well.
+			return;		
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p )
+{
+	TiXmlDocument* document = GetDocument();
+	value = "";
+
+	p = SkipWhiteSpace( p );
+	const char* startTag = "<!--";
+	const char* endTag   = "-->";
+
+	if ( !StringEqual( p, startTag, false ) )
+	{
+		document->SetError( TIXML_ERROR_PARSING_COMMENT );
+		return 0;
+	}
+	p += strlen( startTag );
+	p = ReadText( p, &value, false, endTag, false );
+	return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p )
+{
+	p = SkipWhiteSpace( p );
+	if ( !p || !*p ) return 0;
+
+	// Read the name, the '=' and the value.
+	p = ReadName( p, &name );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
+		return 0;
+	}
+	p = SkipWhiteSpace( p );
+	if ( !p || !*p || *p != '=' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
+		return 0;
+	}
+
+	++p;	// skip '='
+	p = SkipWhiteSpace( p );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
+		return 0;
+	}
+	
+	const char* end;
+
+	if ( *p == '\'' )
+	{
+		++p;
+		end = "\'";
+		p = ReadText( p, &value, false, end, false );
+	}
+	else if ( *p == '"' )
+	{
+		++p;
+		end = "\"";
+		p = ReadText( p, &value, false, end, false );
+	}
+	else
+	{
+		// All attribute values should be in single or double quotes.
+		// But this is such a common error that the parser will try
+		// its best, even without them.
+		value = "";
+		while (    p && *p										// existence
+				&& !isspace( *p ) && *p != '\n' && *p != '\r'	// whitespace
+				&& *p != '/' && *p != '>' )						// tag end
+		{
+			value += *p;
+			++p;
+		}
+	}
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->peek();	
+		if ( c == '<' )
+			return;
+
+		(*tag) += c;
+		in->get();
+	}
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p )
+{
+	value = "";
+
+	//TiXmlDocument* doc = GetDocument();
+	bool ignoreWhite = true;
+//	if ( doc && !doc->IgnoreWhiteSpace() ) ignoreWhite = false;
+
+	const char* end = "<";
+	p = ReadText( p, &value, ignoreWhite, end, false );
+	if ( p )
+		return p-1;	// don't truncate the '<'
+	return 0;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		(*tag) += c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p )
+{
+	p = SkipWhiteSpace( p );
+	// Find the beginning, find the end, and look for
+	// the stuff in-between.
+	TiXmlDocument* document = GetDocument();
+	if ( !p || !*p || !StringEqual( p, "<?xml", true ) )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION );
+		return 0;
+	}
+
+	p += 5;
+//	const char* start = p+5;
+//	const char* end  = strstr( start, "?>" );
+
+	version = "";
+	encoding = "";
+	standalone = "";
+
+	while ( p && *p )
+	{
+		if ( *p == '>' )
+		{
+			++p;
+			return p;
+		}
+
+		p = SkipWhiteSpace( p );
+		if ( StringEqual( p, "version", true ) )
+		{
+//			p += 7;
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p );		
+			version = attrib.Value();
+		}
+		else if ( StringEqual( p, "encoding", true ) )
+		{
+//			p += 8;
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p );		
+			encoding = attrib.Value();
+		}
+		else if ( StringEqual( p, "standalone", true ) )
+		{
+//			p += 10;
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p );		
+			standalone = attrib.Value();
+		}
+		else
+		{
+			// Read over whatever it is.
+			while( p && *p && *p != '>' && !isspace( *p ) )
+				++p;
+		}
+	}
+	return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+	for ( unsigned i=0; i<value.length(); i++ )
+		if ( !isspace( value[i] ) )
+			return false;
+	return true;
+}
+
Index: trunk/VUT/work/tinyxml/tinyxml.cpp
===================================================================
--- trunk/VUT/work/tinyxml/tinyxml.cpp	(revision 61)
+++ trunk/VUT/work/tinyxml/tinyxml.cpp	(revision 61)
@@ -0,0 +1,1108 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+#include "tinyxml.h"
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
+{
+	TIXML_STRING buffer;
+	PutString( str, &buffer );
+	(*stream) << buffer;
+}
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+	int i=0;
+
+	while( i<(int)str.length() )
+	{
+		int c = str[i];
+
+		if (    c == '&' 
+		     && i < ( (int)str.length() - 2 )
+			 && str[i+1] == '#'
+			 && str[i+2] == 'x' )
+		{
+			// Hexadecimal character reference.
+			// Pass through unchanged.
+			// &#xA9;	-- copyright symbol, for example.
+			while ( i<(int)str.length() )
+			{
+				outString->append( str.c_str() + i, 1 );
+				++i;
+				if ( str[i] == ';' )
+					break;
+			}
+		}
+		else if ( c == '&' )
+		{
+			outString->append( entity[0].str, entity[0].strLength );
+			++i;
+		}
+		else if ( c == '<' )
+		{
+			outString->append( entity[1].str, entity[1].strLength );
+			++i;
+		}
+		else if ( c == '>' )
+		{
+			outString->append( entity[2].str, entity[2].strLength );
+			++i;
+		}
+		else if ( c == '\"' )
+		{
+			outString->append( entity[3].str, entity[3].strLength );
+			++i;
+		}
+		else if ( c == '\'' )
+		{
+			outString->append( entity[4].str, entity[4].strLength );
+			++i;
+		}
+		else if ( c < 32 || c > 126 )
+		{
+			// Easy pass at non-alpha/numeric/symbol
+			// 127 is the delete key. Below 32 is symbolic.
+			char buf[ 32 ];
+			sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+			outString->append( buf, strlen( buf ) );
+			++i;
+		}
+		else
+		{
+			char realc = (char) c;
+			outString->append( &realc, 1 );
+			++i;
+		}
+	}
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type )
+{
+	parent = 0;
+	type = _type;
+	firstChild = 0;
+	lastChild = 0;
+	prev = 0;
+	next = 0;
+	userData = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+}
+
+
+void TiXmlNode::Clear()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+
+	firstChild = 0;
+	lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+	node->parent = this;
+
+	node->prev = lastChild;
+	node->next = 0;
+
+	if ( lastChild )
+		lastChild->next = node;
+	else
+		firstChild = node;			// it was an empty list.
+
+	lastChild = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+
+	return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{	
+	if ( !beforeThis || beforeThis->parent != this )
+		return 0;
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->next = beforeThis;
+	node->prev = beforeThis->prev;
+	if ( beforeThis->prev )
+	{
+		beforeThis->prev->next = node;
+	}
+	else
+	{
+		assert( firstChild == beforeThis );
+		firstChild = node;
+	}
+	beforeThis->prev = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+	if ( !afterThis || afterThis->parent != this )
+		return 0;
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->prev = afterThis;
+	node->next = afterThis->next;
+	if ( afterThis->next )
+	{
+		afterThis->next->prev = node;
+	}
+	else
+	{
+		assert( lastChild == afterThis );
+		lastChild = node;
+	}
+	afterThis->next = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+	if ( replaceThis->parent != this )
+		return 0;
+
+	TiXmlNode* node = withThis.Clone();
+	if ( !node )
+		return 0;
+
+	node->next = replaceThis->next;
+	node->prev = replaceThis->prev;
+
+	if ( replaceThis->next )
+		replaceThis->next->prev = node;
+	else
+		lastChild = node;
+
+	if ( replaceThis->prev )
+		replaceThis->prev->next = node;
+	else
+		firstChild = node;
+
+	delete replaceThis;
+	node->parent = this;
+	return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+	if ( removeThis->parent != this )
+	{	
+		assert( 0 );
+		return false;
+	}
+
+	if ( removeThis->next )
+		removeThis->next->prev = removeThis->prev;
+	else
+		lastChild = removeThis->prev;
+
+	if ( removeThis->prev )
+		removeThis->prev->next = removeThis->next;
+	else
+		firstChild = removeThis->next;
+
+	delete removeThis;
+	return true;
+}
+
+TiXmlNode* TiXmlNode::FirstChild( const char * value ) const
+{
+	TiXmlNode* node;
+	for ( node = firstChild; node; node = node->next )
+	{
+		if ( node->SValue() == TIXML_STRING( value ))
+			return node;
+	}
+	return 0;
+}
+
+TiXmlNode* TiXmlNode::LastChild( const char * value ) const
+{
+	TiXmlNode* node;
+	for ( node = lastChild; node; node = node->prev )
+	{
+		if ( node->SValue() == TIXML_STRING (value))
+			return node;
+	}
+	return 0;
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild();
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling();
+	}
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild( val );
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling( val );
+	}
+}
+
+TiXmlNode* TiXmlNode::NextSibling( const char * value ) const
+{
+	TiXmlNode* node;
+	for ( node = next; node; node = node->next )
+	{
+		if ( node->SValue() == TIXML_STRING (value))
+			return node;
+	}
+	return 0;
+}
+
+
+TiXmlNode* TiXmlNode::PreviousSibling( const char * value ) const
+{
+	TiXmlNode* node;
+	for ( node = prev; node; node = node->prev )
+	{
+		if ( node->SValue() == TIXML_STRING (value))
+			return node;
+	}
+	return 0;
+}
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+	TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+	{
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+	TiXmlNode* node;
+
+	for (	node = FirstChild();
+	node;
+	node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement( const char * value ) const
+{
+	TiXmlNode* node;
+
+	for (	node = FirstChild( value );
+	node;
+	node = node->NextSibling( value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+	TiXmlNode* node;
+
+	for (	node = NextSibling();
+	node;
+	node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+TiXmlElement* TiXmlNode::NextSiblingElement( const char * value ) const
+{
+	TiXmlNode* node;
+
+	for (	node = NextSibling( value );
+	node;
+	node = node->NextSibling( value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+
+TiXmlDocument* TiXmlNode::GetDocument() const
+{
+	const TiXmlNode* node;
+
+	for( node = this; node; node = node->parent )
+	{
+		if ( node->ToDocument() )
+			return node->ToDocument();
+	}
+	return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+
+TiXmlElement::~TiXmlElement()
+{
+	while( attributeSet.First() )
+	{
+		TiXmlAttribute* node = attributeSet.First();
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+// BEGIN OGRE CHANGES
+// USE STL ALONE
+#ifndef TIXML_USE_STL
+const char * TiXmlElement::Attribute( const char * name ) const
+{
+	TiXmlAttribute* node = attributeSet.Find( name );
+
+	if ( node )
+		return node->Value();
+
+	return 0;
+}
+
+
+const char * TiXmlElement::Attribute( const char * name, int* i ) const
+{
+	const char * s = Attribute( name );
+	if ( i )
+	{
+		if ( s )
+			*i = atoi( s );
+		else
+			*i = 0;
+	}
+	return s;
+}
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{	
+	char buf[64];
+	sprintf( buf, "%d", val );
+	SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * name, const char * value )
+{
+	TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+	{
+		node->SetValue( value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
+	}
+}
+
+#endif
+
+#ifdef TIXML_USE_STL
+
+const char * TiXmlElement::Attribute( const std::string& name ) const
+{
+	TiXmlAttribute* node = attributeSet.Find( name.c_str() );
+
+	if ( node )
+		return node->Value();
+
+	return 0;
+}
+
+
+const char * TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+	const char * s = Attribute( name );
+	if ( i )
+	{
+		if ( s )
+			*i = atoi( s );
+		else
+			*i = 0;
+	}
+	return s;
+}
+
+
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{	
+	char buf[64];
+	sprintf( buf, "%d", val );
+	SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const std::string& name, const std::string& value )
+{
+	TiXmlAttribute* node = attributeSet.Find( name.c_str() );
+	if ( node )
+	{
+		node->SetValue( value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
+	}
+}
+
+#endif
+// END OGRE CHANGES
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+	int i;
+	for ( i=0; i<depth; i++ )
+	{
+		fprintf( cfile, "    " );
+	}
+
+	fprintf( cfile, "<%s", value.c_str() );
+
+	TiXmlAttribute* attrib;
+	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+	{
+		fprintf( cfile, " " );
+		attrib->Print( cfile, depth );
+	}
+
+	// There are 3 different formatting approaches:
+	// 1) An element without children is printed as a <foo /> node
+	// 2) An element with only a text child is printed as <foo> text </foo>
+	// 3) An element with children is printed on multiple lines.
+	TiXmlNode* node;
+	if ( !firstChild )
+	{
+		fprintf( cfile, " />" );
+	}
+	else if ( firstChild == lastChild && firstChild->ToText() )
+	{
+		fprintf( cfile, ">" );
+		firstChild->Print( cfile, depth + 1 );
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+	else
+	{
+		fprintf( cfile, ">" );
+
+		for ( node = firstChild; node; node=node->NextSibling() )
+		{
+			if ( !node->ToText() )
+			{
+				fprintf( cfile, "\n" );
+			}
+			node->Print( cfile, depth+1 );
+		}
+		fprintf( cfile, "\n" );
+		for( i=0; i<depth; ++i )
+		fprintf( cfile, "    " );
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+}
+
+void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	(*stream) << "<" << value;
+
+	TiXmlAttribute* attrib;
+	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+	{	
+		(*stream) << " ";
+		attrib->StreamOut( stream );
+	}
+
+	// If this node has children, give it a closing tag. Else
+	// make it an empty tag.
+	TiXmlNode* node;
+	if ( firstChild )
+	{ 		
+		(*stream) << ">";
+
+		for ( node = firstChild; node; node=node->NextSibling() )
+		{
+			node->StreamOut( stream );
+		}
+		(*stream) << "</" << value << ">";
+	}
+	else
+	{
+		(*stream) << " />";
+	}
+}
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+	TiXmlElement* clone = new TiXmlElement( Value() );
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+
+	// Clone the attributes, then clone the children.
+	TiXmlAttribute* attribute = 0;
+	for(	attribute = attributeSet.First();
+	attribute;
+	attribute = attribute->Next() )
+	{
+		clone->SetAttribute( attribute->Name(), attribute->Value() );
+	}
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		clone->LinkEndChild( node->Clone() );
+	}
+	return clone;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	error = false;
+	//	ignoreWhiteSpace = true;
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	//	ignoreWhiteSpace = true;
+	value = documentName;
+	error = false;
+}
+
+bool TiXmlDocument::LoadFile()
+{
+	if ( LoadFile( value.c_str() ) )
+		return true;
+
+	return false;
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+	if ( SaveFile( value.c_str() ) )
+		return true;
+
+	return false;
+}
+
+bool TiXmlDocument::LoadFile( const char* filename )
+{
+	// Delete the existing data:
+	Clear();
+
+	// There was a really terrifying little bug here. The code:
+	//		value = filename
+	// in the STL case, cause the assignment method of the std::string to
+	// be called. What is strange, is that the std::string had the same
+	// address as it's c_str() method, and so bad things happen. Looks
+	// like a bug in the Microsoft STL implementation.
+	// See STL_STRING_BUG above.
+	// Fixed with the StringToBuffer class.
+	value = filename;
+
+	FILE* file = fopen( value.c_str (), "r" );
+
+	if ( file )
+	{
+		// Get the file size, so we can pre-allocate the string. HUGE speed impact.
+		long length = 0;
+		fseek( file, 0, SEEK_END );
+		length = ftell( file );
+		fseek( file, 0, SEEK_SET );
+
+		// Strange case, but good to handle up front.
+		if ( length == 0 )
+		{
+			fclose( file );
+			return false;
+		}
+
+		// If we have a file, assume it is all one big XML file, and read it in.
+		// The document parser may decide the document ends sooner than the entire file, however.
+		TIXML_STRING data;
+		data.reserve( length );
+
+		const int BUF_SIZE = 2048;
+		char buf[BUF_SIZE];
+
+		while( fgets( buf, BUF_SIZE, file ) )
+		{
+			data += buf;
+		}
+		fclose( file );
+
+		Parse( data.c_str() );
+		if (  !Error() )
+		{
+			return true;
+		}
+	}
+	SetError( TIXML_ERROR_OPENING_FILE );
+	return false;
+}
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+	// The old c stuff lives on...
+	FILE* fp = fopen( filename, "w" );
+	if ( fp )
+	{
+		Print( fp, 0 );
+		fclose( fp );
+		return true;
+	}
+	return false;
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+	TiXmlDocument* clone = new TiXmlDocument();
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+	clone->error = error;
+	clone->errorDesc = errorDesc.c_str ();
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		clone->LinkEndChild( node->Clone() );
+	}
+	return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+	TiXmlNode* node;
+	for ( node=FirstChild(); node; node=node->NextSibling() )
+	{
+		node->Print( cfile, depth );
+		fprintf( cfile, "\n" );
+	}
+}
+
+void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
+{
+	TiXmlNode* node;
+	for ( node=FirstChild(); node; node=node->NextSibling() )
+	{
+		node->StreamOut( out );
+
+		// Special rule for streams: stop after the root element.
+		// The stream in code will only read one element, so don't
+		// write more than one.
+		if ( node->ToElement() )
+			break;
+	}
+}
+
+TiXmlAttribute* TiXmlAttribute::Next() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( next->value.empty() && next->name.empty() )
+		return 0;
+	return next;
+}
+
+
+TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( prev->value.empty() && prev->name.empty() )
+		return 0;
+	return prev;
+}
+
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
+{
+	TIXML_STRING n, v;
+
+	PutString( Name(), &n );
+	PutString( Value(), &v );
+
+	if (value.find ('\"') == TIXML_STRING::npos)
+		fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+	else
+		fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+}
+
+
+void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	if (value.find( '\"' ) != TIXML_STRING::npos)
+	{
+		PutString( name, stream );
+		(*stream) << "=" << "'";
+		PutString( value, stream );
+		(*stream) << "'";
+	}
+	else
+	{
+		PutString( name, stream );
+		(*stream) << "=" << "\"";
+		PutString( value, stream );
+		(*stream) << "\"";
+	}
+}
+
+void TiXmlAttribute::SetIntValue( int value )
+{
+	char buf [64];
+	sprintf (buf, "%d", value);
+	SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double value )
+{
+	char buf [64];
+	sprintf (buf, "%lf", value);
+	SetValue (buf);
+}
+
+const int TiXmlAttribute::IntValue() const
+{
+	return atoi (value.c_str ());
+}
+
+const double  TiXmlAttribute::DoubleValue() const
+{
+	return atof (value.c_str ());
+}
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+	for ( int i=0; i<depth; i++ )
+	{
+		fputs( "    ", cfile );
+	}
+	fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	(*stream) << "<!--";
+	PutString( value, stream );
+	(*stream) << "-->";
+}
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+	TiXmlComment* clone = new TiXmlComment();
+
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+	return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
+{
+	TIXML_STRING buffer;
+	PutString( value, &buffer );
+	fprintf( cfile, "%s", buffer.c_str() );
+}
+
+
+void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	PutString( value, stream );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{	
+	TiXmlText* clone = 0;
+	clone = new TiXmlText( "" );
+
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+	return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+	const char * _encoding,
+	const char * _standalone )
+: TiXmlNode( TiXmlNode::DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
+{
+	fprintf (cfile, "<?xml ");
+
+	if ( !version.empty() )
+		fprintf (cfile, "version=\"%s\" ", version.c_str ());
+	if ( !encoding.empty() )
+		fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+	if ( !standalone.empty() )
+		fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+	fprintf (cfile, "?>");
+}
+
+void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	(*stream) << "<?xml ";
+
+	if ( !version.empty() )
+	{
+		(*stream) << "version=\"";
+		PutString( version, stream );
+		(*stream) << "\" ";
+	}
+	if ( !encoding.empty() )
+	{
+		(*stream) << "encoding=\"";
+		PutString( encoding, stream );
+		(*stream ) << "\" ";
+	}
+	if ( !standalone.empty() )
+	{
+		(*stream) << "standalone=\"";
+		PutString( standalone, stream );
+		(*stream) << "\" ";
+	}
+	(*stream) << "?>";
+}
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{	
+	TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+	clone->version = version;
+	clone->encoding = encoding;
+	clone->standalone = standalone;
+	return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+	for ( int i=0; i<depth; i++ )
+		fprintf( cfile, "    " );
+	fprintf( cfile, "%s", value.c_str() );
+}
+
+void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
+{
+	(*stream) << "<" << value << ">";		// Don't use entities hear! It is unknown.
+}
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+	TiXmlUnknown* clone = new TiXmlUnknown();
+
+	if ( !clone )
+		return 0;
+
+	CopyToClone( clone );
+	return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+	sentinel.next = &sentinel;
+	sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+	assert( sentinel.next == &sentinel );
+	assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
+
+	addMe->next = &sentinel;
+	addMe->prev = sentinel.prev;
+
+	sentinel.prev->next = addMe;
+	sentinel.prev      = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+	TiXmlAttribute* node;
+
+	for( node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node == removeMe )
+		{
+			node->prev->next = node->next;
+			node->next->prev = node->prev;
+			node->next = 0;
+			node->prev = 0;
+			return;
+		}
+	}
+	assert( 0 );		// we tried to remove a non-linked attribute.
+}
+
+TiXmlAttribute*	TiXmlAttributeSet::Find( const char * name ) const
+{
+	TiXmlAttribute* node;
+
+	for( node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+
+
+#ifdef TIXML_USE_STL	
+TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
+{
+	TIXML_STRING tag;
+	tag.reserve( 8 * 1000 );
+	base.StreamIn( &in, &tag );
+
+	base.Parse( tag.c_str() );
+	return in;
+}
+#endif
+
+
+TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
+{
+	base.StreamOut (& out);
+	return out;
+}
+
Index: trunk/VUT/work/tinyxml/tinyxml.h
===================================================================
--- trunk/VUT/work/tinyxml/tinyxml.h	(revision 61)
+++ trunk/VUT/work/tinyxml/tinyxml.h	(revision 61)
@@ -0,0 +1,956 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#if defined( DEBUG ) && defined( _MSC_VER )
+#define NOMINMAX
+#include <windows.h>
+#define TIXML_LOG OutputDebugString
+#else
+#define TIXML_LOG printf
+#endif
+
+
+#ifdef TIXML_USE_STL
+	#include <string>
+    #include <iostream>
+	#define TIXML_STRING	std::string
+	#define TIXML_ISTREAM	std::istream
+	#define TIXML_OSTREAM	std::ostream
+#else
+	#include "tinystr.h"
+	#define TIXML_STRING	TiXmlString
+	#define TIXML_OSTREAM	TiXmlOutStream
+#endif
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+
+
+/*  TiXmlBase is a base class for every class in TinyXml.
+	It does little except to establish that TinyXml classes
+	can be printed and provide some utility functions.
+
+	In XML, the document and elements can contain
+	other elements and other types of nodes.
+
+	@verbatim
+	A Document can contain:	Element	(container or leaf)
+							Comment (leaf)
+							Unknown (leaf)
+							Declaration( leaf )
+
+	An Element can contain:	Element (container or leaf)
+							Text	(leaf)
+							Attributes (not on tree)
+							Comment (leaf)
+							Unknown (leaf)
+
+	A Decleration contains: Attributes (not on tree)
+	@endverbatim
+*/
+class TiXmlBase
+{
+	friend class TiXmlNode;
+	friend class TiXmlElement;
+	friend class TiXmlDocument;
+
+public:
+	TiXmlBase()								{}
+	virtual ~TiXmlBase()					{}
+
+	/**	All TinyXml classes can print themselves to a filestream.
+		This is a formatted print, and will insert tabs and newlines.
+		
+		(For an unformatted stream, use the << operator.)
+	*/
+	virtual void Print( FILE* cfile, int depth ) const = 0;
+
+	/**	The world does not agree on whether white space should be kept or
+		not. In order to make everyone happy, these global, static functions
+		are provided to set whether or not TinyXml will condense all white space
+		into a single space or not. The default is to condense. Note changing these
+		values is not thread safe.
+	*/
+	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
+
+	/// Return the current white space setting.
+	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
+
+protected:
+
+	static const char*	SkipWhiteSpace( const char* );
+	inline static bool	IsWhiteSpace( int c )		{ return ( isspace( c ) || c == '\n' || c == '\r' ); }
+
+	virtual void StreamOut (TIXML_OSTREAM *) const = 0;
+
+	#ifdef TIXML_USE_STL
+	    static bool	StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	    static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
+	#endif
+
+	/*	Reads an XML name into the string provided. Returns
+		a pointer just past the last character of the name,
+		or 0 if the function has an error.
+	*/
+	static const char* ReadName( const char* p, TIXML_STRING* name );
+
+	/*	Reads text. Returns a pointer past the given end tag.
+		Wickedly complex options, but it keeps the (sensitive) code in one place.
+	*/
+	static const char* ReadText(	const char* in,				// where to start
+									TIXML_STRING* text,			// the string read
+									bool ignoreWhiteSpace,		// whether to keep the white space
+									const char* endTag,			// what ends this text
+									bool ignoreCase );			// whether to ignore case in the end tag
+	virtual const char* Parse( const char* p ) = 0;
+
+	// If an entity has been found, transform it into a character.
+	static const char* GetEntity( const char* in, char* value );
+
+	// Get a character, while interpreting entities.
+	inline static const char* GetChar( const char* p, char* value )
+	{
+		assert( p );
+		if ( *p == '&' )
+		{
+			return GetEntity( p, value );
+		}
+		else
+		{
+			*value = *p;
+			return p+1;
+		}
+	}
+
+	// Puts a string to a stream, expanding entities as it goes.
+	// Note this should not contian the '<', '>', etc, or they will be transformed into entities!
+	static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
+
+	static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
+
+	// Return true if the next characters in the stream are any of the endTag sequences.
+	bool static StringEqual(	const char* p,
+								const char* endTag,
+								bool ignoreCase );
+
+
+	enum
+	{
+		TIXML_NO_ERROR = 0,
+		TIXML_ERROR,
+		TIXML_ERROR_OPENING_FILE,
+		TIXML_ERROR_OUT_OF_MEMORY,
+		TIXML_ERROR_PARSING_ELEMENT,
+		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+		TIXML_ERROR_READING_ELEMENT_VALUE,
+		TIXML_ERROR_READING_ATTRIBUTES,
+		TIXML_ERROR_PARSING_EMPTY,
+		TIXML_ERROR_READING_END_TAG,
+		TIXML_ERROR_PARSING_UNKNOWN,
+		TIXML_ERROR_PARSING_COMMENT,
+		TIXML_ERROR_PARSING_DECLARATION,
+		TIXML_ERROR_DOCUMENT_EMPTY,
+
+		TIXML_ERROR_STRING_COUNT
+	};
+	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+private:
+	struct Entity
+	{
+		const char*     str;
+		unsigned int	strLength;
+		char		    chr;
+	};
+	enum
+	{
+		NUM_ENTITY = 5,
+		MAX_ENTITY_LENGTH = 6
+
+	};
+	static Entity entity[ NUM_ENTITY ];
+	static bool condenseWhiteSpace;
+};
+
+
+/*  The parent class for everything in the Document Object Model.
+	(Except for attributes, which are contained in elements.)
+	Nodes have siblings, a parent, and children. A node can be
+	in a document, or stand on its own. The type of a TiXmlNode
+	can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+	friend class TiXmlDocument;
+	friend class TiXmlElement;
+
+public:
+	#ifdef TIXML_USE_STL	
+
+	    /** An input stream operator, for every class. Tolerant of newlines and
+		    formatting, but doesn't expect them.
+	    */
+	    friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+	    /** An output stream operator, for every class. Note that this outputs
+		    without any newlines or formatting, as opposed to Print(), which
+		    includes tabs and new lines.
+
+		    The operator<< and operator>> are not completely symmetric. Writing
+		    a node to a stream is very well defined. You'll get a nice stream
+		    of output, without any extra whitespace or newlines.
+		    
+		    But reading is not as well defined. (As it always is.) If you create
+		    a TiXmlElement (for example) and read that from an input stream,
+		    the text needs to define an element or junk will result. This is
+		    true of all input streams, but it's worth keeping in mind.
+
+		    A TiXmlDocument will read nodes until it reads a root element.
+	    */	
+	    friend std::ostream & operator<< (std::ostream& out, const TiXmlNode& base);
+
+	#else
+	    // Used internally, not part of the public API.
+	    friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
+	#endif
+
+	/** The types of XML nodes supported by TinyXml. (All the
+			unsupported types are picked up by UNKNOWN.)
+	*/
+	enum NodeType
+	{
+		DOCUMENT,
+		ELEMENT,
+		COMMENT,
+		UNKNOWN,
+		TEXT,
+		DECLARATION,
+		TYPECOUNT
+	};
+
+	virtual ~TiXmlNode();
+
+	/** The meaning of 'value' changes for the specific type of
+		TiXmlNode.
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+
+		The subclasses will wrap this function.
+	*/
+	const char * Value () const { return value.c_str (); }
+
+	/** Changes the value of the node. Defined as:
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+	*/
+	void SetValue (const char * _value) { value = _value;}
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetValue( const std::string& value )    
+	{	  
+		SetValue( value.c_str() );    	
+	}	
+	#endif
+
+	/// Delete all the children of this node. Does not affect 'this'.
+	void Clear();
+
+	/// One step up the DOM.
+	TiXmlNode* Parent() const					{ return parent; }
+
+	TiXmlNode* FirstChild()	const	{ return firstChild; }		///< The first child of this node. Will be null if there are no children.
+	TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.
+
+	TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
+	TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.
+
+    #ifdef TIXML_USE_STL
+	TiXmlNode* FirstChild( const std::string& value ) const	{	return FirstChild (value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* LastChild( const std::string& value ) const	{	return LastChild (value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/** An alternate way to walk the children of a node.
+		One way to iterate over nodes is:
+		@verbatim
+			for( child = parent->FirstChild(); child; child = child->NextSibling() )
+		@endverbatim
+
+		IterateChildren does the same thing with the syntax:
+		@verbatim
+			child = 0;
+			while( child = parent->IterateChildren( child ) )
+		@endverbatim
+
+		IterateChildren takes the previous child as input and finds
+		the next one. If the previous child is null, it returns the
+		first. IterateChildren will return null when done.
+	*/
+	TiXmlNode* IterateChildren( TiXmlNode* previous ) const;
+
+	/// This flavor of IterateChildren searches for children with a particular 'value'
+	TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const;
+
+    #ifdef TIXML_USE_STL
+	TiXmlNode* IterateChildren( const std::string& value, TiXmlNode* previous ) const	{	return IterateChildren (value.c_str (), previous);	}	///< STL std::string form.
+	#endif
+
+	/** Add a new node related to this. Adds a child past the LastChild.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+	/** Add a new node related to this. Adds a child before the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+	/** Add a new node related to this. Adds a child after the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+	/** Replace a child of this node.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+	/// Delete a child of this node.
+	bool RemoveChild( TiXmlNode* removeThis );
+
+	/// Navigate to a sibling node.
+	TiXmlNode* PreviousSibling() const			{ return prev; }
+
+	/// Navigate to a sibling node.
+	TiXmlNode* PreviousSibling( const char * ) const;
+
+    #ifdef TIXML_USE_STL
+	TiXmlNode* PreviousSibling( const std::string& value ) const	{	return PreviousSibling (value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* NextSibling( const std::string& value) const	{	return NextSibling (value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Navigate to a sibling node.
+	TiXmlNode* NextSibling() const				{ return next; }
+
+	/// Navigate to a sibling node with the given 'value'.
+	TiXmlNode* NextSibling( const char * ) const;
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	TiXmlElement* NextSiblingElement() const;
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	TiXmlElement* NextSiblingElement( const char * ) const;
+
+    #ifdef TIXML_USE_STL
+	TiXmlElement* NextSiblingElement( const std::string& value) const	{	return NextSiblingElement (value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Convenience function to get through elements.
+	TiXmlElement* FirstChildElement()	const;
+
+	/// Convenience function to get through elements.
+	TiXmlElement* FirstChildElement( const char * value ) const;
+
+    #ifdef TIXML_USE_STL
+	TiXmlElement* FirstChildElement( const std::string& value ) const	{	return FirstChildElement (value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Query the type (as an enumerated value, above) of this node.
+	virtual int Type() const	{ return type; }
+
+	/** Return a pointer to the Document this node lives in.
+		Returns null if not in a document.
+	*/
+	TiXmlDocument* GetDocument() const;
+
+	/// Returns true if this node has no children.
+	bool NoChildren() const						{ return !firstChild; }
+
+	TiXmlDocument* ToDocument()	const		{ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+	TiXmlElement*  ToElement() const		{ return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+	TiXmlComment*  ToComment() const		{ return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+	TiXmlUnknown*  ToUnknown() const		{ return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+	TiXmlText*	   ToText()    const		{ return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+	TiXmlDeclaration* ToDeclaration() const	{ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	virtual TiXmlNode* Clone() const = 0;
+
+	void  SetUserData( void* user )			{ userData = user; }
+	void* GetUserData()						{ return userData; }
+
+protected:
+	TiXmlNode( NodeType type );
+
+	#ifdef TIXML_USE_STL
+	    // The real work of the input operator.
+	    virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
+	#endif
+
+	// The node is passed in by ownership. This object will delete it.
+	TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+	TiXmlNode* Identify( const char* start );
+	void CopyToClone( TiXmlNode* target ) const	{ target->SetValue (value.c_str() );
+												  target->userData = userData; }
+
+	// Internal Value function returning a TIXML_STRING
+	TIXML_STRING SValue() const	{ return value ; }
+
+	TiXmlNode*		parent;
+	NodeType		type;
+
+	TiXmlNode*		firstChild;
+	TiXmlNode*		lastChild;
+
+	TIXML_STRING	value;
+
+	TiXmlNode*		prev;
+	TiXmlNode*		next;
+	void*			userData;
+};
+
+
+/*  An attribute is a name-value pair. Elements have an arbitrary
+	number of attributes, each with a unique name.
+
+	@note The attributes are not TiXmlNodes, since they are not
+		  part of the tinyXML document object model. There are other
+		  suggested ways to look at this problem.
+
+	@note Attributes have a parent
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+	friend class TiXmlAttributeSet;
+
+public:
+	/// Construct an empty attribute.
+	TiXmlAttribute() : prev( 0 ), next( 0 )	{}
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlAttribute( const std::string& _name, const std::string& _value )
+	{
+		name = _name;
+		value = _value;
+	}
+	#endif
+
+	/// Construct an attribute with a name and value.
+	TiXmlAttribute( const char * _name, const char * _value ): name( _name ), value( _value ), prev( 0 ), next( 0 ) {}
+	const char*		Name()  const		{ return name.c_str (); }		///< Return the name of this attribute.
+	const char*		Value() const		{ return value.c_str (); }		///< Return the value of this attribute.
+	const int       IntValue() const;									///< Return the value of this attribute, converted to an integer.
+	const double	DoubleValue() const;								///< Return the value of this attribute, converted to a double.
+
+	void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
+	void SetValue( const char* _value )	{ value = _value; }				///< Set the value.
+
+	void SetIntValue( int value );										///< Set the value from an integer.
+	void SetDoubleValue( double value );								///< Set the value from a double.
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetName( const std::string& _name )	
+	{	
+		SetName(_name.c_str() );	
+	}
+	/// STL std::string form.	
+	void SetValue( const std::string& _value )	
+	{	
+		SetValue( value.c_str() );	
+	}
+	#endif
+
+	/// Get the next sibling attribute in the DOM. Returns null at end.
+	TiXmlAttribute* Next() const;
+	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
+	TiXmlAttribute* Previous() const;
+
+	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
+	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
+
+	/*	[internal use]
+		Attribtue parsing starts: first letter of the name
+						 returns: the next char after the value end quote
+	*/
+	virtual const char* Parse( const char* p );
+
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	virtual void StreamOut( TIXML_OSTREAM * out ) const;
+	// [internal use]
+	// Set the document pointer so the attribute can report errors.
+	void SetDocument( TiXmlDocument* doc )	{ document = doc; }
+
+private:
+	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
+	TIXML_STRING name;
+	TIXML_STRING value;
+	TiXmlAttribute*	prev;
+	TiXmlAttribute*	next;
+};
+
+
+/*	A class used to manage a group of attributes.
+	It is only used internally, both by the ELEMENT and the DECLARATION.
+	
+	The set can be changed transparent to the Element and Declaration
+	classes that use it, but NOT transparent to the Attribute
+	which has to implement a next() and previous() method. Which makes
+	it a bit problematic and prevents the use of STL.
+
+	This version is implemented with circular lists because:
+		- I like circular lists
+		- it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+	TiXmlAttributeSet();
+	~TiXmlAttributeSet();
+
+	void Add( TiXmlAttribute* attribute );
+	void Remove( TiXmlAttribute* attribute );
+
+	TiXmlAttribute* First() const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+	TiXmlAttribute* Last()  const	{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+	TiXmlAttribute*	Find( const char * name ) const;
+
+private:
+	TiXmlAttribute sentinel;
+};
+
+
+/*  The element is a container class. It has a value, the element name,
+	and can contain other elements, text, comments, and unknowns.
+	Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+	/// Construct an element.
+	TiXmlElement (const char * in_value);
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlElement( const std::string& _value ) : 	TiXmlNode( TiXmlNode::ELEMENT )
+	{
+		firstChild = lastChild = 0;
+		value = _value;
+	}
+	#endif
+
+	virtual ~TiXmlElement();
+
+// OGRE CHANGE 
+// Resolve ambiguity of std::string / const char* conversion of Ogre::String
+#ifndef TIXML_USE_STL
+// OGRE CHANGE
+	/** Given an attribute name, attribute returns the value
+		for the attribute of that name, or null if none exists.
+	*/
+	const char* Attribute( const char* name ) const;
+
+	/** Given an attribute name, attribute returns the value
+		for the attribute of that name, or null if none exists.
+		If the attribute exists and can be converted to an integer,
+		the integer value will be put in the return 'i', if 'i'
+		is non-null.
+	*/
+	const char* Attribute( const char* name, int* i ) const;
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char* name, const char * value );
+// OGRE CHANGE
+#endif
+// OGRE CHANGE
+    #ifdef TIXML_USE_STL
+	const char* Attribute( const std::string& name ) const;
+	const char* Attribute( const std::string& name, int* i ) const;
+
+	/// STL std::string form.
+	void SetAttribute( const std::string& name, const std::string& value );
+	///< STL std::string form.
+	void SetAttribute( const std::string& name, int value );
+	#endif
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char * name, int value );
+
+	/** Deletes an attribute with the given name.
+	*/
+	void RemoveAttribute( const char * name );
+    #ifdef TIXML_USE_STL
+	void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
+	#endif
+
+	TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
+	TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
+
+	// [internal use] Creates a new Element and returs it.
+	virtual TiXmlNode* Clone() const;
+	// [internal use]
+
+	virtual void Print( FILE* cfile, int depth ) const;
+
+protected:
+
+	// Used to be public [internal use]
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+	virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+	/*	[internal use]
+		Attribtue parsing starts: next char past '<'
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p );
+
+	/*	[internal use]
+		Reads the "value" of the element -- another element, or text.
+		This should terminate with the current end tag.
+	*/
+	const char* ReadValue( const char* in );
+
+private:
+	TiXmlAttributeSet attributeSet;
+};
+
+
+/* 	An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+	/// Constructs an empty comment.
+	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
+	virtual ~TiXmlComment()	{}
+
+	// [internal use] Creates a new Element and returs it.
+	virtual TiXmlNode* Clone() const;
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth ) const;
+protected:
+	// used to be public
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+	virtual void StreamOut( TIXML_OSTREAM * out ) const;
+	/*	[internal use]
+		Attribtue parsing starts: at the ! of the !--
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p );
+};
+
+
+/*  XML text. Contained in an element.
+*/
+class TiXmlText : public TiXmlNode
+{
+	friend class TiXmlElement;
+public:
+	/// Constructor.
+	TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+	}
+	virtual ~TiXmlText() {}
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+	}
+	#endif
+
+protected :
+	// [internal use] Creates a new Element and returns it.
+	virtual TiXmlNode* Clone() const;
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth ) const;
+	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+	// [internal use]
+	bool Blank() const;	// returns true if all white space and new lines
+	/*	[internal use]
+			Attribtue parsing starts: First char of the text
+							 returns: next char past '>'
+		*/
+	virtual const char* Parse( const char* p );
+	// [internal use]
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+};
+
+
+/*  In correct XML the declaration is the first entry in the file.
+	@verbatim
+		<?xml version="1.0" standalone="yes"?>
+	@endverbatim
+
+	TinyXml will happily read or write files without a declaration,
+	however. There are 3 possible attributes to the declaration:
+	version, encoding, and standalone.
+
+	Note: In this version of the code, the attributes are
+	handled as special cases, not generic attributes, simply
+	because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+	/// Construct an empty declaration.
+	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDeclaration(
+						const std::string& _version,
+						const std::string& _encoding,
+						const std::string& _standalone )
+					: TiXmlNode( TiXmlNode::DECLARATION )
+	{
+		version = _version;
+		encoding = _encoding;
+		standalone = _standalone;
+	}
+#endif
+
+	/// Construct.
+	TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+										const char * _encoding,
+										const char * _standalone );
+
+	virtual ~TiXmlDeclaration()	{}
+
+	/// Version. Will return empty if none was found.
+	const char * Version() const		{ return version.c_str (); }
+	/// Encoding. Will return empty if none was found.
+	const char * Encoding() const		{ return encoding.c_str (); }
+	/// Is this a standalone document?
+	const char * Standalone() const		{ return standalone.c_str (); }
+
+	// [internal use] Creates a new Element and returs it.
+	virtual TiXmlNode* Clone() const;
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth ) const;
+
+protected:
+	// used to be public
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+	virtual void StreamOut ( TIXML_OSTREAM * out) const;
+	//	[internal use]
+	//	Attribtue parsing starts: next char past '<'
+	//					 returns: next char past '>'
+
+	virtual const char* Parse( const char* p );
+
+private:
+	TIXML_STRING version;
+	TIXML_STRING encoding;
+	TIXML_STRING standalone;
+};
+
+
+/*  Any tag that tinyXml doesn't recognize is save as an
+	unknown. It is a tag of text, but should not be modified.
+	It will be written back to the XML, unchanged, when the file
+	is saved.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
+	virtual ~TiXmlUnknown() {}
+
+	// [internal use]
+	virtual TiXmlNode* Clone() const;
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth ) const;
+protected:
+	// used to be public
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+	virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+	/*	[internal use]
+		Attribute parsing starts: First char of the text
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p );
+};
+
+
+/*  Always the top level node. A document binds together all the
+	XML pieces. It can be saved, loaded, and printed to the screen.
+	The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+	/// Create an empty document, that has no name.
+	TiXmlDocument();
+	/// Create a document with a name. The name of the document is also the filename of the xml.
+	TiXmlDocument( const char * documentName );
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDocument( const std::string& documentName ) :
+	    TiXmlNode( TiXmlNode::DOCUMENT )
+	{
+        value = documentName;
+		error = false;
+	}
+	#endif
+
+	virtual ~TiXmlDocument() {}
+
+	/** Load a file using the current document value.
+		Returns true if successful. Will delete any existing
+		document data before loading.
+	*/
+	bool LoadFile();
+	/// Save a file using the current document value. Returns true if successful.
+	bool SaveFile() const;
+	/// Load a file using the given filename. Returns true if successful.
+	bool LoadFile( const char * filename );
+	/// Save a file using the given filename. Returns true if successful.
+	bool SaveFile( const char * filename ) const;
+
+	#ifdef TIXML_USE_STL
+	bool LoadFile( const std::string& filename )			///< STL std::string version.
+	{
+		return ( LoadFile( filename.c_str() ));
+	}
+	bool SaveFile( const std::string& filename ) const		///< STL std::string version.
+	{
+		//StringToBuffer f( filename );
+		return ( SaveFile( filename.c_str() ));
+	}
+	#endif
+
+	/// Parse the given null terminated block of xml data.
+	virtual const char* Parse( const char* p );
+
+	/** Get the root element -- the only top level element -- of the document.
+		In well formed XML, there should only be one. TinyXml is tolerant of
+		multiple elements at the document level.
+	*/
+	TiXmlElement* RootElement() const		{ return FirstChildElement(); }
+
+	/// If, during parsing, a error occurs, Error will be set to true.
+	bool Error() const						{ return error; }
+
+	/// Contains a textual (english) description of the error if one occurs.
+	const char * ErrorDesc() const	{ return errorDesc.c_str (); }
+
+	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
+			prefer the ErrorId, this function will fetch it.
+		*/
+	const int ErrorId()	const				{ return errorId; }
+
+	/// If you have handled the error, it can be reset with this call.
+	void ClearError()						{ error = false; errorId = 0; errorDesc = ""; }
+
+	/** Dump the document to standard out. */
+	void Print() const						{ Print( stdout, 0 ); }
+
+	// [internal use]
+	virtual void Print( FILE* cfile, int depth = 0 ) const;
+	// [internal use]
+	void SetError( int err ) {		assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+		error   = true;
+		errorId = err;
+	errorDesc = errorString[ errorId ]; }
+
+protected :
+	virtual void StreamOut ( TIXML_OSTREAM * out) const;
+	// [internal use]
+	virtual TiXmlNode* Clone() const;
+	#ifdef TIXML_USE_STL
+	    virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+	#endif
+
+private:
+	bool error;
+	int  errorId;
+	TIXML_STRING errorDesc;
+};
+
+#endif
+
Index: trunk/VUT/work/tinyxml/tinystr.cpp
===================================================================
--- trunk/VUT/work/tinyxml/tinystr.cpp	(revision 61)
+++ trunk/VUT/work/tinyxml/tinystr.cpp	(revision 61)
@@ -0,0 +1,265 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this 
+software in a product, an acknowledgment in the product documentation 
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+distribution.
+*/
+
+#include "tinyxml.h"
+
+#ifndef TIXML_USE_STL
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "tinystr.h"
+
+// TiXmlString constructor, based on a C string
+TiXmlString::TiXmlString (const char* instring)
+{
+    unsigned newlen;
+    char * newstring;
+
+    if (!instring)
+    {
+        allocated = 0;
+        cstring = NULL;
+        return;
+    }
+    newlen = strlen (instring) + 1;
+    newstring = new char [newlen];
+    strcpy (newstring, instring);
+    allocated = newlen;
+    cstring = newstring;
+}
+
+// TiXmlString copy constructor
+TiXmlString::TiXmlString (const TiXmlString& copy)
+{
+    unsigned newlen;
+    char * newstring;
+
+	// Prevent copy to self!
+	if ( &copy == this )
+		return;
+
+    if (! copy . allocated)
+    {
+        allocated = 0;
+        cstring = NULL;
+        return;
+    }
+    newlen = strlen (copy . cstring) + 1;
+    newstring = new char [newlen];
+    strcpy (newstring, copy . cstring);
+    allocated = newlen;
+    cstring = newstring;
+}
+
+// TiXmlString = operator. Safe when assign own content
+void TiXmlString ::operator = (const char * content)
+{
+    unsigned newlen;
+    char * newstring;
+
+    if (! content)
+    {
+        empty_it ();
+        return;
+    }
+    newlen = strlen (content) + 1;
+    newstring = new char [newlen];
+    strcpy (newstring, content);
+    empty_it ();
+    allocated = newlen;
+    cstring = newstring;
+}
+
+// = operator. Safe when assign own content
+void TiXmlString ::operator = (const TiXmlString & copy)
+{
+    unsigned newlen;
+    char * newstring;
+
+    if (! copy . length ())
+    {
+        empty_it ();
+        return;
+    }
+    newlen = copy . length () + 1;
+    newstring = new char [newlen];
+    strcpy (newstring, copy . c_str ());
+    empty_it ();
+    allocated = newlen;
+    cstring = newstring;
+}
+
+
+//// Checks if a TiXmlString contains only whitespace (same rules as isspace)
+//bool TiXmlString::isblank () const
+//{
+//    char * lookup;
+//    for (lookup = cstring; * lookup; lookup++)
+//        if (! isspace (* lookup))
+//            return false;
+//    return true;
+//}
+
+// append a const char * to an existing TiXmlString
+void TiXmlString::append( const char* str, int len )
+{
+    char * new_string;
+    unsigned new_alloc, new_size;
+
+    new_size = length () + len + 1;
+    // check if we need to expand
+    if (new_size > allocated)
+    {
+        // compute new size
+        new_alloc = assign_new_size (new_size);
+
+        // allocate new buffer
+        new_string = new char [new_alloc];        
+        new_string [0] = 0;
+
+        // copy the previous allocated buffer into this one
+        if (allocated && cstring)
+            strcpy (new_string, cstring);
+
+        // append the suffix. It does exist, otherwize we wouldn't be expanding 
+        strncat (new_string, str, len);
+
+        // return previsously allocated buffer if any
+        if (allocated && cstring)
+            delete [] cstring;
+
+        // update member variables
+        cstring = new_string;
+        allocated = new_alloc;
+    }
+    else
+        // we know we can safely append the new string
+        strncat (cstring, str, len);
+}
+
+
+// append a const char * to an existing TiXmlString
+void TiXmlString::append( const char * suffix )
+{
+    char * new_string;
+    unsigned new_alloc, new_size;
+
+    new_size = length () + strlen (suffix) + 1;
+    // check if we need to expand
+    if (new_size > allocated)
+    {
+        // compute new size
+        new_alloc = assign_new_size (new_size);
+
+        // allocate new buffer
+        new_string = new char [new_alloc];        
+        new_string [0] = 0;
+
+        // copy the previous allocated buffer into this one
+        if (allocated && cstring)
+            strcpy (new_string, cstring);
+
+        // append the suffix. It does exist, otherwize we wouldn't be expanding 
+        strcat (new_string, suffix);
+
+        // return previsously allocated buffer if any
+        if (allocated && cstring)
+            delete [] cstring;
+
+        // update member variables
+        cstring = new_string;
+        allocated = new_alloc;
+    }
+    else
+        // we know we can safely append the new string
+        strcat (cstring, suffix);
+}
+
+// Check for TiXmlString equuivalence
+//bool TiXmlString::operator == (const TiXmlString & compare) const
+//{
+//    return (! strcmp (c_str (), compare . c_str ()));
+//}
+
+unsigned TiXmlString::length () const
+{
+    if (allocated)
+        return strlen (cstring);
+    return 0;
+}
+
+
+unsigned TiXmlString::find (char tofind, unsigned offset) const
+{
+    char * lookup;
+
+    if (offset >= length ())
+        return (unsigned) notfound;
+    for (lookup = cstring + offset; * lookup; lookup++)
+        if (* lookup == tofind)
+            return lookup - cstring;
+    return (unsigned) notfound;
+}
+
+
+bool TiXmlString::operator == (const TiXmlString & compare) const
+{
+	if ( allocated && compare.allocated )
+	{
+		assert( cstring );
+		assert( compare.cstring );
+		return ( strcmp( cstring, compare.cstring ) == 0 );
+ 	}
+	return false;
+}
+
+
+bool TiXmlString::operator < (const TiXmlString & compare) const
+{
+	if ( allocated && compare.allocated )
+	{
+		assert( cstring );
+		assert( compare.cstring );
+		return ( strcmp( cstring, compare.cstring ) > 0 );
+ 	}
+	return false;
+}
+
+
+bool TiXmlString::operator > (const TiXmlString & compare) const
+{
+	if ( allocated && compare.allocated )
+	{
+		assert( cstring );
+		assert( compare.cstring );
+		return ( strcmp( cstring, compare.cstring ) < 0 );
+ 	}
+	return false;
+}
+
+
+#endif	// TIXML_USE_STL
Index: trunk/VUT/work/TestCulling/TestCulling.vcproj
===================================================================
--- trunk/VUT/work/TestCulling/TestCulling.vcproj	(revision 61)
+++ trunk/VUT/work/TestCulling/TestCulling.vcproj	(revision 61)
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="TestCulling"
+	ProjectGUID="{248F19A6-2FE0-4F5D-8928-E0EA10609887}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\bin\$(ConfigurationName)"
+			IntermediateDirectory="..\..\obj\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			ReferencesPath="">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\Dependencies\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;../include"
+				PreprocessorDefinitions="_WINDOWS;_STLP_USE_DYNAMIC_LIB;OGRE_LIBRARY_IMPORTS;_DEBUG;WIN32;_STLP_DEBUG;PLUGIN_TERRAIN_IMPORTS"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Plugin_OctreeSceneManager.lib OGREMain_d.LIB CEGUIBase_d.lib OgreGUIRenderer_d.lib Plugin_DotSceneManager.lib"
+				OutputFile="$(OGRE_PATH)/Samples/Common/bin/Debug/TestCulling.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\Dependencies\Lib\Debug&quot;;&quot;$(OGRE_ADDONS_PATH)\dotsceneoctree\PlugIns\DotSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\OgreMain\Lib\Debug&quot;;&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\debug&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/TestCulling.pdb"
+				SubSystem="2"
+				ImportLibrary=""
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\..\Samples\Common\Include, ..\..\..\OgreMain\include"
+				PreprocessorDefinitions="_WINDOWS,_STLP_USE_DYNAMIC_LIB,OGRE_LIBRARY_IMPORTS,_RELEASE,WIN32,_STLP_RELEASE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OGREMain.LIB"
+				OutputFile="..\..\..\Samples\Common\Bin\Release\TestCulling.exe"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\..\OgreMain\Lib\Release"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\TestCullingApplication.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\TestCullingApplication.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: trunk/VUT/work/TestCulling/TestCullingApplication.cpp
===================================================================
--- trunk/VUT/work/TestCulling/TestCullingApplication.cpp	(revision 61)
+++ trunk/VUT/work/TestCulling/TestCullingApplication.cpp	(revision 61)
@@ -0,0 +1,348 @@
+/**
+    \file 
+        TestCullingApplication.cpp
+    \brief
+        Tests the occlusion culling algorithm
+*/
+
+#include <OgreNoMemoryMacros.h>
+#include <CEGUI/CEGUI.h>
+#include <../CEGUIRenderer/include/OgreCEGUIRenderer.h>
+#include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h>
+#include <../CEGUIRenderer/include/OgreCEGUITexture.h>
+#include <OgreMemoryMacros.h>
+
+#include "Ogre.h"
+#include "TestCullingApplication.h"
+//#include "OgreVisibilitySceneTraverser.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+
+/***********************************************/
+/* TestCullingApplication implementation       */
+/***********************************************/
+
+//-----------------------------------------------------------------------
+/*void TestCullingApplication::createCamera( void )
+{
+	// Create the camera
+	mCamera = mSceneMgr->createCamera("PlayerCam");
+
+	// Position it at 500 in Z direction
+	mCamera->setPosition(Vector3(128,25,128));
+
+	// Look back along -Z
+    mCamera->lookAt(Vector3(0,0,-300));
+    mCamera->setNearClipDistance( 1 );
+    mCamera->setFarClipDistance( 1000 );
+}*/
+//-----------------------------------------------------------------------
+void TestCullingApplication::createScene(void)
+{
+	// Set ambient light
+	mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
+	
+	// Create a light
+	Light* l = mSceneMgr->createLight("MainLight");
+	//l->setPosition(20,80,50);
+
+	mMinTranslation = Vector3(-70.0f, -70.0f, 0.0f);
+	mMaxTranslation = Vector3(70.0f, 70.0f, 600.0f);
+
+	mMinAngle = Vector3(0, 0, 0);
+	mMaxAngle = Vector3(360, 360, 360);
+
+	generateScene(330);
+
+	// Create a skybox
+    //mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 1000, false);
+    ColourValue fadeColour(0.1, 0.1, 0.6);
+	mWindow->getViewport(0)->setBackgroundColour(fadeColour);
+
+	// CEGUI setup
+	setupGui();
+}
+//-----------------------------------------------------------------------
+void TestCullingApplication::setupGui( void )
+{
+	 mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, ST_EXTERIOR_CLOSE);
+     mGUISystem = new CEGUI::System(mGUIRenderer);
+
+	 // Mouse
+     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
+     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
+	 mGUISystem->setDefaultMouseCursor(
+                (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
+
+	 CEGUI::MouseCursor::getSingleton().show( );
+}
+//-----------------------------------------------------------------------
+void TestCullingApplication::createFrameListener(void)
+{
+	mFrameListener= new MouseQueryListener(mWindow, mCamera, mSceneMgr, mGUIRenderer);
+	mFrameListener->showDebugOverlay(true);
+	mRoot->addFrameListener(mFrameListener);
+}
+//-----------------------------------------------------------------------
+void TestCullingApplication::chooseSceneManager(void)
+{
+    mSceneMgr = mRoot->getSceneManager(ST_GENERIC);
+}
+//-----------------------------------------------------------------------
+void TestCullingApplication::generateSceneObject(const Vector3 &translationRatio, 
+												 const Vector3 &rotationRatio, const int idx, const String& entName)
+{
+	Vector3 rotation = mMinAngle + rotationRatio * (mMaxAngle - mMinAngle);
+	Vector3 translation = mMinTranslation + translationRatio * (mMaxTranslation - mMinTranslation);
+
+	char name[16];
+    sprintf( name, "object%d", idx );
+
+    Entity *ent = mSceneMgr->createEntity( name, entName );
+	SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( String(name) + "Node", translation);
+	node->attachObject(ent);
+	node->scale(0.1,0.1,0.1);
+
+	node->yaw(Degree(rotation.x));
+    node->pitch(Degree(rotation.y));
+	node->roll(Degree(rotation.z));
+}
+//-----------------------------------------------------------------------
+void TestCullingApplication::generateScene( int numObjects )
+{
+	srand (time (0));
+	
+	Vector3 rotationRatio;
+	Vector3 translationRatio;
+
+	for(int i=0; i < numObjects; i++)
+	{
+		rotationRatio.x = rand() / (float) RAND_MAX;
+		rotationRatio.y = rand() / (float) RAND_MAX;
+		rotationRatio.z = rand() / (float) RAND_MAX;
+
+		translationRatio.x = rand() / (float) RAND_MAX;
+		translationRatio.y = rand() / (float) RAND_MAX;
+		translationRatio.z = rand() / (float) RAND_MAX;
+
+		generateSceneObject(translationRatio, rotationRatio, i, "sphere.mesh");
+	}
+}
+/***********************************************/
+/* MouseQueryListener implementation           */
+/***********************************************/
+//-----------------------------------------------------------------------
+MouseQueryListener::MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer)
+        : ExampleFrameListener(win, cam, false, true), mGUIRenderer(renderer), 
+		mShutdownRequested(false)
+{
+
+	// Setup default variables
+	//mOgreHead = NULL;
+	mLMouseDown = false;
+	mRMouseDown = false;
+	mSceneMgr = sceneManager;
+
+    // Reduce move speed
+	mMoveSpeed = 50;
+	mRotateSpeed *= 2;
+
+	mCurrentAlgorithm = 0;//VisibilitySceneTraverser::RENDER_COHERENT;
+	mThreshold = 0;
+    
+	// Register this so that we get mouse events.
+	mEventProcessor->addMouseListener(this);
+	mEventProcessor->addMouseMotionListener(this);
+	mEventProcessor->addKeyListener(this);
+
+	// show overlay
+	Overlay* pOver = OverlayManager::getSingleton().getByName("Example/VisibilityDemoOverlay"); 
+
+	mAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/AlgorithmInfo");
+	mThresholdInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/ThresholdInfo");
+	mFrustumCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/FrustumCulledNodesInfo");
+	mQueryCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/QueryCulledNodesInfo");
+    mTraversedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/TraversedNodesInfo");
+	mSceneNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/SceneNodesInfo");
+	mHierarchyNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/HierarchyNodesInfo");
+	mRenderedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Occlusion/RenderedNodesInfo");
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mThresholdInfo->setCaption(": 0");
+	mFrustumCulledNodesInfo->setCaption(": 0");
+	mQueryCulledNodesInfo->setCaption(": 0");
+	mTraversedNodesInfo->setCaption(": 0");
+	mSceneNodesInfo->setCaption(": 0");
+	mHierarchyNodesInfo->setCaption(": 0");
+	mRenderedNodesInfo->setCaption(": 0");
+
+    pOver->show();
+} 
+//-----------------------------------------------------------------------
+MouseQueryListener::~MouseQueryListener( )
+{
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseMoved (MouseEvent *e)
+{
+	// Update CEGUI with the mouse motion
+    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight());
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::mousePressed(MouseEvent* e)
+{
+     // Left mouse button down
+     if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+     {
+		mLMouseDown = true; 
+     }
+     // Right mouse button down
+     else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+     {
+         CEGUI::MouseCursor::getSingleton().hide( );
+         mRMouseDown = true;
+     } // else if
+} // mousePressed
+
+ //-----------------------------------------------------------------------
+void MouseQueryListener::mouseReleased(MouseEvent* e)
+{
+    // Left mouse button up
+    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
+    {
+		CEGUI::MouseCursor::getSingleton().show( );
+        mLMouseDown = false;
+    }
+    // Right mouse button up
+    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
+    {
+        CEGUI::MouseCursor::getSingleton().show( );
+        mRMouseDown = false;
+    }
+} 
+//-----------------------------------------------------------------------
+void MouseQueryListener::mouseDragged (MouseEvent *e)
+ {
+	 // If we are dragging the left mouse button.	 	 
+	 if ( mLMouseDown )
+     {
+		
+     }
+	 // If we are dragging the right mouse button.
+	 if ( mRMouseDown )
+	 {
+		 mCamera->yaw( -e->getRelX() * mRotateSpeed );
+		 mCamera->pitch( -e->getRelY() * mRotateSpeed );
+	 }
+}
+//-----------------------------------------------------------------------
+bool MouseQueryListener::frameStarted(const FrameEvent &evt)
+{	 
+	return ExampleFrameListener::frameStarted(evt);
+}
+//-----------------------------------------------------------------------
+bool MouseQueryListener::frameEnded(const FrameEvent& evt)
+{
+	if (mShutdownRequested)
+		return false;
+
+    if (timeDelay >= 0) 
+        timeDelay -= evt.timeSinceLastFrame;
+
+    KEY_PRESSED(KC_SPACE, 0.3, changeAlgorithm());
+
+	KEY_PRESSED(KC_SUBTRACT, 0, changeThreshold(-10));
+	KEY_PRESSED(KC_ADD, 0, changeThreshold(10));
+	//KEY_PRESSED(KC_T, 1, change);
+      
+	changeStats();
+
+    return ExampleFrameListener::frameStarted(evt) && ExampleFrameListener::frameEnded(evt);        
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeThreshold(int incr)
+{
+	mThreshold += incr; if(mThreshold < 0) mThreshold = 0;
+	
+	char str[100]; sprintf(str,": %d", mThreshold);
+
+	mSceneMgr->setOption("Threshold", &mThreshold); 
+	mThresholdInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeAlgorithm()
+{
+    //mCurrentAlgorithm = ++mCurrentAlgorithm % VisibilitySceneTraverser::NUM_RENDERMODES;
+
+	mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]);
+	mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::changeStats()
+{
+	unsigned int opt = 0;
+	char str[100];
+	
+	mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mFrustumCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); 
+	mQueryCulledNodesInfo->setCaption(str);
+	
+	mSceneMgr->getOption("NumTraversedNodes", &opt); sprintf(str,": %d", opt); 
+	mTraversedNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumSceneNodes", &opt); sprintf(str,": %d", opt); 
+	mSceneNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumOctreeNodes", &opt); sprintf(str,": %d", opt); 
+	mHierarchyNodesInfo->setCaption(str);
+
+	mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt); 
+	mRenderedNodesInfo->setCaption(str);
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyPressed(KeyEvent* e)
+{
+	if(e->getKey() == KC_ESCAPE)
+    {
+		mShutdownRequested = true;
+		e->consume();
+		return;
+	}
+
+	CEGUI::System::getSingleton().injectKeyDown(e->getKey());
+	CEGUI::System::getSingleton().injectChar(e->getKeyChar());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyReleased(KeyEvent* e)
+{
+	CEGUI::System::getSingleton().injectKeyUp(e->getKey());
+	e->consume();
+}
+//-----------------------------------------------------------------------
+void MouseQueryListener::keyClicked(KeyEvent* e) 
+{
+	// Do nothing
+	e->consume();
+}
+//-----------------------------------------------------------------------
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+{
+    // Create application object
+    TestCullingApplication app;
+
+	try 
+	{
+        app.go();
+    } 
+	catch( Ogre::Exception& e ) 
+	{
+        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+    }	
+
+    return 0;
+}
Index: trunk/VUT/work/TestCulling/TestCullingApplication.dsp
===================================================================
--- trunk/VUT/work/TestCulling/TestCullingApplication.dsp	(revision 61)
+++ trunk/VUT/work/TestCulling/TestCullingApplication.dsp	(revision 61)
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="Demo_TestCullingApplication" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Demo_TestCullingApplication - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "TestCullingApplication.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "TestCullingApplication.mak" CFG="Demo_TestCullingApplication - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Demo_TestCullingApplication - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "Demo_TestCullingApplication - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Demo_TestCullingApplication - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "..\bin\Release"
+# PROP BASE Intermediate_Dir "..\obj\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\bin\Release"
+# PROP Intermediate_Dir "..\obj\Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /I "$(OGRE_PATH)\OgreMain\include" /I "$(OGRE_PATH)\Samples/Common/include" /D "NDEBUG" /D "_MBCS" /D "_WINDOWS" /D "WIN32" /YX /FD /Zm1000 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OgreMain.lib /nologo /subsystem:windows /machine:I386 /out:"$(OGRE_PATH)\Samples\Common\Bin\Release\Demo_TestCullingApplication.exe" /libpath:"$(OGRE_PATH)\OgreMain\lib\release" 
+# SUBTRACT LINK32 /profile /debug
+
+!ELSEIF  "$(CFG)" == "Demo_TestCullingApplication - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\bin\Debug"
+# PROP BASE Intermediate_Dir "..\obj\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\bin\Debug"
+# PROP Intermediate_Dir "..\obj\Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "$(OGRE_PATH)\OgreMain\include" /I "$(OGRE_PATH)\Samples/Common/include" /D "_MBCS" /D "_WINDOWS" /D "_DEBUG" /D "WIN32" /FD /GZ /Zm1000 /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OgreMain_d.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBCMT" /out:"$(OGRE_PATH)\Samples\Common\Bin\Debug\Demo_TestCullingApplication.exe" /pdbtype:sept /libpath:"$(OGRE_PATH)\OgreMain\lib\debug" 
+# SUBTRACT LINK32 /verbose
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Demo_TestCullingApplication - Win32 Release"
+# Name "Demo_TestCullingApplication - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=TestCullingApplication.cpp
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Index: trunk/VUT/work/TestCulling/TerrainContentGenerator.cpp
===================================================================
--- trunk/VUT/work/TestCulling/TerrainContentGenerator.cpp	(revision 61)
+++ trunk/VUT/work/TestCulling/TerrainContentGenerator.cpp	(revision 61)
@@ -0,0 +1,14 @@
+/**
+    \file 
+        TerrainContentGenerator.cpp
+    \brief
+        Creates content for the terrain,
+*/
+
+#include "TerrainContentGenerator.h"
+
+//-----------------------------------------------------------------------
+TerrainContentGenerator::TerrainContentGenerator( void )
+{
+}
+
Index: trunk/VUT/work/TestCulling/TestCullingApplication.h
===================================================================
--- trunk/VUT/work/TestCulling/TestCullingApplication.h	(revision 61)
+++ trunk/VUT/work/TestCulling/TestCullingApplication.h	(revision 61)
@@ -0,0 +1,121 @@
+/**
+    \file 
+        TestCullingApplication.h
+*/
+#include "CEGUIForwardRefs.h"
+#include "ExampleApplication.h"
+//#include "OgreVisibilitySceneTraverser.h"
+
+
+Real timeDelay = 0;
+#define KEY_PRESSED(_key,_timeDelay, _macro) \
+{ \
+    if (mInputDevice->isKeyDown(_key) && timeDelay <= 0) \
+{ \
+    timeDelay = _timeDelay; \
+    _macro ; \
+} \
+}
+
+String mCurrentAlgorithmCaptions[3] = 
+{
+    "Cull Frustum", 
+	"Stop and Wait", 
+	"Coherent Occlusion Culling"
+};
+
+class MouseQueryListener : public ExampleFrameListener, public MouseListener, public MouseMotionListener
+{
+public:
+
+    MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, 
+			CEGUI::Renderer *renderer);
+
+
+    ~MouseQueryListener( );
+
+	bool frameStarted(const FrameEvent& evt);
+	bool frameEnded(const FrameEvent& evt);
+
+    /* MouseListener callbacks. */
+    virtual void mouseClicked(MouseEvent* e) { }
+    virtual void mouseEntered(MouseEvent* e) { }
+    virtual void mouseExited(MouseEvent* e)  { }
+
+    // This is when the mouse button goes DOWN.
+    virtual void mousePressed(MouseEvent* e);
+
+    // This is when the mouse button is let UP.
+    virtual void mouseReleased(MouseEvent* e);
+
+    /* MouseMotionListener callbacks */
+    virtual void mouseMoved (MouseEvent *e);
+   
+    // This is when the mouse is clicked, held and dragged.
+    virtual void mouseDragged (MouseEvent *e);
+
+    void keyPressed(KeyEvent* e);
+
+	void keyReleased(KeyEvent* e);
+	void keyClicked(KeyEvent* e);
+
+	void changeAlgorithm();
+	void changeThreshold(int incr);
+	void changeStats();
+
+protected:
+    bool mLMouseDown, mRMouseDown;     // True if the mouse buttons are down
+    SceneManager *mSceneMgr;           // A pointer to the scene manager
+    
+	CEGUI::Renderer *mGUIRenderer;     // cegui renderer
+	
+	bool mShutdownRequested;
+	int mCurrentAlgorithm;
+	int mThreshold;
+
+	OverlayElement *mAlgorithmInfo;
+	OverlayElement *mThresholdInfo;
+	OverlayElement *mFrustumCulledNodesInfo;
+	OverlayElement *mQueryCulledNodesInfo;
+    OverlayElement *mTraversedNodesInfo;
+	OverlayElement *mHierarchyNodesInfo;
+	OverlayElement *mSceneNodesInfo;
+	OverlayElement *mRenderedNodesInfo;
+};
+
+
+class TestCullingApplication : public ExampleApplication
+{
+protected:
+	void createScene(void);
+	void createFrameListener(void);
+	void setupGui(void);
+	/** generates a the scene hierarchy with random values 
+	@param number of objects to generate
+	*/
+	void generateScene(int numObjects);
+
+	/** generates a new scene object 
+	@param tranlationRatio ratio between minimal and maximal possible translation
+	@param rotationRatio ratio between minimal and maximal possible rotation
+	@idx the index of the new object
+	@entName the name of the object entity
+	*/
+	void generateSceneObject(const Vector3 &translationRatio, const Vector3 &rotationRatio, 
+							 const int idx, const String &entName);
+
+	//virtual void createCamera(void);
+
+	CEGUI::OgreCEGUIRenderer *mGUIRenderer;
+	CEGUI::System *mGUISystem;
+
+	Vector3 mMinTranslation;
+	Vector3 mMaxTranslation;
+
+	Vector3 mMinAngle;
+	Vector3 mMaxAngle;
+
+private:
+	void chooseSceneManager(void);
+};
+
Index: trunk/VUT/work/TestCulling/TerrainContentGenerator.h
===================================================================
--- trunk/VUT/work/TestCulling/TerrainContentGenerator.h	(revision 61)
+++ trunk/VUT/work/TestCulling/TerrainContentGenerator.h	(revision 61)
@@ -0,0 +1,14 @@
+/**
+    \file 
+        TerrainContentGenerator.h
+*/
+
+class TerrainContentGenerator
+{
+public:
+	TerrainContentGenerator();
+
+protected:
+
+};
+
Index: trunk/VUT/work/TestCulling/TestCullingApplication.dsw
===================================================================
--- trunk/VUT/work/TestCulling/TestCullingApplication.dsw	(revision 61)
+++ trunk/VUT/work/TestCulling/TestCullingApplication.dsw	(revision 61)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Demo_TestCulling"=.\TestCullingApplication.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
