Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPage.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPage.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPage.h	(revision 1273)
@@ -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.
+-----------------------------------------------------------------------------
+*/
+#ifndef __TerrainPage_H__
+#define __TerrainPage_H__
+
+#include "OgreKdTerrainPrerequisites.h"
+#include "OgreRenderQueue.h"
+
+namespace Ogre {
+
+    /** Groups a number of TerrainRenderables (tiles) into a page, which is
+        the unit of loading / unloading.
+    @remarks
+        Note that this class, whilst holding onto TerrainRenderable instances, 
+        does not actually process or initialise them itself - this is 
+        intentional so the TerrainPageSource which is providing the tiles
+        is able to load and prepare each renderable incrementally if required, 
+        thus avoiding any 'single hit' load methods for the page.
+    @par
+        All this class does do is pre-create a 2D vector of 'slots' in which 
+        to place the TerrainRenderable pointers, which it does on 
+        construction. Note that this structure is public to allow completely
+        free access to users of this class.
+    */
+    class _OgreKdTerrainExport KdTerrainPage
+    {
+    public:
+        typedef std::vector < KdTerrainRenderable * > KdTerrainRow;
+        typedef std::vector < KdTerrainRow > KdTerrain2D;
+        
+        /// 2-dimensional vector of tiles, pre-allocated to the correct size
+        KdTerrain2D tiles;
+        /// The number of tiles across a page
+        unsigned short tilesPerPage;
+        /// The scene node to which all the tiles for this page are attached
+        SceneNode* pageSceneNode;
+
+        /** The main constructor. 
+        @param numTiles The number of terrain tiles (TerrainRenderable)
+            across (and down) a page
+        */
+        KdTerrainPage(unsigned short numTiles);
+
+        /** Destructor, will organise the deletion of pages
+        */
+        virtual ~KdTerrainPage();
+        /** After TerrainRenderables have been populated, this method
+            adds the neighbour links. 
+        @remarks
+            Should be called before adding the page to the scene manager.
+        */
+        void linkNeighbours(void);
+
+        /** Returns the TerrainRenderable that contains the given pt.
+        If no tile exists at the point, it returns 0;
+        */
+        KdTerrainRenderable * getTerrainTile( const Vector3 & pt );
+
+		/** Sets the render queue group which the tiles should be rendered in. */
+		void setRenderQueue(uint8 qid);
+
+
+    };
+
+
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1258)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTreeSceneManager.h	(revision 1273)
@@ -13,9 +13,4 @@
 #include <OgreSceneManager.h>
 #include <VisibilityManager.h>
-
-#include <OgreTerrainPrerequisites.h>
-#include <OgreTerrainRenderable.h>
-#include <OgreTerrainPageSource.h>
-#include <OgreIteratorWrappers.h>
 
 #include "OgreKdTree.h"
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdHeightmapTerrainPageSource.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdHeightmapTerrainPageSource.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdHeightmapTerrainPageSource.h	(revision 1273)
@@ -0,0 +1,78 @@
+/*
+-----------------------------------------------------------------------------
+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 __KdHeightmapTerrainPageSource_H__
+#define __KdHeightmapTerrainPageSource_H__
+
+#include "OgreKdTerrainPrerequisites.h"
+#include "OgreKdTerrainPageSource.h"
+#include "OgreImage.h"
+
+namespace Ogre {
+
+    /** Specialisation of the TerrainPageSource class to provide tiles loaded
+        from a 2D greyscale image.
+    @remarks
+        This is a simple tile provider that does not support paging; it is
+        assumed that the entire heightmap is loaded as one page.
+    */
+    class _OgreKdTerrainExport KdHeightmapTerrainPageSource : public KdTerrainPageSource
+    {
+    protected:
+        /// Is this input RAW?
+        bool mIsRaw;
+        /// Should we flip terrain vertically?
+        bool mFlipTerrain;
+        /// Image containing the source heightmap if loaded from non-RAW
+        Image mImage;
+        /// Arbitrary data loaded from RAW
+        MemoryDataStreamPtr mRawData;
+        /// The (single) terrain page this source will provide
+        KdTerrainPage* mPage;
+        /// Source file name
+        String mSource;
+        /// Manual size if source is RAW
+        uint mRawSize;
+        /// Manual bpp if source is RAW
+        uchar mRawBpp;
+        
+        /// Load a heightmap
+        void loadHeightmap(void);
+    public:
+        KdHeightmapTerrainPageSource();
+        ~KdHeightmapTerrainPageSource();
+        /// @see TerrainPageSource
+        void shutdown(void);
+        /// @see TerrainPageSource
+        void requestPage(ushort x, ushort y);
+        /// @see TerrainPageSource
+        void expirePage(ushort x, ushort y);
+        /// @see TerrainPageSource
+        void initialise(KdTerrainSceneManager* tsm, 
+            uint tileSize, uint pageSize, bool asyncLoading, 
+            KdTerrainPageSourceOptionList& optionList);
+    };
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainSceneManager.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainSceneManager.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainSceneManager.h	(revision 1273)
@@ -0,0 +1,310 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of the GameTools Project
+http://www.gametools.org
+
+Author: Martin Szydlowski
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _KdTreeTerrainSceneManager_H__
+#define _KdTreeTerrainSceneManager_H__
+
+#include <OgreIteratorWrappers.h>
+
+#include "OgreKdTerrainPrerequisites.h"
+#include "OgreKdTerrainPageSource.h"
+#include "OgreKdTerrainRenderable.h"
+
+#include "OgreKdTreeSceneManager.h"
+
+
+namespace Ogre
+{
+
+typedef std::vector < KdTerrainPage * > KdTerrainPageRow;
+typedef std::vector < KdTerrainPageRow > KdTerrainPage2D;
+
+/** Default implementation of RaySceneQuery. */
+// TODO: all scene queries in kd-tree
+class _OgreKdTerrainExport KdTerrainRaySceneQuery : public DefaultRaySceneQuery
+{
+protected:
+	WorldFragment mWorldFrag;
+public:
+	KdTerrainRaySceneQuery(SceneManager* creator);
+	~KdTerrainRaySceneQuery();
+
+	/** See RayScenQuery. */
+	void execute(RaySceneQueryListener* listener);
+};
+
+class KdTerrainSceneManager : public KdTreeSceneManager
+{
+public:
+	KdTerrainSceneManager(const String& name, GtpVisibility::VisibilityManager *vm);
+	~KdTerrainSceneManager(void);
+
+	virtual const String& getTypeName(void) const;
+
+	/************************************************************************/
+	/* Functions overriden from (KdTree)SceneManager                        */
+	/************************************************************************/
+
+	/** Loads the terrain using parameters int he given config file. */
+	void setWorldGeometry( const String& filename );
+	/** Loads the terrain using parameters in the given config file (contained 
+	in a stream). */
+	virtual void setWorldGeometry(DataStreamPtr& stream, 
+		const String& typeName = StringUtil::BLANK);
+
+	/** Sets the given option for the SceneManager.
+	@remarks
+	Options are (in addition to those supported by superclasses):
+	"PageSize", int*;
+	"TileSize", int*; 
+	"PrimaryCamera, Camera*;
+	"MaxMipMapLevel", int*;
+	"Scale", Vector3 *;
+	"MaxPixelError", int*;
+	"UseTriStrips", bool*;
+	"VertexProgramMorph", bool*;
+	"DetailTile", int*;
+	"LodMorphStart", Real*;
+	"VertexNormals", bool*;
+	"VertexColours", bool*;
+	"MorphLODFactorParamName", String*;
+	"MorphLODFactorParamIndex", size_t*;
+	"CustomMaterialName", String*;
+	"WorldTexture", String*;
+	"DetailTexture", String*;
+	*/
+	virtual bool setOption(const String& strKey, const void* pValue);
+
+
+	// Overridden from kdtree scene mananger
+	//void _findVisibleObjects(Camera *cam, bool onlyShadowCasters);
+	// Overridden from kdtree scene manager
+	void _renderScene(Camera *cam, Viewport *vp, bool includeOverlays);
+	/** Overridden to user _renderVisibleObjects from KdTreeSceneManager */
+	//virtual void _renderVisibleObjects( void );
+	/** Overridden from SceneManager */
+	void setWorldGeometryRenderQueue(uint8 qid);
+
+	/** Overridden in order to store the first camera created as the primary
+	one, for determining error metrics and the 'home' terrain page.
+	*/
+	Camera* createCamera( const String &name );
+
+
+	/** Creates a RaySceneQuery for this scene manager. */
+	RaySceneQuery* 
+		createRayQuery(const Ray& ray, unsigned long mask = 0xFFFFFFFF);
+
+	/** Overide from scene manager to destroy kdtree properly (before the scene graph is destroyed)
+	*/
+	virtual void clearScene();
+
+	/************************************************************************/
+	/* Functions for terrain rendering                                      */
+	/************************************************************************/
+	/** Returns the height at the given terrain coordinates. */
+	float getHeightAt( float x, float y );
+
+	bool intersectSegment( const Vector3 & start, const Vector3 & end, Vector3 * result );
+
+	/** Sets the texture to use for the main world texture. */
+	void setWorldTexture(const String& textureName);
+	/** Sets the texture to use for the detail texture. */
+	void setDetailTexture(const String& textureName);
+	/** Sets the number of times per tile the detail texture should be repeated. */
+	void setDetailTextureRepeat(int repeat);
+	/** Sets the dimensions of each tile (must be power of 2 + 1) */
+	void setTileSize(int size); 
+	/** Sets the dimensions of each page (must be power of 2 + 1) */
+	void setPageSize(int size); 
+	/** Sets the maximum screen space pixel error.  */
+	void setMaxPixelError(int pixelError); 
+	/** Sets how to scale the terrain data. */
+	void setScale(const Vector3& scale);
+	/** Sets the maximum geomipmap level to allow. */
+	void setMaxGeoMipMapLevel(int maxMip);
+
+	/** Gets the texture to use for the main world texture. */
+	const String& getWorldTexture(void) { return mWorldTextureName; }
+	/** Gets the texture to use for the detail texture. */
+	const String& getDetailTexture(void) { return mDetailTextureName; }
+	/** Gets the number of times per tile the detail texture should be repeated. */
+	int getDetailTextureRepeat(void);
+	/** Gets the dimensions of each tile (must be power of 2 + 1) */
+	int getTileSize(void); 
+	/** Gets the dimensions of each page (must be power of 2 + 1) */
+	int getPageSize(void); 
+	/** Gets the maximum screen space pixel error.  */
+	int getMaxPixelError(void); 
+	/** Gets how to scale the terrain data. */
+	const Vector3& getScale(void);
+	/** Gets the maximum geomipmap level to allow. */
+	int getMaxGeoMipMapLevel(void);
+
+
+	/** Sets whether the terrain should use triangle strips or not.	*/
+	void setUseTriStrips(bool useStrips);
+	/** Sets whether or not terrain tiles should be morphed between LODs
+	(NB requires vertex program support). */
+	void setUseLODMorph(bool useMorph);
+	/** Sets whether vertex normals will be generated for the terrain. */
+	void setUseVertexNormals(bool useNormals);
+	/** Sets whether vertex colours will be used. */
+	void setUseVertexColours(bool useColours);
+
+	/** Sets the name of a custom material to use to shade the landcape. */
+	void setCustomMaterial(const String& materialName);
+	/** Sets the name of the vertex program parameter to which to pass the
+	LOD morph factor. */
+	void setCustomMaterialMorphFactorParam(const String& paramName);
+	/** Sets the index of the vertex program parameter to which to pass the
+	LOD morph factor. */
+	void setCustomMaterialMorphFactorParam(uint paramIndex);
+	/** Sets the distance at which the LOD will start to morph downwards, as
+	a proportion of the distance between the LODs. */
+	void setLODMorphStart(Real morphStart);
+
+	/** Returns the TerrainRenderable that contains the given pt.
+	If no tile exists at the point, it returns 0;
+	*/
+	virtual KdTerrainRenderable * getTerrainTile( const Vector3 & pt );
+
+	/** Returns the TerrainPage that contains the given pt.
+	If no page exists at the point, it returns 0;
+	*/
+	virtual KdTerrainPage* getTerrainPage( const Vector3 & pt );
+
+	/// Gets the terrain options 
+	const KdTerrainOptions& getOptions(void) { return mOptions; }
+
+	/** Sets the 'primary' camera, i.e. the one which will be used to determine
+	the 'home' terrain page, and to calculate the error metrics. 
+	*/
+	virtual void setPrimaryCamera(const Camera* cam);
+	/// Internal map of page source name to page source
+	typedef std::map<String, KdTerrainPageSource*> KdPageSourceMap;
+
+	/// Iterator over all page sources
+	typedef ConstMapIterator<KdPageSourceMap> KdPageSourceIterator;
+	/// Get an iterator over all page sources
+	KdPageSourceIterator getPageSourceIterator(void);
+	/** Registers a TerrainPageSource class and associates it with a named type 
+	of source. */
+	virtual void registerPageSource(const String& typeName, KdTerrainPageSource* source);
+	/** Selects a given page source based on its type name. */
+	virtual void selectPageSource(const String& typeName, 
+		KdTerrainPageSourceOptionList& optionList);
+
+	/** Attaches a previously built page to the list of available pages. */
+	virtual void attachPage(ushort pageX, ushort pageZ, KdTerrainPage* page);
+	/// Get a pointer to the material being used for the terrain
+	MaterialPtr& getTerrainMaterial(void);
+
+	/// Get the SceneNode under which all terrain nodes are attached.
+	SceneNode* getTerrainRootNode(void) const { return mTerrainRoot; }
+
+	/// Get the shared list of indexes cached (internal use only)
+	KdTerrainBufferCache& _getIndexCache(void) {return mIndexCache;}
+
+	/// Get the shared level index list (internal use only)
+	LevelArray& _getLevelIndex(void) { return mLevelIndex; }
+
+	/// Get the current page count (internal use only)
+	uint _getPageCount(void) { return (uint)mTerrainPages.size(); }
+
+	/// Shutdown cleanly before we get destroyed
+	void shutdown(void);
+
+protected:
+	/// Validates that the size picked for the terrain is acceptable
+	bool _checkSize( int s )
+	{
+		for ( int i = 0; i < 16; i++ )
+		{
+			printf( "Checking...%d\n", ( 1 << i ) + 1 );
+
+			if ( s == ( 1 << i ) + 1 )
+				return true;
+		}
+
+		return false;
+
+	}
+
+	/// The node to which all terrain tiles are attached
+	SceneNode * mTerrainRoot;
+	/// Terrain size, detail etc
+	KdTerrainOptions mOptions;
+	/// Should we use an externally-defined custom material?
+	bool mUseCustomMaterial;
+	/// The name of the custom material to use
+	String mCustomMaterialName;
+	/// The name of the world texture
+	String mWorldTextureName;
+	/// The name of the detail texture
+	String mDetailTextureName;
+	/// Are we using a named parameter to hook up LOD morph?
+	bool mUseNamedParameterLodMorph;
+	/// The name of the parameter to send the LOD morph to
+	String mLodMorphParamName;
+	/// The index of the parameter to send the LOD morph to
+	uint mLodMorphParamIndex;
+	/// Whether paging is enabled, or whether a single page will be used
+	bool mPagingEnabled;
+	/// The number of pages to render outside the 'home' page
+	unsigned short mLivePageMargin;
+	/// The number of pages to keep loaded outside the 'home' page
+	unsigned short mBufferedPageMargin;
+	/// Grid of buffered pages
+	KdTerrainPage2D mTerrainPages;
+	//-- attributes to share across tiles
+	/// Shared list of index buffers
+	KdTerrainBufferCache mIndexCache;
+	/// Shared array of IndexData (reuse indexes across tiles)
+	LevelArray mLevelIndex;
+
+	/// Internal method for loading configurations settings
+	void loadConfig(DataStreamPtr& stream);
+
+	/// Sets up the terrain material
+	void setupTerrainMaterial(void);
+	/// Sets up the terrain page slots
+	void setupTerrainPages(void);
+	/// Initialise level indexes
+	void initLevelIndexes(void);
+	/// Destroy level indexes
+	void destroyLevelIndexes(void);
+
+
+	/// Map of source type -> TerrainPageSource
+	KdPageSourceMap mPageSources;
+	/// The currently active page source
+	KdTerrainPageSource* mActivePageSource;
+};
+
+/// Factory for KdTreeSceneManager
+class KdTerrainSceneManagerFactory : public SceneManagerFactory
+{
+protected:
+	typedef std::vector<KdTerrainPageSource*> KdTerrainPageSources;
+	KdTerrainPageSources mTerrainPageSources;
+	GtpVisibility::VisibilityManager *visManager;
+	void initMetaData(void) const;
+public:
+	KdTerrainSceneManagerFactory(GtpVisibility::VisibilityManager * vm);
+	~KdTerrainSceneManagerFactory(void);
+	/// Factory type name
+	static const String FACTORY_TYPE_NAME;
+	SceneManager* createInstance(const String& instanceName);
+	void destroyInstance(SceneManager* instance);
+};
+
+} // namespace Ogre
+
+#endif // _KdTreeTerrainSceneManager_H__
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPageSource.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPageSource.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPageSource.h	(revision 1273)
@@ -0,0 +1,262 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of the GameTools Project
+http://www.gametools.org
+
+Author: Martin Szydlowski
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __KdTerrainPageSource_H__
+#define __KdTerrainPageSource_H__
+
+#include <OgreSingleton.h>
+#include "OgreKdTerrainPrerequisites.h"
+
+namespace Ogre {
+
+    typedef std::pair<String, String> KdTerrainPageSourceOption;
+    typedef std::vector<KdTerrainPageSourceOption> KdTerrainPageSourceOptionList;
+
+    /** Abstract class which classes can override to receive notifications
+        when a page is ready to be added to the terrain manager.
+    */
+    class _OgreKdTerrainExport KdTerrainPageSourceListener
+    {
+    public:
+        /** Listener method called when a new page is about to be constructed. 
+		@param manager The manager in question
+        @param pagex, pagez The index of the page being constructed
+        @param heightData Array of normalised height data (0..1). The size of
+            this buffer will conform to the scene manager page size. The listener
+            may modify the data if it wishes.
+        */
+        virtual void pageConstructed(KdTerrainSceneManager* manager, uint pagex, uint pagez, Real* heightData) = 0;
+    };
+
+	/** Simple manager class to hold onto a list of page source listeners 
+	    across all sources.
+	*/
+	class _OgreKdTerrainExport KdTerrainPageSourceListenerManager :
+		public Singleton<KdTerrainPageSourceListenerManager>
+	{
+	protected:
+        typedef std::vector<KdTerrainPageSourceListener*> KdPageSourceListenerList;
+        KdPageSourceListenerList mPageSourceListeners;
+	public:
+        KdTerrainPageSourceListenerManager() {}
+        ~KdTerrainPageSourceListenerManager() {}
+
+        /** Register a class which will be called back whenever a new page is
+            available.
+        @remarks
+            Since this method is static, it applies to any page source which 
+            is in active use; there is no need to register one per source.
+        */
+        void addListener(KdTerrainPageSourceListener* pl);
+        /** Unregister a class which will be called back whenever a new page is
+        available.
+        */
+        void removeListener(KdTerrainPageSourceListener* pl);
+		
+        /// Fire pageContructed events
+        void firePageConstructed(KdTerrainSceneManager* manager, uint pagex, uint pagez, Real* heightData);
+
+       /** Override standard Singleton retrieval.
+        */
+        static KdTerrainPageSourceListenerManager& getSingleton(void);
+        /** Override standard Singleton retrieval.
+        */
+        static KdTerrainPageSourceListenerManager* getSingletonPtr(void);	
+	
+	};
+
+
+    /** Abstract class which describes the interface which a source of terrain 
+        pages must implement.
+    @remarks
+        The TerrainSceneManager can accept external classes as providers of
+        terrain data, to allow terrain height data to come from anywhere the
+        user application may choose, and additionally to support on-demand
+        loading an unloading of terrain data. Providers must suclass this class, 
+        and implement the abstract methods (details are described within each method)
+    @par
+        The overall sequence of events is this:
+        <ol>
+        <li>TerrainSceneManager is created as usual, and options such as tile
+        size etc are set.</li>
+        <li>CustomTerrainPageSource is registered with TerrainSceneManager by 
+        calling registerPageSource(), registering a particular named type of source 
+        data with this tile source. <li>
+        <li>TerrainSceneManager::setWorldGeometry is called. Depending on the
+        configuration, this will call one of the page source classes 
+        initialise methods, when the scene manager will communicate it's 
+        preferred options. It does not have to load anything immediately on this 
+        call (especially if the terrain options include paging). It will 
+        also set this tile source as the primary.<li>
+        <li>As and when TerrainSceneManager requires more tiles (and this will
+        either be done all up-front, or progressively depending on paging settings)
+        it will call the primary tile source's requestPage() method, with the 
+        page it requires. </li>
+        <li>It is then the responsibility of the tile source to prepare
+        TerrainRenderable instances for the page(s) requested, and to attach them 
+        to the TerrainSceneManager. Note that preparing the tiles does not
+        involve modifying any shared data so may be done in an alternate thread,
+        if required. Attaching them must be done synchronously though.
+        <li>When paging, the TerrainSceneManager will request tiles in advance,
+        within it's 'buffer zone' so some delay in loading is acceptable. It
+        will also indicate when tiles are no longer required (and will detach
+        them); it is up to the tile source whether that memory is actually freed
+        or held for a while longer.
+        </ol>
+    @note The comments on paging above are in principle, the implementation of
+    paging in this manager is not present yet but the system is designed to 
+    extend to it. For now, all tiles are requested up-front.
+    */
+    class _OgreKdTerrainExport KdTerrainPageSource
+    {
+    protected:
+        /// Link back to parent manager
+        KdTerrainSceneManager* mSceneManager;
+        /// Has asynchronous loading been requested?
+        bool mAsyncLoading;
+        /// The expected size of the page in number of vertices
+        uint mPageSize;
+        /// The expected size of a tile in number of vertices
+        uint mTileSize;
+
+        /// Internal method for firing pageContructed events
+        void firePageConstructed(uint pagex, uint pagez, Real* heightData);
+
+        /** Utility method for building a page of tiles based on some source
+        data, wherever that may have come from.
+        @remarks
+            It is expected that this height data is represented in the range
+            [0..1], which will be duly scaled by the TerrainRenderables it
+            creates.
+        */
+        virtual KdTerrainPage* buildPage(Real* heightData, const MaterialPtr& pMaterial);
+
+
+    public:
+        KdTerrainPageSource(); 
+        virtual ~KdTerrainPageSource() { shutdown(); }
+
+        /** Initialise this tile source based on a series of options as
+            dictated by the scene manager. 
+        @param tsm The TerrainSceneManager doing the initialising. This should be 
+            allowed NULL, for use by external tools if they want to read data 
+            generically without necessarily having a real scene manager involved
+        @param tileSize The number of horizontal (and hence also vertical) 
+            vertices in a single tile (which is a TerrainRenderable). This will
+            always be (2^n)+1.
+        @param pageSize The number of horizontal (and hence also vertical) 
+            vertices in a single page. This will always be (2^n)+1.
+        @param asyncLoading
+            True if the scene manager would like the tile source to load tiles
+            asynchronously. It does not have to do this, although if it does not
+            when requested, it will likely result in stalls in the terrain rendering.
+        @param optionList 
+            A list of name/value pairs describing custom options for this particular
+            page source. The expected convention for option names is
+            "TypeName.OptionName", where TypeName is the type under which this
+            page source has been registered.
+        */
+        virtual void initialise(KdTerrainSceneManager* tsm, 
+            uint tileSize, uint pageSize, bool asyncLoading, 
+            KdTerrainPageSourceOptionList& optionList)
+        {
+            mSceneManager = tsm;
+            mTileSize = tileSize;
+            mPageSize = pageSize;
+            mAsyncLoading = asyncLoading;
+        }
+        /** Shut down this tile source, freeing all it's memory ready for 
+            decommissioning.
+        @remarks
+            This method will normally just be called on destruction; however
+            it may also be called by the TerrainSceneManager if another source
+            is provided for the same type of tile source.
+        */
+        virtual void shutdown(void) {}
+
+        /** Requests a new page of tiles from the source.
+        @remarks
+            The TerrainSceneManager will call this method when it needs new tiles.
+            In response, this class must prepare TerrainRenderable instances for
+            the page requested and attach the entire page when ready using 
+            TerrainSceneManager::attachTerrainPage.
+        @par
+            Now, the tile source does not necessarily need to do all that before the
+            return of this method. If it likes, and particularly if asynchronous 
+            loading is enabled, it can merely queue this request, and process it
+            either in another thread, or over a series of frames. The key thing
+            is that attaching the new page has to be done synchronously with 
+            the main rendering loop in order to avoid concurrency issues; 
+            other than that, you are free to load and prepare new tiles in 
+            a concurrent fashion if you like.
+        @par
+            Typically the scene manager will request at least one page up-front,
+            with the possibility of requesting more if paging is enabled.
+        @param x The x index of the page requested
+        @param z The z index of the page requested
+        */
+        virtual void requestPage(ushort x, ushort z) = 0;
+        /** This notifies the tile source that the specified page of tiles 
+            has been automatically detached.
+        @remarks
+            When paging is enabled, tiles go out of scope and the TerrainSceneManager
+            detaches them automatically, notifying the TerrainPageSource that 
+            this has happened. The tile source can choose to either keep these
+            tiles in memory (incase they are requested again) or can delete them
+            if it wishes to free memory. This freeing does not need to be done
+            before the return of this method - like requesting tiles, the
+            freeing of them can be done in another thread or across many frames
+            if required, since the shared data in TerrainSceneManager has already
+            been updated synchronously when the page was detached.
+        @param x The x index of the page expired
+        @param z The z index of the page expired
+        */
+        virtual void expirePage(ushort x, ushort z) = 0;
+        
+        /** Register a class which will be called back whenever a new page is
+            available.
+        @remarks
+            Since this method is static, it applies to any page source which 
+            is in active use; there is no need to register one per source.
+        */
+        static void addListener(KdTerrainPageSourceListener* pl);
+        /** Unregister a class which will be called back whenever a new page is
+        available.
+        */
+        static void removeListener(KdTerrainPageSourceListener* pl);
+
+    };
+
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainRenderable.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainRenderable.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainRenderable.h	(revision 1273)
@@ -0,0 +1,441 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+KdTerrainRenderable.h  -  description
+-------------------
+begin                : Sat Oct 5 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+
+#ifndef _KdTerrainRenderable_H__
+#define _KdTerrainRenderable_H__
+
+#include "OgreKdTerrainPrerequisites.h"
+#include <OgreRenderable.h>
+#include <OgreMovableObject.h>
+#include <OgreAxisAlignedBox.h>
+#include <OgreString.h>
+#include <OgreHardwareBufferManager.h>
+
+#include <vector>
+
+#define MORPH_CUSTOM_PARAM_ID 77
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+#define MAX_RENDERLEVEL_INDEX 15 // maximal different number of render levels, e.g., used for chc
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+namespace Ogre
+{
+    typedef std::map <unsigned int, IndexData* > IndexMap;
+    typedef std::vector < IndexData* > IndexArray;
+    typedef std::vector < IndexMap* > LevelArray;
+
+    /**
+    * A cache of TerrainIndexBuffers.  Used to keep track of the buffers, and
+    * delete them when the program finishes.
+    */
+    class KdTerrainBufferCache
+    {
+    public:
+        void shutdown(void)
+        {
+            for( size_t i=0; i<mCache.size(); i++ )
+            {
+                delete mCache[i];
+            }
+            mCache.clear();
+        }
+        ~KdTerrainBufferCache()
+        {
+            shutdown();
+        }
+
+        IndexArray mCache;
+    };
+
+    //inline Real _max( Real x, Real y )
+    //{
+    //    return ( x > y ) ? x : y;
+    //}
+
+    /** A simple class for encapsulating parameters which are commonly needed by 
+    both TerrainSceneManager and KdTerrainRenderable.
+    */
+    class KdTerrainOptions
+    {
+    public:
+        KdTerrainOptions()
+        {
+            pageSize = 0;
+            tileSize = 0;
+            tilesPerPage = 0;
+            maxGeoMipMapLevel = 0;
+            scale = Vector3::UNIT_SCALE;
+            maxPixelError = 4;
+            detailTile = 1;
+            lit = false;
+            coloured = false;
+            lodMorph = false;
+            lodMorphStart = 0.5;
+            useTriStrips = false;
+            primaryCamera = 0;
+            terrainMaterial.setNull();
+        };
+        /// The size of one edge of a terrain page, in vertices
+        uint pageSize;
+        /// The size of one edge of a terrain tile, in vertices
+        uint tileSize; 
+        /// Precalculated number of tiles per page
+        uint tilesPerPage;
+        /// The primary camera, used for error metric calculation and page choice
+        const Camera* primaryCamera;
+        /// The maximum terrain geo-mipmap level
+        uint maxGeoMipMapLevel;
+        /// The scale factor to apply to the terrain (each vertex is 1 unscaled unit
+        /// away from the next, and height is from 0 to 1)
+        Vector3 scale;
+        /// The maximum pixel error allowed
+        uint maxPixelError;
+        /// Whether we should use triangle strips
+        bool useTriStrips;
+        /// The number of times to repeat a detail texture over a tile
+        uint detailTile;
+        /// Whether LOD morphing is enabled
+        bool lodMorph;
+        /// At what point (parametric) should LOD morphing start
+        Real lodMorphStart;
+        /// Whether dynamic lighting is enabled
+        bool lit;
+        /// Whether vertex colours are enabled
+        bool coloured;
+        /// Pointer to the material to use to render the terrain
+        MaterialPtr terrainMaterial;
+
+    };
+
+#define STITCH_NORTH_SHIFT 0
+#define STITCH_SOUTH_SHIFT 8
+#define STITCH_WEST_SHIFT  16
+#define STITCH_EAST_SHIFT  24
+
+#define STITCH_NORTH  128 << STITCH_NORTH_SHIFT
+#define STITCH_SOUTH  128 << STITCH_SOUTH_SHIFT
+#define STITCH_WEST   128 << STITCH_WEST_SHIFT
+#define STITCH_EAST   128 << STITCH_EAST_SHIFT
+
+    /**
+    Represents a terrain tile.
+    @remarks
+    A KdTerrainRenderable represents a tile used to render a block of terrain using the geomipmap approach
+    for LOD.
+    *@author Jon Anderson
+    */
+
+    class _OgreKdTerrainExport KdTerrainRenderable : public Renderable, public MovableObject
+    {
+    public:
+
+        KdTerrainRenderable(const String& name, KdTerrainSceneManager* tsm);
+        ~KdTerrainRenderable();
+
+        void deleteGeometry();
+
+        enum Neighbor
+        {
+            NORTH = 0,
+            SOUTH = 1,
+            EAST = 2,
+            WEST = 3,
+            HERE = 4
+        };
+
+        /** Initializes the KdTerrainRenderable.
+        @param startx, startz 
+        The starting points of the top-left of this tile, in terms of the
+        number of vertices.
+        @param pageHeightData The source height data for the entire parent page
+        */
+        void initialise(int startx, int startz, Real* pageHeightData);
+
+        //movable object methods
+
+        /** Returns the type of the movable. */
+        virtual const String& getMovableType( void ) const
+        {
+            return mType;
+        };
+
+        /** Returns the bounding box of this KdTerrainRenderable */
+        const AxisAlignedBox& getBoundingBox( void ) const
+        {
+            return mBounds;
+        };
+
+        /** Updates the level of detail to be used for rendering this KdTerrainRenderable based on the passed in Camera */
+        virtual void _notifyCurrentCamera( Camera* cam );
+
+        virtual void _updateRenderQueue( RenderQueue* queue );
+
+        /**
+        Constructs a RenderOperation to render the KdTerrainRenderable.
+        @remarks
+        Each KdTerrainRenderable has a block of vertices that represent the terrain.  Index arrays are dynamically
+        created for mipmap level, and then cached.
+        */
+        virtual void getRenderOperation( RenderOperation& rend );
+
+        virtual const MaterialPtr& getMaterial( void ) const
+        {
+            return mMaterial;
+        };
+
+        virtual void getWorldTransforms( Matrix4* xform ) const;
+
+        virtual const Quaternion& getWorldOrientation(void) const;
+        virtual const Vector3& getWorldPosition(void) const;
+
+        /** Returns the mipmap level that will be rendered for this frame. */
+        inline int getRenderLevel() const
+        {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            return mRenderLevel[msCurrentRenderLevelIndex];
+#else
+            return mRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        };
+
+        /** Forces the LOD to the given level from this point on. */
+        inline void setForcedRenderLevel( int i )
+        {
+            mForcedRenderLevel = i;
+        }
+
+        /** Calculates the normal at the given location */
+        void _getNormalAt( float x, float y, Vector3 * result );
+
+        /** Returns the terrain height at the given coordinates */
+        float getHeightAt( float x, float y );
+
+        /** Intersects the segment witht he terrain tile
+        */
+        bool intersectSegment( const Vector3 & start, const Vector3 & end, Vector3 * result );
+
+        /** Sets the appropriate neighbor for this KdTerrainRenderable.  Neighbors are necessary
+        to know when to bridge between LODs.
+        */
+        void _setNeighbor( Neighbor n, KdTerrainRenderable *t )
+        {
+            mNeighbors[ n ] = t;
+        };
+
+        /** Returns the neighbor KdTerrainRenderable.
+        */
+        KdTerrainRenderable * _getNeighbor( Neighbor n )
+        {
+            return mNeighbors[ n ];
+        }
+
+
+        void setMaterial(const MaterialPtr& m )
+        {
+            mMaterial = m;
+        };
+
+        /** Calculates static normals for lighting the terrain. */
+        void _calculateNormals();
+
+
+
+
+        /** Generates terrain shadows and lighting using vertex colors
+        */
+        void _generateVertexLighting( const Vector3 &sun, ColourValue ambient );
+
+
+        /** Overridden, see Renderable */
+        Real getSquaredViewDepth(const Camera* cam) const;
+
+        /** Overridden from MovableObject */
+        Real getBoundingRadius(void) const { return mBoundingRadius; }
+
+        /** @copydoc Renderable::getLights */
+        const LightList& getLights(void) const;
+
+        /// Overridden from Renderable to allow the morph LOD entry to be set
+        void _updateCustomGpuParameter(
+            const GpuProgramParameters::AutoConstantEntry& constantEntry,
+            GpuProgramParameters* params) const;
+		/// @see MovableObject
+		uint32 getTypeFlags(void) const;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		// resets index of renderlevel used for current pass
+		static void ResetRenderLevelIndex();
+		// next index of renderlevel
+		static void NextRenderLevelIndex();
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+		/// Parent SceneManager
+		KdTerrainSceneManager* mSceneManager;
+        /// Link to shared options
+        const KdTerrainOptions* mOptions;
+
+        /** Returns the index into the height array for the given coords. */
+        inline size_t _index( int x, int z ) const
+        {
+            return ( x + z * mOptions->tileSize );
+        };
+
+        /** Returns the  vertex coord for the given coordinates */
+        inline float _vertex( int x, int z, int n )
+        {
+            return mPositionBuffer[x * 3 + z * mOptions->tileSize * 3 + n];
+        };
+
+
+        inline int _numNeighbors() const
+        {
+            int n = 0;
+
+            for ( int i = 0; i < 4; i++ )
+            {
+                if ( mNeighbors[ i ] != 0 )
+                    n++;
+            }
+
+            return n;
+        }
+
+        inline bool _hasNeighborRenderLevel( int i ) const
+        {
+            for ( int j = 0; j < 4; j++ )
+            {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+				if ( mNeighbors[ j ] != 0 && mNeighbors[ j ] ->getRenderLevel() == i )
+                    return true;
+#else
+                if ( mNeighbors[ j ] != 0 && mNeighbors[ j ] ->mRenderLevel == i )
+                    return true;
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+            }
+
+            return false;
+
+        }
+
+        void _adjustRenderLevel( int i );
+
+        bool _checkSize( int n );
+
+        void _calculateMinLevelDist2( Real C );
+
+        Real _calculateCFactor();
+
+        VertexData* mTerrain;
+
+        /// The current LOD level
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        int mRenderLevel[MAX_RENDERLEVEL_INDEX];
+
+		/*** msz: added for v1-2-0 compatibility ***/
+		// index of renderlevel of current pass
+		static int msCurrentRenderLevelIndex;
+#else
+		int mRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        /// The previous 'next' LOD level down, for frame coherency
+        int mLastNextLevel; 
+        /// The morph factor between this and the next LOD level down
+        Real mLODMorphFactor;
+        /// List of squared distances at which LODs change
+        Real *mMinLevelDistSqr;
+        /// Connection to tiles four neighbours
+        KdTerrainRenderable *mNeighbors [ 4 ];
+        /// Whether light list need to re-calculate
+        mutable bool mLightListDirty;
+        /// Cached light list
+        mutable LightList mLightList;
+        /// The bounding radius of this tile
+        Real mBoundingRadius;
+        /// Bounding box of this tile
+        AxisAlignedBox mBounds;
+        /// The center point of this tile
+        Vector3 mCenter;
+        /// The MovableObject type
+        static String mType;
+        /// Current material used by this tile
+        MaterialPtr mMaterial;    
+        /// Whether this tile has been initialised    
+        bool mInit;
+        /// The buffer with all the renderable geometry in it
+        HardwareVertexBufferSharedPtr mMainBuffer;
+        /// Optional set of delta buffers, used to morph from one LOD to the next
+        HardwareVertexBufferSharedPtr* mDeltaBuffers;
+        /// System-memory buffer with just positions in it, for CPU operations
+        float* mPositionBuffer;
+        /// Forced rendering LOD level, optional
+        int mForcedRenderLevel;
+        /// Array of LOD indexes specifying which LOD is the next one down
+        /// (deals with clustered error metrics which cause LODs to be skipped)
+        int mNextLevelDown[10];
+        /// Gets the index data for this tile based on current settings
+        IndexData* getIndexData(void);
+        /// Internal method for generating stripified terrain indexes
+        IndexData* generateTriStripIndexes(unsigned int stitchFlags);
+        /// Internal method for generating triangle list terrain indexes
+        IndexData* generateTriListIndexes(unsigned int stitchFlags);
+        /** Utility method to generate stitching indexes on the edge of a tile
+        @param neighbor The neighbor direction to stitch
+        @param hiLOD The LOD of this tile
+        @param loLOD The LOD of the neighbor
+        @param omitFirstTri Whether the first tri of the stitch (always clockwise
+        relative to the centre of this tile) is to be omitted because an 
+        adjoining edge is also being stitched
+        @param omitLastTri Whether the last tri of the stitch (always clockwise
+        relative to the centre of this tile) is to be omitted because an 
+        adjoining edge is also being stitched
+        @param pIdx Pointer to a pointer to the index buffer to push the results 
+        into (this pointer will be updated)
+        @returns The number of indexes added
+        */
+        int stitchEdge(Neighbor neighbor, int hiLOD, int loLOD, 
+            bool omitFirstTri, bool omitLastTri, unsigned short** ppIdx);
+
+        /// Create a blank delta buffer for usein morphing
+        HardwareVertexBufferSharedPtr createDeltaBuffer(void);
+
+    };
+
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPrerequisites.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPrerequisites.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainPrerequisites.h	(revision 1273)
@@ -0,0 +1,57 @@
+/*
+-----------------------------------------------------------------------------
+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 __KdTerrainPrerequisites_H__
+#define __KdTerrainPrerequisites_H__
+
+#include "OgrePrerequisites.h"
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace Ogre
+{
+    class KdTerrainSceneManager;
+    class KdTerrainPageSource;
+    class KdTerrainRenderable;
+    class KdTerrainPage;
+}
+//-----------------------------------------------------------------------
+// Windows Settings
+//-----------------------------------------------------------------------
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 
+#   ifdef PLUGIN_KD_TERRAIN_EXPORTS 
+#       define _OgreKdTerrainExport __declspec(dllexport) 
+#   else 
+#       define _OgreKdTerrainExport __declspec(dllimport) 
+#   endif 
+#else 
+#   define _OgreKdTerrainExport 
+#endif 
+
+#endif
+
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainVertexProgram.h
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainVertexProgram.h	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreKdTerrainVertexProgram.h	(revision 1273)
@@ -0,0 +1,222 @@
+/*
+-----------------------------------------------------------------------------
+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 __KdTerrainVertexProgram_H__
+#define __KdTerrainVertexProgram_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreCommon.h"
+#include "OgreString.h"
+
+namespace Ogre {
+
+    /*
+    Static class containing the source to vertex programs used to 
+    morph the terrain LOD levels. The programs are generated from 
+    the following Cg:
+    @code 	
+    // No fog morphing terrain
+    void terrain_vp(
+	    float4 position : POSITION,
+	    float2 uv1   	: TEXCOORD0,
+	    float2 uv2	 	: TEXCOORD1,
+	    float delta     : BLENDWEIGHT,
+
+	    out float4 oPosition : POSITION,
+	    out float2 oUv1		 : TEXCOORD0,
+	    out float2 oUv2		 : TEXCOORD1,
+	    out float4 colour    : COLOR,
+	    uniform float4x4 worldViewProj,
+	    uniform float morphFactor
+	    )
+    {
+	    // Apply morph
+	    position.y = position.y + (delta.x * morphFactor);
+	    // world / view / projection
+	    oPosition = mul(worldViewProj, position);
+	    // Main texture coords
+	    oUv1 = uv1;
+	    // Detail texture coords
+	    oUv2 = uv2;
+	    // Full bright (no lighting)
+	    colour = float4(1,1,1,1);
+    }
+
+
+    // Linear fogged morphing terrain
+    void terrain_vp_linear(
+	    float4 position : POSITION,
+	    float2 uv1   	: TEXCOORD0,
+	    float2 uv2	 	: TEXCOORD1,
+	    float delta     : BLENDWEIGHT,
+
+	    out float4 oPosition : POSITION,
+	    out float2 oUv1		 : TEXCOORD0,
+	    out float2 oUv2		 : TEXCOORD1,
+	    out float4 colour    : COLOR,
+	    out float fog		 : FOG,
+	    uniform float4x4 worldViewProj,
+	    uniform float morphFactor
+	    )
+    {
+	    // Apply morph
+	    position.y = position.y + (delta.x * morphFactor);
+	    // world / view / projection
+	    oPosition = mul(worldViewProj, position);
+	    // Main texture coords
+	    oUv1 = uv1;
+	    // Detail texture coords
+	    oUv2 = uv2;
+	    // Full bright (no lighting)
+	    colour = float4(1,1,1,1);
+	    // Fog 
+	    // f = end - camz / end - start
+	    // when start / end has been set, fog value is distance
+	    fog = oPosition.z;
+    }
+
+
+    // Exp fogged morphing terrain
+    void terrain_vp_exp(
+	    float4 position : POSITION,
+	    float2 uv1   	: TEXCOORD0,
+	    float2 uv2	 	: TEXCOORD1,
+	    float delta     : BLENDWEIGHT,
+
+	    out float4 oPosition : POSITION,
+	    out float2 oUv1		 : TEXCOORD0,
+	    out float2 oUv2		 : TEXCOORD1,
+	    out float4 colour    : COLOR,
+	    out float fog		 : FOG,
+	    uniform float4x4 worldViewProj,
+	    uniform float morphFactor,
+	    uniform float fogDensity)
+    {
+	    // Apply morph
+	    position.y = position.y + (delta.x * morphFactor);
+	    // world / view / projection
+	    oPosition = mul(worldViewProj, position);
+	    // Main texture coords
+	    oUv1 = uv1;
+	    // Detail texture coords
+	    oUv2 = uv2;
+	    // Full bright (no lighting)
+	    colour = float4(1,1,1,1);
+	    // Fog 
+	    // f = 1 / e ^ (camz x density)
+	    // note pow = exp(src1 * log(src0)).
+	    fog = 1 / (exp((oPosition.z * fogDensity) * log(2.718281828)));
+    }
+
+
+    // Exp2 fogged morphing terrain
+    void terrain_vp_exp2(
+	    float4 position : POSITION,
+	    float2 uv1   	: TEXCOORD0,
+	    float2 uv2	 	: TEXCOORD1,
+	    float delta     : BLENDWEIGHT,
+
+	    out float4 oPosition : POSITION,
+	    out float2 oUv1		 : TEXCOORD0,
+	    out float2 oUv2		 : TEXCOORD1,
+	    out float4 colour    : COLOR,
+	    out float fog		 : FOG,
+	    uniform float4x4 worldViewProj,
+	    uniform float morphFactor,
+	    uniform float fogDensity)
+    {
+	    // Apply morph
+	    position.y = position.y + (delta.x * morphFactor);
+	    // world / view / projection
+	    oPosition = mul(worldViewProj, position);
+	    // Main texture coords
+	    oUv1 = uv1;
+	    // Detail texture coords
+	    oUv2 = uv2;
+	    // Full bright (no lighting)
+	    colour = float4(1,1,1,1);
+	    // Fog 
+	    // f = 1 / e ^ (camz x density)^2
+	    // note pow = exp(src1 * log(src0)).
+	    float src1 = oPosition.z * 0.002;
+	    fog = 1 / (exp((src1*src1) * log(2.718281828f)));
+    }
+
+	// Shadow receiver vertex program
+    void terrain_shadow_receiver_vp(
+	    float4 position : POSITION,
+	    float2 uv1   	: TEXCOORD0,
+	    float2 uv2	 	: TEXCOORD1,
+	    float delta     : BLENDWEIGHT,
+
+	    out float4 oPosition : POSITION,
+	    out float2 oUv1		 : TEXCOORD0,
+	    out float4 colour    : COLOR,
+	    uniform float4x4 worldViewProj,
+		uniform float4x4 world,
+	    uniform float4x4 textureViewProj,
+	    uniform float morphFactor
+	    )
+    {
+	    // Apply morph
+	    position.y = position.y + (delta.x * morphFactor);
+	    // world / view / projection
+	    oPosition = mul(worldViewProj, position);
+		
+	    // Main texture coords
+		float4 worldpos = mul(world, position);
+	    float4 projuv = mul(textureViewProj, worldpos);
+		oUv1.xy = projuv.xy / projuv.w;
+	    // Full bright (no lighting)
+	    colour = float4(1,1,1,1);
+    }
+
+    @endcode
+    */
+    class KdTerrainVertexProgram
+    {
+    private:
+        static String mNoFogArbvp1;
+        static String mLinearFogArbvp1;
+        static String mExpFogArbvp1;
+        static String mExp2FogArbvp1;
+		static String mShadowReceiverArbvp1;
+
+        static String mNoFogVs_1_1;
+        static String mLinearFogVs_1_1;
+        static String mExpFogVs_1_1;
+        static String mExp2FogVs_1_1;
+		static String mShadowReceiverVs_1_1;
+
+    public:
+        /// General purpose method to get any of the program sources
+        static const String& getProgramSource(FogMode fogMode, 
+			const String syntax, bool shadowReceiver = false);
+
+
+    };
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj	(revision 1239)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj	(revision 1273)
@@ -21,5 +21,5 @@
 				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include&quot;;..\include;..\..\..\OnlineCullingCHC\include;..\..\..\Preprocessing\src"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_OCCLUSIONCULLINGSCENEMANAGER_EXPORTS;GTP_VISIBILITY_MODIFIED_OGRE"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_KD_TERRAIN_EXPORTS;GTP_VISIBILITY_MODIFIED_OGRE"
 				MinimalRebuild="TRUE"
 				BasicRuntimeChecks="3"
@@ -74,4 +74,73 @@
 			OutputDirectory="..\lib\$(ConfigurationName)"
 			IntermediateDirectory="..\obj\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			WholeProgramOptimization="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				GlobalOptimizations="TRUE"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="TRUE"
+				ImproveFloatingPointConsistency="TRUE"
+				FavorSizeOrSpeed="1"
+				OmitFramePointers="TRUE"
+				EnableFiberSafeOptimizations="TRUE"
+				OptimizeForProcessor="2"
+				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include&quot;;..\include;..\..\..\OnlineCullingCHC\include;..\..\..\Preprocessing\src"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_KD_TERRAIN_EXPORTS;GTP_VISIBILITY_MODIFIED_OGRE"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="FALSE"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				IgnoreImportLibrary="TRUE"
+				AdditionalDependencies="OgreMain.lib CEGUIBase.lib OgreGUIRenderer.lib Plugin_OctreeSceneManager.lib GtpVisibility.lib zdll.lib zziplib.lib Preprocessor.lib xerces-c_2.lib devil.lib glut32.lib OpenGL32.Lib glu32.lib glew32.lib glew32s.lib"
+				OutputFile="$(OutDir)/Plugin_VisibilitySceneManager.dll"
+				Version="0.99"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\OgreMain\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;;&quot;$(OGRE_PATH)\Dependencies\lib\$(ConfigurationName)&quot;;&quot;..\..\..\Preprocessing\lib\$(ConfigurationName)&quot;;..\..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;..\..\..\Preprocessing\src\GL;..\..\..\..\..\..\..\NonGTP\Zlib\lib;&quot;..\..\lib\$(ConfigurationName)&quot;"
+				ModuleDefinitionFile="..\misc\OgreVisibilitySceneManager.def"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="$(OutDir)/Plugin_VisibilitySceneManager.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="copy $(OutDir)\$(TargetFileName) $(OGRE_PATH)\Samples\Common\bin\$(ConfigurationName)"/>
+			<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="mlrt|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
 			CharacterSet="2"
@@ -104,10 +173,10 @@
 				Name="VCLinkerTool"
 				IgnoreImportLibrary="TRUE"
-				AdditionalDependencies="OgreMain.lib CEGUIBase.lib OgreGUIRenderer.lib Plugin_OctreeSceneManager.lib GtpVisibility.lib zdll.lib zziplib.lib Preprocessor.lib xerces-c_2.lib devil.lib glut32.lib OpenGL32.Lib glu32.lib glew32.lib glew32s.lib"
+				AdditionalDependencies="OgreMain.lib CEGUIBase.lib OgreGUIRenderer.lib Plugin_OctreeSceneManager.lib GtpVisibility.lib zdll.lib zziplib.lib Preprocessor.lib xerces-c_2.lib devil.lib glut32.lib OpenGL32.Lib glu32.lib cg.lib cgGL.lib glew32.lib glew32s.lib"
 				OutputFile="$(OutDir)/Plugin_VisibilitySceneManager.dll"
 				Version="0.99"
 				LinkIncremental="1"
 				SuppressStartupBanner="TRUE"
-				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\OgreMain\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;;&quot;$(OGRE_PATH)\Dependencies\lib\$(ConfigurationName)&quot;;&quot;..\..\..\Preprocessing\lib\$(ConfigurationName)&quot;;..\..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;..\..\..\Preprocessing\src\GL;..\..\..\..\..\..\..\NonGTP\Zlib\lib;&quot;..\..\lib\$(ConfigurationName)&quot;"
+				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\OgreMain\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;;&quot;..\..\GtpVisibility\lib\$(ConfigurationName)&quot;;&quot;..\..\lib\$(ConfigurationName)&quot;;&quot;..\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Dependencies\lib\$(ConfigurationName)&quot;;&quot;..\..\..\Preprocessing\lib\$(ConfigurationName)&quot;;..\..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;..\..\..\Preprocessing\src\GL;&quot;$(CG_LIB_PATH)&quot;;..\..\..\..\..\..\..\NonGTP\Zlib\lib"
 				ModuleDefinitionFile="..\misc\OgreVisibilitySceneManager.def"
 				GenerateDebugInformation="TRUE"
@@ -140,5 +209,5 @@
 		</Configuration>
 		<Configuration
-			Name="mlrt|Win32"
+			Name="Release_Internal|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
@@ -209,5 +278,5 @@
 		</Configuration>
 		<Configuration
-			Name="Release_Internal|Win32"
+			Name="Release Internal|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
@@ -277,73 +346,4 @@
 				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
 		</Configuration>
-		<Configuration
-			Name="Release Internal|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="2"
-			WholeProgramOptimization="TRUE">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="3"
-				GlobalOptimizations="TRUE"
-				InlineFunctionExpansion="2"
-				EnableIntrinsicFunctions="TRUE"
-				ImproveFloatingPointConsistency="TRUE"
-				FavorSizeOrSpeed="1"
-				OmitFramePointers="TRUE"
-				EnableFiberSafeOptimizations="TRUE"
-				OptimizeForProcessor="2"
-				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include&quot;;..\include;..\..\..\OnlineCullingCHC\include;..\..\..\Preprocessing\src"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GTP_VISIBILITY_MODIFIED_OGRE"
-				StringPooling="TRUE"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="FALSE"
-				EnableFunctionLevelLinking="TRUE"
-				RuntimeTypeInfo="TRUE"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="3"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				IgnoreImportLibrary="TRUE"
-				AdditionalDependencies="OgreMain.lib CEGUIBase.lib OgreGUIRenderer.lib Plugin_OctreeSceneManager.lib GtpVisibility.lib zdll.lib zziplib.lib Preprocessor.lib xerces-c_2.lib devil.lib glut32.lib OpenGL32.Lib glu32.lib cg.lib cgGL.lib glew32.lib glew32s.lib"
-				OutputFile="$(OutDir)/Plugin_VisibilitySceneManager.dll"
-				Version="0.99"
-				LinkIncremental="1"
-				SuppressStartupBanner="TRUE"
-				AdditionalLibraryDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\bin\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\OgreMain\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\lib&quot;;&quot;..\..\GtpVisibility\lib\$(ConfigurationName)&quot;;&quot;..\..\lib\$(ConfigurationName)&quot;;&quot;..\lib\$(ConfigurationName)&quot;;&quot;$(OGRE_PATH)\Dependencies\lib\$(ConfigurationName)&quot;;&quot;..\..\..\Preprocessing\lib\$(ConfigurationName)&quot;;..\..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;..\..\..\Preprocessing\src\GL;&quot;$(CG_LIB_PATH)&quot;;..\..\..\..\..\..\..\NonGTP\Zlib\lib"
-				ModuleDefinitionFile="..\misc\OgreVisibilitySceneManager.def"
-				GenerateDebugInformation="TRUE"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				ImportLibrary="$(OutDir)/Plugin_VisibilitySceneManager.lib"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine="copy $(OutDir)\$(TargetFileName) $(OGRE_PATH)\Samples\Common\bin\$(ConfigurationName)"/>
-			<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>
@@ -355,5 +355,5 @@
 			<Filter
 				Name="Header Files"
-				Filter="">
+				Filter="h;hpp;hxx;hm;inl;inc">
 				<File
 					RelativePath="..\include\OgreOcclusionCullingSceneManager.h">
@@ -368,5 +368,5 @@
 			<Filter
 				Name="Source Files"
-				Filter="">
+				Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
 				<File
 					RelativePath="..\src\OgreOcclusionCullingSceneManager.cpp">
@@ -472,5 +472,5 @@
 			<Filter
 				Name="Header Files"
-				Filter="">
+				Filter="h;hpp;hxx;hm;inl;inc">
 				<File
 					RelativePath="..\include\OgreKdRenderable.h">
@@ -494,5 +494,5 @@
 			<Filter
 				Name="Source Files"
-				Filter="">
+				Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
 				<File
 					RelativePath="..\src\OgreKdTree.cpp">
@@ -509,4 +509,55 @@
 				<File
 					RelativePath="..\src\OgreKdTreeSceneNode.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="KdTreeTerrainSceneManager"
+			Filter="">
+			<Filter
+				Name="Header Files"
+				Filter="h;hpp;hxx;hm;inl;inc">
+				<File
+					RelativePath="..\include\OgreKdHeightmapTerrainPageSource.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainPage.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainPageSource.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainPrerequisites.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainRenderable.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainSceneManager.h">
+				</File>
+				<File
+					RelativePath="..\include\OgreKdTerrainVertexProgram.h">
+				</File>
+			</Filter>
+			<Filter
+				Name="Source Files"
+				Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+				<File
+					RelativePath=".\OgreKdHeightmapTerrainPageSource.cpp">
+				</File>
+				<File
+					RelativePath=".\OgreKdTerrainPage.cpp">
+				</File>
+				<File
+					RelativePath=".\OgreKdTerrainPageSource.cpp">
+				</File>
+				<File
+					RelativePath=".\OgreKdTerrainRenderable.cpp">
+				</File>
+				<File
+					RelativePath=".\OgreKdTerrainSceneManager.cpp">
+				</File>
+				<File
+					RelativePath=".\OgreKdTerrainVertexProgram.cpp">
 				</File>
 			</Filter>
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1264)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp	(revision 1273)
@@ -13,8 +13,4 @@
 #include <OgreLogManager.h>
 #include <OgreStringConverter.h>
-
-#include <OgreTerrainPage.h>
-#include <OgreTerrainVertexProgram.h>
-#include <OgreHeightmapTerrainPageSource.h>
 
 #include "OgreKdTreeSceneManager.h"
@@ -293,45 +289,45 @@
 	}
 	// options for CHC
-	if (strKey == "UseDepthPass")
+	else if (strKey == "UseDepthPass")
 	{
 		mUseDepthPass = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "PrepareVisualization")
+	else if (strKey == "PrepareVisualization")
 	{
 		mShowVisualization = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "RenderNodesForViz")
+	else if (strKey == "RenderNodesForViz")
 	{
 		mRenderNodesForViz = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "RenderNodesContentForViz")
+	else if (strKey == "RenderNodesContentForViz")
 	{
 		mRenderNodesContentForViz = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "SkyBoxEnabled")
+	else if (strKey == "SkyBoxEnabled")
 	{
 		mSkyBoxEnabled = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "SkyPlaneEnabled")
+	else if (strKey == "SkyPlaneEnabled")
 	{
 		mSkyPlaneEnabled = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "SkyDomeEnabled")
+	else if (strKey == "SkyDomeEnabled")
 	{
 		mSkyDomeEnabled = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "VisualizeCulledNodes")
+	else if (strKey == "VisualizeCulledNodes")
 	{
 		mVisualizeCulledNodes = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "DelayRenderTransparents")
+	else if (strKey == "DelayRenderTransparents")
 	{
 		mDelayRenderTransparents = (*static_cast<const bool *>(pValue));
@@ -339,20 +335,20 @@
 	}
 
-	if (strKey == "DepthWrite")
+	else if (strKey == "DepthWrite")
 	{
 		mEnableDepthWrite = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "UseItemBuffer")
+	else if (strKey == "UseItemBuffer")
 	{
 		mUseItemBuffer = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "ExecuteVertexProgramForAllPasses")
+	else if (strKey == "ExecuteVertexProgramForAllPasses")
 	{ 
 		mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(pValue));
 		return true;
 	}
-	if (strKey == "RenderTransparentsForItemBuffer")
+	else if (strKey == "RenderTransparentsForItemBuffer")
 	{ 
 		mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(pValue));
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdHeightmapTerrainPageSource.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdHeightmapTerrainPageSource.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdHeightmapTerrainPageSource.cpp	(revision 1273)
@@ -0,0 +1,283 @@
+/*
+-----------------------------------------------------------------------------
+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 <OgreException.h>
+#include <OgreStringConverter.h>
+#include <OgreResourceManager.h>
+#include <OgreLogManager.h>
+
+#include "OgreKdHeightmapTerrainPageSource.h"
+#include "OgreKdTerrainSceneManager.h"
+#include "OgreKdTerrainPage.h"
+
+namespace Ogre {
+
+    //-------------------------------------------------------------------------
+    KdHeightmapTerrainPageSource::KdHeightmapTerrainPageSource()
+        : mIsRaw(false), mFlipTerrain(false), mPage(0)
+    {
+    }
+    //-------------------------------------------------------------------------
+    KdHeightmapTerrainPageSource::~KdHeightmapTerrainPageSource()
+    {
+        shutdown();
+    }
+    //-------------------------------------------------------------------------
+    void KdHeightmapTerrainPageSource::shutdown(void)
+    {
+        // Image will destroy itself
+        delete mPage;
+        mPage = 0;
+    }
+    //-------------------------------------------------------------------------
+    void KdHeightmapTerrainPageSource::loadHeightmap(void)
+    {
+        size_t imgSize;
+        // Special-case RAW format
+        if (mIsRaw)
+        {
+            // Image size comes from setting (since RAW is not self-describing)
+            imgSize = mRawSize;
+            
+            // Load data
+            mRawData.setNull();
+            DataStreamPtr stream = 
+                ResourceGroupManager::getSingleton().openResource(
+                    mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
+            mRawData = MemoryDataStreamPtr(new MemoryDataStream(mSource, stream));
+
+            // Validate size
+            size_t numBytes = imgSize * imgSize * mRawBpp;
+            if (mRawData->size() != numBytes)
+            {
+                shutdown();
+                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                    "RAW size (" + StringConverter::toString(mRawData->size()) + 
+                    ") does not agree with configuration settings.", 
+                    "HeightmapTerrainPageSource::loadHeightmap");
+            }
+        }
+        else
+        {
+            mImage.load(mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
+            // Must be square (dimensions checked later)
+            if ( mImage.getWidth() != mImage.getHeight())
+            {
+                shutdown();
+                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+                    "Heightmap must be square",
+                    "HeightmapTerrainPageSource::loadHeightmap");
+            }
+            imgSize = mImage.getWidth();
+        }
+        //check to make sure it's the expected size
+        if ( imgSize != mPageSize)
+        {
+            shutdown();
+            String err = "Error: Invalid heightmap size : " +
+                StringConverter::toString( imgSize ) +
+                ". Should be " + StringConverter::toString(mPageSize);
+            OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, 
+                "HeightmapTerrainPageSource::loadHeightmap" );
+        }
+
+    }
+    //-------------------------------------------------------------------------
+    void KdHeightmapTerrainPageSource::initialise(KdTerrainSceneManager* tsm, 
+		uint tileSize, uint pageSize, bool asyncLoading, 
+        KdTerrainPageSourceOptionList& optionList)
+    {
+        // Shutdown to clear any previous data
+        shutdown();
+
+        KdTerrainPageSource::initialise(tsm, tileSize, pageSize, asyncLoading, optionList);
+
+        // Get source image
+        KdTerrainPageSourceOptionList::iterator ti, tiend;
+        tiend = optionList.end();
+        bool imageFound = false;
+        mIsRaw = false;
+        bool rawSizeFound = false;
+        bool rawBppFound = false;
+        for (ti = optionList.begin(); ti != tiend; ++ti)
+        {
+            String val = ti->first;
+            StringUtil::trim(val);
+            if (StringUtil::startsWith(val, "Heightmap.image", false))
+            {
+                mSource = ti->second;
+                imageFound = true;
+                // is it a raw?
+                if (StringUtil::endsWith(mSource, "raw"))
+                {
+                    mIsRaw = true;
+                }
+            }
+            else if (StringUtil::startsWith(val, "Heightmap.raw.size", false))
+            {
+                mRawSize = atoi(ti->second.c_str());
+                rawSizeFound = true;
+            }
+            else if (StringUtil::startsWith(val, "Heightmap.raw.bpp", false))
+            {
+                mRawBpp = atoi(ti->second.c_str());
+                if (mRawBpp < 1 || mRawBpp > 2)
+                {
+                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                        "Invalid value for 'Heightmap.raw.bpp', must be 1 or 2",
+                        "HeightmapTerrainPageSource::initialise");
+                }
+                rawBppFound = true;
+            }
+            else if (StringUtil::startsWith(val, "Heightmap.flip", false))
+            {
+                mFlipTerrain = StringConverter::parseBool(ti->second);
+            }
+            else
+            {
+                LogManager::getSingleton().logMessage("Warning: ignoring unknown Heightmap option '"
+                    + val + "'");
+            }
+        }
+        if (!imageFound)
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+                "Missing option 'Heightmap.image'", 
+                "HeightmapTerrainPageSource::initialise");
+        }
+        if (mIsRaw && 
+            (!rawSizeFound || !rawBppFound))
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+                "Options 'Heightmap.raw.size' and 'Heightmap.raw.bpp' must "
+                "be specified for RAW heightmap sources", 
+                "HeightmapTerrainPageSource::initialise");
+        }
+        // Load it!
+        loadHeightmap();
+    }
+    //-------------------------------------------------------------------------
+    void KdHeightmapTerrainPageSource::requestPage(ushort x, ushort y)
+    {
+        // Only 1 page provided
+        if (x == 0 && y == 0 && !mPage)
+        {
+            // Convert the image data to unscaled floats
+            ulong totalPageSize = mPageSize * mPageSize; 
+            Real *heightData = new Real[totalPageSize];
+            const uchar* pOrigSrc, *pSrc;
+            Real* pDest = heightData;
+            Real invScale;
+            bool is16bit = false;
+            
+            if (mIsRaw)
+            {
+                pOrigSrc = mRawData->getPtr();
+                is16bit = (mRawBpp == 2);
+            }
+            else
+            {
+                PixelFormat pf = mImage.getFormat();
+                if (pf != PF_L8 && pf != PF_L16)
+                {
+                    OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, 
+                        "Error: Image is not a grayscale image.",
+                        "HeightmapTerrainPageSource::requestPage" );
+                }
+
+                pOrigSrc = mImage.getData();
+                is16bit = (pf == PF_L16);
+            }
+            // Determine mapping from fixed to floating
+            ulong rowSize;
+            if ( is16bit )
+            {
+                invScale = 1.0f / 65535.0f; 
+                rowSize =  mPageSize * 2;
+            }
+            else 
+            {
+                invScale = 1.0f / 255.0f; 
+                rowSize =  mPageSize;
+            }
+            // Read the data
+            pSrc = pOrigSrc;
+            for (ulong j = 0; j < mPageSize; ++j)
+            {
+                if (mFlipTerrain)
+                {
+                    // Work backwards 
+                    pSrc = pOrigSrc + (rowSize * (mPageSize - j - 1));
+                }
+                for (ulong i = 0; i < mPageSize; ++i)
+                {
+                    if (is16bit)
+                    {
+                        #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+                            ushort val = *pSrc++ << 8;
+                            val += *pSrc++;
+                        #else
+                            ushort val = *pSrc++;
+                            val += *pSrc++ << 8;
+                        #endif
+                        *pDest++ = Real(val) * invScale;
+                    }
+                    else
+                    {
+                        *pDest++ = Real(*pSrc++) * invScale;
+                    }
+                }
+            }
+
+            // Call listeners
+            firePageConstructed(0, 0, heightData);
+            // Now turn into TerrainPage
+            // Note that we're using a single material for now
+            if (mSceneManager)
+            {
+                mPage = buildPage(heightData, 
+                    mSceneManager->getOptions().terrainMaterial);
+                mSceneManager->attachPage(0, 0, mPage);
+            }
+
+            // Free temp store
+            delete [] heightData;
+        }
+    }
+    //-------------------------------------------------------------------------
+    void KdHeightmapTerrainPageSource::expirePage(ushort x, ushort y)
+    {
+        // Single page
+        if (x == 0 && y == 0 && mPage)
+        {
+            delete mPage;
+            mPage = 0;
+        }
+
+    }
+    //-------------------------------------------------------------------------
+
+
+}
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreVisibilitySceneManagerDll.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreVisibilitySceneManagerDll.cpp	(revision 1264)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreVisibilitySceneManagerDll.cpp	(revision 1273)
@@ -24,6 +24,7 @@
 */
 
-#include <OgreOcclusionCullingSceneManager.h>
-#include <OgreKdTreeSceneManager.h>
+#include "OgreOcclusionCullingSceneManager.h"
+#include "OgreKdTreeSceneManager.h"
+#include "OgreKdTerrainSceneManager.h"
 #include <OgreRoot.h>
 #include <OgreLogManager.h>
@@ -40,4 +41,5 @@
 OcclusionCullingSceneManagerFactory *occlusionCullingPlugin;
 KdTreeSceneManagerFactory *kdTreeFactory;
+KdTerrainSceneManagerFactory *kdTerrainFactory;
 
 //-----------------------------------------------------------------------
@@ -51,11 +53,13 @@
 	occlusionCullingPlugin = new OcclusionCullingSceneManagerFactory(visManager);
 	kdTreeFactory = new KdTreeSceneManagerFactory(visManager);
-
+	kdTerrainFactory = new KdTerrainSceneManagerFactory(visManager);
 	// Construct listener manager singleton
 	new TerrainPageSourceListenerManager();
+	new KdTerrainPageSourceListenerManager();
 
 	// Register
 	Root::getSingleton().addSceneManagerFactory(occlusionCullingPlugin);
 	Root::getSingleton().addSceneManagerFactory(kdTreeFactory);
+	Root::getSingleton().addSceneManagerFactory(kdTerrainFactory);
 }
 //-----------------------------------------------------------------------
@@ -64,7 +68,8 @@
 	Root::getSingleton().removeSceneManagerFactory(occlusionCullingPlugin);
 	Root::getSingleton().removeSceneManagerFactory(kdTreeFactory);
-
+	Root::getSingleton().removeSceneManagerFactory(kdTerrainFactory);
 	// destroy listener manager
 	delete TerrainPageSourceListenerManager::getSingletonPtr();
+	delete KdTerrainPageSourceListenerManager::getSingletonPtr();
 }
 //-----------------------------------------------------------------------
@@ -75,4 +80,5 @@
 	delete occlusionCullingPlugin;
 	delete kdTreeFactory;
+	delete kdTerrainFactory;
 
 	delete visManager;
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainSceneManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainSceneManager.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainSceneManager.cpp	(revision 1273)
@@ -0,0 +1,933 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of the GameTools Project
+http://www.gametools.org
+
+Author: Martin Szydlowski
+-----------------------------------------------------------------------------
+*/
+#include <OgreGpuProgramManager.h>
+#include <OgreConfigFile.h>
+#include <OgreMaterialManager.h>
+#include <OgreLogManager.h>
+
+#include "OgreKdTerrainPage.h"
+#include "OgreKdHeightmapTerrainPageSource.h"
+#include "OgreKdTerrainVertexProgram.h"
+
+#include "OgreKdTerrainSceneManager.h"
+
+#define TERRAIN_MATERIAL_NAME "TerrainSceneManager/Terrain"
+
+namespace Ogre
+{
+
+KdTerrainSceneManager::KdTerrainSceneManager(const String& name, GtpVisibility::VisibilityManager *vm):
+KdTreeSceneManager(name, vm),
+mUseCustomMaterial(false),
+mUseNamedParameterLodMorph(false),
+mLodMorphParamIndex(3),
+mTerrainRoot(0),
+mActivePageSource(0),
+mPagingEnabled(false),
+mLivePageMargin(0),
+mBufferedPageMargin(0)
+{
+
+}
+//-----------------------------------------------------------------------
+KdTerrainSceneManager::~KdTerrainSceneManager()
+{
+	shutdown();
+}
+//-----------------------------------------------------------------------
+const String& KdTerrainSceneManager::getTypeName() const
+{
+	return KdTerrainSceneManagerFactory::FACTORY_TYPE_NAME;
+}
+//-----------------------------------------------------------------------
+void KdTerrainSceneManager::clearScene()
+{
+	KdTreeSceneManager::clearScene();
+
+	// clear terrain
+	mTerrainPages.clear();
+	destroyLevelIndexes();
+	// sm has destroyed our root
+	mTerrainRoot = 0;
+}
+//-----------------------------------------------------------------------
+bool KdTerrainSceneManager::setOption(const String& strKey, const void* pValue)
+{
+	// options for terrain
+	if (strKey == "PageSize")
+	{
+		setPageSize(*static_cast<const int*>(pValue));
+		return true;
+	} 
+	else if (strKey == "TileSize")
+	{
+		setTileSize(*static_cast<const int*>(pValue));
+		return true;
+	}
+	else if (strKey == "PrimaryCamera")
+	{
+		setPrimaryCamera(static_cast<const Camera*>(pValue));
+		return true;
+	}
+	else if (strKey == "MaxMipMapLevel")
+	{
+		setMaxGeoMipMapLevel(*static_cast<const int*>(pValue));
+		return true;
+	}
+	else if (strKey == "Scale")
+	{
+		setScale(*static_cast<const Vector3*>(pValue));
+		return true;
+	}
+	else if (strKey == "MaxPixelError")
+	{
+		setMaxPixelError(*static_cast<const int*>(pValue));
+		return true;
+	}
+	else if (strKey == "UseTriStrips")
+	{
+		setUseTriStrips(*static_cast<const bool*>(pValue));
+		return true;
+	}
+	else if (strKey == "VertexProgramMorph")
+	{
+		setUseLODMorph(*static_cast<const bool*>(pValue));
+		return true;
+	}
+	else if (strKey == "DetailTile")
+	{
+		setDetailTextureRepeat(*static_cast<const int*>(pValue));
+		return true;
+	}
+	else if (strKey == "LodMorphStart")
+	{
+		setLODMorphStart(*static_cast<const Real*>(pValue));
+		return true;
+	}
+	else if (strKey == "VertexNormals")
+	{
+		setUseVertexNormals(*static_cast<const bool*>(pValue));
+		return true;
+	}
+	else if (strKey == "VertexColours")
+	{
+		setUseVertexColours(*static_cast<const bool*>(pValue));
+		return true;
+	}
+	else if (strKey == "MorphLODFactorParamName")
+	{
+		setCustomMaterialMorphFactorParam(*static_cast<const String*>(pValue));
+		return true;
+	}
+	else if (strKey == "MorphLODFactorParamIndex")
+	{
+		setCustomMaterialMorphFactorParam(*static_cast<const uint*>(pValue));
+		return true;
+	}
+	else if (strKey == "CustomMaterialName")
+	{
+		setCustomMaterial(*static_cast<const String*>(pValue));
+		return true;
+	}
+	else if (strKey == "WorldTexture")
+	{
+		setWorldTexture(*static_cast<const String*>(pValue));
+		return true;
+	}
+	else if (strKey == "DetailTexture")
+	{
+		setDetailTexture(*static_cast<const String*>(pValue));
+		return true;
+	}
+
+	return KdTreeSceneManager::setOption(strKey, pValue);
+}
+//-----------------------------------------------------------------------
+Camera* KdTerrainSceneManager::createCamera(const String &name )
+{
+	Camera* cam = KdTreeSceneManager::createCamera(name);
+
+	// Set primary camera, if none
+	if (!mOptions.primaryCamera)
+		setPrimaryCamera(cam);
+
+	return cam;
+}
+//-------------------------------------------------------------------------
+//void _findVisibleObjects(Camera *cam, bool onlyShadowCasters)
+//{
+//	KdTreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
+//}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::_renderScene(Camera* cam, Viewport *vp, bool includeOverlays)
+{
+	// For now, no paging and expect immediate response
+	if (!mTerrainPages.empty() && mTerrainPages[0][0] == 0)
+	{
+		mActivePageSource->requestPage(0, 0);
+	}
+	KdTreeSceneManager::_renderScene(cam, vp, includeOverlays);
+
+}
+//-----------------------------------------------------------------------
+//void KdTerrainSceneManager::_renderVisibleObjects()
+//{
+//	KdTreeSceneManager::_renderVisibleObjects();
+//}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::shutdown(void)
+{
+	// Make sure the indexes are destroyed during orderly shutdown
+	// and not when statics are destroyed (may be too late)
+	mIndexCache.shutdown();
+	destroyLevelIndexes();
+
+	// Make sure we free up material (static)
+	mOptions.terrainMaterial.setNull();
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::loadConfig(DataStreamPtr& stream)
+{
+	/* Set up the options */
+	ConfigFile config;
+	String val;
+
+	config.load( stream );
+
+	val = config.getSetting( "DetailTile" );
+	if ( !val.empty() )
+		setDetailTextureRepeat(atoi(val.c_str()));
+
+	val = config.getSetting( "MaxMipMapLevel" );
+	if ( !val.empty() )
+		setMaxGeoMipMapLevel(atoi( val.c_str() ));
+
+
+	val = config.getSetting( "PageSize" );
+	if ( !val.empty() )
+		setPageSize(atoi( val.c_str() ));
+	else
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSize'",
+		"TerrainSceneManager::loadConfig");
+
+
+	val = config.getSetting( "TileSize" );
+	if ( !val.empty() )
+		setTileSize(atoi( val.c_str() ));
+	else
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'TileSize'",
+		"TerrainSceneManager::loadConfig");
+
+	Vector3 v = Vector3::UNIT_SCALE;
+
+	val = config.getSetting( "PageWorldX" );
+	if ( !val.empty() )
+		v.x = atof( val.c_str() );
+
+	val = config.getSetting( "MaxHeight" );
+	if ( !val.empty() )
+		v.y = atof( val.c_str() );
+
+	val = config.getSetting( "PageWorldZ" );
+	if ( !val.empty() )
+		v.z = atof( val.c_str() );
+
+	// Scale x/z relative to pagesize
+	v.x /= mOptions.pageSize;
+	v.z /= mOptions.pageSize;
+	setScale(v);
+
+	val = config.getSetting( "MaxPixelError" );
+	if ( !val.empty() )
+		setMaxPixelError(atoi( val.c_str() ));
+
+	mDetailTextureName = config.getSetting( "DetailTexture" );
+
+	mWorldTextureName = config.getSetting( "WorldTexture" );
+
+	if ( config.getSetting( "VertexColours" ) == "yes" )
+		mOptions.coloured = true;
+
+	if ( config.getSetting( "VertexNormals" ) == "yes" )
+		mOptions.lit = true;
+
+	if ( config.getSetting( "UseTriStrips" ) == "yes" )
+		setUseTriStrips(true);
+
+	if ( config.getSetting( "VertexProgramMorph" ) == "yes" )
+		setUseLODMorph(true);
+
+	val = config.getSetting( "LODMorphStart");
+	if ( !val.empty() )
+		setLODMorphStart(atof(val.c_str()));
+
+	val = config.getSetting( "CustomMaterialName" );
+	if ( !val.empty() )
+		setCustomMaterial(val);
+
+	val = config.getSetting( "MorphLODFactorParamName" );
+	if ( !val.empty() )
+		setCustomMaterialMorphFactorParam(val);
+
+	val = config.getSetting( "MorphLODFactorParamIndex" );
+	if ( !val.empty() )
+		setCustomMaterialMorphFactorParam(atoi(val.c_str()));
+
+	// Now scan through the remaining settings, looking for any PageSource
+	// prefixed items
+	String pageSourceName = config.getSetting("PageSource");
+	if (pageSourceName == "")
+	{
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSource'",
+			"TerrainSceneManager::loadConfig");
+	}
+	KdTerrainPageSourceOptionList optlist;
+	ConfigFile::SettingsIterator setIt = config.getSettingsIterator();
+	while (setIt.hasMoreElements())
+	{
+		String name = setIt.peekNextKey();
+		String value = setIt.getNext();
+		if (StringUtil::startsWith(name, pageSourceName, false))
+		{
+			optlist.push_back(KdTerrainPageSourceOption(name, value));
+		}
+	}
+	// set the page source
+	selectPageSource(pageSourceName, optlist);
+
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setupTerrainMaterial(void)
+{
+	if (mCustomMaterialName == "")
+	{
+		// define our own material
+		mOptions.terrainMaterial = 
+			MaterialManager::getSingleton().getByName(TERRAIN_MATERIAL_NAME);
+		if (mOptions.terrainMaterial.isNull())
+		{
+			// Make unique terrain material name
+			StringUtil::StrStreamType s;
+			s << mName << "/Terrain";
+			mOptions.terrainMaterial = MaterialManager::getSingleton().create(
+				s.str(),
+				ResourceGroupManager::getSingleton().getWorldResourceGroupName());
+
+		}
+		else
+		{
+			mOptions.terrainMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
+		}
+
+		Pass* pass = mOptions.terrainMaterial->getTechnique(0)->getPass(0);
+
+		if ( mWorldTextureName != "" )
+		{
+			pass->createTextureUnitState( mWorldTextureName, 0 );
+		}
+		if ( mDetailTextureName != "" )
+		{
+			pass->createTextureUnitState( mDetailTextureName, 1 );
+		}
+
+		mOptions.terrainMaterial -> setLightingEnabled( mOptions.lit );
+
+		if (mOptions.lodMorph && 
+			mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM) &&
+			GpuProgramManager::getSingleton().getByName("Terrain/VertexMorph").isNull())
+		{
+			// Create & assign LOD morphing vertex program
+			String syntax;
+			if (GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1"))
+			{
+				syntax = "arbvp1";
+			}
+			else
+			{
+				syntax = "vs_1_1";
+			}
+
+			// Get source, and take into account current fog mode
+			FogMode fm = getFogMode();
+			const String& source = KdTerrainVertexProgram::getProgramSource(
+				fm, syntax);
+
+			GpuProgramPtr prog = GpuProgramManager::getSingleton().createProgramFromString(
+				"Terrain/VertexMorph", ResourceGroupManager::getSingleton().getWorldResourceGroupName(), 
+				source, GPT_VERTEX_PROGRAM, syntax);
+
+			// Attach
+			pass->setVertexProgram("Terrain/VertexMorph");
+
+			// Get params
+			GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
+
+			// worldviewproj
+			params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+			// morph factor
+			params->setAutoConstant(4, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
+			// fog exp density(if relevant)
+			if (fm == FOG_EXP || fm == FOG_EXP2)
+			{
+				params->setConstant(5, Vector3(getFogDensity(), 0, 0));
+				// Override scene fog since otherwise it's applied twice
+				// Set to linear and we derive [0,1] fog value in the shader
+				pass->setFog(true, FOG_LINEAR, getFogColour(), 0, 1, 0);
+			}
+
+			// Also set shadow receiver program
+			const String& source2 = KdTerrainVertexProgram::getProgramSource(
+				fm, syntax, true);
+
+			prog = GpuProgramManager::getSingleton().createProgramFromString(
+				"Terrain/VertexMorphShadowReceive", 
+				ResourceGroupManager::getSingleton().getWorldResourceGroupName(), 
+				source2, GPT_VERTEX_PROGRAM, syntax);
+			pass->setShadowReceiverVertexProgram("Terrain/VertexMorphShadowReceive");
+			params = pass->getShadowReceiverVertexProgramParameters();
+			// worldviewproj
+			params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+			// world
+			params->setAutoConstant(4, GpuProgramParameters::ACT_WORLD_MATRIX);
+			// texture view / proj
+			params->setAutoConstant(8, GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX);
+			// morph factor
+			params->setAutoConstant(12, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
+
+
+			// Set param index
+			mLodMorphParamName = "";
+			mLodMorphParamIndex = 4;
+		}
+
+		mOptions.terrainMaterial->load();
+
+	}
+	else
+	{
+		// Custom material
+		mOptions.terrainMaterial = 
+			MaterialManager::getSingleton().getByName(mCustomMaterialName);
+		mOptions.terrainMaterial->load();
+
+	}
+
+	// now set up the linkage between vertex program and LOD morph param
+	if (mOptions.lodMorph)
+	{
+		Technique* t = mOptions.terrainMaterial->getBestTechnique();
+		for (ushort i = 0; i < t->getNumPasses(); ++i)
+		{
+			Pass* p = t->getPass(i);
+			if (p->hasVertexProgram())
+			{
+				// we have to assume vertex program includes LOD morph capability
+				GpuProgramParametersSharedPtr params = 
+					p->getVertexProgramParameters();
+				// Check to see if custom param is already there
+				GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
+				bool found = false;
+				while (aci.hasMoreElements())
+				{
+					const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
+					if (ace.paramType == GpuProgramParameters::ACT_CUSTOM && 
+						ace.data == MORPH_CUSTOM_PARAM_ID)
+					{
+						found = true;
+					}
+				}
+				if (!found)
+				{
+					if(mLodMorphParamName != "")
+					{
+						params->setNamedAutoConstant(mLodMorphParamName, 
+							GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
+					}
+					else
+					{
+						params->setAutoConstant(mLodMorphParamIndex, 
+							GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
+					}
+				}
+
+			}
+		}
+	}
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setupTerrainPages(void)
+{
+
+	//create a root terrain node.
+	if (!mTerrainRoot)
+		mTerrainRoot = getRootSceneNode() -> createChildSceneNode( "Terrain" );
+
+	//setup the page array.
+	unsigned short pageSlots = 1 + (mBufferedPageMargin * 2);
+	unsigned short i, j;
+	for (i = 0; i < pageSlots; ++i)
+	{
+		mTerrainPages.push_back(KdTerrainPageRow());
+		for (j = 0; j < pageSlots; ++j)
+		{
+			mTerrainPages[i].push_back(0);
+		}
+	}
+
+	// If we're not paging, load immediate for convenience
+	if ( mActivePageSource && !mPagingEnabled )
+		mActivePageSource->requestPage(0,0);
+
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setWorldGeometry( const String& filename )
+{
+	// try to open in the current folder first
+	std::ifstream fs;
+	fs.open(filename.c_str());
+	if (fs)
+	{
+		// Wrap as a stream
+		DataStreamPtr stream(
+			new FileStreamDataStream(filename, &fs, false));
+		setWorldGeometry(stream);
+	}
+	else
+	{
+		// otherwise try resource system
+		DataStreamPtr stream = 
+			ResourceGroupManager::getSingleton().openResource(filename, 
+			ResourceGroupManager::getSingleton().getWorldResourceGroupName());
+
+		setWorldGeometry(stream);
+	}
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setWorldGeometry(DataStreamPtr& stream, const String& typeName )
+{
+	// Clear out any existing world resources (if not default)
+	if (ResourceGroupManager::getSingleton().getWorldResourceGroupName() != 
+		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
+	{
+		ResourceGroupManager::getSingleton().clearResourceGroup(
+			ResourceGroupManager::getSingleton().getWorldResourceGroupName());
+	}
+	destroyLevelIndexes();
+	mTerrainPages.clear();
+	// Load the configuration
+	loadConfig(stream);
+	initLevelIndexes();
+
+	// Resize the octree, allow for 1 page for now
+	//float max_x = mOptions.scale.x * mOptions.pageSize;
+	//float max_y = mOptions.scale.y;
+	//float max_z = mOptions.scale.z * mOptions.pageSize;
+	//resize( AxisAlignedBox( 0, 0, 0, max_x, max_y, max_z ) );
+
+	setupTerrainMaterial();
+
+	setupTerrainPages();
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::attachPage(ushort pageX, ushort pageZ, KdTerrainPage* page)
+{
+	assert(pageX == 0 && pageZ == 0 && "Multiple pages not yet supported");
+
+	assert(mTerrainPages[pageX][pageZ] == 0 && "Page at that index not yet expired!");
+	// Insert page into list
+	mTerrainPages[pageX][pageZ] = page;
+	// Attach page to terrain root
+	mTerrainRoot->addChild(page->pageSceneNode);
+
+}
+//-------------------------------------------------------------------------
+float KdTerrainSceneManager::getHeightAt( float x, float z )
+{
+
+
+	Vector3 pt( x, 0, z );
+
+	KdTerrainRenderable * t = getTerrainTile( pt );
+
+	if ( t == 0 )
+	{
+		//  printf( "No tile found for point\n" );
+		return -1;
+	}
+
+	float h = t -> getHeightAt( x, z );
+
+	// printf( "Height is %f\n", h );
+	return h;
+
+}
+//-------------------------------------------------------------------------
+KdTerrainPage* KdTerrainSceneManager::getTerrainPage( const Vector3 & pt )
+{
+	if (mPagingEnabled)
+	{
+		// TODO
+		return 0;
+	}
+	else
+	{
+		// Single page
+		if (mTerrainPages.empty() || mTerrainPages[0].empty())
+			return 0;
+		return mTerrainPages[0][0];
+	}
+}
+//-------------------------------------------------------------------------
+KdTerrainRenderable * KdTerrainSceneManager::getTerrainTile( const Vector3 & pt )
+{
+	KdTerrainPage* tp = getTerrainPage(pt);
+	if (!tp)
+		return NULL;
+	else
+		return tp->getTerrainTile(pt);
+}
+//-------------------------------------------------------------------------
+bool KdTerrainSceneManager::intersectSegment( const Vector3 & start, 
+										  const Vector3 & end, Vector3 * result )
+{
+	KdTerrainRenderable * t = getTerrainTile( start );
+
+	if ( t == 0 )
+	{
+		*result = Vector3( -1, -1, -1 );
+		return false;
+	}
+
+	return t -> intersectSegment( start, end, result );
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setUseTriStrips(bool useStrips)
+{
+	mOptions.useTriStrips = useStrips;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setUseLODMorph(bool morph)
+{
+	// Set true only if vertex programs are supported
+	mOptions.lodMorph = morph && 
+		mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM);
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setUseVertexNormals(bool useNormals)
+{
+	mOptions.lit = useNormals;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setUseVertexColours(bool useColours)
+{
+	mOptions.coloured = useColours;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setWorldTexture(const String& textureName)
+{
+	mWorldTextureName = textureName;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setDetailTexture(const String& textureName)
+{
+	mDetailTextureName = textureName;
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setDetailTextureRepeat(int repeat)
+{
+	mOptions.detailTile = repeat;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setTileSize(int size) 
+{
+	mOptions.tileSize = size;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setPageSize(int size)
+{
+	mOptions.pageSize = size;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setMaxPixelError(int pixelError) 
+{
+	mOptions.maxPixelError = pixelError;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setScale(const Vector3& scale)
+{
+	mOptions.scale = scale;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setMaxGeoMipMapLevel(int maxMip)
+{
+	mOptions.maxGeoMipMapLevel = maxMip;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setCustomMaterial(const String& materialName)
+{
+	mCustomMaterialName = materialName;
+	if (materialName != "")
+		mUseCustomMaterial = true;
+	else
+		mUseCustomMaterial = false;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setCustomMaterialMorphFactorParam(const String& paramName)
+{
+	mUseNamedParameterLodMorph = true;
+	mLodMorphParamName = paramName;
+
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setCustomMaterialMorphFactorParam(uint paramIndex)
+{
+	mUseNamedParameterLodMorph = false;
+	mLodMorphParamIndex = paramIndex;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setLODMorphStart(Real morphStart)
+{
+	mOptions.lodMorphStart = morphStart;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setPrimaryCamera(const Camera* cam)
+{
+	mOptions.primaryCamera = cam;
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::registerPageSource(const String& typeName, 
+											KdTerrainPageSource* source)
+{
+	std::pair<KdPageSourceMap::iterator, bool> retPair = 
+		mPageSources.insert(
+		KdPageSourceMap::value_type(typeName, source));
+	if (!retPair.second)
+	{
+		OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
+			"The page source " + typeName + " is already registered",
+			"TerrainSceneManager::registerPageSource");
+	}
+	LogManager::getSingleton().logMessage(
+		"TerrainSceneManager: Registered a new PageSource for "
+		"type " + typeName);
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::selectPageSource(const String& typeName, 
+										  KdTerrainPageSourceOptionList& optionList)
+{
+	KdPageSourceMap::iterator i = mPageSources.find(typeName);
+	if (i == mPageSources.end())
+	{
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+			"Cannot locate a TerrainPageSource for type " + typeName,
+			"TerrainSceneManager::selectPageSource");
+	}
+
+	if (mActivePageSource)
+	{
+		mActivePageSource->shutdown();
+	}
+	mActivePageSource = i->second;
+	mActivePageSource->initialise(this, mOptions.tileSize, mOptions.pageSize,
+		mPagingEnabled, optionList);
+
+	LogManager::getSingleton().logMessage(
+		"TerrainSceneManager: Activated PageSource " + typeName);
+
+}
+//-------------------------------------------------------------------------
+int KdTerrainSceneManager::getDetailTextureRepeat(void)
+{
+	return (int)mOptions.detailTile;
+}
+//-------------------------------------------------------------------------
+int KdTerrainSceneManager::getTileSize(void)
+{
+	return (int)mOptions.tileSize;
+}
+//-------------------------------------------------------------------------
+int KdTerrainSceneManager::getPageSize(void)
+{
+	return (int)mOptions.pageSize;
+}
+//-------------------------------------------------------------------------
+int KdTerrainSceneManager::getMaxPixelError(void)
+{
+	return (int)mOptions.maxPixelError;
+}
+//-------------------------------------------------------------------------
+const Vector3& KdTerrainSceneManager::getScale(void)
+{
+	return mOptions.scale;
+}
+//-------------------------------------------------------------------------
+int KdTerrainSceneManager::getMaxGeoMipMapLevel(void)
+{
+	return (int)mOptions.maxGeoMipMapLevel;
+}
+//-----------------------------------------------------------------------
+void KdTerrainSceneManager::initLevelIndexes()
+{
+	if ( mLevelIndex.size() == 0 )
+	{
+		for ( int i = 0; i < 16; i++ )
+		{
+
+			mLevelIndex.push_back( new IndexMap() );
+
+		}
+
+	}
+}
+//-----------------------------------------------------------------------
+void KdTerrainSceneManager::destroyLevelIndexes()
+{
+	for ( size_t i = 0; i < mLevelIndex.size(); i++ )
+	{
+		delete mLevelIndex[i];
+	}
+	mLevelIndex.clear();
+}
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+RaySceneQuery* 
+KdTerrainSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
+{
+	KdTerrainRaySceneQuery *trsq = new KdTerrainRaySceneQuery(this);
+	trsq->setRay(ray);
+	trsq->setQueryMask(mask);
+	return trsq;
+}
+//-------------------------------------------------------------------------
+KdTerrainRaySceneQuery::KdTerrainRaySceneQuery(SceneManager* creator)
+:DefaultRaySceneQuery(creator)
+{
+	mSupportedWorldFragments.insert(SceneQuery::WFT_SINGLE_INTERSECTION);
+}
+//-------------------------------------------------------------------------
+KdTerrainRaySceneQuery::~KdTerrainRaySceneQuery()
+{
+}
+//-------------------------------------------------------------------------
+void KdTerrainRaySceneQuery::execute(RaySceneQueryListener* listener)
+{
+	mWorldFrag.fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;
+
+	const Vector3& dir = mRay.getDirection();
+	const Vector3& origin = mRay.getOrigin();
+	// Straight up / down?
+	if (dir == Vector3::UNIT_Y || dir == Vector3::NEGATIVE_UNIT_Y)
+	{
+		Real height = static_cast<KdTerrainSceneManager*>(mParentSceneMgr)->getHeightAt(
+			origin.x, origin.z);
+		if (height != -1 && (height <= origin.y && dir.y < 0) || (height >= origin.y && dir.y > 0))
+		{
+			mWorldFrag.singleIntersection.x = origin.x;
+			mWorldFrag.singleIntersection.z = origin.z;
+			mWorldFrag.singleIntersection.y = height;
+			if (!listener->queryResult(&mWorldFrag, 
+				(mWorldFrag.singleIntersection - origin).length()))
+				return;
+		}
+	}
+	else
+	{
+		// Perform arbitrary query
+		if (static_cast<KdTerrainSceneManager*>(mParentSceneMgr)->intersectSegment(
+			origin, origin + (dir * 100000), &mWorldFrag.singleIntersection))
+		{
+			if (!listener->queryResult(&mWorldFrag, 
+				(mWorldFrag.singleIntersection - origin).length()))
+				return;
+		}
+	}
+	DefaultRaySceneQuery::execute(listener);
+}
+//-------------------------------------------------------------------------
+MaterialPtr& KdTerrainSceneManager::getTerrainMaterial(void)
+{
+	return mOptions.terrainMaterial;
+}
+//-------------------------------------------------------------------------
+KdTerrainSceneManager::KdPageSourceIterator KdTerrainSceneManager::getPageSourceIterator(void)
+{
+	return KdPageSourceIterator(mPageSources.begin(), mPageSources.end());
+}
+//-------------------------------------------------------------------------
+void KdTerrainSceneManager::setWorldGeometryRenderQueue(uint8 qid)
+{
+	for (KdTerrainPage2D::iterator pi = mTerrainPages.begin(); 
+		pi != mTerrainPages.end(); ++pi)
+	{
+		KdTerrainPageRow& row = *pi;
+		for (KdTerrainPageRow::iterator ri = row.begin(); ri != row.end(); ++ri)
+		{
+			KdTerrainPage* page = *ri;
+			if (page)
+			{
+				page->setRenderQueue(qid);
+			}
+		}
+	}
+
+}
+/************************************************************************/
+/* Factory for KdTreeTerrainSceneManager                                */
+/************************************************************************/
+//-----------------------------------------------------------------------
+const String KdTerrainSceneManagerFactory::FACTORY_TYPE_NAME = "KdTreeTerrainSceneManager";
+//-----------------------------------------------------------------------
+void KdTerrainSceneManagerFactory::initMetaData(void) const
+{
+	mMetaData.typeName = FACTORY_TYPE_NAME;
+	mMetaData.description = "Scene manager that organises the scene based on a kd-tree and renders terrain";
+	mMetaData.sceneTypeMask = 0xFFFF; // support all types of scenes (hopefully)
+	mMetaData.worldGeometrySupported = true;
+}
+//-----------------------------------------------------------------------
+KdTerrainSceneManagerFactory::
+KdTerrainSceneManagerFactory(GtpVisibility::VisibilityManager * vm)
+{
+	visManager = vm;
+}
+//-----------------------------------------------------------------------
+KdTerrainSceneManagerFactory::~KdTerrainSceneManagerFactory()
+{
+	for (KdTerrainPageSources::iterator i = mTerrainPageSources.begin();
+		i != mTerrainPageSources.end(); ++i)
+	{
+		delete *i;
+	}
+	mTerrainPageSources.clear();
+}
+//-----------------------------------------------------------------------
+SceneManager* KdTerrainSceneManagerFactory::createInstance(
+	const String& instanceName)
+{
+	KdTerrainSceneManager * sm = 
+		new KdTerrainSceneManager(instanceName, visManager);
+
+	KdHeightmapTerrainPageSource* ps = new KdHeightmapTerrainPageSource();
+	mTerrainPageSources.push_back(ps);
+	sm->registerPageSource("Heightmap", ps);
+
+	return sm;
+}
+//-----------------------------------------------------------------------
+void KdTerrainSceneManagerFactory::destroyInstance(SceneManager* instance)
+{
+	delete instance;
+}
+} // namespace Ogre
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPageSource.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPageSource.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPageSource.cpp	(revision 1273)
@@ -0,0 +1,177 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of the GameTools Project
+http://www.gametools.org
+
+Author: Martin Szydlowski
+-----------------------------------------------------------------------------
+*/
+
+#include <OgreSceneNode.h>
+#include "OgreKdTerrainPage.h"
+#include "OgreKdTerrainRenderable.h"
+#include "OgreKdTerrainPageSource.h"
+#include "OgreKdTerrainSceneManager.h"
+
+#pragma warning(disable : 4267)
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------
+    template<> KdTerrainPageSourceListenerManager* Singleton<KdTerrainPageSourceListenerManager>::ms_Singleton = 0;
+    KdTerrainPageSourceListenerManager* KdTerrainPageSourceListenerManager::getSingletonPtr(void)
+    {
+        return ms_Singleton;
+    }
+    KdTerrainPageSourceListenerManager& KdTerrainPageSourceListenerManager::getSingleton(void)
+    {  
+        assert( ms_Singleton );  return ( *ms_Singleton );  
+    }
+    //-------------------------------------------------------------------------
+	void KdTerrainPageSourceListenerManager::addListener(KdTerrainPageSourceListener* pl)
+	{
+        mPageSourceListeners.push_back(pl);
+	}
+    //-------------------------------------------------------------------------
+	void KdTerrainPageSourceListenerManager::removeListener(KdTerrainPageSourceListener* pl)
+	{
+        KdPageSourceListenerList::iterator i, iend;
+        iend = mPageSourceListeners.end();
+        for(i = mPageSourceListeners.begin(); i != iend; ++i)
+        {
+            if (*i == pl)
+            {
+                mPageSourceListeners.erase(i);
+                break;
+            }
+        }
+	}
+    //-------------------------------------------------------------------------
+	void KdTerrainPageSourceListenerManager::firePageConstructed(
+		KdTerrainSceneManager* sm, uint pagex, uint pagez, Real* heightData)
+	{
+        KdPageSourceListenerList::iterator i, iend;
+        iend = mPageSourceListeners.end();
+        for(i = mPageSourceListeners.begin(); i != iend; ++i)
+        {
+            (*i)->pageConstructed(sm, pagex, pagez, heightData);
+        }
+	}
+	//-------------------------------------------------------------------------
+	KdTerrainPageSource::KdTerrainPageSource() : mSceneManager(0), mAsyncLoading(false) {
+	}
+	//-------------------------------------------------------------------------
+	KdTerrainPage* KdTerrainPageSource::buildPage(Real* heightData, const MaterialPtr& pMaterial)
+    {
+        String name;
+
+        // Create a Terrain Page
+        KdTerrainPage* page = new KdTerrainPage((mPageSize-1) / (mTileSize-1));
+        // Create a node for all tiles to be attached to
+        // Note we sequentially name since page can be attached at different points
+        // so page x/z is not appropriate
+		StringUtil::StrStreamType page_str;
+		uint pageIndex = mSceneManager->_getPageCount();
+		page_str << pageIndex;
+        name = "page[";
+        name += page_str.str() + "]";
+        page->pageSceneNode = mSceneManager->createSceneNode(name);
+        
+        size_t q = 0;
+        for ( size_t j = 0; j < mPageSize - 1; j += ( mTileSize - 1 ) )
+        {
+            size_t p = 0;
+
+            for ( size_t i = 0; i < mPageSize - 1; i += ( mTileSize - 1 ) )
+            {
+				StringUtil::StrStreamType new_name_str;
+				
+                // Create scene node for the tile and the TerrainRenderable
+                new_name_str << "tile[" << pageIndex << "][" << (int)p << "," << (int)q << "]";
+				name = new_name_str.str();
+
+                SceneNode *c = page->pageSceneNode->createChildSceneNode( name );
+                KdTerrainRenderable *tile = new KdTerrainRenderable(name, mSceneManager);
+				// set queue
+				tile->setRenderQueueGroup(mSceneManager->getWorldGeometryRenderQueue());
+                // Initialise the tile
+                tile->setMaterial(pMaterial);
+                tile->initialise(i, j, heightData);
+                // Attach it to the page
+                page->tiles[ p ][ q ] = tile;
+                // Attach it to the node
+                c ->attachObject( tile );
+                p++;
+            }
+
+            q++;
+
+        }
+
+        pageIndex++;
+
+        // calculate neighbours for page
+        page->linkNeighbours();
+
+		if(mSceneManager->getOptions().lit)
+		{
+			q = 0;
+			for ( size_t j = 0; j < mPageSize - 1; j += ( mTileSize - 1 ) )
+			{
+				size_t p = 0;
+
+				for ( size_t i = 0; i < mPageSize - 1; i += ( mTileSize - 1 ) )
+				{
+					page->tiles[ p ][ q ]->_calculateNormals();
+					p++;
+				}
+				q++;
+			}
+		}
+
+        return page;
+    }
+    //-------------------------------------------------------------------------
+    void KdTerrainPageSource::firePageConstructed(size_t pagex, size_t pagez, Real* heightData)
+    {
+		KdTerrainPageSourceListenerManager::getSingleton().firePageConstructed(
+			mSceneManager, pagex, pagez, heightData);
+    }
+    //-------------------------------------------------------------------------
+    void KdTerrainPageSource::addListener(KdTerrainPageSourceListener* pl)
+    {
+		KdTerrainPageSourceListenerManager::getSingleton().addListener(pl);
+    }
+    //-------------------------------------------------------------------------
+    void KdTerrainPageSource::removeListener(KdTerrainPageSourceListener* pl)
+    {
+		KdTerrainPageSourceListenerManager::getSingleton().removeListener(pl);
+
+    }
+    //-------------------------------------------------------------------------
+
+}
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainRenderable.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainRenderable.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainRenderable.cpp	(revision 1273)
@@ -0,0 +1,1593 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+terrainrenderable.cpp  -  description
+-------------------
+begin                : Sat Oct 5 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+
+#include "OgreKdTerrainRenderable.h"
+#include "OgreSceneNode.h"
+#include "OgreRenderQueue.h"
+#include "OgreRenderOperation.h"
+#include "OgreCamera.h"
+#include "OgreRoot.h"
+#include "OgreKdTerrainSceneManager.h"
+#include "OgreLogManager.h"
+#include "OgreStringConverter.h"
+#include "OgreViewport.h"
+#include "OgreException.h"
+
+#pragma  warning(disable : 4267)
+
+namespace Ogre
+{
+    //-----------------------------------------------------------------------
+    #define MAIN_BINDING 0
+    #define DELTA_BINDING 1
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+    String KdTerrainRenderable::mType = "TerrainMipMap";
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	int KdTerrainRenderable::msCurrentRenderLevelIndex = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+    KdTerrainRenderable::KdTerrainRenderable(const String& name, KdTerrainSceneManager* tsm)
+        : Renderable(), MovableObject(name), mSceneManager(tsm), mTerrain(0), mDeltaBuffers(0), mPositionBuffer(0)
+    {
+        mForcedRenderLevel = -1;
+        mLastNextLevel = -1;
+
+        mMinLevelDistSqr = 0;
+
+        mInit = false;
+        mLightListDirty = true;
+		MovableObject::mCastShadows = false;
+
+        for ( int i = 0; i < 4; i++ )
+        {
+            mNeighbors[ i ] = 0;
+        }
+
+		mOptions = &(mSceneManager->getOptions());
+
+
+    }
+    //-----------------------------------------------------------------------
+    KdTerrainRenderable::~KdTerrainRenderable()
+    {
+
+        deleteGeometry();
+    }
+	//-----------------------------------------------------------------------
+	uint32 KdTerrainRenderable::getTypeFlags(void) const
+	{
+		// return world flag
+		return SceneManager::WORLD_GEOMETRY_TYPE_MASK;
+	}
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::deleteGeometry()
+    {
+        if(mTerrain)
+            delete mTerrain;
+
+        if (mPositionBuffer)
+            delete [] mPositionBuffer;
+
+        if (mDeltaBuffers)
+            delete [] mDeltaBuffers;
+
+        if ( mMinLevelDistSqr != 0 )
+            delete [] mMinLevelDistSqr;
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::initialise(int startx, int startz,  
+        Real* pageHeightData)
+    {
+
+        if ( mOptions->maxGeoMipMapLevel != 0 )
+        {
+            uint i = ( uint ) 1 << ( mOptions->maxGeoMipMapLevel - 1 ) ;
+
+            if ( ( i + 1 ) > mOptions->tileSize )
+            {
+                printf( "Invalid maximum mipmap specifed, must be n, such that 2^(n-1)+1 < tileSize \n" );
+                return ;
+            }
+        }
+
+        deleteGeometry();
+
+        //calculate min and max heights;
+        Real min = 256000, max = 0;
+
+        mTerrain = new VertexData;
+        mTerrain->vertexStart = 0;
+        mTerrain->vertexCount = mOptions->tileSize * mOptions->tileSize;
+
+        VertexDeclaration* decl = mTerrain->vertexDeclaration;
+        VertexBufferBinding* bind = mTerrain->vertexBufferBinding;
+
+        // positions
+        size_t offset = 0;
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
+        offset += VertexElement::getTypeSize(VET_FLOAT3);
+        if (mOptions->lit)
+        {
+            decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
+            offset += VertexElement::getTypeSize(VET_FLOAT3);
+        }
+        // texture coord sets
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
+        offset += VertexElement::getTypeSize(VET_FLOAT2);
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
+        offset += VertexElement::getTypeSize(VET_FLOAT2);
+        if (mOptions->coloured)
+        {
+            decl->addElement(MAIN_BINDING, offset, VET_COLOUR, VES_DIFFUSE);
+            offset += VertexElement::getTypeSize(VET_COLOUR);
+        }
+
+        // Create shared vertex buffer
+        mMainBuffer =
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+            decl->getVertexSize(MAIN_BINDING),
+            mTerrain->vertexCount, 
+            HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+        // Create system memory copy with just positions in it, for use in simple reads
+        mPositionBuffer = new float[mTerrain->vertexCount * 3];
+
+        bind->setBinding(MAIN_BINDING, mMainBuffer);
+
+        if (mOptions->lodMorph)
+        {
+            // Create additional element for delta
+            decl->addElement(DELTA_BINDING, 0, VET_FLOAT1, VES_BLEND_WEIGHTS);
+            // NB binding is not set here, it is set when deriving the LOD
+        }
+
+
+        mInit = true;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		for (int i = 0; i < MAX_RENDERLEVEL_INDEX; ++i )
+		{
+			mRenderLevel[i] = 1;
+		}
+#else
+		mRenderLevel = 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        mMinLevelDistSqr = new Real[ mOptions->maxGeoMipMapLevel ];
+
+        int endx = startx + mOptions->tileSize;
+
+        int endz = startz + mOptions->tileSize;
+
+        Vector3 left, down, here;
+
+        const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION);
+        const VertexElement* texelem0 = decl->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
+        const VertexElement* texelem1 = decl->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
+        float* pSysPos = mPositionBuffer;
+
+        unsigned char* pBase = static_cast<unsigned char*>(mMainBuffer->lock(HardwareBuffer::HBL_DISCARD));
+
+        for ( int j = startz; j < endz; j++ )
+        {
+            for ( int i = startx; i < endx; i++ )
+            {
+                float *pPos, *pTex0, *pTex1;
+                poselem->baseVertexPointerToElement(pBase, &pPos);
+                texelem0->baseVertexPointerToElement(pBase, &pTex0);
+                texelem1->baseVertexPointerToElement(pBase, &pTex1);
+    
+                Real height = pageHeightData[j * mOptions->pageSize + i];
+                height = height * mOptions->scale.y; // scale height 
+
+                *pSysPos++ = *pPos++ = ( float ) i * mOptions->scale.x; //x
+                *pSysPos++ = *pPos++ = height; // y
+                *pSysPos++ = *pPos++ = ( float ) j * mOptions->scale.z; //z
+
+                *pTex0++ = ( float ) i / ( float ) ( mOptions->pageSize - 1 );
+                *pTex0++ = ( float ) j / ( float ) ( mOptions->pageSize - 1 );
+
+                *pTex1++ = ( ( float ) i / ( float ) ( mOptions->tileSize - 1 ) ) * mOptions->detailTile;
+                *pTex1++ = ( ( float ) j / ( float ) ( mOptions->tileSize - 1 ) ) * mOptions->detailTile;
+
+                if ( height < min )
+                    min = ( Real ) height;
+
+                if ( height > max )
+                    max = ( Real ) height;
+
+                pBase += mMainBuffer->getVertexSize();
+            }
+        }
+
+        mMainBuffer->unlock();
+
+        mBounds.setExtents( 
+            ( Real ) startx * mOptions->scale.x, 
+            min, 
+            ( Real ) startz * mOptions->scale.z,
+            ( Real ) ( endx - 1 ) * mOptions->scale.x, 
+            max, 
+            ( Real ) ( endz - 1 ) * mOptions->scale.z );
+
+
+        mCenter = Vector3( ( startx * mOptions->scale.x + (endx - 1) * mOptions->scale.x ) / 2,
+            ( min + max ) / 2,
+            ( startz * mOptions->scale.z + (endz - 1) * mOptions->scale.z ) / 2 );
+
+        mBoundingRadius =
+            std::max(max - min,
+                std::max((endx - 1 - startx) * mOptions->scale.x,
+                         (endz - 1 - startz) * mOptions->scale.z)) / 2;
+
+        // Create delta buffer list if required to morph
+        if (mOptions->lodMorph)
+        {
+            // Create delta buffer for all except the lowest mip
+            mDeltaBuffers = new HardwareVertexBufferSharedPtr[mOptions->maxGeoMipMapLevel - 1];
+        }
+
+        Real C = _calculateCFactor();
+
+        _calculateMinLevelDist2( C );
+
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_getNormalAt( float x, float z, Vector3 * result )
+    {
+
+        assert(mOptions->lit && "No normals present");
+
+        Vector3 here, left, down;
+        here.x = x;
+        here.y = getHeightAt( x, z );
+        here.z = z;
+
+        left.x = x - 1;
+        left.y = getHeightAt( x - 1, z );
+        left.z = z;
+
+        down.x = x;
+        down.y = getHeightAt( x, z + 1 );
+        down.z = z + 1;
+
+        left = left - here;
+
+        down = down - here;
+
+        left.normalise();
+        down.normalise();
+
+        *result = left.crossProduct( down );
+        result -> normalise();
+
+        // result->x = - result->x;
+        // result->y = - result->y;
+        // result->z = - result->z;
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_calculateNormals()
+    {
+
+        Vector3 norm;
+
+        assert (mOptions->lit && "No normals present");
+
+        HardwareVertexBufferSharedPtr vbuf = 
+            mTerrain->vertexBufferBinding->getBuffer(MAIN_BINDING);
+        const VertexElement* elem = mTerrain->vertexDeclaration->findElementBySemantic(VES_NORMAL);
+        unsigned char* pBase = static_cast<unsigned char*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) );
+        float* pNorm;
+
+        for ( uint j = 0; j < mOptions->tileSize; j++ )
+        {
+            for ( uint i = 0; i < mOptions->tileSize; i++ )
+            {
+
+                _getNormalAt( _vertex( i, j, 0 ), _vertex( i, j, 2 ), &norm );
+
+                //  printf( "Normal = %5f,%5f,%5f\n", norm.x, norm.y, norm.z );
+                elem->baseVertexPointerToElement(pBase, &pNorm);
+                *pNorm++ = norm.x;
+                *pNorm++ = norm.y;
+                *pNorm++ = norm.z;
+                pBase += vbuf->getVertexSize();
+            }
+
+        }
+        vbuf->unlock();
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_notifyCurrentCamera( Camera* cam )
+    {
+		MovableObject::_notifyCurrentCamera(cam);
+
+        if ( mForcedRenderLevel >= 0 )
+        {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            mRenderLevel[msCurrentRenderLevelIndex] = mForcedRenderLevel;
+#else
+			mRenderLevel = mForcedRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+            return ;
+        }
+
+
+        Vector3 cpos = cam -> getDerivedPosition();
+        const AxisAlignedBox& aabb = getWorldBoundingBox(true);
+        Vector3 diff(0, 0, 0);
+        diff.makeFloor(cpos - aabb.getMinimum());
+        diff.makeCeil(cpos - aabb.getMaximum());
+
+        Real L = diff.squaredLength();
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        mRenderLevel[msCurrentRenderLevelIndex] = -1;;
+#else
+		mRenderLevel = -1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+
+        for ( uint i = 0; i < mOptions->maxGeoMipMapLevel; i++ )
+        {
+            if ( mMinLevelDistSqr[ i ] > L )
+            {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+                mRenderLevel[msCurrentRenderLevelIndex] = i - 1;
+#else
+				mRenderLevel = i - 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+                break;
+            }
+        }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        if ( getRenderLevel() < 0 )
+            mRenderLevel[msCurrentRenderLevelIndex] = mOptions->maxGeoMipMapLevel - 1;
+#else
+		if ( mRenderLevel < 0 )
+            mRenderLevel = mOptions->maxGeoMipMapLevel - 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        if (mOptions->lodMorph)
+        {
+            // Get the next LOD level down
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            int nextLevel = mNextLevelDown[getRenderLevel()];
+#else
+			int nextLevel = mNextLevelDown[mRenderLevel];
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+            if (nextLevel == 0)
+            {
+                // No next level, so never morph
+                mLODMorphFactor = 0;
+            }
+            else
+            {
+                // Set the morph such that the morph happens in the last 0.25 of
+                // the distance range
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+				Real range = mMinLevelDistSqr[nextLevel] - mMinLevelDistSqr[getRenderLevel()];
+#else
+                Real range = mMinLevelDistSqr[nextLevel] - mMinLevelDistSqr[mRenderLevel];
+#endif // GTP_VISIBILITY_MODIFIED_OGRE   
+                if (range)
+                {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+					Real percent = (L - mMinLevelDistSqr[getRenderLevel()]) / range;
+#else
+                    Real percent = (L - mMinLevelDistSqr[mRenderLevel]) / range;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+                    // scale result so that msLODMorphStart == 0, 1 == 1, clamp to 0 below that
+                    Real rescale = 1.0f / (1.0f - mOptions->lodMorphStart);
+                    mLODMorphFactor = std::max((percent - mOptions->lodMorphStart) * rescale, 
+						static_cast<Real>(0.0));
+                }
+                else
+                {
+                    // Identical ranges
+                    mLODMorphFactor = 0.0f;
+                }
+
+                assert(mLODMorphFactor >= 0 && mLODMorphFactor <= 1);
+            }
+
+            // Bind the correct delta buffer if it has changed
+            // nextLevel - 1 since the first entry is for LOD 1 (since LOD 0 never needs it)
+            if (mLastNextLevel != nextLevel)
+            {
+                if (nextLevel > 0)
+                {
+                    mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, 
+                        mDeltaBuffers[nextLevel - 1]);
+                }
+                else
+                {
+                    // bind dummy (incase bindings checked)
+                    mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, 
+                        mDeltaBuffers[0]);
+                }
+            }
+            mLastNextLevel = nextLevel;
+
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_updateRenderQueue( RenderQueue* queue )
+    {
+        // Notify need to calculate light list when our sending to render queue
+        mLightListDirty = true;
+
+        queue->addRenderable( this );
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::getRenderOperation( RenderOperation& op )
+    {
+        //setup indexes for vertices and uvs...
+
+        assert( mInit && "Uninitialized" );
+
+        op.useIndexes = true;
+        op.operationType = mOptions->useTriStrips ? 
+            RenderOperation::OT_TRIANGLE_STRIP : RenderOperation::OT_TRIANGLE_LIST;
+        op.vertexData = mTerrain;
+        op.indexData = getIndexData();
+
+
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::getWorldTransforms( Matrix4* xform ) const
+    {
+        *xform = mParentNode->_getFullTransform();
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& KdTerrainRenderable::getWorldOrientation(void) const
+    {
+        return mParentNode->_getDerivedOrientation();
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& KdTerrainRenderable::getWorldPosition(void) const
+    {
+        return mParentNode->_getDerivedPosition();
+    }
+    //-----------------------------------------------------------------------
+    bool KdTerrainRenderable::_checkSize( int n )
+    {
+        for ( int i = 0; i < 10; i++ )
+        {
+            if ( ( ( 1 << i ) + 1 ) == n )
+                return true;
+        }
+
+        return false;
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_calculateMinLevelDist2( Real C )
+    {
+        //level 0 has no delta.
+        mMinLevelDistSqr[ 0 ] = 0;
+
+        int i, j;
+
+        for ( int level = 1; level < mOptions->maxGeoMipMapLevel; level++ )
+        {
+            mMinLevelDistSqr[ level ] = 0;
+
+            int step = 1 << level;
+            // The step of the next higher LOD
+            int higherstep = step >> 1;
+
+            float* pDeltas = 0;
+            if (mOptions->lodMorph)
+            {
+                // Create a set of delta values (store at index - 1 since 0 has none)
+                mDeltaBuffers[level - 1]  = createDeltaBuffer();
+                // Lock, but don't discard (we want the pre-initialised zeros)
+                pDeltas = static_cast<float*>(
+                    mDeltaBuffers[level - 1]->lock(HardwareBuffer::HBL_NORMAL));
+            }
+
+            for ( j = 0; j < mOptions->tileSize - step; j += step )
+            {
+                for ( i = 0; i < mOptions->tileSize - step; i += step )
+                {
+                    /* Form planes relating to the lower detail tris to be produced
+                    For tri lists and even tri strip rows, they are this shape:
+                    x---x
+                    | / |
+                    x---x
+                    For odd tri strip rows, they are this shape:
+                    x---x
+                    | \ |
+                    x---x
+                    */
+
+                    Vector3 v1(_vertex( i, j, 0 ), _vertex( i, j, 1 ), _vertex( i, j, 2 ));
+                    Vector3 v2(_vertex( i + step, j, 0 ), _vertex( i + step, j, 1 ), _vertex( i + step, j, 2 ));
+                    Vector3 v3(_vertex( i, j + step, 0 ), _vertex( i, j + step, 1 ), _vertex( i, j + step, 2 ));
+                    Vector3 v4(_vertex( i + step, j + step, 0 ), _vertex( i + step, j + step, 1 ), _vertex( i + step, j + step, 2 ));
+
+                    Plane t1, t2;
+                    bool backwardTri = false;
+                    if (!mOptions->useTriStrips || j % 2 == 0)
+                    {
+                        t1.redefine(v1, v3, v2);
+                        t2.redefine(v2, v3, v4);
+                    }
+                    else
+                    {
+                        t1.redefine(v1, v3, v4);
+                        t2.redefine(v1, v4, v2);
+                        backwardTri = true;
+                    }
+
+                    // include the bottommost row of vertices if this is the last row
+                    int zubound = (j == (mOptions->tileSize - step)? step : step - 1);
+                    for ( int z = 0; z <= zubound; z++ )
+                    {
+                        // include the rightmost col of vertices if this is the last col
+                        int xubound = (i == (mOptions->tileSize - step)? step : step - 1);
+                        for ( int x = 0; x <= xubound; x++ )
+                        {
+                            int fulldetailx = i + x;
+                            int fulldetailz = j + z;
+                            if ( fulldetailx % step == 0 && 
+                                fulldetailz % step == 0 )
+                            {
+                                // Skip, this one is a vertex at this level
+                                continue;
+                            }
+
+                            Real zpct = (Real)z / (Real)step;
+                            Real xpct = (Real)x / (Real)step;
+
+                            //interpolated height
+                            Vector3 actualPos(
+                                _vertex( fulldetailx, fulldetailz, 0 ), 
+                                _vertex( fulldetailx, fulldetailz, 1 ), 
+                                _vertex( fulldetailx, fulldetailz, 2 ));
+                            Real interp_h;
+                            // Determine which tri we're on 
+                            if ((xpct + zpct <= 1.0f && !backwardTri) ||
+                                (xpct + (1-zpct) <= 1.0f && backwardTri))
+                            {
+                                // Solve for x/z
+                                interp_h = 
+                                    (-(t1.normal.x * actualPos.x)
+                                    - t1.normal.z * actualPos.z
+                                    - t1.d) / t1.normal.y;
+                            }
+                            else
+                            {
+                                // Second tri
+                                interp_h = 
+                                    (-(t2.normal.x * actualPos.x)
+                                    - t2.normal.z * actualPos.z
+                                    - t2.d) / t2.normal.y;
+                            }
+
+                            Real actual_h = _vertex( fulldetailx, fulldetailz, 1 );
+                            Real delta = fabs( interp_h - actual_h );
+
+                            Real D2 = delta * delta * C * C;
+
+                            if ( mMinLevelDistSqr[ level ] < D2 )
+                                mMinLevelDistSqr[ level ] = D2;
+
+                            // Should be save height difference?
+                            // Don't morph along edges
+                            if (mOptions->lodMorph && 
+                                fulldetailx != 0  && fulldetailx != (mOptions->tileSize - 1) && 
+                                fulldetailz != 0  && fulldetailz != (mOptions->tileSize - 1) )
+                            {
+                                // Save height difference 
+                                pDeltas[fulldetailx + (fulldetailz * mOptions->tileSize)] = 
+                                    interp_h - actual_h;
+                            }
+
+                        }
+
+                    }
+                }
+            }
+
+            // Unlock morph deltas if required
+            if (mOptions->lodMorph)
+            {
+                mDeltaBuffers[level - 1]->unlock();
+            }
+        }
+
+
+
+        // Post validate the whole set
+        for ( i = 1; i < mOptions->maxGeoMipMapLevel; i++ )
+        {
+
+            // Make sure no LOD transition within the tile
+            // This is especially a problem when using large tiles with flat areas
+            /* Hmm, this can look bad on some areas, disable for now
+            Vector3 delta(_vertex(0,0,0), mCenter.y, _vertex(0,0,2));
+            delta = delta - mCenter;
+            Real minDist = delta.squaredLength();
+            mMinLevelDistSqr[ i ] = std::max(mMinLevelDistSqr[ i ], minDist);
+            */
+
+            //make sure the levels are increasing...
+            if ( mMinLevelDistSqr[ i ] < mMinLevelDistSqr[ i - 1 ] )
+            {
+                mMinLevelDistSqr[ i ] = mMinLevelDistSqr[ i - 1 ];
+            }
+        }
+
+        // Now reverse traverse the list setting the 'next level down'
+        Real lastDist = -1;
+        int lastIndex = 0;
+        for (i = mOptions->maxGeoMipMapLevel - 1; i >= 0; --i)
+        {
+            if (i == mOptions->maxGeoMipMapLevel - 1)
+            {
+                // Last one is always 0
+                lastIndex = i;
+                lastDist = mMinLevelDistSqr[i];
+                mNextLevelDown[i] = 0;
+            }
+            else
+            {
+                mNextLevelDown[i] = lastIndex;
+                if (mMinLevelDistSqr[i] != lastDist)
+                {
+                    lastIndex = i;
+                    lastDist = mMinLevelDistSqr[i];
+                }
+            }
+
+        }
+
+
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_adjustRenderLevel( int i )
+    {
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        mRenderLevel[msCurrentRenderLevelIndex] = i;
+#else
+		mRenderLevel = i;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    }
+    //-----------------------------------------------------------------------
+    Real KdTerrainRenderable::_calculateCFactor()
+    {
+        Real A, T;
+
+        if (!mOptions->primaryCamera)
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+                "You have not created a camera yet!", 
+                "KdTerrainRenderable::_calculateCFactor");
+        }
+
+        //A = 1 / Math::Tan(Math::AngleUnitsToRadians(opts.primaryCamera->getFOVy()));
+        // Turn off detail compression at higher FOVs
+        A = 1.0f;
+
+        int vertRes = mOptions->primaryCamera->getViewport()->getActualHeight();
+
+        T = 2 * ( Real ) mOptions->maxPixelError / ( Real ) vertRes;
+
+        return A / T;
+    }
+    //-----------------------------------------------------------------------
+    float KdTerrainRenderable::getHeightAt( float x, float z )
+    {
+        Vector3 start;
+        Vector3 end;
+
+        start.x = _vertex( 0, 0, 0 );
+        start.y = _vertex( 0, 0, 1 );
+        start.z = _vertex( 0, 0, 2 );
+
+        end.x = _vertex( mOptions->tileSize - 1, mOptions->tileSize - 1, 0 );
+        end.y = _vertex( mOptions->tileSize - 1, mOptions->tileSize - 1, 1 );
+        end.z = _vertex( mOptions->tileSize - 1, mOptions->tileSize - 1, 2 );
+
+        /* Safety catch, if the point asked for is outside
+        * of this tile, it will ask the appropriate tile
+        */
+
+        if ( x < start.x )
+        {
+            if ( mNeighbors[ WEST ] != 0 )
+                return mNeighbors[ WEST ] ->getHeightAt( x, z );
+            else
+                x = start.x;
+        }
+
+        if ( x > end.x )
+        {
+            if ( mNeighbors[ EAST ] != 0 )
+                return mNeighbors[ EAST ] ->getHeightAt( x, z );
+            else
+                x = end.x;
+        }
+
+        if ( z < start.z )
+        {
+            if ( mNeighbors[ NORTH ] != 0 )
+                return mNeighbors[ NORTH ] ->getHeightAt( x, z );
+            else
+                z = start.z;
+        }
+
+        if ( z > end.z )
+        {
+            if ( mNeighbors[ SOUTH ] != 0 )
+                return mNeighbors[ SOUTH ] ->getHeightAt( x, z );
+            else
+                z = end.z;
+        }
+
+
+
+        float x_pct = ( x - start.x ) / ( end.x - start.x );
+        float z_pct = ( z - start.z ) / ( end.z - start.z );
+
+        float x_pt = x_pct * ( float ) ( mOptions->tileSize - 1 );
+        float z_pt = z_pct * ( float ) ( mOptions->tileSize - 1 );
+
+        int x_index = ( int ) x_pt;
+        int z_index = ( int ) z_pt;
+
+        // If we got to the far right / bottom edge, move one back
+        if (x_index == mOptions->tileSize - 1)
+        {
+            --x_index;
+            x_pct = 1.0f;
+        }
+        else
+        {
+            // get remainder
+            x_pct = x_pt - x_index;
+        }
+        if (z_index == mOptions->tileSize - 1)
+        {
+            --z_index;
+            z_pct = 1.0f;
+        }
+        else
+        {
+            z_pct = z_pt - z_index;
+        }
+
+        //bilinear interpolate to find the height.
+
+        float t1 = _vertex( x_index, z_index, 1 );
+        float t2 = _vertex( x_index + 1, z_index, 1 );
+        float b1 = _vertex( x_index, z_index + 1, 1 );
+        float b2 = _vertex( x_index + 1, z_index + 1, 1 );
+
+        float midpoint = (b1 + t2) / 2.0;
+
+        if (x_pct + z_pct <= 1) {
+            b2 = midpoint + (midpoint - t1);
+        } else {
+            t1 = midpoint + (midpoint - b2);
+        }
+
+        float t = ( t1 * ( 1 - x_pct ) ) + ( t2 * ( x_pct ) );
+        float b = ( b1 * ( 1 - x_pct ) ) + ( b2 * ( x_pct ) );
+
+        float h = ( t * ( 1 - z_pct ) ) + ( b * ( z_pct ) );
+
+        return h;
+    }
+    //-----------------------------------------------------------------------
+    bool KdTerrainRenderable::intersectSegment( const Vector3 & start, const Vector3 & end, Vector3 * result )
+    {
+        Vector3 dir = end - start;
+        Vector3 ray = start;
+
+        //special case...
+        if ( dir.x == 0 && dir.z == 0 )
+        {
+            if ( ray.y <= getHeightAt( ray.x, ray.z ) )
+            {
+                if ( result != 0 )
+                    * result = start;
+
+                return true;
+            }
+        }
+
+        dir.normalise();
+
+        //dir.x *= mScale.x;
+        //dir.y *= mScale.y;
+        //dir.z *= mScale.z;
+
+        const Vector3 * corners = getBoundingBox().getAllCorners();
+
+        //start with the next one...
+        ray += dir;
+
+
+        while ( ! ( ( ray.x < corners[ 0 ].x ) ||
+            ( ray.x > corners[ 4 ].x ) ||
+            ( ray.z < corners[ 0 ].z ) ||
+            ( ray.z > corners[ 4 ].z ) ) )
+        {
+
+
+            float h = getHeightAt( ray.x, ray.z );
+
+            if ( ray.y <= h )
+            {
+                if ( result != 0 )
+                    * result = ray;
+
+                return true;
+            }
+
+            else
+            {
+                ray += dir;
+            }
+
+        }
+
+        if ( ray.x < corners[ 0 ].x && mNeighbors[ WEST ] != 0 )
+            return mNeighbors[ WEST ] ->intersectSegment( ray, end, result );
+        else if ( ray.z < corners[ 0 ].z && mNeighbors[ NORTH ] != 0 )
+            return mNeighbors[ NORTH ] ->intersectSegment( ray, end, result );
+        else if ( ray.x > corners[ 4 ].x && mNeighbors[ EAST ] != 0 )
+            return mNeighbors[ EAST ] ->intersectSegment( ray, end, result );
+        else if ( ray.z > corners[ 4 ].z && mNeighbors[ SOUTH ] != 0 )
+            return mNeighbors[ SOUTH ] ->intersectSegment( ray, end, result );
+        else
+        {
+            if ( result != 0 )
+                * result = Vector3( -1, -1, -1 );
+
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_generateVertexLighting( const Vector3 &sun, ColourValue ambient )
+    {
+
+        Vector3 pt;
+        Vector3 normal;
+        Vector3 light;
+
+        HardwareVertexBufferSharedPtr vbuf = 
+            mTerrain->vertexBufferBinding->getBuffer(MAIN_BINDING);
+        const VertexElement* elem = mTerrain->vertexDeclaration->findElementBySemantic(VES_DIFFUSE);
+        //for each point in the terrain, see if it's in the line of sight for the sun.
+        for ( size_t i = 0; i < mOptions->tileSize; i++ )
+        {
+            for ( size_t j = 0; j < mOptions->tileSize; j++ )
+            {
+                //  printf( "Checking %f,%f,%f ", pt.x, pt.y, pt.z );
+                pt.x = _vertex( i, j, 0 );
+                pt.y = _vertex( i, j, 1 );
+                pt.z = _vertex( i, j, 2 );
+
+                light = sun - pt;
+
+                light.normalise();
+
+                if ( ! intersectSegment( pt, sun, 0 ) )
+                {
+                    //
+                    _getNormalAt( _vertex( i, j, 0 ), _vertex( i, j, 2 ), &normal );
+
+                    float l = light.dotProduct( normal );
+
+                    ColourValue v;
+                    v.r = ambient.r + l;
+                    v.g = ambient.g + l;
+                    v.b = ambient.b + l;
+
+                    if ( v.r > 1 ) v.r = 1;
+
+                    if ( v.g > 1 ) v.g = 1;
+
+                    if ( v.b > 1 ) v.b = 1;
+
+                    if ( v.r < 0 ) v.r = 0;
+
+                    if ( v.g < 0 ) v.g = 0;
+
+                    if ( v.b < 0 ) v.b = 0;
+
+                    RGBA colour;
+                    Root::getSingleton().convertColourValue( v, &colour );
+                    vbuf->writeData(
+                        (_index( i, j ) * vbuf->getVertexSize()) + elem->getOffset(),
+                        sizeof(RGBA), &colour);
+                }
+
+                else
+                {
+                    RGBA colour;
+                    Root::getSingleton().convertColourValue( ambient, &colour );
+
+                    vbuf->writeData(
+                        (_index( i, j ) * vbuf->getVertexSize()) + elem->getOffset(), 
+                        sizeof(RGBA), &colour);
+                }
+
+            }
+
+        }
+
+        printf( "." );
+    }
+    //-----------------------------------------------------------------------
+    Real KdTerrainRenderable::getSquaredViewDepth(const Camera* cam) const
+    {
+        Vector3 diff = mCenter - cam->getDerivedPosition();
+        // Use squared length to avoid square root
+        return diff.squaredLength();
+    }
+
+    //-----------------------------------------------------------------------
+    const LightList& KdTerrainRenderable::getLights(void) const
+    {
+        if (mLightListDirty)
+        {
+            getParentSceneNode()->getCreator()->_populateLightList(
+                mCenter, this->getBoundingRadius(), mLightList);
+            mLightListDirty = false;
+        }
+        return mLightList;
+    }
+    //-----------------------------------------------------------------------
+    IndexData* KdTerrainRenderable::getIndexData(void)
+    {
+        unsigned int stitchFlags = 0;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        if ( mNeighbors[ EAST ] != 0 && mNeighbors[ EAST ] -> getRenderLevel() > getRenderLevel() )
+        {
+            stitchFlags |= STITCH_EAST;
+            stitchFlags |= 
+                (mNeighbors[ EAST ] -> getRenderLevel() - getRenderLevel()) << STITCH_EAST_SHIFT;
+        }
+
+        if ( mNeighbors[ WEST ] != 0 && mNeighbors[ WEST ] -> getRenderLevel() > getRenderLevel() )
+        {
+            stitchFlags |= STITCH_WEST;
+            stitchFlags |= 
+                (mNeighbors[ WEST ] -> getRenderLevel() - getRenderLevel()) << STITCH_WEST_SHIFT;
+        }
+
+        if ( mNeighbors[ NORTH ] != 0 && mNeighbors[ NORTH ] -> getRenderLevel() > getRenderLevel() )
+        {
+            stitchFlags |= STITCH_NORTH;
+            stitchFlags |= 
+                (mNeighbors[ NORTH ] -> getRenderLevel() - getRenderLevel()) << STITCH_NORTH_SHIFT;
+        }
+
+        if ( mNeighbors[ SOUTH ] != 0 && mNeighbors[ SOUTH ] -> getRenderLevel() > getRenderLevel() )
+        {
+            stitchFlags |= STITCH_SOUTH;
+            stitchFlags |= 
+                (mNeighbors[ SOUTH ] -> getRenderLevel() - getRenderLevel()) << STITCH_SOUTH_SHIFT;
+        }
+#else
+         if ( mNeighbors[ EAST ] != 0 && mNeighbors[ EAST ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_EAST;
+            stitchFlags |= 
+                (mNeighbors[ EAST ] -> mRenderLevel - mRenderLevel) << STITCH_EAST_SHIFT;
+        }
+
+        if ( mNeighbors[ WEST ] != 0 && mNeighbors[ WEST ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_WEST;
+            stitchFlags |= 
+                (mNeighbors[ WEST ] -> mRenderLevel - mRenderLevel) << STITCH_WEST_SHIFT;
+        }
+
+        if ( mNeighbors[ NORTH ] != 0 && mNeighbors[ NORTH ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_NORTH;
+            stitchFlags |= 
+                (mNeighbors[ NORTH ] -> mRenderLevel - mRenderLevel) << STITCH_NORTH_SHIFT;
+        }
+
+        if ( mNeighbors[ SOUTH ] != 0 && mNeighbors[ SOUTH ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_SOUTH;
+            stitchFlags |= 
+                (mNeighbors[ SOUTH ] -> mRenderLevel - mRenderLevel) << STITCH_SOUTH_SHIFT;
+        }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        // Check preexisting
+		LevelArray& levelIndex = mSceneManager->_getLevelIndex();
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		IndexMap::iterator ii = levelIndex[ getRenderLevel() ]->find( stitchFlags );
+#else
+        IndexMap::iterator ii = levelIndex[ mRenderLevel ]->find( stitchFlags );
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        IndexData* indexData;
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		if ( ii == levelIndex[ getRenderLevel() ]->end())
+#else
+		if ( ii == levelIndex[ mRenderLevel ]->end())
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        {
+            // Create
+            if (mOptions->useTriStrips)
+            {
+                indexData = generateTriStripIndexes(stitchFlags);
+            }
+            else
+            {
+                indexData = generateTriListIndexes(stitchFlags);
+            }
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            levelIndex[ getRenderLevel() ]->insert(
+                IndexMap::value_type(stitchFlags, indexData));
+#else
+            levelIndex[ mRenderLevel ]->insert(
+                IndexMap::value_type(stitchFlags, indexData));
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        else
+        {
+            indexData = ii->second;
+        }
+
+
+        return indexData;
+
+
+    }
+    //-----------------------------------------------------------------------
+    IndexData* KdTerrainRenderable::generateTriStripIndexes(unsigned int stitchFlags)
+    {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        // The step used for the current level
+        int step = 1 << getRenderLevel();
+        // The step used for the lower level
+        int lowstep = 1 << (getRenderLevel() + 1);
+#else
+        // The step used for the current level
+        int step = 1 << mRenderLevel;
+        // The step used for the lower level
+        int lowstep = 1 << (mRenderLevel + 1);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        int numIndexes = 0;
+
+        // Calculate the number of indexes required
+        // This is the number of 'cells' at this detail level x 2
+        // plus 3 degenerates to turn corners
+        int numTrisAcross = (((mOptions->tileSize-1) / step) * 2) + 3;
+        // Num indexes is number of tris + 2
+        int new_length = numTrisAcross * ((mOptions->tileSize-1) / step) + 2;
+        //this is the maximum for a level.  It wastes a little, but shouldn't be a problem.
+
+        IndexData* indexData = new IndexData;
+        indexData->indexBuffer = 
+            HardwareBufferManager::getSingleton().createIndexBuffer(
+            HardwareIndexBuffer::IT_16BIT,
+            new_length, HardwareBuffer::HBU_STATIC_WRITE_ONLY);//, false);
+
+        mSceneManager->_getIndexCache().mCache.push_back( indexData );
+
+        unsigned short* pIdx = static_cast<unsigned short*>(
+            indexData->indexBuffer->lock(0, 
+            indexData->indexBuffer->getSizeInBytes(), 
+            HardwareBuffer::HBL_DISCARD));
+
+        // Stripified mesh
+        for ( uint j = 0; j < mOptions->tileSize - 1; j += step )
+        {
+            uint i;
+            // Forward strip
+            // We just do the |/ here, final | done after
+            for ( i = 0; i < mOptions->tileSize - 1; i += step )
+            {
+                int x[4], y[4];
+                x[0] = x[1] = i;
+                x[2] = x[3] = i + step;
+                y[0] = y[2] = j;
+                y[1] = y[3] = j + step;
+
+                if (j == 0  && (stitchFlags & STITCH_NORTH))
+                {
+                    // North reduction means rounding x[0] and x[2]
+                    if (x[0] % lowstep != 0)
+                    {
+                        // Since we know we only drop down one level of LOD,
+                        // removing 1 step of higher LOD should return to lower
+                        x[0] -= step;
+                    }
+                    if (x[2] % lowstep != 0)
+                    {
+                        x[2] -= step;
+                    }
+                }
+
+                // Never get a south tiling on a forward strip (always finish on 
+                // a backward strip)
+
+                if (i == 0  && (stitchFlags & STITCH_WEST))
+                {
+                    // West reduction means rounding y[0] / y[1]
+                    if (y[0] % lowstep != 0)
+                    {
+                        y[0] -= step;
+                    }
+                    if (y[1] % lowstep != 0)
+                    {
+                        y[1] -= step;
+                    }
+                }
+                if (i == (mOptions->tileSize - 1 - step) && (stitchFlags & STITCH_EAST))
+                {
+                    // East tiling means rounding y[2] & y[3]
+                    if (y[2] % lowstep != 0)
+                    {
+                        y[2] -= step;
+                    }
+                    if (y[3] % lowstep != 0)
+                    {
+                        y[3] -= step;
+                    }
+                }
+
+                //triangles
+                if (i == 0)
+                {
+                    // Starter
+                    *pIdx++ = _index( x[0], y[0] ); numIndexes++;
+                }
+                *pIdx++ = _index( x[1], y[1] ); numIndexes++;
+                *pIdx++ = _index( x[2], y[2] ); numIndexes++;
+
+                if (i == mOptions->tileSize - 1 - step)
+                {
+                    // Emit extra index to finish row
+                    *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    if (j < mOptions->tileSize - 1 - step)
+                    {
+                        // Emit this index twice more (this is to turn around without
+                        // artefacts)
+                        // ** Hmm, looks like we can drop this and it's unnoticeable
+                        //*pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                        //*pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    }
+                }
+
+            }
+            // Increment row
+            j += step;
+            // Backward strip
+            for ( i = mOptions->tileSize - 1; i > 0 ; i -= step )
+            {
+                int x[4], y[4];
+                x[0] = x[1] = i;
+                x[2] = x[3] = i - step;
+                y[0] = y[2] = j;
+                y[1] = y[3] = j + step;
+
+                // Never get a north tiling on a backward strip (always
+                // start on a forward strip)
+                if (j == (mOptions->tileSize - 1 - step) && (stitchFlags & STITCH_SOUTH))
+                {
+                    // South reduction means rounding x[1] / x[3]
+                    if (x[1] % lowstep != 0)
+                    {
+                        x[1] -= step;
+                    }
+                    if (x[3] % lowstep != 0)
+                    {
+                        x[3] -= step;
+                    }
+                }
+
+                if (i == step  && (stitchFlags & STITCH_WEST))
+                {
+                    // West tiling on backward strip is rounding of y[2] / y[3]
+                    if (y[2] % lowstep != 0)
+                    {
+                        y[2] -= step;
+                    }
+                    if (y[3] % lowstep != 0)
+                    {
+                        y[3] -= step;
+                    }
+                }
+                if (i == mOptions->tileSize - 1 && (stitchFlags & STITCH_EAST))
+                {
+                    // East tiling means rounding y[0] and y[1] on backward strip
+                    if (y[0] % lowstep != 0)
+                    {
+                        y[0] -= step;
+                    }
+                    if (y[1] % lowstep != 0)
+                    {
+                        y[1] -= step;
+                    }
+                }
+
+                //triangles
+                if (i == mOptions->tileSize)
+                {
+                    // Starter
+                    *pIdx++ = _index( x[0], y[0] ); numIndexes++;
+                }
+                *pIdx++ = _index( x[1], y[1] ); numIndexes++;
+                *pIdx++ = _index( x[2], y[2] ); numIndexes++;
+
+                if (i == step)
+                {
+                    // Emit extra index to finish row
+                    *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    if (j < mOptions->tileSize - 1 - step)
+                    {
+                        // Emit this index once more (this is to turn around)
+                        *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    }
+                }
+            }
+        }
+
+
+        indexData->indexBuffer->unlock();
+        indexData->indexCount = numIndexes;
+        indexData->indexStart = 0;
+
+        return indexData;
+
+    }
+    //-----------------------------------------------------------------------
+    IndexData* KdTerrainRenderable::generateTriListIndexes(unsigned int stitchFlags)
+    {
+
+        int numIndexes = 0;
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		int step = 1 << getRenderLevel();
+#else
+        int step = 1 << mRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        IndexData* indexData = 0;
+
+        int north = stitchFlags & STITCH_NORTH ? step : 0;
+        int south = stitchFlags & STITCH_SOUTH ? step : 0;
+        int east = stitchFlags & STITCH_EAST ? step : 0;
+        int west = stitchFlags & STITCH_WEST ? step : 0;
+
+        int new_length = ( mOptions->tileSize / step ) * ( mOptions->tileSize / step ) * 2 * 2 * 2 ;
+        //this is the maximum for a level.  It wastes a little, but shouldn't be a problem.
+
+        indexData = new IndexData;
+        indexData->indexBuffer = 
+            HardwareBufferManager::getSingleton().createIndexBuffer(
+            HardwareIndexBuffer::IT_16BIT,
+            new_length, HardwareBuffer::HBU_STATIC_WRITE_ONLY);//, false);
+
+        mSceneManager->_getIndexCache().mCache.push_back( indexData );
+
+        unsigned short* pIdx = static_cast<unsigned short*>(
+            indexData->indexBuffer->lock(0, 
+            indexData->indexBuffer->getSizeInBytes(), 
+            HardwareBuffer::HBL_DISCARD));
+
+        // Do the core vertices, minus stitches
+        for ( uint j = north; j < mOptions->tileSize - 1 - south; j += step )
+        {
+            for ( uint i = west; i < mOptions->tileSize - 1 - east; i += step )
+            {
+                //triangles
+                *pIdx++ = _index( i, j ); numIndexes++;
+                *pIdx++ = _index( i, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j ); numIndexes++;
+
+                *pIdx++ = _index( i, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j ); numIndexes++;
+            }
+        }
+
+        // North stitching
+        if ( north > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(NORTH, getRenderLevel(), mNeighbors[NORTH]->getRenderLevel(),
+                west > 0, east > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(NORTH, mRenderLevel, mNeighbors[NORTH]->mRenderLevel,
+                west > 0, east > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        // East stitching
+        if ( east > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(EAST, getRenderLevel(), mNeighbors[EAST]->getRenderLevel(),
+                north > 0, south > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(EAST, mRenderLevel, mNeighbors[EAST]->mRenderLevel,
+                north > 0, south > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        // South stitching
+        if ( south > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(SOUTH, getRenderLevel(), mNeighbors[SOUTH]->getRenderLevel(),
+                east > 0, west > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(SOUTH, mRenderLevel, mNeighbors[SOUTH]->mRenderLevel,
+                east > 0, west > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		}
+        // West stitching
+        if ( west > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(WEST, getRenderLevel(), mNeighbors[WEST]->getRenderLevel(),
+                south > 0, north > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(WEST, mRenderLevel, mNeighbors[WEST]->mRenderLevel,
+                south > 0, north > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+
+
+        indexData->indexBuffer->unlock();
+        indexData->indexCount = numIndexes;
+        indexData->indexStart = 0;
+
+        return indexData;
+    }
+    //-----------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr KdTerrainRenderable::createDeltaBuffer(void)
+    {
+        // Delta buffer is a 1D float buffer of height offsets
+        HardwareVertexBufferSharedPtr buf = 
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+            VertexElement::getTypeSize(VET_FLOAT1), 
+            mOptions->tileSize * mOptions->tileSize,
+            HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+        // Fill the buffer with zeros, we will only fill in delta
+        void* pVoid = buf->lock(HardwareBuffer::HBL_DISCARD);
+        memset(pVoid, 0, mOptions->tileSize * mOptions->tileSize * sizeof(float));
+        buf->unlock();
+
+        return buf;
+
+    }
+    //-----------------------------------------------------------------------
+    void KdTerrainRenderable::_updateCustomGpuParameter(
+        const GpuProgramParameters::AutoConstantEntry& constantEntry, 
+        GpuProgramParameters* params) const
+    {
+        if (constantEntry.data == MORPH_CUSTOM_PARAM_ID)
+        {
+            // Update morph LOD factor
+            params->setConstant(constantEntry.index, mLODMorphFactor);
+        }
+        else
+        {
+            Renderable::_updateCustomGpuParameter(constantEntry, params);
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    int KdTerrainRenderable::stitchEdge(Neighbor neighbor, int hiLOD, int loLOD, 
+        bool omitFirstTri, bool omitLastTri, unsigned short** ppIdx)
+    {
+        assert(loLOD > hiLOD);
+        /* 
+        Now do the stitching; we can stitch from any level to any level.
+        The stitch pattern is like this for each pair of vertices in the lower LOD
+        (excuse the poor ascii art):
+
+        lower LOD
+        *-----------*
+        |\  \ 3 /  /|
+        |1\2 \ / 4/5|
+        *--*--*--*--*
+        higher LOD
+
+        The algorithm is, for each pair of lower LOD vertices:
+        1. Iterate over the higher LOD vertices, generating tris connected to the 
+        first lower LOD vertex, up to and including 1/2 the span of the lower LOD 
+        over the higher LOD (tris 1-2). Skip the first tri if it is on the edge 
+        of the tile and that edge is to be stitched itself.
+        2. Generate a single tri for the middle using the 2 lower LOD vertices and 
+        the middle vertex of the higher LOD (tri 3). 
+        3. Iterate over the higher LOD vertices from 1/2 the span of the lower LOD
+        to the end, generating tris connected to the second lower LOD vertex 
+        (tris 4-5). Skip the last tri if it is on the edge of a tile and that
+        edge is to be stitched itself.
+
+        The same algorithm works for all edges of the patch; stitching is done
+        clockwise so that the origin and steps used change, but the general
+        approach does not.
+        */
+
+        // Get pointer to be updated
+        unsigned short* pIdx = *ppIdx;
+
+        // Work out the steps ie how to increment indexes
+        // Step from one vertex to another in the high detail version
+        int step = 1 << hiLOD;
+        // Step from one vertex to another in the low detail version
+        int superstep = 1 << loLOD;
+        // Step half way between low detail steps
+        int halfsuperstep = superstep >> 1;
+
+        // Work out the starting points and sign of increments
+        // We always work the strip clockwise
+        int startx, starty, endx, rowstep;
+        bool horizontal;
+        switch(neighbor)
+        {
+        case NORTH:
+            startx = starty = 0;
+            endx = mOptions->tileSize - 1;
+            rowstep = step;
+            horizontal = true;
+            break;
+        case SOUTH:
+            // invert x AND y direction, helps to keep same winding
+            startx = starty = mOptions->tileSize - 1;
+            endx = 0;
+            rowstep = -step;
+            step = -step;
+            superstep = -superstep;
+            halfsuperstep = -halfsuperstep;
+            horizontal = true;
+            break;
+        case EAST:
+            startx = 0;
+            endx = mOptions->tileSize - 1;
+            starty = mOptions->tileSize - 1;
+            rowstep = -step;
+            horizontal = false;
+            break;
+        case WEST:
+            startx = mOptions->tileSize - 1;
+            endx = 0;
+            starty = 0;
+            rowstep = step;
+            step = -step;
+            superstep = -superstep;
+            halfsuperstep = -halfsuperstep;
+            horizontal = false;
+            break;
+        };
+
+        int numIndexes = 0;
+
+        for ( int j = startx; j != endx; j += superstep )
+        {
+            int k;
+            for (k = 0; k != halfsuperstep; k += step)
+            {
+                int jk = j + k;
+                //skip the first bit of the corner?
+                if ( j != startx || k != 0 || !omitFirstTri )
+                {
+                    if (horizontal)
+                    {
+                        *pIdx++ = _index( j , starty ); numIndexes++;
+                        *pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
+                        *pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
+                    }
+                    else
+                    {
+                        *pIdx++ = _index( starty, j ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk + step); numIndexes++;
+                    }
+                }
+            }
+
+            // Middle tri
+            if (horizontal)
+            {
+                *pIdx++ = _index( j, starty ); numIndexes++;
+                *pIdx++ = _index( j + halfsuperstep, starty + rowstep); numIndexes++;
+                *pIdx++ = _index( j + superstep, starty ); numIndexes++;
+            }
+            else
+            {
+                *pIdx++ = _index( starty, j ); numIndexes++;
+                *pIdx++ = _index( starty + rowstep, j + halfsuperstep ); numIndexes++;
+                *pIdx++ = _index( starty, j + superstep ); numIndexes++;
+            }
+
+            for (k = halfsuperstep; k != superstep; k += step)
+            {
+                int jk = j + k;
+                if ( j != endx - superstep || k != superstep - step || !omitLastTri )
+                {
+                    if (horizontal)
+                    {
+                        *pIdx++ = _index( j + superstep, starty ); numIndexes++;
+                        *pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
+                        *pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
+                    }
+                    else
+                    {
+                        *pIdx++ = _index( starty, j + superstep ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk + step ); numIndexes++;
+                    }
+                }
+            }
+        }
+
+        *ppIdx = pIdx;
+
+        return numIndexes;
+
+    }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//-----------------------------------------------------------------------
+	void KdTerrainRenderable::ResetRenderLevelIndex() 
+	{
+		msCurrentRenderLevelIndex = 0;
+	}
+	//-----------------------------------------------------------------------
+	void KdTerrainRenderable::NextRenderLevelIndex()
+	{
+		if ((++ msCurrentRenderLevelIndex) > MAX_RENDERLEVEL_INDEX)
+			msCurrentRenderLevelIndex = 0;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+} //namespace
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainVertexProgram.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainVertexProgram.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainVertexProgram.cpp	(revision 1273)
@@ -0,0 +1,342 @@
+
+/*
+-----------------------------------------------------------------------------
+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 "OgreKdTerrainVertexProgram.h"
+
+namespace Ogre {
+
+    String KdTerrainVertexProgram::mNoFogArbvp1 = 
+        "!!ARBvp1.0\n"
+        "PARAM c5 = { 1, 1, 1, 1 };\n"
+        "#var float4x4 worldViewProj :  : c[0], 4 : 8 : 1\n"
+        "#var float morphFactor :  : c[4] : 9 : 1\n"
+        "TEMP R0;\n"
+        "ATTRIB v17 = vertex.weight;\n"
+        "ATTRIB v25 = vertex.texcoord[1];\n"
+        "ATTRIB v24 = vertex.texcoord[0];\n"
+        "ATTRIB v16 = vertex.position;\n"
+        "PARAM c0[4] = { program.local[0..3] };\n"
+        "PARAM c4 = program.local[4];\n"
+        "	MOV result.texcoord[0], v24;\n"
+        "	MOV result.texcoord[1], v25;\n"
+        "	MOV R0, v16;\n"
+        "	MAD R0.y, v17.x, c4.x, R0.y;\n"
+        "	DP4 result.position.x, c0[0], R0;\n"
+        "	DP4 result.position.y, c0[1], R0;\n"
+        "	DP4 result.position.z, c0[2], R0;\n"
+        "	DP4 result.position.w, c0[3], R0;\n"
+        "	MOV result.color.front.primary, c5.x;\n"
+        "END\n";
+
+	String KdTerrainVertexProgram::mShadowReceiverArbvp1 = 
+		"!!ARBvp1.0\n"
+		"PARAM c[14] = { program.local[0..12], { 1 } };\n"
+		"TEMP R0;\n"
+		"TEMP R1;\n"
+		"TEMP R2;\n"
+		"MOV result.color, c[13].x;\n"
+		"MUL R0.x, vertex.weight, c[12];\n"
+		"ADD R1.y, R0.x, vertex.position;\n"
+		"MOV R1.xzw, vertex.position;\n"
+		"DP4 result.position.w, R1, c[3];\n"
+		"DP4 result.position.z, R1, c[2];\n"
+		"DP4 R0.w, R1, c[7];\n"
+		"DP4 R0.z, R1, c[6];\n"
+		"DP4 R0.y, R1, c[5];\n"
+		"DP4 R0.x, R1, c[4];\n"
+		"DP4 result.position.y, R1, c[1];\n"
+		"DP4 R2.y, R0, c[9];\n"
+		"DP4 R2.z, R0, c[11];\n"
+		"DP4 R2.x, R0, c[8];\n"
+		"RCP R0.x, R2.z;\n"
+		"DP4 result.position.x, R1, c[0];\n"
+		"MUL result.texcoord[0].xy, R2, R0.x;\n"
+		"END\n";
+    String KdTerrainVertexProgram::mLinearFogArbvp1 = 
+        "!!ARBvp1.0\n"
+        "PARAM c5 = { 1, 1, 1, 1 };\n"
+        "#var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "#var float morphFactor :  : c[4] : 10 : 1\n"
+        "TEMP R0, R1;\n"
+        "ATTRIB v17 = vertex.weight;\n"
+        "ATTRIB v25 = vertex.texcoord[1];\n"
+        "ATTRIB v24 = vertex.texcoord[0];\n"
+        "ATTRIB v16 = vertex.position;\n"
+        "PARAM c0[4] = { program.local[0..3] };\n"
+        "PARAM c4 = program.local[4];\n"
+        "	MOV result.texcoord[0], v24;\n"
+        "	MOV result.texcoord[1], v25;\n"
+        "	MOV R1, v16;\n"
+        "	MAD R1.y, v17.x, c4.x, R1.y;\n"
+        "	DP4 R0.x, c0[0], R1;\n"
+        "	DP4 R0.y, c0[1], R1;\n"
+        "	DP4 R0.z, c0[2], R1;\n"
+        "	DP4 R0.w, c0[3], R1;\n"
+        "	MOV result.fogcoord.x, R0.z;\n"
+        "	MOV result.position, R0;\n"
+        "	MOV result.color.front.primary, c5.x;\n"
+        "END\n";
+    String KdTerrainVertexProgram::mExpFogArbvp1 = 
+        "!!ARBvp1.0\n"
+        "PARAM c6 = { 1, 1, 1, 1 };\n"
+        "PARAM c7 = { 2.71828, 0, 0, 0 };\n"
+        "#var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "#var float morphFactor :  : c[4] : 10 : 1\n"
+        "#var float fogDensity :  : c[5] : 11 : 1\n"
+        "TEMP R0, R1;\n"
+        "ATTRIB v17 = vertex.weight;\n"
+        "ATTRIB v25 = vertex.texcoord[1];\n"
+        "ATTRIB v24 = vertex.texcoord[0];\n"
+        "ATTRIB v16 = vertex.position;\n"
+        "PARAM c5 = program.local[5];\n"
+        "PARAM c0[4] = { program.local[0..3] };\n"
+        "PARAM c4 = program.local[4];\n"
+        "	MOV result.texcoord[0], v24;\n"
+        "	MOV result.texcoord[1], v25;\n"
+        "	MOV R1, v16;\n"
+        "	MAD R1.y, v17.x, c4.x, R1.y;\n"
+        "	DP4 R0.x, c0[0], R1;\n"
+        "	DP4 R0.y, c0[1], R1;\n"
+        "	DP4 R0.z, c0[2], R1;\n"
+        "	DP4 R0.w, c0[3], R1;\n"
+        "	MOV result.position, R0;\n"
+        "	MOV result.color.front.primary, c6.x;\n"
+        "	MUL R0.zw, R0.z, c5.x;\n"
+        "	MOV R0.xy, c7.x;\n"
+        "	LIT R0.z, R0;\n"
+        "	RCP result.fogcoord.x, R0.z;\n"
+        "END\n";
+    String KdTerrainVertexProgram::mExp2FogArbvp1 = 
+        "!!ARBvp1.0\n"
+        "PARAM c6 = { 1, 1, 1, 1 };\n"
+        "PARAM c7 = { 0.002, 2.71828, 0, 0 };\n"
+        "#var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "#var float morphFactor :  : c[4] : 10 : 1\n"
+        "#var float fogDensity :  : c[5] : 11 : 1\n"
+        "TEMP R0, R1;\n"
+        "ATTRIB v17 = vertex.weight;\n"
+        "ATTRIB v25 = vertex.texcoord[1];\n"
+        "ATTRIB v24 = vertex.texcoord[0];\n"
+        "ATTRIB v16 = vertex.position;\n"
+        "PARAM c0[4] = { program.local[0..3] };\n"
+        "PARAM c4 = program.local[4];\n"
+        "	MOV result.texcoord[0], v24;\n"
+        "	MOV result.texcoord[1], v25;\n"
+        "	MOV R1, v16;\n"
+        "	MAD R1.y, v17.x, c4.x, R1.y;\n"
+        "	DP4 R0.x, c0[0], R1;\n"
+        "	DP4 R0.y, c0[1], R1;\n"
+        "	DP4 R0.z, c0[2], R1;\n"
+        "	DP4 R0.w, c0[3], R1;\n"
+        "	MOV result.position, R0;\n"
+        "	MOV result.color.front.primary, c6.x;\n"
+        "	MUL R0.x, R0.z, c7.x;\n"
+        "	MUL R0.zw, R0.x, R0.x;\n"
+        "	MOV R0.xy, c7.y;\n"
+        "	LIT R0.z, R0;\n"
+        "	RCP result.fogcoord.x, R0.z;\n"
+        "END\n";
+
+    String KdTerrainVertexProgram::mNoFogVs_1_1 = 
+        "vs_1_1\n"
+        "def c5, 1, 1, 1, 1\n"
+        "//var float4x4 worldViewProj :  : c[0], 4 : 8 : 1\n"
+        "//var float morphFactor :  : c[4] : 9 : 1\n"
+        "dcl_blendweight v1\n"
+        "dcl_texcoord1 v8\n"
+        "dcl_texcoord0 v7\n"
+        "dcl_position v0\n"
+        "	mov oT0.xy, v7\n"
+        "	mov oT1.xy, v8\n"
+        "	mov r0, v0\n"
+        "	mad r0.y, v1.x, c4.x, r0.y\n"
+        "	dp4 oPos.x, c0, r0\n"
+        "	dp4 oPos.y, c1, r0\n"
+        "	dp4 oPos.z, c2, r0\n"
+        "	dp4 oPos.w, c3, r0\n"
+        "	mov oD0, c5.x\n";
+    String KdTerrainVertexProgram::mLinearFogVs_1_1 = 
+        "vs_1_1\n"
+        "def c5, 1, 1, 1, 1\n"
+        "//var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "//var float morphFactor :  : c[4] : 10 : 1\n"
+        "dcl_blendweight v1\n"
+        "dcl_texcoord1 v8\n"
+        "dcl_texcoord0 v7\n"
+        "dcl_position v0\n"
+        "	mov oT0.xy, v7\n"
+        "	mov oT1.xy, v8\n"
+        "	mov r1, v0\n"
+        "	mad r1.y, v1.x, c4.x, r1.y\n"
+        "	dp4 r0.x, c0, r1\n"
+        "	dp4 r0.y, c1, r1\n"
+        "	dp4 r0.z, c2, r1\n"
+        "	dp4 r0.w, c3, r1\n"
+        "	mov oFog, r0.z\n"
+        "	mov oPos, r0\n"
+        "	mov oD0, c5.x\n";
+
+	String KdTerrainVertexProgram::mShadowReceiverVs_1_1 = 
+		"vs_1_1\n"
+		"def c13, 1, 1, 1, 1\n"
+		"dcl_blendweight v1\n"
+		"dcl_texcoord1 v8\n"
+		"dcl_texcoord0 v7\n"
+		"dcl_position v0\n"
+		"mov r1, v0\n"
+		"mad r1.y, v1.x, c12.x, r1.y\n"
+		"dp4 oPos.x, c0, r1\n"
+		"dp4 oPos.y, c1, r1\n"
+		"dp4 oPos.z, c2, r1\n"
+		"dp4 oPos.w, c3, r1\n"
+		"dp4 r0.x, c4, r1\n"
+		"dp4 r0.y, c5, r1\n"
+		"dp4 r0.z, c6, r1\n"
+		"dp4 r0.w, c7, r1\n"
+		"dp4 r1.x, c8, r0\n"
+		"dp4 r1.y, c9, r0\n"
+		"dp4 r1.w, c11, r0\n"
+		"rcp r0.x, r1.w\n"
+		"mul oT0.xy, r1.xy, r0.x\n"
+		"mov oD0, c13\n";
+	String KdTerrainVertexProgram::mExpFogVs_1_1 = 
+        "vs_1_1\n"
+        "def c6, 1, 1, 1, 1\n"
+        "def c7, 2.71828, 0, 0, 0\n"
+        "//var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "//var float morphFactor :  : c[4] : 10 : 1\n"
+        "//var float fogDensity :  : c[5] : 11 : 1\n"
+        "dcl_blendweight v1\n"
+        "dcl_texcoord1 v8\n"
+        "dcl_texcoord0 v7\n"
+        "dcl_position v0\n"
+        "	mov oT0.xy, v7\n"
+        "	mov oT1.xy, v8\n"
+        "	mov r1, v0\n"
+        "	mad r1.y, v1.x, c4.x, r1.y\n"
+        "	dp4 r0.x, c0, r1\n"
+        "	dp4 r0.y, c1, r1\n"
+        "	dp4 r0.z, c2, r1\n"
+        "	dp4 r0.w, c3, r1\n"
+        "	mov oPos, r0\n"
+        "	mov oD0, c6.x\n"
+        "	mul r0.zw, r0.z, c5.x\n"
+        "	mov r0.xy, c7.x\n"
+        "	lit r0.z, r0\n"
+        "	rcp oFog, r0.z\n";
+    String KdTerrainVertexProgram::mExp2FogVs_1_1 = 
+        "vs_1_1\n"
+        "def c6, 1, 1, 1, 1\n"
+        "def c7, 0.002, 2.71828, 0, 0\n"
+        "//var float4x4 worldViewProj :  : c[0], 4 : 9 : 1\n"
+        "//var float morphFactor :  : c[4] : 10 : 1\n"
+        "//var float fogDensity :  : c[5] : 11 : 1\n"
+        "dcl_blendweight v1\n"
+        "dcl_texcoord1 v8\n"
+        "dcl_texcoord0 v7\n"
+        "dcl_position v0\n"
+        "	mov oT0.xy, v7\n"
+        "	mov oT1.xy, v8\n"
+        "	mov r1, v0\n"
+        "	mad r1.y, v1.x, c4.x, r1.y\n"
+        "	dp4 r0.x, c0, r1\n"
+        "	dp4 r0.y, c1, r1\n"
+        "	dp4 r0.z, c2, r1\n"
+        "	dp4 r0.w, c3, r1\n"
+        "	mov oPos, r0\n"
+        "	mov oD0, c6.x\n"
+        "	mul r0.x, r0.z, c7.x\n"
+        "	mul r0.zw, r0.x, r0.x\n"
+        "	mov r0.xy, c7.y\n"
+        "	lit r0.z, r0\n"
+        "	rcp oFog, r0.z\n";
+
+    const String& KdTerrainVertexProgram::getProgramSource(
+        FogMode fogMode, const String syntax, bool shadowReceiver)
+    {
+		if (shadowReceiver)
+		{
+			if (syntax == "arbvp1")
+			{
+				return mShadowReceiverArbvp1;
+			}
+			else
+			{
+				return mShadowReceiverVs_1_1;
+			}
+		}
+		else
+		{
+
+			switch(fogMode)
+			{
+			case FOG_NONE:
+				if (syntax == "arbvp1")
+				{
+					return mNoFogArbvp1;
+				}
+				else
+				{
+					return mNoFogVs_1_1;
+				}
+				break;
+			case FOG_LINEAR:
+				if (syntax == "arbvp1")
+				{
+					return mLinearFogArbvp1;
+				}
+				else
+				{
+					return mLinearFogVs_1_1;
+				}
+				break;
+			case FOG_EXP:
+				if (syntax == "arbvp1")
+				{
+					return mExpFogArbvp1;
+				}
+				else
+				{
+					return mExpFogVs_1_1;
+				}
+				break;
+			case FOG_EXP2:
+				if (syntax == "arbvp1")
+				{
+					return mExp2FogArbvp1;
+				}
+				else
+				{
+					return mExp2FogVs_1_1;
+				}
+				break;
+			};
+		}
+        // default
+        return StringUtil::BLANK;
+
+    }
+}
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPage.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPage.cpp	(revision 1273)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTerrainPage.cpp	(revision 1273)
@@ -0,0 +1,134 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreKdTerrainPage.h"
+#include "OgreKdTerrainRenderable.h"
+
+namespace Ogre {
+
+    //-------------------------------------------------------------------------
+    KdTerrainPage::KdTerrainPage(unsigned short numTiles)
+    {
+        tilesPerPage = numTiles;
+        // Set up an empty array of TerrainRenderable pointers
+        int i, j;
+        for ( i = 0; i < tilesPerPage; i++ )
+        {
+            tiles.push_back( KdTerrainRow() );
+
+            for ( j = 0; j < tilesPerPage; j++ )
+            {
+                tiles[ i ].push_back( 0 );
+            }
+        }
+
+        pageSceneNode = 0;
+
+    }
+    //-------------------------------------------------------------------------
+    KdTerrainPage::~KdTerrainPage()
+    {
+        KdTerrain2D::iterator i, iend;
+        iend = tiles.end();
+        for (i = tiles.begin(); i != iend; ++i)
+        {
+            KdTerrainRow::iterator j, jend;
+            jend = i->end();
+            for (j = i->begin(); j != jend; ++j)
+            {
+                delete *j;
+                *j = 0;
+            }
+        }
+
+    }
+    //-------------------------------------------------------------------------
+    void KdTerrainPage::linkNeighbours(void)
+    {
+        //setup the neighbor links.
+
+        for ( size_t j = 0; j < tilesPerPage; j++ )
+        {
+            for ( size_t i = 0; i < tilesPerPage; i++ )
+            {
+                if ( j != tilesPerPage - 1 )
+                {
+                    tiles[ i ][ j ] -> _setNeighbor( KdTerrainRenderable::SOUTH, tiles[ i ][ j + 1 ] );
+                    tiles[ i ][ j + 1 ] -> _setNeighbor( KdTerrainRenderable::NORTH, tiles[ i ][ j ] );
+                }
+
+                if ( i != tilesPerPage - 1 )
+                {
+                    tiles[ i ][ j ] -> _setNeighbor( KdTerrainRenderable::EAST, tiles[ i + 1 ][ j ] );
+                    tiles[ i + 1 ][ j ] -> _setNeighbor( KdTerrainRenderable::WEST, tiles[ i ][ j ] );
+                }
+
+            }
+        }
+    }
+    //-------------------------------------------------------------------------
+    KdTerrainRenderable * KdTerrainPage::getTerrainTile( const Vector3 & pt )
+    {
+        /* Since we don't know if the terrain is square, or has holes, we use a line trace
+        to find the containing tile...
+        */
+
+        KdTerrainRenderable * tile = tiles[ 0 ][ 0 ];
+
+        while ( tile != 0 )
+        {
+            AxisAlignedBox b = tile -> getBoundingBox();
+            const Vector3 *corners = b.getAllCorners();
+
+            if ( pt.x < corners[ 0 ].x )
+                tile = tile -> _getNeighbor( KdTerrainRenderable::WEST );
+            else if ( pt.x > corners[ 4 ].x )
+                tile = tile -> _getNeighbor( KdTerrainRenderable::EAST );
+            else if ( pt.z < corners[ 0 ].z )
+                tile = tile -> _getNeighbor( KdTerrainRenderable::NORTH );
+            else if ( pt.z > corners[ 4 ].z )
+                tile = tile -> _getNeighbor( KdTerrainRenderable::SOUTH );
+            else
+                return tile;
+        }
+
+        return 0;
+    }
+	//-------------------------------------------------------------------------
+	void KdTerrainPage::setRenderQueue(uint8 qid)
+	{
+		for ( size_t j = 0; j < tilesPerPage; j++ )
+		{
+			for ( size_t i = 0; i < tilesPerPage; i++ )
+			{
+				if ( j != tilesPerPage - 1 )
+				{
+					tiles[ i ][ j ]->setRenderQueueGroup(qid);
+				}
+			}
+		}
+	}
+
+}
+
