Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreRenderable.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreRenderable.h	(revision 131)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreRenderable.h	(revision 131)
@@ -0,0 +1,243 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Renderable_H__
+#define __Renderable_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreCommon.h"
+
+#include "OgreRenderOperation.h"
+#include "OgreMatrix4.h"
+#include "OgreMaterial.h"
+#include "OgrePlane.h"
+#include "OgreGpuProgram.h"
+#include "OgreVector4.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+    /** Abstract class defining the interface all renderable objects must implement.
+        @remarks
+            This interface abstracts renderable discrete objects which will be queued in the render pipeline,
+            grouped by material. Classes implementing this interface must be based on a single material, a single
+            world matrix (or a collection of world matrices which are blended by weights), and must be 
+            renderable via a single render operation.
+        @par
+            Note that deciding whether to put these objects in the rendering pipeline is done from the more specific
+            classes e.g. entities. Only once it is decided that the specific class is to be rendered is the abstract version
+            created (could be more than one per visible object) and pushed onto the rendering queue.
+    */
+    class _OgreExport Renderable
+    {
+    public:
+		Renderable() {mId = 0;}
+        /** Virtual destructor needed as class has virtual methods. */
+        virtual ~Renderable() { }
+        /** Retrieves a weak reference to the material this renderable object uses.
+        @remarks
+            Note that the Renderable also has the option to override the getTechnique method
+            to specify a particular Technique to use instead of the best one available.
+        */
+        virtual const MaterialPtr& getMaterial(void) const = 0;
+        /** Retrieves a pointer to the Material Technique this renderable object uses.
+        @remarks
+            This is to allow Renderables to use a chosen Technique if they wish, otherwise
+            they will use the best Technique available for the Material they are using.
+        */
+        virtual Technique* getTechnique(void) const { return getMaterial()->getBestTechnique(); }
+        /** Gets the render operation required to send this object to the frame buffer.
+        */
+        virtual void getRenderOperation(RenderOperation& op) = 0;
+        /** Gets the world transform matrix / matrices for this renderable object.
+            @remarks
+                If the object has any derived transforms, these are expected to be up to date as long as
+                all the SceneNode structures have been updated before this is called.
+            @par
+                This method will populate xform with 1 matrix if it does not use vertex blending. If it
+                does use vertex blending it will fill the passed in pointer with an array of matrices,
+                the length being the value returned from getNumWorldTransforms.
+        */
+        virtual void getWorldTransforms(Matrix4* xform) const = 0;
+        /** Gets the worldspace orientation of this renderable; this is used in order to
+            more efficiently update parameters to vertex & fragment programs, since inverting Quaterion
+            and Vector in order to derive object-space positions / directions for cameras and
+            lights is much more efficient than inverting a complete 4x4 matrix, and also 
+            eliminates problems introduced by scaling. */
+        virtual const Quaternion& getWorldOrientation(void) const = 0;
+        /** Gets the worldspace orientation of this renderable; this is used in order to
+            more efficiently update parameters to vertex & fragment programs, since inverting Quaterion
+            and Vector in order to derive object-space positions / directions for cameras and
+            lights is much more efficient than inverting a complete 4x4 matrix, and also 
+            eliminates problems introduced by scaling. */
+        virtual const Vector3& getWorldPosition(void) const = 0;
+
+        /** Returns the number of world transform matrices this renderable requires.
+        @remarks
+            When a renderable uses vertex blending, it uses multiple world matrices instead of a single
+            one. Each vertex sent to the pipeline can reference one or more matrices in this list
+            with given weights.
+            If a renderable does not use vertex blending this method returns 1, which is the default for 
+            simplicity.
+        */
+        virtual unsigned short getNumWorldTransforms(void) const { return 1; }
+
+        /** Returns whether or not to use an 'identity' projection.
+        @remarks
+            Usually Renderable objects will use a projection matrix as determined
+            by the active camera. However, if they want they can cancel this out
+            and use an identity projection, which effectively projects in 2D using
+            a {-1, 1} view space. Useful for overlay rendering. Normal renderables need
+            not override this.
+        */
+        virtual bool useIdentityProjection(void) const { return false; }
+
+        /** Returns whether or not to use an 'identity' projection.
+        @remarks
+            Usually Renderable objects will use a view matrix as determined
+            by the active camera. However, if they want they can cancel this out
+            and use an identity matrix, which means all geometry is assumed
+            to be relative to camera space already. Useful for overlay rendering. 
+            Normal renderables need not override this.
+        */
+        virtual bool useIdentityView(void) const { return false; }
+
+		/** Returns the camera-relative squared depth of this renderable.
+		@remarks
+			Used to sort transparent objects. Squared depth is used rather than
+			actual depth to avoid having to perform a square root on the result.
+		*/
+		virtual Real getSquaredViewDepth(const Camera* cam) const = 0;
+
+        /** Returns the preferred rasterisation mode of this renderable.
+        */
+        virtual SceneDetailLevel getRenderDetail() const {return SDL_SOLID;} 
+
+        /** Returns whether or not this Renderable wishes the hardware to normalise normals. */
+        virtual bool getNormaliseNormals(void) const { return false; }
+
+        /** Gets a list of lights, ordered relative to how close they are to this renderable.
+        @remarks
+            Directional lights, which have no position, will always be first on this list.
+        */
+        virtual const LightList& getLights(void) const = 0;
+
+        virtual const PlaneList& getClipPlanes() const { return msDummyPlaneList; };
+
+        /** Method which reports whether this renderable would normally cast a
+            shadow. 
+        @remarks
+            Subclasses should override this if they could have been used to 
+            generate a shadow.
+        */
+        virtual bool getCastsShadows(void) const { return false; }
+
+        /** Sets a custom parameter for this Renderable, which may be used to 
+            drive calculations for this specific Renderable, like GPU program parameters.
+        @remarks
+            Calling this method simply associates a numeric index with a 4-dimensional
+            value for this specific Renderable. This is most useful if the material
+            which this Renderable uses a vertex or fragment program, and has an 
+            ACT_CUSTOM parameter entry. This parameter entry can refer to the
+            index you specify as part of this call, thereby mapping a custom
+            parameter for this renderable to a program parameter.
+        @param index The index with which to associate the value. Note that this
+            does not have to start at 0, and can include gaps. It also has no direct
+            correlation with a GPU program parameter index - the mapping between the
+            two is performed by the ACT_CUSTOM entry, if that is used.
+        @param value The value to associate.
+        */
+        void setCustomParameter(size_t index, const Vector4& value) 
+        {
+            mCustomParameters[index] = value;
+        }
+
+        /** Gets the custom value associated with this Renderable at the given index.
+        @param
+            @see setCustomParaemter for full details.
+        */
+        const Vector4& getCustomParameter(size_t index) const
+        {
+            CustomParameterMap::const_iterator i = mCustomParameters.find(index);
+            if (i != mCustomParameters.end())
+            {
+                return i->second;
+            }
+            else
+            {
+                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+                    "Parameter at the given index was not found.",
+                    "Renderable::getCustomParameter");
+            }
+        }
+
+        /** Update a custom GpuProgramParameters constant which is derived from 
+            information only this Renderable knows.
+        @remarks
+            This method allows a Renderable to map in a custom GPU program parameter
+            based on it's own data. This is represented by a GPU auto parameter
+            of ACT_CUSTOM, and to allow there to be more than one of these per
+            Renderable, the 'data' field on the auto parameter will identify
+            which parameter is being updated. The implementation of this method
+            must identify the parameter being updated, and call a 'setConstant' 
+            method on the passed in GpuProgramParameters object, using the details
+            provided in the incoming auto constant setting to identify the index
+            at which to set the parameter.
+        @par
+            You do not need to override this method if you're using the standard
+            sets of data associated with the Renderable as provided by setCustomParameter
+            and getCustomParameter. By default, the implementation will map from the
+            value indexed by the 'constantEntry.data' parameter to a value previously
+            set by setCustomParameter. But custom Renderables are free to override
+            this if they want, in any case.
+        @param constantEntry The auto constant entry referring to the parameter
+            being updated
+        @param params The parameters object which this method should call to 
+            set the updated parameters.
+        */
+        virtual void _updateCustomGpuParameter(
+            const GpuProgramParameters::AutoConstantEntry& constantEntry,
+            GpuProgramParameters* params) const
+        {
+            CustomParameterMap::const_iterator i = mCustomParameters.find(constantEntry.data);
+            if (i != mCustomParameters.end())
+            {
+                params->setConstant(constantEntry.index, i->second);
+            }
+        }
+		void setId(int id) {mId = id;}
+		int getId() {return mId;}
+
+    protected:
+        static const PlaneList msDummyPlaneList;
+        typedef std::map<size_t, Vector4> CustomParameterMap;
+        CustomParameterMap mCustomParameters;
+		int mId;
+    };
+
+
+
+}
+
+#endif //__Renderable_H__
Index: trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 115)
+++ trunk/VUT/work/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 131)
@@ -149,4 +149,13 @@
         */
         virtual Pass* setPass(Pass* pass);
+
+		/** Renders an Ogre Entity.
+		*/
+		//void renderEntity(Entity *ent);
+		
+		/** Renders an Ogre MovableObject.
+		*/
+		void _renderMovableObject(MovableObject *mov, const bool leaveTransparentsInQueue);
+
 #endif // GTP_VISIBILITY_MODIFIED_OGRE
 
Index: trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 115)
+++ trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 131)
@@ -646,8 +646,8 @@
 
     // TEST
-    /*
-    LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) + 
-    " of " + pass->getParent()->getParent()->getName());
-    */
+    
+    //LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) + 
+    //" of " + pass->getParent()->getParent()->getName() + "\n");
+    
     bool passSurfaceAndLightParams = true;
 
@@ -779,4 +779,5 @@
 void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
 {
+	LogManager::getSingleton().logMessage("***********RENDER SCENE************");
     Root::getSingleton()._setCurrentSceneManager(this);
     // Prep Pass for use in debug shadows
@@ -1540,4 +1541,5 @@
             renderShadowVolumesToStencil(l, mCameraInProgress);
             // render full-screen shadow modulator for all lights
+			//LogManager::getSingleton().logMessage("setting shadow modulative pass");
             setPass(mShadowModulativePass);
             // turn stencil check on
@@ -1800,4 +1802,5 @@
             continue;
 
+		//LogManager::getSingleton().logMessage("setting solid pass");
         // For solids, we try to do each pass in turn
         Pass* usedPass = setPass(ipass->first);
@@ -1830,4 +1833,5 @@
         itrans != itransend; ++itrans)
     {
+		//LogManager::getSingleton().logMessage("setting transparent pass");
         // For transparents, we have to accept that we can't sort entirely by pass
         setPass(itrans->pass);
@@ -1915,4 +1919,5 @@
 		if (p->getParent()->getParent()->getTransparencyCastsShadows())
 		{
+			//LogManager::getSingleton().logMessage("setting transparent shadow pass");
 			setPass(p);
 			renderSingleObject(itrans->renderable, p, doLightIteration, manualLightList);
@@ -2413,4 +2418,5 @@
         mDestRenderSystem->_beginFrame();
 
+	//LogManager::getSingleton().logMessage("setting manual pass");
     setPass(pass);
     mDestRenderSystem->_render(*rend);
@@ -2656,22 +2662,22 @@
 		if (l->isVisible())
 		{
-        if (l->getType() == Light::LT_DIRECTIONAL)
-        {
-            // Always visible
-            mLightsAffectingFrustum.push_back(l);
-        }
-        else
-        {
-            // NB treating spotlight as point for simplicity
-            // Just see if the lights attenuation range is within the frustum
-            sphere.setCenter(l->getDerivedPosition());
-            sphere.setRadius(l->getAttenuationRange());
-            if (camera->isVisible(sphere))
-            {
-                mLightsAffectingFrustum.push_back(l);
-            }
-
-        }
-    }
+			if (l->getType() == Light::LT_DIRECTIONAL)
+			{
+				// Always visible
+				mLightsAffectingFrustum.push_back(l);
+			}
+			else
+			{
+				// NB treating spotlight as point for simplicity
+				// Just see if the lights attenuation range is within the frustum
+				sphere.setCenter(l->getDerivedPosition());
+				sphere.setRadius(l->getAttenuationRange());
+				if (camera->isVisible(sphere))
+				{
+					mLightsAffectingFrustum.push_back(l);
+				}
+
+			}
+		}
     }
 
@@ -3008,4 +3014,5 @@
 Pass* SceneManager::deriveShadowCasterPass(Pass* pass)
 {
+	//LogManager::getSingleton().logMessage("*********derive shadow caster pass*********");
     switch (mShadowTechnique)
     {
@@ -3013,8 +3020,10 @@
 		if (mShadowTextureCustomCasterPass)
 		{
+			//LogManager::getSingleton().logMessage("custom caster pass");
 			// Caster pass has been customised
 
 			if (!pass->getShadowCasterVertexProgramName().empty())
 			{
+				//LogManager::getSingleton().logMessage("custom caster pass has vertex program");
 				// Have to merge the shadow caster vertex program in
 				mShadowTextureCustomCasterPass->setVertexProgram(
@@ -3033,4 +3042,5 @@
 			else if (mShadowTextureCasterVPDirty)
 			{
+				//LogManager::getSingleton().logMessage("caster pass dirty");
 				// reset
 				mShadowTextureCustomCasterPass->setVertexProgram(
@@ -3048,7 +3058,9 @@
 		else
 		{
+			//LogManager::getSingleton().logMessage("standard caster pass");
 			// Standard pass
 			if (pass->hasVertexProgram())
 			{
+				//LogManager::getSingleton().logMessage("standard caster pass has vertex program");
 				// Have to merge the shadow caster vertex program in
 				// This may in fact be blank, in which case it falls back on 
@@ -3071,4 +3083,5 @@
 			else if (mShadowCasterPlainBlackPass->hasVertexProgram())
 			{
+				//LogManager::getSingleton().logMessage("standard caster pass no vertex program");
 				// reset
 				mShadowCasterPlainBlackPass->setVertexProgram("");
@@ -3084,5 +3097,5 @@
 Pass* SceneManager::deriveShadowReceiverPass(Pass* pass)
 {
-
+	//LogManager::getSingleton().logMessage("*********derive shadow receiver pass*********");
     switch (mShadowTechnique)
     {
@@ -3091,7 +3104,8 @@
 		{
 			// Receiver pass has been customised
-
+			//LogManager::getSingleton().logMessage("custom receiver pass");
 			if (!pass->getShadowReceiverVertexProgramName().empty())
 			{
+				//LogManager::getSingleton().logMessage("merge receiver pass shadow vertex program");
 				// Have to merge the shadow Receiver vertex program in
 				mShadowTextureCustomReceiverPass->setVertexProgram(
@@ -3110,4 +3124,5 @@
 			else if (mShadowTextureReceiverVPDirty)
 			{
+				//LogManager::getSingleton().logMessage("receiver pass dirty");
 				// reset
 				mShadowTextureCustomReceiverPass->setVertexProgram(
@@ -3125,6 +3140,8 @@
 		else
 		{
+			//LogManager::getSingleton().logMessage("no custom receiver pass");
 			if (pass->hasVertexProgram())
 			{
+				//LogManager::getSingleton().logMessage("standard receiver pass has vertex program");
 				// Have to merge the receiver vertex program in
 				// This may return "" which means fixed function will be used
@@ -3146,4 +3163,5 @@
 			else if (mShadowReceiverPass->hasVertexProgram())
 			{
+				//LogManager::getSingleton().logMessage("standard receiver pass no vertex program");
 				// reset
 				mShadowReceiverPass->setVertexProgram("");
@@ -3367,4 +3385,5 @@
                 setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
                 zfailAlgo ? ColourValue(0.7, 0.0, 0.2) : ColourValue(0.0, 0.7, 0.2));
+			//LogManager::getSingleton().logMessage("setting shadow debug pass");
             setPass(mShadowDebugPass);
             renderShadowVolumeObjects(iShadowRenderables, mShadowDebugPass, &lightList, flags,
@@ -4183,5 +4202,5 @@
 	node->_findVisibleObjects(cam, getRenderQueue(), false, mDisplayNodes, false);
 	SceneManager::_renderVisibleObjects();
-	
+
 	// delete all rendered objects from renderqueue
 	_deleteRenderedQueueGroups(leaveTransparentsInQueue);
@@ -4206,6 +4225,6 @@
 			else
 			{
-			pGroup->clear();
-	}
+				pGroup->clear();
+			}
 		}
 	}
@@ -4214,4 +4233,26 @@
 	// Pass::processPendingPassUpdates();
 }
+//-----------------------------------------------------------------------
+/*void SceneManager::renderEntity(Entity *ent)
+{
+	int n = (int)ent->getNumSubEntities();
+
+	for (int i = 0; i < n; ++i)
+	{
+		Pass *pass = setPass(ent->getSubEntity(i)->getTechnique()->getPass(0));
+
+		_renderSingleObject(ent->getSubEntity(i), pass, false);
+	}
+}*/
+//-----------------------------------------------------------------------
+void SceneManager::_renderMovableObject(MovableObject *mov, const bool leaveTransparentsInQueue)
+{
+	mov->_updateRenderQueue(getRenderQueue());
+	SceneManager::_renderVisibleObjects();
+	
+	// delete rendered objects from renderqueue
+	//TODO: should be first
+	_deleteRenderedQueueGroups(leaveTransparentsInQueue);
+}
 #endif //GTP_VISIBILITY_MODIFIED_OGRE
 }
Index: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h
===================================================================
--- trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 131)
+++ trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 131)
@@ -0,0 +1,424 @@
+/*
+-----------------------------------------------------------------------------
+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.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 TERRAINRENDERABLE_H
+#define TERRAINRENDERABLE_H
+
+#include "OgreTerrainPrerequisites.h"
+#include <OgreRenderable.h>
+#include <OgreMovableObject.h>
+#include <OgreAxisAlignedBox.h>
+#include <OgreString.h>
+#include <OgreHardwareBufferManager.h>
+
+#include <vector>
+
+#define MORPH_CUSTOM_PARAM_ID 77
+
+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 TerrainBufferCache
+    {
+    public:
+        void shutdown(void)
+        {
+            for( size_t i=0; i<mCache.size(); i++ )
+            {
+                delete mCache[i];
+            }
+            mCache.clear();
+        }
+        ~TerrainBufferCache()
+        {
+            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 TerrainRenderable.
+    */
+    class TerrainOptions
+    {
+    public:
+        TerrainOptions()
+        {
+            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
+        size_t pageSize;
+        /// The size of one edge of a terrain tile, in vertices
+        size_t tileSize; 
+        /// Precalculated number of tiles per page
+        size_t tilesPerPage;
+        /// The primary camera, used for error metric calculation and page choice
+        const Camera* primaryCamera;
+        /// The maximum terrain geo-mipmap level
+        size_t 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
+        size_t maxPixelError;
+        /// Whether we should use triangle strips
+        bool useTriStrips;
+        /// The number of times to repeat a detail texture over a tile
+        size_t 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 TerrainRenderable represents a tile used to render a block of terrain using the geomipmap approach
+    for LOD.
+    *@author Jon Anderson
+    */
+
+    class _OgreTerrainExport TerrainRenderable : public Renderable, public MovableObject
+    {
+    public:
+
+        TerrainRenderable(const String& name);
+        ~TerrainRenderable();
+
+        void deleteGeometry();
+
+        enum Neighbor
+        {
+            NORTH = 0,
+            SOUTH = 1,
+            EAST = 2,
+            WEST = 3,
+            HERE = 4
+        };
+
+        /** Initializes the TerrainRenderable.
+        @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 name of the TerrainRenderable */
+        virtual const String& getName( void ) const
+        {
+            return mName;
+        };
+
+        /** Returns the type of the movable. */
+        virtual const String& getMovableType( void ) const
+        {
+            return mType;
+        };
+
+        /** Returns the bounding box of this TerrainRenderable */
+        const AxisAlignedBox& getBoundingBox( void ) const
+        {
+            return mBounds;
+        };
+
+        /** Updates the level of detail to be used for rendering this TerrainRenderable based on the passed in Camera */
+        virtual void _notifyCurrentCamera( Camera* cam );
+
+        virtual void _updateRenderQueue( RenderQueue* queue );
+
+        /**
+        Constructs a RenderOperation to render the TerrainRenderable.
+        @remarks
+        Each TerrainRenderable 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
+        {
+            return mRenderLevel[msCurrentRenderLevelIndex];
+        };
+
+        /** 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 TerrainRenderable.  Neighbors are necessary
+        to know when to bridge between LODs.
+        */
+        void _setNeighbor( Neighbor n, TerrainRenderable *t )
+        {
+            mNeighbors[ n ] = t;
+        };
+
+        /** Returns the neighbor TerrainRenderable.
+        */
+        TerrainRenderable * _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 0; /* not needed */ }
+
+        /** @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;
+        /// Get the static list of indexes cached (internal use only)
+        static TerrainBufferCache& _getIndexCache(void) {return msIndexCache;}
+		// index of renderlevel of current pass
+		static int getCurrentRenderLevelIndex() {return msCurrentRenderLevelIndex;}
+		static void setCurrentRenderLevelIndex(int index) {msCurrentRenderLevelIndex = index;}
+    protected:
+		// index of renderlevel of current pass
+		static int msCurrentRenderLevelIndex;
+        /// Static list of index buffers
+        static TerrainBufferCache msIndexCache;
+        /// Static link to static shared options
+        static const TerrainOptions* msOptions;
+
+        /** Returns the index into the height array for the given coords. */
+        inline size_t _index( int x, int z ) const
+        {
+            return ( x + z * msOptions->tileSize );
+        };
+
+        /** Returns the  vertex coord for the given coordinates */
+        inline float _vertex( int x, int z, int n )
+        {
+            return mPositionBuffer[x * 3 + z * msOptions->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++ )
+            {
+                if ( mNeighbors[ j ] != 0 && mNeighbors[ j ] ->getRenderLevel() == i )
+                    return true;
+            }
+
+            return false;
+
+        }
+
+        void _adjustRenderLevel( int i );
+
+        void _initLevelIndexes();
+        void _destroyLevelIndexes();
+
+        bool _checkSize( int n );
+
+        void _calculateMinLevelDist2( Real C );
+
+        Real _calculateCFactor();
+
+        VertexData* mTerrain;
+
+        /// The current LOD level: for multiple passes, up to 10 renderlevels can be saved
+        int mRenderLevel[10];
+        /// 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
+        TerrainRenderable *mNeighbors [ 4 ];
+        /// Bounding box of this tile
+        AxisAlignedBox mBounds;
+        /// The center point of this tile
+        Vector3 mCenter;
+        /// Name of this renderable
+        String mName;
+        /// The MovableObject type
+        static String mType;
+        /// Current material used by this tile
+        MaterialPtr mMaterial;    
+        /// Whether this tile has been initialised    
+        bool mInit;
+        /// Shared array of IndexData (reuse indexes across tiles)
+        static LevelArray mLevelIndex;
+        /// Whether the level array as been initialised yet
+        static bool mLevelInit;
+        /// 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
