Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 115)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 115)
@@ -0,0 +1,147 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef _HardwareOcclusionQuery__
+#define _HardwareOcclusionQuery__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+
+
+/**
+  * Hardware occlusion query flags
+  */
+typedef enum _OCCLUSIONQUERY 
+{
+	HWOCCLUSIONQUERY_FLUSH,   /** Direct3D uses this, but not OpenGL */
+	HWOCCLUSIONQUERY_NOFLUSH, /** To decide if the driver should flush all batched API calls to serve an occlusion query faster. */
+} HW_OCCLUSIONQUERY;
+
+/**
+  * This is a abstract class that that provides the interface for the query class for 
+  * hardware occlusion.
+  *
+  * @author Lee Sandberg
+  */
+class _OgreExport HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+	/**
+	  * Object public member functions
+	  */
+
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	HardwareOcclusionQuery();
+
+	/**
+	  * Object destructor
+	  */
+	virtual ~HardwareOcclusionQuery();
+
+	/**
+	  * Starts the hardware occlusion query
+	  * @Remarks	Simple usage: Create one or more OcclusionQuery object one per outstanding query or one per tested object 
+	  *				OcclusionQuery* m_pOcclusionQuery;
+	  *				createOcclusionQuery( &m_pOcclusionQuery );
+	  *				In the rendering loop:
+	  *				Draw all occluders
+	  *				m_pOcclusionQuery->startOcclusionQuery();
+	  *				Draw the polygons to be tested
+	  *				m_pOcclusionQuery->endOcclusionQuery();
+	  *
+	  *				Results must be pulled using:
+	  *				UINT	m_uintNumberOfPixelsVisable;
+	  *				pullOcclusionQuery( &m_dwNumberOfPixelsVisable );
+	  *				You may not get the result directlly after the first pass or frame.
+	  *				Objects not visable must be tested every frame, visable objects may be tested less freqvent.
+	  *			
+	  */
+	virtual void beginOcclusionQuery() = 0;
+
+	/**
+	  * Ends the hardware occlusion test
+	  */
+	virtual void endOcclusionQuery() = 0;
+
+	/**
+      * Pulls the hardware occlusion query too see if there is a result.
+      * @retval NumOfFragments will get the resulting number of fragments.
+      * @return True if success or false if not.
+	  * @Remarks In DX9 mode specifying OCCLUSIONQUERY_FLUSH as the flag, will case the driver to flush whatever API calls are batched.
+	  * In OpenGL mode it makes no difference if you specify OCCLUSIONQUERY_FLUSH or OCCLUSIONQUERY_NOFLUSH.
+      */
+	virtual bool pullOcclusionQuery(unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag = HWOCCLUSIONQUERY_FLUSH) = 0;
+
+	/**
+	  * Let's you get the last pixel count with out doing the hardware occlusion test
+	  * @return The last fragment count from the last test.
+	  * Remarks This function won't give you new values, just the old value.
+	  */
+	virtual unsigned int getLastQuerysPixelcount() = 0;
+
+	/**
+	  *   
+	  * @Remarks This function allows you to set how often the hardware occlusion really are sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 1 only the half of your queries are sent 
+	  * for all visable objects. 2 will result in 25% of all queries to acctualy be sent. 
+	  * New and none visable objects will be tested all the time.
+	  * This functionality is here because this class can keep track on visable and none visable objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+	virtual void	setSkipRate( int skip ) = 0;
+	virtual int		getSkipRate() = 0;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/**
+		Pulls occlusion query.
+		@param NumOfFragments number of visible fragments if query result was available.
+		Last query result if query result was not yet available.
+
+		@param waitForResult if true, the function waits until the result is available.
+		Otherwise the function returns immediately, not waiting for the result.
+		@returns true if query result was available, false if result was not yet available
+	*/
+	virtual bool pullOcclusionQuery( unsigned int* NumOfFragments, const bool waitForResult, 
+		const HW_OCCLUSIONQUERY flag = HWOCCLUSIONQUERY_FLUSH ) = 0; 
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+//----------------------------------------------------------------------
+// Private members
+//--
+private:
+
+};
+
+}
+#endif
+
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderable.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderable.h	(revision 193)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderable.h	(revision 193)
@@ -0,0 +1,275 @@
+/*
+-----------------------------------------------------------------------------
+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() : mRenderDetailOverrideable(true) 
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+, mId(-1)
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+{}
+		
+        /** 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);
+            }
+        }
+
+		/** Sets whether this renderable's chosen detail level can be
+			overridden (downgraded) by the camera setting. 
+		@param override true means that a lower camera detail will override this
+			renderables detail level, false means it won't.
+		*/
+		virtual void setRenderDetailOverrideable(bool override)
+		{
+			mRenderDetailOverrideable = override;
+		}
+
+		/** Gets whether this renderable's chosen detail level can be
+			overridden (downgraded) by the camera setting. 
+		*/
+		virtual bool getRenderDetailOverrideable(void) const
+		{
+			return mRenderDetailOverrideable;
+		}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		/** Sets an id for this renderable.
+		*/
+		void setId(int id) {mId = id;}
+		/** see set 
+		*/
+		int getId() {return mId;}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    protected:
+        static const PlaneList msDummyPlaneList;
+        typedef std::map<size_t, Vector4> CustomParameterMap;
+        CustomParameterMap mCustomParameters;
+		bool mRenderDetailOverrideable;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		int mId;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    };
+
+
+
+}
+
+#endif //__Renderable_H__
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneNode.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneNode.h	(revision 158)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneNode.h	(revision 158)
@@ -0,0 +1,458 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef _SceneNode_H__
+#define _SceneNode_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreNode.h"
+#include "OgreIteratorWrappers.h"
+#include "OgreAxisAlignedBox.h"
+
+namespace Ogre {
+
+    /** Class representing a node in the scene graph.
+        @remarks
+            A SceneNode is a type of Node which is used to organise objects in a scene.
+            It has the same hierarchical transformation properties of the generic Node class,
+            but also adds the ability to attach world objects to the node, and stores hierarchical
+            bounding volumes of the nodes in the tree.
+            Child nodes are contained within the bounds of the parent, and so on down the
+            tree, allowing for fast culling.
+    */
+    class _OgreExport SceneNode : public Node
+    {
+    public:
+        typedef HashMap<String, MovableObject*> ObjectMap;
+        typedef MapIterator<ObjectMap> ObjectIterator;
+		typedef ConstMapIterator<ObjectMap> ConstObjectIterator;
+
+    protected:
+        ObjectMap mObjectsByName;
+        mutable LightList mLightList;
+        mutable bool mLightListDirty;
+
+		/// Pointer to a Wire Bounding Box for this Node
+		WireBoundingBox *mWireBoundingBox;
+		/// Flag that determines if the bounding box of the node should be displayed
+		bool mShowBoundingBox;
+
+        /// SceneManager which created this node
+        SceneManager* mCreator;
+
+        /// World-Axis aligned bounding box, updated only through _update
+        AxisAlignedBox mWorldAABB;
+
+        /** Tells the SceneNode to update the world bound info it stores.
+        */
+        virtual void _updateBounds(void);
+
+        /** See Node. */
+        Node* createChildImpl(void);
+
+        /** See Node. */
+        Node* createChildImpl(const String& name);
+
+		/** See Node */
+		void setParent(Node* parent);
+
+		/** Internal method for setting whether the node is in the scene 
+			graph.
+		*/
+		void setInSceneGraph(bool inGraph);
+
+        /// Whether to yaw around a fixed axis.
+        bool mYawFixed;
+        /// Fixed axis to yaw around
+        Vector3 mYawFixedAxis;
+
+        /// Auto tracking target
+        SceneNode* mAutoTrackTarget;
+        /// Tracking offset for fine tuning
+        Vector3 mAutoTrackOffset;
+        /// Local 'normal' direction vector
+        Vector3 mAutoTrackLocalDirection;
+		/// Is this node a current part of the scene graph?
+		bool mIsInSceneGraph;
+    public:
+        /** Constructor, only to be called by the creator SceneManager.
+        @remarks
+            Creates a node with a generated name.
+        */
+        SceneNode(SceneManager* creator);
+        /** Constructor, only to be called by the creator SceneManager.
+        @remarks
+            Creates a node with a specified name.
+        */
+        SceneNode(SceneManager* creator, const String& name);
+        ~SceneNode();
+
+        /** Adds an instance of a scene object to this node.
+        @remarks
+            Scene objects can include Entity objects, Camera objects, Light objects, 
+            ParticleSystem objects etc. Anything that subclasses from MovableObject.
+        */
+        virtual void attachObject(MovableObject* obj);
+
+        /** Reports the number of objects attached to this node.
+        */
+        virtual unsigned short numAttachedObjects(void) const;
+
+        /** Retrieves a pointer to an attached object.
+        @remarks Retrieves by index, see alternate version to retrieve by name. The index
+        of an object may change as other objects are added / removed.
+        */
+        virtual MovableObject* getAttachedObject(unsigned short index);
+
+        /** Retrieves a pointer to an attached object.
+        @remarks Retrieves by object name, see alternate version to retrieve by index.
+        */
+        virtual MovableObject* getAttachedObject(const String& name);
+
+        /** Detaches the indexed object from this scene node.
+        @remarks
+            Detaches by index, see the alternate version to detach by name. Object indexes
+            may change as other objects are added / removed.
+        */
+        virtual MovableObject* detachObject(unsigned short index);
+        /** Detaches an object by pointer. */
+        virtual void detachObject(MovableObject* obj);
+
+        /** Detaches the named object from this node and returns a pointer to it. */
+        virtual MovableObject* detachObject(const String& name);
+
+        /** Detaches all objects attached to this node.
+        */
+        virtual void detachAllObjects(void);
+
+		/** Determines whether this node is in the scene graph, ie
+			whether it's ulitimate ancestor is the root scene node.
+		*/
+		virtual bool isInSceneGraph(void) const { return mIsInSceneGraph; }
+
+		/** Notifies this SceneNode that it is the root scene node. 
+		@remarks
+			Only SceneManager should call this!
+		*/
+		virtual void _notifyRootNode(void) { mIsInSceneGraph = true; }
+			
+
+        /** Internal method to update the Node.
+            @note
+                Updates this scene node and any relevant children to incorporate transforms etc.
+                Don't call this yourself unless you are writing a SceneManager implementation.
+            @param
+                updateChildren If true, the update cascades down to all children. Specify false if you wish to
+                update children separately, e.g. because of a more selective SceneManager implementation.
+            @param
+                parentHasChanged This flag indicates that the parent xform has changed,
+                    so the child should retrieve the parent's xform and combine it with its own
+                    even if it hasn't changed itself.
+        */
+        virtual void _update(bool updateChildren, bool parentHasChanged);
+
+        /** Internal method which locates any visible objects attached to this node and adds them to the passed in queue.
+            @remarks
+                Should only be called by a SceneManager implementation, and only after the _updat method has been called to
+                ensure transforms and world bounds are up to date.
+                SceneManager implementations can choose to let the search cascade automatically, or choose to prevent this
+                and select nodes themselves based on some other criteria.
+            @param
+                cam The active camera
+            @param
+                queue The SceneManager's rendering queue
+            @param
+                includeChildren If true, the call is cascaded down to all child nodes automatically.
+            @param
+                displayNodes If true, the nodes themselves are rendered as a set of 3 axes as well
+                    as the objects being rendered. For debugging purposes.
+        */
+        virtual void _findVisibleObjects(Camera* cam, RenderQueue* queue, 
+            bool includeChildren = true, bool displayNodes = false, bool onlyShadowCasters = false);
+
+        /** Gets the axis-aligned bounding box of this node (and hence all subnodes).
+        @remarks
+            Recommended only if you are extending a SceneManager, because the bounding box returned
+            from this method is only up to date after the SceneManager has called _update.
+        */
+        virtual AxisAlignedBox _getWorldAABB(void) const;
+
+        /** Retrieves an iterator which can be used to efficiently step through the objects 
+            attached to this node.
+        @remarks
+            This is a much faster way to go through <B>all</B> the objects attached to the node
+            than using getAttachedObject. But the iterator returned is only valid until a change
+            is made to the collection (ie an addition or removal) so treat the returned iterator
+            as transient, and don't add / remove items as you go through the iterator, save changes
+            until the end, or retrieve a new iterator after making the change. Making changes to
+            the object returned through the iterator is OK though.
+        */
+        virtual ObjectIterator getAttachedObjectIterator(void);
+        /** Retrieves an iterator which can be used to efficiently step through the objects 
+            attached to this node.
+        @remarks
+            This is a much faster way to go through <B>all</B> the objects attached to the node
+            than using getAttachedObject. But the iterator returned is only valid until a change
+            is made to the collection (ie an addition or removal) so treat the returned iterator
+            as transient, and don't add / remove items as you go through the iterator, save changes
+            until the end, or retrieve a new iterator after making the change. Making changes to
+            the object returned through the iterator is OK though.
+        */
+		virtual ConstObjectIterator getAttachedObjectIterator(void) const;
+
+        /** Gets the creator of this scene node. 
+        @remarks
+            This method returns the SceneManager which created this node.
+            This can be useful for destroying this node.
+        */
+        SceneManager* getCreator(void) const;
+
+        /** This method removes and destroys the named child and all of its children.
+        @remarks
+            Unlike removeChild, which removes a single named child from this
+            node but does not destroy it, this method destroys the child
+            and all of it's children. 
+        @par
+            Use this if you wish to recursively destroy a node as well as 
+            detaching it from it's parent. Note that any objects attached to
+            the nodes will be detached but will not themselves be destroyed.
+        */
+        virtual void removeAndDestroyChild(const String& name);
+
+        /** This method removes and destroys the child and all of its children.
+        @remarks
+            Unlike removeChild, which removes a single named child from this
+            node but does not destroy it, this method destroys the child
+            and all of it's children. 
+        @par
+            Use this if you wish to recursively destroy a node as well as 
+            detaching it from it's parent. Note that any objects attached to
+            the nodes will be detached but will not themselves be destroyed.
+        */
+        virtual void removeAndDestroyChild(unsigned short index);
+
+        /** Removes and destroys all children of this node.
+        @remarks
+            Use this to destroy all child nodes of this node and remove
+            them from the scene graph. Note that all objects attached to this
+            node will be detached but will not be destroyed.
+        */
+        virtual void removeAndDestroyAllChildren(void);
+
+        /** Allows the showing of the node's bounding box.
+        @remarks
+            Use this to show or hide the bounding box of the node.
+        */
+		virtual void showBoundingBox(bool bShow);
+
+        /** Add the bounding box to the rendering queue.
+        */
+		virtual void _addBoundingBoxToQueue(RenderQueue* queue);
+
+        /** This allows scene managers to determine if the node's bounding box
+			should be added to the rendering queue.
+        @remarks
+            Scene Managers that implement their own _findVisibleObjects will have to 
+			check this flag and then use _addBoundingBoxToQueue to add the bounding box
+			wireframe.
+        */
+		virtual bool getShowBoundingBox() const;
+
+        /** Creates an unnamed new SceneNode as a child of this node.
+        @param
+            translate Initial translation offset of child relative to parent
+        @param
+            rotate Initial rotation relative to parent
+        */
+        virtual SceneNode* createChildSceneNode(
+            const Vector3& translate = Vector3::ZERO, 
+            const Quaternion& rotate = Quaternion::IDENTITY );
+
+        /** Creates a new named SceneNode as a child of this node.
+        @remarks
+            This creates a child node with a given name, which allows you to look the node up from 
+            the parent which holds this collection of nodes.
+            @param
+                translate Initial translation offset of child relative to parent
+            @param
+                rotate Initial rotation relative to parent
+        */
+        virtual SceneNode* createChildSceneNode(const String& name, const Vector3& translate = Vector3::ZERO, const Quaternion& rotate = Quaternion::IDENTITY);
+
+        /** Allows retrieval of the nearest lights to the centre of this SceneNode.
+        @remarks
+            This method allows a list of lights, ordered by proximity to the centre of
+            this SceneNode, to be retrieved. Multiple access to this method when neither 
+            the node nor the lights have moved will result in the same list being returned
+            without recalculation. Can be useful when implementing Renderable::getLights.
+        @param radius Optional parameter to specify lights intersecting a given radius of
+            this SceneNode's centre.
+        */
+        const LightList& findLights(Real radius) const;
+
+        /** Tells the node whether to yaw around it's own local Y axis or a fixed axis of choice.
+        @remarks
+        This method allows you to change the yaw behaviour of the node - by default, it
+        yaws around it's own local Y axis when told to yaw with TS_LOCAL, this makes it
+        yaw around a fixed axis. 
+        You only really need this when you're using auto tracking (see setAutoTracking,
+        because when you're manually rotating a node you can specify the TransformSpace
+        in which you wish to work anyway.
+        @param
+        useFixed If true, the axis passed in the second parameter will always be the yaw axis no
+        matter what the node orientation. If false, the node returns to it's default behaviour.
+        @param
+        fixedAxis The axis to use if the first parameter is true.
+        */
+        void setFixedYawAxis( bool useFixed, const Vector3& fixedAxis = Vector3::UNIT_Y );
+
+		/** Rotate the node around the Y-axis.
+		*/
+		virtual void yaw(const Radian& angle, TransformSpace relativeTo = TS_LOCAL);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+		inline void yaw(Real degrees, TransformSpace relativeTo = TS_LOCAL) {
+			yaw ( Angle(degrees), relativeTo );
+		}
+#endif//OGRE_FORCE_ANGLE_TYPES
+        /** Sets the node's direction vector ie it's local -z.
+        @remarks
+        Note that the 'up' vector for the orientation will automatically be 
+        recalculated based on the current 'up' vector (i.e. the roll will 
+        remain the same). If you need more control, use setOrientation.
+        @param x,y,z The components of the direction vector
+        @param relativeTo The space in which this direction vector is expressed
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void setDirection(Real x, Real y, Real z, 
+            TransformSpace relativeTo = TS_LOCAL, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+
+        /** Sets the node's direction vector ie it's local -z.
+        @remarks
+        Note that the 'up' vector for the orientation will automatically be 
+        recalculated based on the current 'up' vector (i.e. the roll will 
+        remain the same). If you need more control, use setOrientation.
+        @param vec The direction vector
+        @param relativeTo The space in which this direction vector is expressed
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void setDirection(const Vector3& vec, TransformSpace relativeTo = TS_LOCAL, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+        /** Points the local -Z direction of this node at a point in space.
+        @param targetPoint A vector specifying the look at point.
+        @param relativeTo The space in which the point resides
+        @param localDirectionVector The vector which normally describes the natural
+        direction of the node, usually -Z
+        */
+        void lookAt( const Vector3& targetPoint, TransformSpace relativeTo,
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+        /** Enables / disables automatic tracking of another SceneNode.
+        @remarks
+        If you enable auto-tracking, this SceneNode will automatically rotate to
+        point it's -Z at the target SceneNode every frame, no matter how 
+        it or the other SceneNode move. Note that by default the -Z points at the 
+        origin of the target SceneNode, if you want to tweak this, provide a 
+        vector in the 'offset' parameter and the target point will be adjusted.
+        @param enabled If true, tracking will be enabled and the next 
+        parameter cannot be null. If false tracking will be disabled and the 
+        current orientation will be maintained.
+        @param target Pointer to the SceneNode to track. Make sure you don't
+        delete this SceneNode before turning off tracking (e.g. SceneManager::clearScene will
+        delete it so be careful of this). Can be null if and only if the enabled param is false.
+        @param localDirectionVector The local vector considered to be the usual 'direction'
+        of the node; normally the local -Z but can be another direction.
+        @param offset If supplied, this is the target point in local space of the target node
+        instead of the origin of the target node. Good for fine tuning the look at point.
+        */
+        void setAutoTracking(bool enabled, SceneNode* target = 0, 
+            const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z,
+            const Vector3& offset = Vector3::ZERO);
+		/** Get the auto tracking target for this node, if any. */
+        SceneNode* getAutoTrackTarget(void) { return mAutoTrackTarget; }
+		/** Get the auto tracking offset for this node, if the node is auto tracking. */
+		const Vector3& getAutoTrackOffset(void) { return mAutoTrackOffset; }
+		/** Get the auto tracking local direction for this node, if it is auto tracking. */
+		const Vector3& getAutoTrackLocalDirection(void) { return mAutoTrackLocalDirection; }
+		/** Internal method used by OGRE to update auto-tracking cameras. */
+        void _autoTrack(void);
+        /** Gets the parent of this SceneNode. */
+        SceneNode* getParentSceneNode(void) const;
+        /** Makes all objects attached to this node become visible / invisble.
+        @remarks    
+            This is a shortcut to calling setVisible() on the objects attached
+            to this node, and optionally to all objects attached to child
+            nodes. 
+        @param visible Whether the objects are to be made visible or invisible
+        @param cascade If true, this setting cascades into child nodes too.
+        */
+        void setVisible(bool visible, bool cascade = true);
+        /** Inverts the visibility of all objects attached to this node.
+        @remarks    
+        This is a shortcut to calling setVisible(!isVisible()) on the objects attached
+        to this node, and optionally to all objects attached to child
+        nodes. 
+        @param cascade If true, this setting cascades into child nodes too.
+        */
+        void flipVisibility(bool cascade = true);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	public:
+		/** Returns last visited frame id. */
+		int lastVisited(void);
+		/** Set to current frame id.
+        @param current frame id.
+        */
+		void setLastVisited(int frameid);
+		/** Makes this node become visible / invisble.
+        @param visible Whether this node is to be made visible or invisible
+        */
+		void setNodeVisible(bool visible);
+		/** Returns true if this node is marked visible, false otherwise. */
+		bool isNodeVisible(void);
+
+		/** Frame id when this octree was last rendered. 
+		@return last rendered frame id
+		*/	
+		int lastRendered(void);
+		/** Sets frame id when this octree was last rendered. 
+		@param last rendered frame id
+		*/
+		void setLastRendered(int frameid);
+
+	protected:
+		int mLastVisited;
+		bool mVisible;
+		int mLastRendered;
+		int mId;
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+
+    };
+
+
+}// namespace
+
+#endif
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderSystem.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderSystem.h	(revision 316)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderSystem.h	(revision 316)
@@ -0,0 +1,989 @@
+/*
+-----------------------------------------------------------------------------
+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 __RenderSystem_H_
+#define __RenderSystem_H_
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+
+#include "OgreTextureUnitState.h"
+#include "OgreCommon.h"
+
+#include "OgreRenderOperation.h"
+#include "OgreRenderSystemCapabilities.h"
+#include "OgreRenderTarget.h"
+#include "OgreRenderTexture.h"
+#include "OgreFrameListener.h"
+#include "OgreConfigOptionMap.h"
+#include "OgreGpuProgram.h"
+#include "OgrePlane.h"
+
+namespace Ogre
+{
+    typedef std::map< String, RenderTarget * > RenderTargetMap;
+	typedef std::multimap<uchar, RenderTarget * > RenderTargetPriorityMap;
+
+    class TextureManager;
+    /// Enum describing the ways to generate texture coordinates
+    enum TexCoordCalcMethod
+    {
+        /// No calculated texture coordinates
+        TEXCALC_NONE,
+        /// Environment map based on vertex normals
+        TEXCALC_ENVIRONMENT_MAP,
+        /// Environment map based on vertex positions
+        TEXCALC_ENVIRONMENT_MAP_PLANAR,
+        TEXCALC_ENVIRONMENT_MAP_REFLECTION,
+        TEXCALC_ENVIRONMENT_MAP_NORMAL,
+        /// Projective texture
+        TEXCALC_PROJECTIVE_TEXTURE
+    };
+    /// Enum describing the various actions which can be taken onthe stencil buffer
+    enum StencilOperation
+    {
+        /// Leave the stencil buffer unchanged
+        SOP_KEEP,
+        /// Set the stencil value to zero
+        SOP_ZERO,
+        /// Set the stencil value to the reference value
+        SOP_REPLACE,
+        /// Increase the stencil value by 1, clamping at the maximum value
+        SOP_INCREMENT,
+        /// Decrease the stencil value by 1, clamping at 0
+        SOP_DECREMENT,
+        /// Increase the stencil value by 1, wrapping back to 0 when incrementing the maximum value
+        SOP_INCREMENT_WRAP,
+        /// Decrease the stencil value by 1, wrapping when decrementing 0
+        SOP_DECREMENT_WRAP,
+        /// Invert the bits of the stencil buffer
+        SOP_INVERT
+    };
+
+    /** Defines the frame buffers which can be cleared. */
+    enum FrameBufferType {
+        FBT_COLOUR  = 0x1,
+        FBT_DEPTH   = 0x2,
+        FBT_STENCIL = 0x4
+    };
+    
+    /** Defines the functionality of a 3D API
+        @remarks
+            The RenderSystem class provides a base interface
+            which abstracts the general functionality of the 3D API
+            e.g. Direct3D or OpenGL. Whilst a few of the general
+            methods have implementations, most of this class is
+            abstract, requiring a subclass based on a specific API
+            to be constructed to provide the full functionality.
+            Note there are 2 levels to the interface - one which
+            will be used often by the caller of the Ogre library,
+            and one which is at a lower level and will be used by the
+            other classes provided by Ogre. These lower level
+            methods are prefixed with '_' to differentiate them.
+            The advanced user of the library may use these lower
+            level methods to access the 3D API at a more fundamental
+            level (dealing direct with render states and rendering
+            primitives), but still benefitting from Ogre's abstraction
+            of exactly which 3D API is in use.
+        @author
+            Steven Streeting
+        @version
+            1.0
+     */
+    class _OgreExport RenderSystem
+    {
+    public:
+        /** Default Constructor.
+        */
+        RenderSystem();
+
+        /** Destructor.
+        */
+        virtual ~RenderSystem();
+
+        /** Returns the name of the rendering system.
+        */
+        virtual const String& getName(void) const = 0;
+
+        /** Returns the details of this API's configuration options
+            @remarks
+                Each render system must be able to inform the world
+                of what options must/can be specified for it's
+                operation.
+            @par
+                These are passed as strings for portability, but
+                grouped into a structure (_ConfigOption) which includes
+                both options and current value.
+            @par
+                Note that the settings returned from this call are
+                affected by the options that have been set so far,
+                since some options are interdependent.
+            @par
+                This routine is called automatically by the default
+                configuration dialogue produced by Root::showConfigDialog
+                or may be used by the caller for custom settings dialogs
+            @returns
+                A 'map' of options, i.e. a list of options which is also
+                indexed by option name.
+         */
+        virtual ConfigOptionMap& getConfigOptions(void) = 0;
+
+        /** Sets an option for this API
+            @remarks
+                Used to confirm the settings (normally chosen by the user) in
+                order to make the renderer able to initialise with the settings as required.
+                This may be video mode, D3D driver, full screen / windowed etc.
+                Called automatically by the default configuration
+                dialog, and by the restoration of saved settings.
+                These settings are stored and only activated when
+                RenderSystem::initialise or RenderSystem::reinitialise
+                are called.
+            @par
+                If using a custom configuration dialog, it is advised that the
+                caller calls RenderSystem::getConfigOptions
+                again, since some options can alter resulting from a selection.
+            @param
+                name The name of the option to alter.
+            @param
+                value The value to set the option to.
+         */
+        virtual void setConfigOption(const String &name, const String &value) = 0;
+
+		virtual HardwareOcclusionQuery* createHardwareOcclusionQuery() = 0;
+
+        /** Validates the options set for the rendering system, returning a message if there are problems.
+            @note
+                If the returned string is empty, there are no problems.
+        */
+        virtual String validateConfigOptions(void) = 0;
+
+        /** Start up the renderer using the settings selected (Or the defaults if none have been selected).
+            @remarks
+                Called by Root::setRenderSystem. Shouldn't really be called
+                directly, although  this can be done if the app wants to.
+            @param
+                autoCreateWindow If true, creates a render window
+                automatically, based on settings chosen so far. This saves
+                an extra call to RenderSystem::createRenderWindow
+                for the main render window.
+            @par
+                If an application has more specific window requirements,
+                however (e.g. a level design app), it should specify false
+                for this parameter and do it manually.
+            @returns
+                A pointer to the automatically created window, if requested, otherwise null.
+        */
+        virtual RenderWindow* initialise(bool autoCreateWindow, const String& windowTitle = "OGRE Render Window");
+
+        /** Restart the renderer (normally following a change in settings).
+        */
+        virtual void reinitialise(void) = 0;
+
+        /** Shutdown the renderer and cleanup resources.
+        */
+        virtual void shutdown(void);
+
+
+        /** Sets the colour & strength of the ambient (global directionless) light in the world.
+        */
+        virtual void setAmbientLight(float r, float g, float b) = 0;
+
+        /** Sets the type of light shading required (default = Gouraud).
+        */
+        virtual void setShadingType(ShadeOptions so) = 0;
+
+        /** Sets whether or not dynamic lighting is enabled.
+            @param
+                enabled If true, dynamic lighting is performed on geometry with normals supplied, geometry without
+                normals will not be displayed. If false, no lighting is applied and all geometry will be full brightness.
+        */
+        virtual void setLightingEnabled(bool enabled) = 0;
+
+        /** Sets whether or not W-buffers are enabled if they are avalible for this renderer.
+			@param
+				enabled If true and the renderer supports them W-buffers will be used.  If false 
+				W-buffers will not be used even if avalible.  W-buffers are enabled by default 
+				for 16bit depth buffers and disabled for all other depths.
+        */
+		void setWBufferEnabled(bool enabled);
+
+		/** Returns true if the renderer will try to use W-buffers when avalible.
+		*/
+		bool getWBufferEnabled(void) const;
+
+		/** Creates a new rendering window.
+            @remarks
+                This method creates a new rendering window as specified
+                by the paramteters. The rendering system could be
+                responible for only a single window (e.g. in the case
+                of a game), or could be in charge of multiple ones (in the
+                case of a level editor). The option to create the window
+                as a child of another is therefore given.
+                This method will create an appropriate subclass of
+                RenderWindow depending on the API and platform implementation.
+            @par
+                After creation, this window can be retrieved using getRenderTarget().
+            @param
+                name The name of the window. Used in other methods
+                later like setRenderTarget and getRenderWindow.
+            @param
+                width The width of the new window.
+            @param
+                height The height of the new window.
+            @param
+                fullScreen Specify true to make the window full screen
+                without borders, title bar or menu bar.
+            @param
+                miscParams A NameValuePairList describing the other parameters for the new rendering window. 
+					Options are case sensitive. Unrecognised parameters will be ignored silently.
+					These values might be platform dependent, but these are present for all platorms unless
+					indicated otherwise:
+				**
+				Key: "title"
+				Description: The title of the window that will appear in the title bar
+				Values: string
+				Default: RenderTarget name
+				**
+				Key: "colourDepth"
+				Description: Colour depth of the resulting rendering window; only applies if fullScreen
+					is set.
+				Values: 16 or 32
+				Default: desktop depth
+				Notes: [W32 specific]
+				**
+				Key: "left"
+				Description: screen x coordinate from left
+				Values: positive integers
+				Default: 'center window on screen'
+				Notes: Ignored in case of full screen
+				**
+				Key: "top"
+				Description: screen y coordinate from top
+				Values: positive integers
+				Default: 'center window on screen'
+				Notes: Ignored in case of full screen
+				**
+				Key: "depthBuffer" [DX9 specific]
+				Description: Use depth buffer
+				Values: false or true
+				Default: true
+				**
+				Key: "externalWindowHandle" [API specific]
+				Description: External window handle, for embedding the OGRE context
+				Values: positive integer for W32 (HWND handle)
+				        posint:posint:posint for GLX (display:screen:windowHandle)
+				Default: 0 (None)
+				**
+				Key: "parentWindowHandle" [API specific]
+				Description: Parent window handle, for embedding the OGRE context
+				Values: positive integer for W32 (HWND handle)
+				        posint:posint:posint for GLX (display:screen:windowHandle)
+				Default: 0 (None)
+				**
+				Key: "FSAA"
+				Description: Full screen antialiasing factor
+				Values: 0,2,4,6,...
+				Default: 0 
+				**
+				Key: "displayFrequency"
+				Description: Display frequency rate, for fullscreen mode
+				Values: 60...?
+				Default: Desktop vsync rate
+				**
+				Key: "vsync"
+				Description: Synchronize buffer swaps to vsync
+				Values: true, false
+				Default: 0
+				** 
+				Key: "border" 
+				Description: The type of window border (in windowed mode)
+				Values: none, fixed, resize
+				Default: resize
+				**
+				Key: "outerDimensions" 
+				Description: Whether the width/height is expressed as the size of the 
+				outer window, rather than the content area
+				Values: true, false
+				Default: false 
+        */
+		virtual RenderWindow* createRenderWindow(const String &name, unsigned int width, unsigned int height, 
+			bool fullScreen, const NameValuePairList *miscParams = 0) = 0;
+
+		/** Creates and registers a render texture object.
+			@param name 
+				The name for the new render texture. Note that names must be unique.
+			@param width
+				The requested width for the render texture. See Remarks for more info.
+			@param height
+				The requested width for the render texture. See Remarks for more info.
+			@param texType
+				The type of texture; defaults to TEX_TYPE_2D
+			@param internalFormat
+				The internal format of the texture; defaults to PF_X8R8G8B8
+			@param miscParams A NameValuePairList describing the other parameters for the new rendering window.
+					Unrecognised parameters will be ignored silently.
+					These values might be platform dependent, but these are present for all platorms unless
+					indicated otherwise:
+				**
+				Key: "FSAA"
+				Description: Full screen antialiasing factor
+				Values: 0,2,4,6,...
+				Default: 0
+				**
+				Key: "depth"
+				Description: Depth in case of render-to-texture TEX_3D
+				Values: positive integers
+			@returns
+				On succes, a pointer to a new platform-dependernt, RenderTexture-derived
+				class is returned. On failiure, NULL is returned.
+			@remarks
+				Because a render texture is basically a wrapper around a texture object,
+				the width and height parameters of this method just hint the preferred
+				size for the texture. Depending on the hardware driver or the underlying
+				API, these values might change when the texture is created. The same applies
+				to the internalFormat parameter.
+		*/
+		virtual RenderTexture * createRenderTexture( const String & name, unsigned int width, unsigned int height,
+		 	TextureType texType = TEX_TYPE_2D, PixelFormat internalFormat = PF_X8R8G8B8, 
+			const NameValuePairList *miscParams = 0 ) = 0; 
+
+        /** Destroys a render window */
+        virtual void destroyRenderWindow(const String& name);
+        /** Destroys a render texture */
+        virtual void destroyRenderTexture(const String& name);
+        /** Destroys a render target of any sort */
+        virtual void destroyRenderTarget(const String& name);
+
+        /** Attaches the passed render target to the render system.
+        */
+        virtual void attachRenderTarget( RenderTarget &target );
+        /** Returns a pointer to the render target with the passed name, or NULL if that
+            render target cannot be found.
+        */
+        virtual RenderTarget * getRenderTarget( const String &name );
+        /** Detaches the render target with the passed name from the render system and
+            returns a pointer to it.
+            @note
+                If the render target cannot be found, NULL is returned.
+        */
+        virtual RenderTarget * detachRenderTarget( const String &name );
+
+        /** Returns a description of an error code.
+        */
+        virtual String getErrorDescription(long errorNumber) const = 0;
+
+        /** Defines whether or now fullscreen render windows wait for the vertical blank before flipping buffers.
+            @remarks
+                By default, all rendering windows wait for a vertical blank (when the CRT beam turns off briefly to move
+                from the bottom right of the screen back to the top left) before flipping the screen buffers. This ensures
+                that the image you see on the screen is steady. However it restricts the frame rate to the refresh rate of
+                the monitor, and can slow the frame rate down. You can speed this up by not waiting for the blank, but
+                this has the downside of introducing 'tearing' artefacts where part of the previous frame is still displayed
+                as the buffers are switched. Speed vs quality, you choose.
+            @note
+                Has NO effect on windowed mode render targets. Only affects fullscreen mode.
+            @param
+                enabled If true, the system waits for vertical blanks - quality over speed. If false it doesn't - speed over quality.
+        */
+        void setWaitForVerticalBlank(bool enabled);
+
+        /** Returns true if the system is synchronising frames with the monitor vertical blank.
+        */
+        bool getWaitForVerticalBlank(void) const;
+
+        // ------------------------------------------------------------------------
+        //                     Internal Rendering Access
+        // All methods below here are normally only called by other OGRE classes
+        // They can be called by library user if required
+        // ------------------------------------------------------------------------
+
+
+        /** Tells the rendersystem to use the attached set of lights (and no others) 
+        up to the number specified (this allows the same list to be used with different
+        count limits) */
+        virtual void _useLights(const LightList& lights, unsigned short limit) = 0;
+        /** Sets the world transform matrix. */
+        virtual void _setWorldMatrix(const Matrix4 &m) = 0;
+        /** Sets multiple world matrices (vertex blending). */
+        virtual void _setWorldMatrices(const Matrix4* m, unsigned short count);
+        /** Sets the view transform matrix */
+        virtual void _setViewMatrix(const Matrix4 &m) = 0;
+        /** Sets the projection transform matrix */
+        virtual void _setProjectionMatrix(const Matrix4 &m) = 0;
+        /** Utility function for setting all the properties of a texture unit at once.
+            This method is also worth using over the individual texture unit settings because it
+            only sets those settings which are different from the current settings for this
+            unit, thus minimising render state changes.
+        */
+        virtual void _setTextureUnitSettings(size_t texUnit, TextureUnitState& tl);
+        /** Turns off a texture unit. */
+        virtual void _disableTextureUnit(size_t texUnit);
+        /** Disables all texture units from the given unit upwards */
+        virtual void _disableTextureUnitsFrom(size_t texUnit);
+        /** Sets the surface properties to be used for future rendering.
+
+            This method sets the the properties of the surfaces of objects
+            to be rendered after it. In this context these surface properties
+            are the amount of each type of light the object reflects (determining
+            it's colour under different types of light), whether it emits light
+            itself, and how shiny it is. Textures are not dealt with here,
+            see the _setTetxure method for details.
+            This method is used by _setMaterial so does not need to be called
+            direct if that method is being used.
+
+            @param ambient The amount of ambient (sourceless and directionless)
+            light an object reflects. Affected by the colour/amount of ambient light in the scene.
+            @param diffuse The amount of light from directed sources that is
+            reflected (affected by colour/amount of point, directed and spot light sources)
+            @param specular The amount of specular light reflected. This is also
+            affected by directed light sources but represents the colour at the
+            highlights of the object.
+            @param emissive The colour of light emitted from the object. Note that
+            this will make an object seem brighter and not dependent on lights in
+            the scene, but it will not act as a light, so will not illuminate other
+            objects. Use a light attached to the same SceneNode as the object for this purpose.
+            @param shininess A value which only has an effect on specular highlights (so
+            specular must be non-black). The higher this value, the smaller and crisper the
+            specular highlights will be, imitating a more highly polished surface.
+            This value is not constrained to 0.0-1.0, in fact it is likely to
+            be more (10.0 gives a modest sheen to an object).
+            @param tracking A bit field that describes which of the ambient, diffuse, specular
+            and emissive colours follow the vertex colour of the primitive. When a bit in this field is set
+            its ColourValue is ignored. This is a combination of TVC_AMBIENT, TVC_DIFFUSE, TVC_SPECULAR(note that the shininess value is still
+            taken from shininess) and TVC_EMISSIVE. TVC_NONE means that there will be no material property
+            tracking the vertex colours.
+        */
+        virtual void _setSurfaceParams(const ColourValue &ambient,
+            const ColourValue &diffuse, const ColourValue &specular,
+            const ColourValue &emissive, Real shininess,
+            TrackVertexColourType tracking = TVC_NONE) = 0;
+        /**
+          Sets the status of a single texture stage.
+
+          Sets the details of a texture stage, to be used for all primitives
+          rendered afterwards. User processes would
+          not normally call this direct unless rendering
+          primitives themselves - the SubEntity class
+          is designed to manage materials for objects.
+          Note that this method is called by _setMaterial.
+
+          @param unit The index of the texture unit to modify. Multitexturing hardware
+          can support multiple units (see RenderSystemCapabilites::numTextureUnits)
+          @param enabled Boolean to turn the unit on/off
+          @param texname The name of the texture to use - this should have
+              already been loaded with TextureManager::load.
+         */
+        virtual void _setTexture(size_t unit, bool enabled, const String &texname) = 0;
+
+        /**
+          Sets the texture coordinate set to use for a texture unit.
+
+          Meant for use internally - not generally used directly by apps - the Material and TextureUnitState
+          classes let you manage textures far more easily.
+
+          @param unit Texture unit as above
+          @param index The index of the texture coordinate set to use.
+         */
+        virtual void _setTextureCoordSet(size_t unit, size_t index) = 0;
+
+        /**
+          Sets a method for automatically calculating texture coordinates for a stage.
+          Should not be used by apps - for use by Ogre only.
+          @param unit Texture unit as above
+          @param m Calculation method to use
+          @param frustum Optional Frustum param, only used for projective effects
+         */
+        virtual void _setTextureCoordCalculation(size_t unit, TexCoordCalcMethod m, 
+            const Frustum* frustum = 0) = 0;
+
+        /** Sets the texture blend modes from a TextureUnitState record.
+            Meant for use internally only - apps should use the Material
+            and TextureUnitState classes.
+            @param unit Texture unit as above
+            @param bm Details of the blending mode
+        */
+        virtual void _setTextureBlendMode(size_t unit, const LayerBlendModeEx& bm) = 0;
+
+        /** Sets the filtering options for a given texture unit.
+        @param unit The texture unit to set the filtering options for
+        @param minFilter The filter used when a texture is reduced in size
+        @param magFilter The filter used when a texture is magnified
+        @param mipFilter The filter used between mipmap levels, FO_NONE disables mipmapping
+        */
+        virtual void _setTextureUnitFiltering(size_t unit, FilterOptions minFilter,
+            FilterOptions magFilter, FilterOptions mipFilter);
+
+        /** Sets a single filter for a given texture unit.
+        @param unit The texture unit to set the filtering options for
+        @param ftype The filter type
+        @param filter The filter to be used
+        */
+        virtual void _setTextureUnitFiltering(size_t unit, FilterType ftype, FilterOptions filter) = 0;
+
+		/** Sets the maximal anisotropy for the specified texture unit.*/
+		virtual void _setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy) = 0;
+
+		/** Sets the texture addressing mode for a texture unit.*/
+        virtual void _setTextureAddressingMode(size_t unit, TextureUnitState::TextureAddressingMode tam) = 0;
+
+        /** Sets the texture coordinate transformation matrix for a texture unit.
+            @param unit Texture unit to affect
+            @param xform The 4x4 matrix
+        */
+        virtual void _setTextureMatrix(size_t unit, const Matrix4& xform) = 0;
+
+        /** Sets the global blending factors for combining subsequent renders with the existing frame contents.
+            The result of the blending operation is:</p>
+            <p align="center">final = (texture * sourceFactor) + (pixel * destFactor)</p>
+            Each of the factors is specified as one of a number of options, as specified in the SceneBlendFactor
+            enumerated type.
+            @param sourceFactor The source factor in the above calculation, i.e. multiplied by the texture colour components.
+            @param destFactor The destination factor in the above calculation, i.e. multiplied by the pixel colour components.
+        */
+        virtual void _setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor) = 0;
+
+        /** Sets the global alpha rejection approach for future renders.
+            By default images are rendered regardless of texture alpha. This method lets you change that.
+            @param func The comparison function which must pass for a pixel to be written.
+            @param val The value to compare each pixels alpha value to (0-255)
+        */
+        virtual void _setAlphaRejectSettings(CompareFunction func, unsigned char value) = 0;
+        /**
+         * Signifies the beginning of a frame, ie the start of rendering on a single viewport. Will occur
+         * several times per complete frame if multiple viewports exist.
+         */
+        virtual void _beginFrame(void) = 0;
+
+
+        /**
+         * Ends rendering of a frame to the current viewport.
+         */
+        virtual void _endFrame(void) = 0;
+        /**
+          Sets the provided viewport as the active one for future
+          rendering operations. This viewport is aware of it's own
+          camera and render target. Must be implemented by subclass.
+
+          @param target Pointer to the appropriate viewport.
+         */
+        virtual void _setViewport(Viewport *vp) = 0;
+        /** Get the current active viewport for rendering. */
+        virtual Viewport* _getViewport(void);
+
+        /** Sets the culling mode for the render system based on the 'vertex winding'.
+            A typical way for the rendering engine to cull triangles is based on the
+            'vertex winding' of triangles. Vertex winding refers to the direction in
+            which the vertices are passed or indexed to in the rendering operation as viewed
+            from the camera, and will wither be clockwise or anticlockwise (that's 'counterclockwise' for
+            you Americans out there ;) The default is CULL_CLOCKWISE i.e. that only triangles whose vertices
+            are passed/indexed in anticlockwise order are rendered - this is a common approach and is used in 3D studio models
+            for example. You can alter this culling mode if you wish but it is not advised unless you know what you are doing.
+            You may wish to use the CULL_NONE option for mesh data that you cull yourself where the vertex
+            winding is uncertain.
+        */
+        virtual void _setCullingMode(CullingMode mode) = 0;
+
+        virtual CullingMode _getCullingMode(void) const;
+
+        /** Sets the mode of operation for depth buffer tests from this point onwards.
+            Sometimes you may wish to alter the behaviour of the depth buffer to achieve
+            special effects. Because it's unlikely that you'll set these options for an entire frame,
+            but rather use them to tweak settings between rendering objects, this is an internal
+            method (indicated by the '_' prefix) which will be used by a SceneManager implementation
+            rather than directly from the client application.
+            If this method is never called the settings are automatically the same as the default parameters.
+            @param depthTest If true, the depth buffer is tested for each pixel and the frame buffer is only updated
+                if the depth function test succeeds. If false, no test is performed and pixels are always written.
+            @param depthWrite If true, the depth buffer is updated with the depth of the new pixel if the depth test succeeds.
+                If false, the depth buffer is left unchanged even if a new pixel is written.
+            @param depthFunction Sets the function required for the depth test.
+        */
+        virtual void _setDepthBufferParams(bool depthTest = true, bool depthWrite = true, CompareFunction depthFunction = CMPF_LESS_EQUAL) = 0;
+
+        /** Sets whether or not the depth buffer check is performed before a pixel write.
+            @param enabled If true, the depth buffer is tested for each pixel and the frame buffer is only updated
+                if the depth function test succeeds. If false, no test is performed and pixels are always written.
+        */
+        virtual void _setDepthBufferCheckEnabled(bool enabled = true) = 0;
+        /** Sets whether or not the depth buffer is updated after a pixel write.
+            @param enabled If true, the depth buffer is updated with the depth of the new pixel if the depth test succeeds.
+                If false, the depth buffer is left unchanged even if a new pixel is written.
+        */
+        virtual void _setDepthBufferWriteEnabled(bool enabled = true) = 0;
+        /** Sets the comparison function for the depth buffer check.
+            Advanced use only - allows you to choose the function applied to compare the depth values of
+            new and existing pixels in the depth buffer. Only an issue if the deoth buffer check is enabled
+            (see _setDepthBufferCheckEnabled)
+            @param  func The comparison between the new depth and the existing depth which must return true
+             for the new pixel to be written.
+        */
+        virtual void _setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL) = 0;
+		/** Sets whether or not colour buffer writing is enabled, and for which channels. 
+		@remarks
+			For some advanced effects, you may wish to turn off the writing of certain colour
+			channels, or even all of the colour channels so that only the depth buffer is updated
+			in a rendering pass. However, the chances are that you really want to use this option
+			through the Material class.
+		@param red, green, blue, alpha Whether writing is enabled for each of the 4 colour channels. */
+		virtual void _setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha) = 0;
+        /** Sets the depth bias, NB you should use the Material version of this. 
+        @remarks
+            When polygons are coplanar, you can get problems with 'depth fighting' where
+            the pixels from the two polys compete for the same screen pixel. This is particularly
+            a problem for decals (polys attached to another surface to represent details such as
+            bulletholes etc.).
+        @par
+            A way to combat this problem is to use a depth bias to adjust the depth buffer value
+            used for the decal such that it is slightly higher than the true value, ensuring that
+            the decal appears on top.
+        @param bias The bias value, should be between 0 and 16.
+        */
+        virtual void _setDepthBias(ushort bias) = 0;
+        /** Sets the fogging mode for future geometry.
+            @param mode Set up the mode of fog as described in the FogMode enum, or set to FOG_NONE to turn off.
+            @param colour The colour of the fog. Either set this to the same as your viewport background colour,
+                or to blend in with a skydome or skybox.
+            @param expDensity The density of the fog in FOG_EXP or FOG_EXP2 mode, as a value between 0 and 1. The default is 1. i.e. completely opaque, lower values can mean
+                that fog never completely obscures the scene.
+            @param linearStart Distance at which linear fog starts to encroach. The distance must be passed
+                as a parametric value between 0 and 1, with 0 being the near clipping plane, and 1 being the far clipping plane. Only applicable if mode is FOG_LINEAR.
+            @param linearEnd Distance at which linear fog becomes completely opaque.The distance must be passed
+                as a parametric value between 0 and 1, with 0 being the near clipping plane, and 1 being the far clipping plane. Only applicable if mode is FOG_LINEAR.
+        */
+        virtual void _setFog(FogMode mode = FOG_NONE, const ColourValue& colour = ColourValue::White, Real expDensity = 1.0, Real linearStart = 0.0, Real linearEnd = 1.0) = 0;
+
+
+        /** The RenderSystem will keep a count of tris rendered, this resets the count. */
+        virtual void _beginGeometryCount(void);
+        /** Reports the number of tris rendered since the last _beginGeometryCount call. */
+        virtual unsigned int _getFaceCount(void) const;
+        /** Reports the number of vertices passed to the renderer since the last _beginGeometryCount call. */
+        virtual unsigned int _getVertexCount(void) const;
+
+        /** Generates a packed data version of the passed in ColourValue suitable for
+            use as with this RenderSystem.
+        @remarks
+            Since different render systems have different colour data formats (eg
+            RGBA for GL, ARGB for D3D) this method allows you to use 1 method for all.
+        @param colour The colour to convert
+        @param pDest Pointer to location to put the result.
+        */
+        virtual void convertColourValue(const ColourValue& colour, uint32* pDest) = 0;
+
+        /** Builds a perspective projection matrix suitable for this render system.
+        @remarks
+            Because different APIs have different requirements (some incompatible) for the
+            projection matrix, this method allows each to implement their own correctly and pass
+            back a generic OGRE matrix for storage in the engine.
+        */
+        virtual void _makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane, 
+            Matrix4& dest, bool forGpuProgram = false) = 0;
+
+        /** Builds a perspective projection matrix for the case when frustum is
+            not centered around camera.
+        @remarks
+            Viewport coordinates are in camera coordinate frame, i.e. camera is 
+            at the origin.
+        */
+        virtual void _makeProjectionMatrix(Real left, Real right, Real bottom, Real top, 
+            Real nearPlane, Real farPlane, Matrix4& dest, bool forGpuProgram = false) = 0;
+        /** Builds an orthographic projection matrix suitable for this render system.
+        @remarks
+            Because different APIs have different requirements (some incompatible) for the
+            projection matrix, this method allows each to implement their own correctly and pass
+            back a generic OGRE matrix for storage in the engine.
+        */
+        virtual void _makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane, 
+            Matrix4& dest, bool forGpuProgram = false) = 0;
+
+		/** Update a perspective projection matrix to use 'oblique depth projection'.
+		@remarks
+			This method can be used to change the nature of a perspective 
+			transform in order to make the near plane not perpendicular to the 
+			camera view direction, but to be at some different orientation. 
+			This can be useful for performing arbitrary clipping (e.g. to a 
+			reflection plane) which could otherwise only be done using user
+			clip planes, which are more expensive, and not necessarily supported
+			on all cards.
+		@param matrix The existing projection matrix. Note that this must be a
+			perspective transform (not orthographic), and must not have already
+			been altered by this method. The matrix will be altered in-place.
+		@param plane The plane which is to be used as the clipping plane. This
+			plane must be in CAMERA (view) space.
+        @param forGpuProgram Is this for use with a Gpu program or fixed-function
+		*/
+		virtual void _applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane, 
+            bool forGpuProgram) = 0;
+		
+        /** Sets how to rasterise triangles, as points, wireframe or solid polys. */
+        virtual void _setRasterisationMode(SceneDetailLevel level) = 0;
+
+        /** Turns stencil buffer checking on or off. 
+        @remarks
+            Stencilling (masking off areas of the rendering target based on the stencil 
+            buffer) canbe turned on or off using this method. By default, stencilling is
+            disabled.
+        */
+        virtual void setStencilCheckEnabled(bool enabled) = 0;
+        /** Determines if this system supports hardware accelerated stencil buffer. 
+        @remarks
+            Note that the lack of this function doesn't mean you can't do stencilling, but
+            the stencilling operations will be provided in software, which will NOT be
+            fast.
+        @par
+            Generally hardware stencils are only supported in 32-bit colour modes, because
+            the stencil buffer shares the memory of the z-buffer, and in most cards the 
+            z-buffer has to be the same depth as the colour buffer. This means that in 32-bit
+            mode, 24 bits of the z-buffer are depth and 8 bits are stencil. In 16-bit mode there
+            is no room for a stencil (although some cards support a 15:1 depth:stencil option,
+            this isn't useful for very much) so 8 bits of stencil are provided in software.
+            This can mean that if you use stencilling, your applications may be faster in 
+            32-but colour than in 16-bit, which may seem odd to some people.
+        */
+        /*virtual bool hasHardwareStencil(void) = 0;*/
+
+        /** This method allows you to set all the stencil buffer parameters in one call.
+        @remarks
+            The stencil buffer is used to mask out pixels in the render target, allowing
+            you to do effects like mirrors, cut-outs, stencil shadows and more. Each of
+            your batches of rendering is likely to ignore the stencil buffer, 
+            update it with new values, or apply it to mask the output of the render.
+            The stencil test is:<PRE>
+            (Reference Value & Mask) CompareFunction (Stencil Buffer Value & Mask)</PRE>
+            The result of this will cause one of 3 actions depending on whether the test fails,
+            succeeds but with the depth buffer check still failing, or succeeds with the
+            depth buffer check passing too.
+        @par
+            Unlike other render states, stencilling is left for the application to turn
+            on and off when it requires. This is because you are likely to want to change
+            parameters between batches of arbitrary objects and control the ordering yourself.
+            In order to batch things this way, you'll want to use OGRE's separate render queue
+            groups (see RenderQueue) and register a RenderQueueListener to get notifications
+            between batches.
+        @par
+            There are individual state change methods for each of the parameters set using 
+            this method. 
+            Note that the default values in this method represent the defaults at system 
+            start up too.
+        @param func The comparison function applied.
+        @param refValue The reference value used in the comparison
+        @param mask The bitmask applied to both the stencil value and the reference value 
+            before comparison
+        @param stencilFailOp The action to perform when the stencil check fails
+        @param depthFailOp The action to perform when the stencil check passes, but the
+            depth buffer check still fails
+        @param passOp The action to take when both the stencil and depth check pass.
+        @param twoSidedOperation If set to true, then if you render both back and front faces 
+            (you'll have to turn off culling) then these parameters will apply for front faces, 
+            and the inverse of them will happen for back faces (keep remains the same).
+        */
+        virtual void setStencilBufferParams(CompareFunction func = CMPF_ALWAYS_PASS, 
+            uint32 refValue = 0, uint32 mask = 0xFFFFFFFF, 
+            StencilOperation stencilFailOp = SOP_KEEP, 
+            StencilOperation depthFailOp = SOP_KEEP,
+            StencilOperation passOp = SOP_KEEP, 
+            bool twoSidedOperation = false) = 0;
+
+
+
+		/** Sets the current vertex declaration, ie the source of vertex data. */
+		virtual void setVertexDeclaration(VertexDeclaration* decl) = 0;
+		/** Sets the current vertex buffer binding state. */
+		virtual void setVertexBufferBinding(VertexBufferBinding* binding) = 0;
+
+        /** Sets whether or not normals are to be automatically normalised.
+        @remarks
+            This is useful when, for example, you are scaling SceneNodes such that
+            normals may not be unit-length anymore. Note though that this has an
+            overhead so should not be turn on unless you really need it.
+        @par
+            You should not normally call this direct unless you are rendering
+            world geometry; set it on the Renderable because otherwise it will be
+            overridden by material settings. 
+        */
+        virtual void setNormaliseNormals(bool normalise) = 0;
+
+        /**
+          Render something to the active viewport.
+
+          Low-level rendering interface to perform rendering
+          operations. Unlikely to be used directly by client
+          applications, since the SceneManager and various support
+          classes will be responsible for calling this method.
+          Can only be called between _beginScene and _endScene
+
+          @param op A rendering operation instance, which contains
+            details of the operation to be performed.
+         */
+        virtual void _render(const RenderOperation& op);
+
+		/** Gets the capabilities of the render system. */
+		const RenderSystemCapabilities* getCapabilities(void) const { return mCapabilities; }
+
+        /** Binds a given GpuProgram (but not the parameters). 
+        @remarks Only one GpuProgram of each type can be bound at once, binding another
+        one will simply replace the exsiting one.
+        */
+        virtual void bindGpuProgram(GpuProgram* prg) = 0;
+
+        /** Bind Gpu program parameters. */
+        virtual void bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params) = 0;
+        /** Unbinds GpuPrograms of a given GpuProgramType.
+        @remarks
+            This returns the pipeline to fixed-function processing for this type.
+        */
+        virtual void unbindGpuProgram(GpuProgramType gptype) = 0;
+
+        /** sets the clipping region.
+        */
+        virtual void setClipPlanes(const PlaneList& clipPlanes) = 0;
+
+        /** Utility method for initialising all render targets attached to this rendering system. */
+        virtual void _initRenderTargets(void);
+
+        /** Utility method to notify all render targets that a camera has been removed, 
+            incase they were referring to it as their viewer. 
+        */
+        virtual void _notifyCameraRemoved(const Camera* cam);
+
+        /** Internal method for updating all render targets attached to this rendering system. */
+        virtual void _updateAllRenderTargets(void);
+
+        /** Set a clipping plane. */
+        virtual void setClipPlane (ushort index, const Plane &p);
+        /** Set a clipping plane. */
+        virtual void setClipPlane (ushort index, Real A, Real B, Real C, Real D) = 0;
+        /** Enable the clipping plane. */
+        virtual void enableClipPlane (ushort index, bool enable) = 0;
+
+        /** Sets whether or not vertex windings set should be inverted; this can be important
+            for rendering reflections. */
+        virtual void setInvertVertexWinding(bool invert);
+        /** Sets the 'scissor region' ie the region of the target in which rendering can take place.
+        @remarks
+            This method allows you to 'mask off' rendering in all but a given rectangular area
+            as identified by the parameters to this method.
+        @note
+            Not all systems support this method. Check the RenderSystemCapabilities for the
+            RSC_SCISSOR_TEST capability to see if it is supported.
+        @param enabled True to enable the scissor test, false to disable it.
+        @param left, top, right, bottom The location of the corners of the rectangle, expressed in
+            <i>pixels</i>.
+        */
+        virtual void setScissorTest(bool enabled, size_t left = 0, size_t top = 0, 
+            size_t right = 800, size_t bottom = 600) = 0;
+
+        /** Clears one or more frame buffers on the active render target. 
+        @param buffers Combination of one or more elements of FrameBufferType
+            denoting which buffers are to be cleared
+        @param colour The colour to clear the colour buffer with, if enabled
+        @param depth The value to initialise the depth buffer with, if enabled
+        @param stencil The value to initialise the stencil buffer with, if enabled.
+        */
+        virtual void clearFrameBuffer(unsigned int buffers, 
+            const ColourValue& colour = ColourValue::Black, 
+            Real depth = 1.0f, unsigned short stencil = 0) = 0;
+        /** Returns the horizontal texel offset value required for mapping 
+            texel origins to pixel origins in this rendersystem.
+        @remarks
+            Since rendersystems sometimes disagree on the origin of a texel, 
+            mapping from texels to pixels can sometimes be problematic to 
+            implement generically. This method allows you to retrieve the offset
+            required to map the origin of a texel to the origin of a pixel in
+            the horizontal direction.
+        */
+        virtual Real getHorizontalTexelOffset(void) = 0;
+        /** Returns the vertical texel offset value required for mapping 
+        texel origins to pixel origins in this rendersystem.
+        @remarks
+        Since rendersystems sometimes disagree on the origin of a texel, 
+        mapping from texels to pixels can sometimes be problematic to 
+        implement generically. This method allows you to retrieve the offset
+        required to map the origin of a texel to the origin of a pixel in
+        the vertical direction.
+        */
+        virtual Real getVerticalTexelOffset(void) = 0;
+
+        /** Gets the minimum (closest) depth value to be used when rendering
+            using identity transforms.
+        @remarks
+            When using identity transforms you can manually set the depth
+            of a vertex; however the input values required differ per
+            rendersystem. This method lets you retrieve the correct value.
+        @see Renderable::useIdentityView, Renderable::useIdentityProjection
+        */
+        virtual Real getMinimumDepthInputValue(void) = 0;
+        /** Gets the maximum (farthest) depth value to be used when rendering
+            using identity transforms.
+        @remarks
+            When using identity transforms you can manually set the depth
+            of a vertex; however the input values required differ per
+            rendersystem. This method lets you retrieve the correct value.
+        @see Renderable::useIdentityView, Renderable::useIdentityProjection
+        */
+        virtual Real getMaximumDepthInputValue(void) = 0;
+
+    protected:
+
+
+        /** The render targets. */
+        RenderTargetMap mRenderTargets;
+		/** The render targets, ordered by priority. */
+		RenderTargetPriorityMap mPrioritisedRenderTargets;
+		/** The Active render target. */
+		RenderTarget * mActiveRenderTarget;
+
+        // Texture manager
+        // A concrete class of this will be created and
+        // made available under the TextureManager singleton,
+        // managed by the RenderSystem
+        TextureManager* mTextureManager;
+
+        /// Used to store the capabilities of the graphics card
+        RenderSystemCapabilities* mCapabilities;
+
+        // Active viewport (dest for future rendering operations)
+        Viewport* mActiveViewport;
+
+        CullingMode mCullingMode;
+
+        bool mVSync;
+		bool mWBuffer;
+
+        size_t mFaceCount;
+        size_t mVertexCount;
+
+        /// Saved set of world matrices
+        Matrix4 mWorldMatrices[256];
+
+		/// Saved manual colour blends
+		ColourValue mManualBlendColours[OGRE_MAX_TEXTURE_LAYERS][2];
+
+        bool mInvertVertexWinding;
+    };
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreFrustum.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreFrustum.h	(revision 61)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreFrustum.h	(revision 61)
@@ -0,0 +1,474 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Frustum_H__
+#define __Frustum_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreMovableObject.h"
+#include "OgreRenderable.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreVertexIndexData.h"
+#include "OgreMovablePlane.h"
+
+namespace Ogre
+{
+    /** Specifies perspective (realistic) or orthographic (architectural) projection.
+    */
+    enum ProjectionType
+    {
+        PT_ORTHOGRAPHIC,
+        PT_PERSPECTIVE
+    };
+
+    /** Worldspace clipping planes.
+    */
+    enum FrustumPlane
+    {
+        FRUSTUM_PLANE_NEAR   = 0,
+        FRUSTUM_PLANE_FAR    = 1,
+        FRUSTUM_PLANE_LEFT   = 2,
+        FRUSTUM_PLANE_RIGHT  = 3,
+        FRUSTUM_PLANE_TOP    = 4,
+        FRUSTUM_PLANE_BOTTOM = 5
+    };
+
+    /** A frustum represents a pyramid, capped at the near and far end which is
+        used to represent either a visible area or a projection area. Can be used
+        for a number of applications.
+    */
+    class _OgreExport Frustum : public MovableObject, public Renderable
+    {
+    protected:
+        /// Orthographic or perspective?
+        ProjectionType mProjType;
+
+        /// y-direction field-of-view (default 45)
+        Radian mFOVy;
+        /// Far clip distance - default 10000
+        Real mFarDist;
+        /// Near clip distance - default 100
+        Real mNearDist;
+        /// x/y viewport ratio - default 1.3333
+        Real mAspect;
+
+        /// The 6 main clipping planes
+        mutable Plane mFrustumPlanes[6];
+
+        /// Stored versions of parent orientation / position
+        mutable Quaternion mLastParentOrientation;
+        mutable Vector3 mLastParentPosition;
+
+        /// Pre-calced projection matrix
+        mutable Matrix4 mProjMatrix;
+        /// Pre-calced standard projection matrix
+        mutable Matrix4 mStandardProjMatrix;
+        /// Pre-calced view matrix
+        mutable Matrix4 mViewMatrix;
+        /// Something's changed in the frustrum shape?
+        mutable bool mRecalcFrustum;
+        /// Something re the view pos has changed
+        mutable bool mRecalcView;
+
+
+        /** Temp coefficient values calculated from a frustum change,
+            used when establishing the frustum planes when the view changes
+        */
+        mutable Real mCoeffL[2], mCoeffR[2], mCoeffB[2], mCoeffT[2];
+
+
+
+		
+        // Internal functions for calcs
+        virtual void updateFrustum(void) const;
+        virtual void updateView(void) const;
+        virtual bool isViewOutOfDate(void) const;
+        virtual bool isFrustumOutOfDate(void) const;
+        /// Signal to update frustum information.
+        virtual void invalidateFrustum(void) const;
+        /// Signal to update view information.
+        virtual void invalidateView(void) const;
+
+        /// Shared class-level name for Movable type
+        static String msMovableType;
+
+        mutable AxisAlignedBox mBoundingBox;
+        mutable VertexData mVertexData;
+
+        MaterialPtr mMaterial;
+        mutable Vector3 mWorldSpaceCorners[8];
+
+        /// Is this frustum to act as a reflection of itself?
+        bool mReflect;
+		/// Derived reflection matrix
+        mutable Matrix4 mReflectMatrix;
+        /// Fixed reflection plane
+		mutable Plane mReflectPlane;
+		/// Pointer to a reflection plane (automatically updated)
+		const MovablePlane* mLinkedReflectPlane;
+		/// Record of the last world-space reflection plane info used
+		mutable Plane mLastLinkedReflectionPlane;
+		
+        /// Is this frustum using an oblique depth projection?
+		bool mObliqueDepthProjection;
+		/// Fixed oblique projection plane
+		mutable Plane mObliqueProjPlane;
+		/// Pointer to oblique projection plane (automatically updated)
+		const MovablePlane* mLinkedObliqueProjPlane;
+		/// Record of the last world-space oblique depth projection plane info used
+		mutable Plane mLastLinkedObliqueProjPlane;
+
+		
+		/** Get the derived position of this frustum. */
+        virtual const Vector3& getPositionForViewUpdate(void) const;
+        /** Get the derived orientation of this frustum. */
+        virtual const Quaternion& getOrientationForViewUpdate(void) const;
+
+
+    public:
+
+        Frustum();
+        virtual ~Frustum();
+        /** Sets the Y-dimension Field Of View (FOV) of the frustum.
+            @remarks
+                Field Of View (FOV) is the angle made between the frustum's position, and the edges
+                of the 'screen' onto which the scene is projected. High values (90+ degrees) result in a wide-angle,
+                fish-eye kind of view, low values (30- degrees) in a stretched, telescopic kind of view. Typical values
+                are between 45 and 60 degrees.
+            @par
+                This value represents the VERTICAL field-of-view. The horizontal field of view is calculated from
+                this depending on the dimensions of the viewport (they will only be the same if the viewport is square).
+            @note
+                Setting the FOV overrides the value supplied for frustum::setNearClipPlane.
+         */
+        virtual void setFOVy(const Radian& fovy);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        inline void setFOVy(Real fovy) {
+            setFOVy ( Angle(fovy) );
+        }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Retrieves the frustums Y-dimension Field Of View (FOV).
+        */
+        virtual const Radian& getFOVy(void) const;
+
+        /** Sets the position of the near clipping plane.
+            @remarks
+                The position of the near clipping plane is the distance from the frustums position to the screen
+                on which the world is projected. The near plane distance, combined with the field-of-view and the
+                aspect ratio, determines the size of the viewport through which the world is viewed (in world
+                co-ordinates). Note that this world viewport is different to a screen viewport, which has it's
+                dimensions expressed in pixels. The frustums viewport should have the same aspect ratio as the
+                screen viewport it renders into to avoid distortion.
+            @param
+                near The distance to the near clipping plane from the frustum in world coordinates.
+         */
+        virtual void setNearClipDistance(Real nearDist);
+
+        /** Sets the position of the near clipping plane.
+        */
+        virtual Real getNearClipDistance(void) const;
+
+        /** Sets the distance to the far clipping plane.
+            @remarks
+                The view frustrum is a pyramid created from the frustum position and the edges of the viewport.
+                This method sets the distance for the far end of that pyramid. 
+                Different applications need different values: e.g. a flight sim
+                needs a much further far clipping plane than a first-person 
+                shooter. An important point here is that the larger the ratio 
+                between near and far clipping planes, the lower the accuracy of
+                the Z-buffer used to depth-cue pixels. This is because the
+                Z-range is limited to the size of the Z buffer (16 or 32-bit) 
+                and the max values must be spread over the gap between near and
+                far clip planes. As it happens, you can affect the accuracy far 
+                more by altering the near distance rather than the far distance, 
+                but keep this in mind.
+            @param
+                far The distance to the far clipping plane from the frustum in 
+                world coordinates.If you specify 0, this means an infinite view
+                distance which is useful especially when projecting shadows; but
+                be careful not to use a near distance too close.
+        */
+        virtual void setFarClipDistance(Real farDist);
+
+        /** Retrieves the distance from the frustum to the far clipping plane.
+        */
+        virtual Real getFarClipDistance(void) const;
+
+        /** Sets the aspect ratio for the frustum viewport.
+            @remarks
+                The ratio between the x and y dimensions of the rectangular area visible through the frustum
+                is known as aspect ratio: aspect = width / height .
+            @par
+                The default for most fullscreen windows is 1.3333 - this is also assumed by Ogre unless you
+                use this method to state otherwise.
+        */
+        virtual void setAspectRatio(Real ratio);
+
+        /** Retreives the current aspect ratio.
+        */
+        virtual Real getAspectRatio(void) const;
+
+        /** Gets the projection matrix for this frustum. Mainly for use by OGRE internally.
+        @remarks
+            This method retrieves the rendering-API dependent version of the projection
+            matrix. If you want a 'typical' projection matrix then use 
+            getStandardProjectionMatrix.
+
+        */
+        virtual const Matrix4& getProjectionMatrix(void) const;
+        /** Gets the 'standard' projection matrix for this frustum, ie the 
+        projection matrix which conforms to standard right-handed rules.
+        @remarks
+            This differs from the rendering-API dependent getProjectionMatrix
+            in that it always returns a right-handed projection matrix result 
+            no matter what rendering API is being used - this is required for
+            vertex and fragment programs for example. However, the resulting depth
+            range may still vary between render systems since D3D uses [0,1] and 
+            GL uses [-1,1], and the range must be kept the same between programmable
+            and fixed-function pipelines.
+        */
+        virtual const Matrix4& getStandardProjectionMatrix(void) const;
+
+        /** Gets the view matrix for this frustum. Mainly for use by OGRE internally.
+        */
+        virtual const Matrix4& getViewMatrix(void) const;
+
+        /** Retrieves a specified plane of the frustum.
+            @remarks
+                Gets a reference to one of the planes which make up the frustum frustum, e.g. for clipping purposes.
+        */
+        virtual const Plane& getFrustumPlane( unsigned short plane ) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding box to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding sphere to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the sphere was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Sphere& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given vertex is visible in the Frustum.
+            @param
+                vert Vertex to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
+
+
+        /** Overridden from MovableObject */
+        const AxisAlignedBox& getBoundingBox(void) const;
+
+        /** Overridden from MovableObject */
+		Real getBoundingRadius(void) const;
+
+		/** Overridden from MovableObject */
+        void _updateRenderQueue(RenderQueue* queue);
+
+        /** Overridden from MovableObject */
+        const String& getMovableType(void) const;
+
+        /** Overridden from MovableObject */
+        const String& getName(void) const;
+
+        /** Overridden from MovableObject */
+        void _notifyCurrentCamera(Camera* cam);
+
+        /** Overridden from Renderable */
+        const MaterialPtr& getMaterial(void) const;
+
+        /** Overridden from Renderable */
+        void getRenderOperation(RenderOperation& op);
+
+        /** Overridden from Renderable */
+        void getWorldTransforms(Matrix4* xform) const;
+
+        /** Overridden from Renderable */
+        const Quaternion& getWorldOrientation(void) const;
+
+        /** Overridden from Renderable */
+        const Vector3& getWorldPosition(void) const;
+
+        /** Overridden from Renderable */
+        Real getSquaredViewDepth(const Camera* cam) const;
+
+        /** Overridden from Renderable */
+        const LightList& getLights(void) const;
+
+        /** Gets the world space corners of the frustum.
+        @remarks
+            The corners are ordered as follows: top-right near, 
+            top-left near, bottom-left near, bottom-right near, 
+            top-right far, top-left far, bottom-left far, bottom-right far.
+        */
+        virtual const Vector3* getWorldSpaceCorners(void) const;
+
+        /** Sets the type of projection to use (orthographic or perspective). Default is perspective.
+        */
+        virtual void setProjectionType(ProjectionType pt);
+
+        /** Retrieves info on the type of projection used (orthographic or perspective).
+        */
+        virtual ProjectionType getProjectionType(void) const;
+
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const Plane& p);
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified. Note that this version of the method links to a plane
+		so that changes to it are picked up automatically. It is important that
+		this plane continues to exist whilst this object does; do not destroy
+		the plane before the frustum.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const MovablePlane* p);
+
+        /** Disables reflection modification previously turned on with enableReflection */
+        virtual void disableReflection(void);
+
+        /// Returns whether this frustum is being reflected
+        virtual bool isReflected(void) const { return mReflect; }
+        /// Returns the reflection matrix of the frustum if appropriate
+        virtual const Matrix4& getReflectionMatrix(void) const { return mReflectMatrix; }
+        /// Returns the reflection plane of the frustum if appropriate
+        virtual const Plane& getReflectionPlane(void) const { return mReflectPlane; }
+
+        /** Project a sphere onto the near plane and get the bounding rectangle. 
+        @param sphere The world-space sphere to project
+        @param radius Radius of the sphere
+        @param left, top, right, bottom Pointers to destination values, these
+            will be completed with the normalised device coordinates (in the 
+            range {-1,1})
+        @returns true if the sphere was projected to a subset of the near plane,
+            false if the entire near plane was contained
+        */
+        virtual bool projectSphere(const Sphere& sphere, 
+            Real* left, Real* top, Real* right, Real* bottom) const;
+
+
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to 
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@par 
+			This version of the method links to a plane, rather than requiring
+			a by-value plane definition, and therefore you can 
+			make changes to the plane (e.g. by moving / rotating the node it is
+			attached to) and they will automatically affect this object.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const MovablePlane* plane);
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to  
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const Plane& plane);
+		/** Disables any custom near clip plane. */
+		virtual void disableCustomNearClipPlane(void);
+		
+
+        /// Small constant used to reduce far plane projection to avoid inaccuracies
+        static const Real INFINITE_FAR_PLANE_ADJUST;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		//added by matt: 050405
+		/** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding box to be checked
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+			@param
+				intersects returns the information if the box intersects the near plane.
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy = 0) const;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    };
+
+
+}
+
+#endif 
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderQueueSortingGrouping.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderQueueSortingGrouping.h	(revision 343)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderQueueSortingGrouping.h	(revision 343)
@@ -0,0 +1,411 @@
+/*
+-----------------------------------------------------------------------------
+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 __RenderQueueSortingGrouping_H__
+#define __RenderQueueSortingGrouping_H__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreIteratorWrappers.h"
+#include "OgreMaterial.h"
+#include "OgreTechnique.h"
+#include "OgrePass.h"
+#include "OgreMaterialManager.h"
+
+namespace Ogre {
+
+    /** Renderables in the queue grouped by priority.
+    @remarks
+        This class simply groups renderables for rendering. All the 
+        renderables contained in this class are destined for the same
+        RenderQueueGroup (coarse groupings like those between the main
+        scene and overlays) and have the same priority (fine groupings
+        for detailed overlap control).
+    @par
+        This class optimises the grouped renderables by sorting them by
+        material to reduce render state changes, and outsorts transparent
+        objects.
+    */
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	class _OgreExport RenderPriorityGroup
+#else
+    class _OgrePrivate RenderPriorityGroup
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    {
+        /** Internal struct reflecting a single Pass for a Renderable. 
+        This is used to sort transparent objects.
+        */
+        struct RenderablePass
+        {
+            /// Pointer to the Renderable details
+            Renderable* renderable;
+            /// Pointer to the Pass
+            Pass* pass;
+
+            RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
+        };
+
+        /// Comparator to order non-transparent object passes
+        struct SolidQueueItemLess
+        {
+            bool _OgreExport operator()(const Pass* a, const Pass* b) const
+            {
+                // Sort by passHash, which is pass, then texture unit changes
+                unsigned long hasha = a->getHash();
+                unsigned long hashb = b->getHash();
+                if (hasha == hashb)
+                {
+                    // Must differentiate by pointer incase 2 passes end up with the same hash
+                    return a < b;
+                }
+                else
+                {
+                    return hasha < hashb;
+                }
+            }
+        };
+        /// Comparator to order transparent object passes
+        struct TransparentQueueItemLess
+        {
+            const Camera* camera;
+            bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
+            {
+                if (a.renderable == b.renderable)
+                {
+                    // Same renderable, sort by pass hash
+                    return a.pass->getHash() < b.pass->getHash();
+                }
+                else
+                {
+                    // Different renderables, sort by depth
+                    Real adepth = a.renderable->getSquaredViewDepth(camera);
+                    Real bdepth = b.renderable->getSquaredViewDepth(camera);
+				    if (adepth == bdepth)
+				    {
+                        // Must return deterministic result, doesn't matter what
+                        return a.pass < b.pass;
+				    }
+				    else
+				    {
+				        // Sort DESCENDING by depth (ie far objects first)
+					    return (adepth > bdepth);
+				    }
+                }
+
+            }
+        };
+    public:
+        /** Vector of RenderablePass objects, this is built on the assumption that
+         vectors only ever increase in size, so even if we do clear() the memory stays
+         allocated, ie fast */
+        typedef std::vector<RenderablePass> TransparentRenderablePassList;
+        typedef std::vector<Renderable*> RenderableList;
+        /** Map of pass to renderable lists, used for solid objects since ordering within objects not
+        important. */
+        typedef std::map<Pass*, RenderableList*, SolidQueueItemLess> SolidRenderablePassMap;
+    protected:
+        /// Parent queue group
+        RenderQueueGroup* mParent;
+        bool mSplitPassesByLightingType;
+        bool mSplitNoShadowPasses;
+        /// Solid pass list, used when no shadows, modulative shadows, or ambient passes for additive
+        SolidRenderablePassMap mSolidPasses;
+        /// Solid per-light pass list, used with additive shadows
+        SolidRenderablePassMap mSolidPassesDiffuseSpecular;
+        /// Solid decal (texture) pass list, used with additive shadows
+        SolidRenderablePassMap mSolidPassesDecal;
+        /// Solid pass list, used when shadows are enabled but shadow receive is turned off for these passes
+        SolidRenderablePassMap mSolidPassesNoShadow;
+
+		/// Transparent list
+		TransparentRenderablePassList mTransparentPasses;
+
+        /// Totally empties and destroys a solid pass map
+        void destroySolidPassMap(SolidRenderablePassMap& passmap);
+
+        /// remove a pass entry from all solid pass maps
+        void removeSolidPassEntry(Pass* p);
+
+        /// Clear a solid pass map at the end of a frame
+        void clearSolidPassMap(SolidRenderablePassMap& passmap);
+        /// Internal method for adding a solid renderable
+        void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
+        /// Internal method for adding a solid renderable
+        void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
+        /// Internal method for adding a transparent renderable
+        void addTransparentRenderable(Technique* pTech, Renderable* rend);
+
+    public:
+        RenderPriorityGroup(RenderQueueGroup* parent, 
+            bool splitPassesByLightingType, bool splitNoShadowPasses) 
+            :mParent(parent), mSplitPassesByLightingType(splitPassesByLightingType),
+            mSplitNoShadowPasses(splitNoShadowPasses) { }
+
+        ~RenderPriorityGroup() {
+            // destroy all the pass map entries
+            destroySolidPassMap(mSolidPasses);
+            destroySolidPassMap(mSolidPassesDecal);
+            destroySolidPassMap(mSolidPassesDiffuseSpecular);
+            destroySolidPassMap(mSolidPassesNoShadow);
+            mTransparentPasses.clear();
+
+        }
+
+        /** Get the collection of solid passes currently queued */
+        const SolidRenderablePassMap& _getSolidPasses(void) const
+        { return mSolidPasses; }
+        /** Get the collection of solid passes currently queued (per-light) */
+        const SolidRenderablePassMap& _getSolidPassesDiffuseSpecular(void) const
+        { return mSolidPassesDiffuseSpecular; }
+        /** Get the collection of solid passes currently queued (decal textures)*/
+        const SolidRenderablePassMap& _getSolidPassesDecal(void) const
+        { return mSolidPassesDecal; }
+        /** Get the collection of solid passes for which shadow receipt is disabled*/
+        const SolidRenderablePassMap& _getSolidPassesNoShadow(void) const
+        { return mSolidPassesNoShadow; }
+        /** Get the collection of transparent passes currently queued */
+        const TransparentRenderablePassList& _getTransparentPasses(void) const
+        { return mTransparentPasses; }
+
+
+        /** Add a renderable to this group. */
+        void addRenderable(Renderable* pRend);
+
+		/** Sorts the objects which have been added to the queue; transparent objects by their 
+            depth in relation to the passed in Camera. */
+		void sort(const Camera* cam);
+
+        /** Clears this group of renderables. 
+        */
+        void clear(void);
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	
+		enum {SOLID_PASSES = 1,
+			  SOLID_PASSES_DECAL = 2,
+			  SOLID_PASSES_DIFFUSE_SPECULAR = 4,
+			  SOLID_PASSES_NOSHADOW = 8,
+			  TRANSPARENT_PASSES = 16};
+
+		/** Clears passes determined by parameter.
+			@param passes can be one or several (combined by |) of:
+			SOLID_PASSES 
+			SOLID_PASSES_DECAL 
+			SOLID_PASSES_DIFFUSE_SPECULAR
+			SOLID_PASSES_NOSHADOW
+			TRANSPARENT_PASSES
+		*/
+		void clear(const int leavePassesInQueue);
+		/** Destroys passes determined by parameter.
+			@param passes can be one or several (combined by |) of:
+			SOLID_PASSES 
+			SOLID_PASSES_DECAL 
+			SOLID_PASSES_DIFFUSE_SPECULAR
+			SOLID_PASSES_NOSHADOW
+			TRANSPARENT_PASSES
+		*/
+		void destroyPassMaps(const int leavePassesInQueue);
+
+#endif // GTP_VISIBILITY_MODIFIED_OGRE		
+        /** Sets whether or not the queue will split passes by their lighting type,
+        ie ambient, per-light and decal. 
+        */
+        void setSplitPassesByLightingType(bool split)
+        {
+            mSplitPassesByLightingType = split;
+        }
+
+        /** Sets whether or not passes which have shadow receive disabled should
+            be separated. 
+        */
+        void setSplitNoShadowPasses(bool split)
+        {
+            mSplitNoShadowPasses = split;
+        }
+
+
+    };
+
+
+    /** A grouping level underneath RenderQueue which groups renderables
+    to be issued at coarsely the same time to the renderer.
+    @remarks
+        Each instance of this class itself hold RenderPriorityGroup instances, 
+        which are the groupings of renderables by priority for fine control
+        of ordering (not required for most instances).
+    @par
+        This is an internal OGRE class, not intended for apps to use.
+    */
+    class _OgrePrivate RenderQueueGroup
+    {
+    public:
+        typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
+        typedef MapIterator<PriorityMap> PriorityMapIterator;
+    protected:
+        RenderQueue* mParent;
+        bool mSplitPassesByLightingType;
+        bool mSplitNoShadowPasses;
+        /// Map of RenderPriorityGroup objects
+        PriorityMap mPriorityGroups;
+		/// Whether shadows are enabled for this queue
+		bool mShadowsEnabled;
+
+
+    public:
+		RenderQueueGroup(RenderQueue* parent, bool splitPassesByLightingType, 
+            bool splitNoShadowPasses) 
+            :mParent(parent), mSplitPassesByLightingType(splitPassesByLightingType),
+            mSplitNoShadowPasses(splitNoShadowPasses), mShadowsEnabled(true) {}
+
+        ~RenderQueueGroup() {
+            // destroy contents now
+            PriorityMap::iterator i;
+            for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
+            {
+                delete i->second;
+            }
+        }
+
+        /** Get an iterator for browsing through child contents. */
+        PriorityMapIterator getIterator(void)
+        {
+            return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
+        }
+
+        /** Add a renderable to this group, with the given priority. */
+        void addRenderable(Renderable* pRend, ushort priority)
+        {
+            // Check if priority group is there
+            PriorityMap::iterator i = mPriorityGroups.find(priority);
+            RenderPriorityGroup* pPriorityGrp;
+            if (i == mPriorityGroups.end())
+            {
+                // Missing, create
+                pPriorityGrp = new RenderPriorityGroup(this, 
+                    mSplitPassesByLightingType, mSplitNoShadowPasses);
+                mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
+            }
+            else
+            {
+                pPriorityGrp = i->second;
+            }
+
+            // Add
+            pPriorityGrp->addRenderable(pRend);
+
+        }
+
+        /** Clears this group of renderables. 
+        @remarks
+            Doesn't delete any priority groups, just empties them. Saves on 
+            memory deallocations since the chances are rougly the same kinds of 
+            renderables are going to be sent to the queue again next time.
+        */
+        void clear(void)
+        {
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+                i->second->clear();
+            }
+
+        }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE	
+		void clear(int passes)
+        {
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+                i->second->clear(passes);
+            }
+
+        }
+	
+		void destroyPasses(int passes)
+        {
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+                i->second->destroyPassMaps(passes);
+            }
+
+        }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE		
+
+		/** Indicate whether a given queue group will be doing any
+		shadow setup.
+		@remarks
+		This method allows you to inform the queue about a queue group, and to 
+		indicate whether this group will require shadow processing of any sort.
+		In order to preserve rendering order, OGRE has to treat queue groups
+		as very separate elements of the scene, and this can result in it
+		having to duplicate shadow setup for each group. Therefore, if you
+		know that a group which you are using will never need shadows, you
+		should preregister the group using this method in order to improve
+		the performance.
+		*/
+		void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
+
+		/** Are shadows enabled for this queue? */
+		bool getShadowsEnabled(void) const { return mShadowsEnabled; }
+
+        /** Sets whether or not the queue will split passes by their lighting type,
+        ie ambient, per-light and decal. 
+        */
+        void setSplitPassesByLightingType(bool split)
+        {
+            mSplitPassesByLightingType = split;
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+                i->second->setSplitPassesByLightingType(split);
+            }
+        }
+        /** Sets whether or not the queue will split passes which have shadow receive
+        turned off (in their parent material), which is needed when certain shadow
+        techniques are used.
+        */
+        void setSplitNoShadowPasses(bool split)
+        {
+            mSplitNoShadowPasses = split;
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+                i->second->setSplitNoShadowPasses(split);
+            }
+        }
+
+    };
+
+
+
+}
+
+#endif
+
+
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderTarget.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderTarget.h	(revision 156)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreRenderTarget.h	(revision 156)
@@ -0,0 +1,338 @@
+/*
+-----------------------------------------------------------------------------
+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 __RenderTarget_H__
+#define __RenderTarget_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+#include "OgreTextureManager.h"
+#include "OgreViewport.h"
+#include "OgreTimer.h"
+
+/* Define the number of priority groups for the render system's render targets. */
+#ifndef OGRE_NUM_RENDERTARGET_GROUPS
+	#define OGRE_NUM_RENDERTARGET_GROUPS 10
+	#define OGRE_DEFAULT_RT_GROUP 4
+	#define OGRE_REND_TO_TEX_RT_GROUP 2
+#endif
+
+namespace Ogre {
+
+    /** A 'canvas' which can receive the results of a rendering
+        operation.
+        @remarks
+            This abstract class defines a common root to all targets of rendering operations. A
+            render target could be a window on a screen, or another
+            offscreen surface like a texture or bump map etc.
+        @author
+            Steven Streeting
+        @version
+            1.0
+     */
+    class _OgreExport RenderTarget
+    {
+    public:
+        enum StatFlags
+        {
+            SF_NONE           = 0,
+            SF_FPS            = 1,
+            SF_AVG_FPS        = 2,
+            SF_BEST_FPS       = 4,
+            SF_WORST_FPS      = 8,
+            SF_TRIANGLE_COUNT = 16,
+            SF_ALL            = 0xFFFF
+        };
+
+        struct FrameStats
+        {
+            float lastFPS;
+            float avgFPS;
+            float bestFPS;
+            float worstFPS;
+            unsigned long bestFrameTime;
+            unsigned long worstFrameTime;
+            size_t triangleCount;
+        };
+
+        RenderTarget();
+        virtual ~RenderTarget();
+
+        /// Retrieve target's name.
+        virtual const String& getName(void) const;
+
+        /// Retrieve information about the render target.
+        virtual void getMetrics(unsigned int& width, unsigned int& height, unsigned int& colourDepth);
+
+        virtual unsigned int getWidth(void) const;
+        virtual unsigned int getHeight(void) const;
+        virtual unsigned int getColourDepth(void) const;
+
+        /** Tells the target to update it's contents.
+            @remarks
+                If OGRE is not running in an automatic rendering loop
+                (started using Root::startRendering),
+                the user of the library is responsible for asking each render
+                target to refresh. This is the method used to do this. It automatically
+                re-renders the contents of the target using whatever cameras have been
+                pointed at it (using Camera::setRenderTarget).
+            @par
+                This allows OGRE to be used in multi-windowed utilities
+                and for contents to be refreshed only when required, rather than
+                constantly as with the automatic rendering loop.
+        */
+        virtual void update(void);
+
+        /** Adds a viewport to the rendering target.
+            @remarks
+                A viewport is the rectangle into which redering output is sent. This method adds
+                a viewport to the render target, rendering from the supplied camera. The
+                rest of the parameters are only required if you wish to add more than one viewport
+                to a single rendering target. Note that size information passed to this method is
+                passed as a parametric, i.e. it is relative rather than absolute. This is to allow
+                viewports to automatically resize along with the target.
+            @param
+                cam The camera from which the viewport contents will be rendered (mandatory)
+            @param
+                ZOrder The relative order of the viewport with others on the target (allows overlapping
+                viewports i.e. picture-in-picture). Higher ZOrders are on top of lower ones. The actual number
+                is irrelevant, only the relative ZOrder matters (you can leave gaps in the numbering)
+            @param
+                left The relative position of the left of the viewport on the target, as a value between 0 and 1.
+            @param
+                top The relative position of the top of the viewport on the target, as a value between 0 and 1.
+            @param
+                width The relative width of the viewport on the target, as a value between 0 and 1.
+            @param
+                height The relative height of the viewport on the target, as a value between 0 and 1.
+        */
+        virtual Viewport* addViewport(Camera* cam, int ZOrder = 0, float left = 0.0f, float top = 0.0f ,
+            float width = 1.0f, float height = 1.0f);
+
+        /** Returns the number of viewports attached to this target.*/
+        virtual unsigned short getNumViewports(void) const;
+
+        /** Retrieves a pointer to the viewport with the given index. */
+        virtual Viewport* getViewport(unsigned short index);
+
+        /** Removes a viewport at a given ZOrder.
+        */
+        virtual void removeViewport(int ZOrder);
+
+        /** Removes all viewports on this target.
+        */
+        virtual void removeAllViewports(void);
+
+        /** Retieves details of current rendering performance.
+            @remarks
+                If the user application wishes to do it's own performance
+                display, or use performance for some other means, this
+                method allows it to retrieve the statistics.
+                @param
+                    lastFPS Pointer to a float to receive the number of frames per second (FPS)
+                    based on the last frame rendered.
+                @param
+                    avgFPS Pointer to a float to receive the FPS rating based on an average of all
+                    the frames rendered since rendering began (the call to
+                    Root::startRendering).
+                @param
+                    bestFPS Pointer to a float to receive the best FPS rating that has been achieved
+                    since rendering began.
+                @param
+                    worstFPS Pointer to a float to receive the worst FPS rating seen so far.
+        */
+        virtual void getStatistics(float& lastFPS, float& avgFPS,
+            float& bestFPS, float& worstFPS) const;  // Access to stats
+
+        virtual const FrameStats& getStatistics(void) const;
+
+        /** Individual stats access - gets the number of frames per second (FPS) based on the last frame rendered.
+        */
+        virtual float getLastFPS() const;
+
+        /** Individual stats access - gets the average frames per second (FPS) since call to Root::startRendering.
+        */
+        virtual float getAverageFPS() const;
+
+        /** Individual stats access - gets the best frames per second (FPS) since call to Root::startRendering.
+        */
+        virtual float getBestFPS() const;
+
+        /** Individual stats access - gets the worst frames per second (FPS) since call to Root::startRendering.
+        */
+        virtual float getWorstFPS() const;
+
+        /** Individual stats access - gets the best frame time
+        */
+        virtual float getBestFrameTime() const;
+
+        /** Individual stats access - gets the worst frame time
+        */
+        virtual float getWorstFrameTime() const;
+
+        /** Resets saved frame-rate statistices.
+        */
+        virtual void resetStatistics(void);
+
+        /** Gets a custom (maybe platform-specific) attribute.
+            @remarks
+                This is a nasty way of satisfying any API's need to see platform-specific details.
+                It horrid, but D3D needs this kind of info. At least it's abstracted.
+            @param
+                name The name of the attribute.
+            @param
+                pData Pointer to memory of the right kind of structure to receive the info.
+        */
+        virtual void getCustomAttribute(const String& name, void* pData);
+
+        /** Adds debug text to this window. */
+        virtual void setDebugText(const String& text);
+
+		/** Returns the debug text. */
+		const String& getDebugText() const;
+
+        /** Add a listener to this RenderTarget which will be called back before & after rendering.
+        @remarks
+            If you want notifications before and after a target is updated by the system, use
+            this method to register your own custom RenderTargetListener class. This is useful
+            for potentially adding your own manual rendering commands before and after the
+            'normal' system rendering.
+        @par NB this should not be used for frame-based scene updates, use Root::addFrameListener for that.
+        */
+        virtual void addListener(RenderTargetListener* listener);
+        /** Removes a RenderTargetListener previously registered using addListener. */
+        virtual void removeListener(RenderTargetListener* listener);
+        /** Removes all listeners from this instance. */
+        virtual void removeAllListeners(void);
+
+		/** Sets the priority of this render target in relation to the others. 
+        @remarks
+            This can be used in order to schedule render target updates. Lower
+            priorities will be rendered first. Note that the priority must be set
+            at the time the render target is attached to the render system, changes
+            afterwards will not affect the ordering.
+        */
+        virtual void setPriority( uchar priority ) { mPriority = priority; }
+        /** Gets the priority of a render target. */
+		virtual uchar getPriority() const { return mPriority; }
+
+        /** Used to retrieve or set the active state of the render target.
+        */
+        virtual bool isActive() const;
+
+        /** Used to set the active state of the render target.
+        */
+        virtual void setActive( bool state );
+
+        /** Sets whether this target should be automatically updated if Ogre's rendering
+            loop or Root::_updateAllRenderTargets is being used.
+        @remarks
+            By default, if you use Ogre's own rendering loop (Root::startRendering)
+            or call Root::_updateAllRenderTargets, all render targets are updated 
+            automatically. This method allows you to control that behaviour, if 
+            for example you have a render target which you only want to update periodically.
+        @param autoupdate If true, the render target is updated during the automatic render
+            loop or when Root::_updateAllRenderTargets is called. If false, the 
+            target is only updated when its update() method is called explicitly.
+        */
+        virtual void setAutoUpdated(bool autoupdate);
+        /** Gets whether this target is automatically updated if Ogre's rendering
+            loop or Root::_updateAllRenderTargets is being used.
+        */
+        virtual bool isAutoUpdated(void) const;
+
+        /** Writes the current contents of the render target to the named file. */
+        virtual void writeContentsToFile(const String& filename) = 0;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		virtual uchar *getBufferContents(int &dimx, int &dimy) = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+	/** Writes the current contents of the render target to the (PREFIX)(time-stamp)(SUFFIX) file.
+		@returns the name of the file used.*/
+	virtual String writeContentsToTimestampedFile(const String& filenamePrefix, const String& filenameSuffix);
+
+		virtual bool requiresTextureFlipping() const = 0;
+
+		/** Gets the number of triangles rendered in the last update() call. */
+		virtual size_t getTriangleCount(void) const;
+        /** Utility method to notify a render target that a camera has been removed, 
+        incase it was referring to it as a viewer. 
+        */
+        virtual void _notifyCameraRemoved(const Camera* cam);
+
+        /** Indicates whether this target is the primary window. The
+            primary window is special in that it is destroyed when 
+            ogre is shut down, and cannot be destroyed directly.
+            This is the case because it holds the context for vertex,
+            index buffers and textures.
+        */
+        virtual bool isPrimary(void) const;
+
+    protected:
+        /// The name of this target.
+        String mName;
+		/// The priority of the render target.
+		uchar mPriority;
+
+        unsigned int mWidth;
+        unsigned int mHeight;
+        unsigned int mColourDepth;
+        bool mIsDepthBuffered;
+
+        // Stats
+		FrameStats mStats;
+        
+        Timer* mTimer ;
+        String mDebugText;
+        unsigned long mLastSecond;
+        unsigned long mLastTime;
+        size_t mFrameCount;
+
+        bool mActive;
+        bool mAutoUpdate;
+
+        void updateStats(void);
+
+        typedef std::map<int, Viewport*, std::less<int> > ViewportList;
+        /// List of viewports, map on Z-order
+        ViewportList mViewportList;
+
+        typedef std::vector<RenderTargetListener*> RenderTargetListenerList;
+        RenderTargetListenerList mListeners;
+
+        /// internal method for firing events
+        virtual void firePreUpdate(void);
+        /// internal method for firing events
+        virtual void firePostUpdate(void);
+        /// internal method for firing events
+        virtual void fireViewportPreUpdate(Viewport* vp);
+        /// internal method for firing events
+        virtual void fireViewportPostUpdate(Viewport* vp);
+    };
+
+} // Namespace
+
+#endif
Index: OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneManager.h
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 316)
+++ OGRE/trunk/ogre_changes/OgreMain/include/OgreSceneManager.h	(revision 316)
@@ -0,0 +1,1911 @@
+/*-------------------------------------------------------------------------
+This source file is a part of OGRE
+(Object-oriented Graphics Rendering Engine)
+
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This library is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License (LGPL) as 
+published by the Free Software Foundation; either version 2.1 of the 
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License 
+along with this library; if not, write to the Free Software Foundation, 
+Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
+http://www.gnu.org/copyleft/lesser.txt
+-------------------------------------------------------------------------*/
+#ifndef __SceneManager_H__
+#define __SceneManager_H__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+#include "OgreSceneNode.h"
+#include "OgrePlane.h"
+#include "OgreQuaternion.h"
+#include "OgreColourValue.h"
+#include "OgreCommon.h"
+#include "OgreRenderQueue.h"
+#include "OgreAnimationState.h"
+#include "OgreSceneQuery.h"
+#include "OgreAutoParamDataSource.h"
+#include "OgreAnimationState.h"
+#include "OgreRenderQueue.h"
+#include "OgreRenderQueueSortingGrouping.h"
+#include "OgreRectangle2D.h"
+
+namespace Ogre {
+
+    /** Structure for holding a position & orientation pair. */
+    struct ViewPoint
+    {
+        Vector3 position;
+        Quaternion orientation;
+    };
+
+	// Forward declarations
+	class DefaultIntersectionSceneQuery;
+	class DefaultRaySceneQuery;
+	class DefaultSphereSceneQuery;
+	class DefaultAxisAlignedBoxSceneQuery;
+
+    /** Manages the rendering of a 'scene' i.e. a collection of primitives.
+        @remarks
+            This class defines the basic behaviour of the 'Scene Manager' family. These classes will
+            organise the objects in the scene and send them to the rendering system, a subclass of
+            RenderSystem. This basic superclass does no sorting, culling or organising of any sort.
+        @par
+            Subclasses may use various techniques to organise the scene depending on how they are
+            designed (e.g. BSPs, octrees etc). As with other classes, methods preceded with '_' are
+            designed to be called by other classes in the Ogre system, not by user applications,
+            although this is not forbidden.
+        @author
+            Steve Streeting
+        @version
+            1.0
+     */
+    class _OgreExport SceneManager
+    {
+		friend class DefaultIntersectionSceneQuery; 
+	    friend class DefaultRaySceneQuery;
+	    friend class DefaultSphereSceneQuery;
+	    friend class DefaultAxisAlignedBoxSceneQuery;
+        friend class DefaultPlaneBoundedVolumeListSceneQuery;
+    public:
+        /// Query mask which will be used for world geometry @see SceneQuery
+        static unsigned long WORLD_GEOMETRY_QUERY_MASK;
+        /** Comparator for material map, for sorting materials into render order (e.g. transparent last).
+        */
+        struct materialLess
+        {
+            _OgreExport bool operator()(const Material* x, const Material* y) const;
+        };
+        /// Comparator for sorting lights relative to a point
+        struct lightLess
+        {
+            _OgreExport bool operator()(const Light* a, const Light* b) const;
+        };
+
+        /// Describes the stage of rendering when performing complex illumination
+        enum IlluminationRenderStage
+        {
+            /// No special illumination stage
+            IRS_NONE,
+            /// Ambient stage, when background light is added
+            IRS_AMBIENT,
+            /// Diffuse / specular stage, when individual light contributions are added
+            IRS_PER_LIGHT,
+            /// Decal stage, when texture detail is added to the lit base
+            IRS_DECAL,
+            /// Render to texture stage, used for texture based shadows
+            IRS_RENDER_TO_TEXTURE,
+            /// Modulative render from shadow texture stage
+            IRS_RENDER_MODULATIVE_PASS
+        };
+
+		/** Enumeration of the possible modes allowed for processing the special case
+		render queue list.
+		@see SceneManager::setSpecialCaseRenderQueueMode
+		*/
+		enum SpecialCaseRenderQueueMode
+		{
+			/// Render only the queues in the special case list
+			SCRQM_INCLUDE,
+			/// Render all except the queues in the special case list
+			SCRQM_EXCLUDE
+		};
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		/** added by matt: Render content of current scene node.
+			@param node scene node to be rendered
+			@param cam current camera
+			@param leavePassesInQueue list of passes which are left in queue
+		*/
+		void _renderSceneNode(Camera *cam, SceneNode *node, const int leavePassesInQueue = 0);
+		/** deletes all processed queues
+			@param leavePassesInQueue pass list which is not deleted from queue
+			@remark used to clear render queues before rendering scene node
+		*/
+		void _deleteRenderedQueueGroups(int leavePassesInQueue = 0);
+		/** Wrapper for useRenderableViewProjMde with is an 
+			Internal method used by _renderVisibleObjects to deal with renderables
+            which override the camera's own view / projection materices. 
+		*/
+        void useRenderableViewProjModeWrapper(Renderable* pRend); // HACK
+		/** HACK: A public wrapper method for setting up the renderstate for a rendering pass.
+            @param
+                pass The Pass details to set.
+            @returns
+                A Pass object that was used instead of the one passed in, can
+                happen when rendering shadow passes
+			@remark made public by matt
+        */
+        virtual Pass* setPassWrapper(Pass* pass);
+
+		/** Renders an Ogre Entity.
+		*/
+		//void renderEntity(Entity *ent);
+		
+		/** Renders an Ogre MovableObject.
+			@param mov the movable object to be rendered
+			@param leavePassesInQueue flag determining the passes which are left
+			in render queue after rendering
+		*/
+		void _renderMovableObject(MovableObject *mov, const int leavePassesInQueue);
+
+		/** Renders a single renderable using pass 0 of the renderable.
+		*/
+		void _renderSingleRenderable(Renderable *rend);
+
+		/** Tells the scene manager that the frame ends (i.e.,
+			one frame in the main loop.
+		*/
+		virtual void endFrame() {};
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+
+        /// Queue of objects for rendering
+        RenderQueue* mRenderQueue;
+
+        /// Current ambient light, cached for RenderSystem
+        ColourValue mAmbientLight;
+
+        /// The rendering system to send the scene to
+        RenderSystem *mDestRenderSystem;
+
+        typedef std::map<String, Camera* > CameraList;
+
+        /** Central list of cameras - for easy memory management and lookup.
+        */
+        CameraList mCameras;
+
+        typedef std::map<String, Light* > SceneLightList;
+
+        /** Central list of lights - for easy memory management and lookup.
+        */
+        SceneLightList mLights;
+
+
+        typedef std::map<String, Entity* > EntityList;
+
+        /** Central list of entities - for easy memory management and lookup.
+        */
+        EntityList mEntities;
+
+        typedef std::map<String, BillboardSet* > BillboardSetList;
+
+        /** Central list of billboard sets - for easy memory management and lookup.
+        */
+        BillboardSetList mBillboardSets;
+
+		typedef std::map<String, StaticGeometry* > StaticGeometryList;
+		StaticGeometryList mStaticGeometryList;
+
+        typedef std::map<String, SceneNode*> SceneNodeList;
+
+        /** Central list of SceneNodes - for easy memory management.
+            @note
+                Note that this list is used only for memory management; the structure of the scene
+                is held using the hierarchy of SceneNodes starting with the root node. However you
+                can look up nodes this way.
+        */
+        SceneNodeList mSceneNodes;
+
+        /// Camera in progress
+        Camera* mCameraInProgress;
+        /// Current Viewport
+        Viewport* mCurrentViewport;
+
+        /// Root scene node
+        SceneNode* mSceneRoot;
+
+        /// Autotracking scene nodes
+        typedef std::set<SceneNode*> AutoTrackingSceneNodes;
+        AutoTrackingSceneNodes mAutoTrackingSceneNodes;
+
+        // Sky params
+        // Sky plane
+        Entity* mSkyPlaneEntity;
+        Entity* mSkyDomeEntity[5];
+        Entity* mSkyBoxEntity[6];
+
+        SceneNode* mSkyPlaneNode;
+        SceneNode* mSkyDomeNode;
+        SceneNode* mSkyBoxNode;
+
+        bool mSkyPlaneEnabled;
+        bool mSkyPlaneDrawFirst;
+        Plane mSkyPlane;
+        // Sky box
+        bool mSkyBoxEnabled;
+        bool mSkyBoxDrawFirst;
+        Quaternion mSkyBoxOrientation;
+        // Sky dome
+        bool mSkyDomeEnabled;
+        bool mSkyDomeDrawFirst;
+        Quaternion mSkyDomeOrientation;
+        // Fog
+        FogMode mFogMode;
+        ColourValue mFogColour;
+        Real mFogStart;
+        Real mFogEnd;
+        Real mFogDensity;
+
+		typedef std::set<RenderQueueGroupID> SpecialCaseRenderQueueList;
+		SpecialCaseRenderQueueList mSpecialCaseQueueList;
+		SpecialCaseRenderQueueMode mSpecialCaseQueueMode;
+		RenderQueueGroupID mWorldGeometryRenderQueue;
+
+        /** Internal method for initialising the render queue.
+        @remarks
+            Subclasses can use this to install their own RenderQueue implementation.
+        */
+        virtual void initRenderQueue(void);
+        /** Retrieves the internal render queue. */
+        virtual RenderQueue* getRenderQueue(void);
+
+        /** Internal method for setting up the renderstate for a rendering pass.
+            @param
+                pass The Pass details to set.
+            @returns
+                A Pass object that was used instead of the one passed in, can
+                happen when rendering shadow passes
+        */
+        virtual Pass* setPass(Pass* pass);
+
+        /// A pass designed to let us render shadow colour on white for texture shadows
+        Pass* mShadowCasterPlainBlackPass;
+        /// A pass designed to let us render shadow receivers for texture shadows
+        Pass* mShadowReceiverPass;
+        /** Internal method for turning a regular pass into a shadow caster pass.
+        @remarks
+            This is only used for texture shadows, basically we're trying to
+            ensure that objects are rendered solid black.
+            This method will usually return the standard solid black pass for
+            all fixed function passes, but will merge in a vertex program
+            and fudge the AutpoParamDataSource to set black lighting for
+            passes with vertex programs. 
+        */
+        Pass* deriveShadowCasterPass(Pass* pass);
+        /** Internal method for turning a regular pass into a shadow receiver pass.
+        @remarks
+        This is only used for texture shadows, basically we're trying to
+        ensure that objects are rendered with a projective texture.
+        This method will usually return a standard single-texture pass for
+        all fixed function passes, but will merge in a vertex program
+        for passes with vertex programs. 
+        */
+        Pass* deriveShadowReceiverPass(Pass* pass);
+    
+        /** Internal method to validate whether a Pass should be allowed to render.
+        @remarks
+            Called just before a pass is about to be used for rendering a group to
+            allow the SceneManager to omit it if required. A return value of false
+            skips this pass. 
+        */
+        bool validatePassForRendering(Pass* pass);
+
+        /** Internal method to validate whether a Renderable should be allowed to render.
+        @remarks
+        Called just before a pass is about to be used for rendering a Renderable to
+        allow the SceneManager to omit it if required. A return value of false
+        skips it. 
+        */
+        bool validateRenderableForRendering(Pass* pass, Renderable* rend);
+
+        enum BoxPlane
+        {
+            BP_FRONT = 0,
+            BP_BACK = 1,
+            BP_LEFT = 2,
+            BP_RIGHT = 3,
+            BP_UP = 4,
+            BP_DOWN = 5
+        };
+
+        /* Internal utility method for creating the planes of a skybox.
+        */
+        MeshPtr createSkyboxPlane(
+            BoxPlane bp,
+            Real distance,
+            const Quaternion& orientation,
+            const String& groupName);
+
+        /* Internal utility method for creating the planes of a skydome.
+        */
+        MeshPtr createSkydomePlane(
+            BoxPlane bp,
+            Real curvature, Real tiling, Real distance,
+            const Quaternion& orientation,
+            int xsegments, int ysegments, int ySegmentsToKeep, 
+            const String& groupName);
+
+        // Flag indicating whether SceneNodes will be rendered as a set of 3 axes
+        bool mDisplayNodes;
+
+        /// Storage of animations, lookup by name
+        typedef std::map<String, Animation*> AnimationList;
+        AnimationList mAnimationsList;
+        AnimationStateSet mAnimationStates;
+
+        /** Internal method used by _renderVisibleObjects to deal with renderables
+            which override the camera's own view / projection materices. */
+        void useRenderableViewProjMode(Renderable* pRend);
+
+        /// Controller flag for determining if we need to set view/proj matrices
+        bool mCamChanged;
+
+        typedef std::vector<RenderQueueListener*> RenderQueueListenerList;
+        RenderQueueListenerList mRenderQueueListeners;
+
+        /// Internal method for firing the queue start event, returns true if queue is to be skipped
+        bool fireRenderQueueStarted(RenderQueueGroupID id);
+        /// Internal method for firing the queue end event, returns true if queue is to be repeated
+        bool fireRenderQueueEnded(RenderQueueGroupID id);
+
+        /** Internal method for setting the destination viewport for the next render. */
+        virtual void setViewport(Viewport *vp);
+
+		/** Flag that indicates if all of the scene node's bounding boxes should be shown as a wireframe. */
+		bool mShowBoundingBoxes;       
+
+        /** Internal utility method for rendering a single object. 
+        @remarks
+            Assumes that the pass has already been set up.
+        @param rend The renderable to issue to the pipeline
+        @param pass The pass which is being used
+        @param doLightIteration If true, this method will issue the renderable to
+            the pipeline possibly multiple times, if the pass indicates it should be
+            done once per light
+        @param manualLightList Only applicable if doLightIteration is false, this
+            method allows you to pass in a previously determined set of lights
+            which will be used for a single render of this object.
+        */
+        virtual void renderSingleObject(Renderable* rend, Pass* pass, bool doLightIteration, 
+            const LightList* manualLightList = 0);
+
+        /// Utility class for calculating automatic parameters for gpu programs
+        AutoParamDataSource mAutoParamDataSource;
+
+        ShadowTechnique mShadowTechnique;
+        bool mDebugShadows;
+        ColourValue mShadowColour;
+        Pass* mShadowDebugPass;
+        Pass* mShadowStencilPass;
+        Pass* mShadowModulativePass;
+		bool mShadowMaterialInitDone;
+        LightList mLightsAffectingFrustum;
+        HardwareIndexBufferSharedPtr mShadowIndexBuffer;
+		size_t mShadowIndexBufferSize;
+        Rectangle2D* mFullScreenQuad;
+        Real mShadowDirLightExtrudeDist;
+        IlluminationRenderStage mIlluminationStage;
+        unsigned short mShadowTextureSize;
+        unsigned short mShadowTextureCount;
+		PixelFormat mShadowTextureFormat;
+        typedef std::vector<RenderTexture*> ShadowTextureList;
+        ShadowTextureList mShadowTextures;
+        RenderTexture* mCurrentShadowTexture;
+		bool mShadowUseInfiniteFarPlane;
+        /** Internal method for locating a list of lights which could be affecting the frustum. 
+        @remarks
+            Custom scene managers are encouraged to override this method to make use of their
+            scene partitioning scheme to more efficiently locate lights, and to eliminate lights
+            which may be occluded by word geometry.
+        */
+        virtual void findLightsAffectingFrustum(const Camera* camera);
+        /// Internal method for setting up materials for shadows
+        virtual void initShadowVolumeMaterials(void);
+        /// Internal method for creating shadow textures (texture-based shadows)
+        virtual void createShadowTextures(unsigned short size, unsigned short count, 
+			PixelFormat fmt);
+        /// Internal method for preparing shadow textures ready for use in a regular render
+        virtual void prepareShadowTextures(Camera* cam, Viewport* vp);
+
+        /** Internal method for rendering all the objects for a given light into the 
+            stencil buffer.
+        @param light The light source
+        @param cam The camera being viewed from
+        */
+        virtual void renderShadowVolumesToStencil(const Light* light, const Camera* cam);
+        /** Internal utility method for setting stencil state for rendering shadow volumes. 
+        @param secondpass Is this the second pass?
+        @param zfail Should we be using the zfail method?
+        @param twosided Should we use a 2-sided stencil?
+        */
+        virtual void setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided);
+        /** Render a set of shadow renderables. */
+        void renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
+            Pass* pass, const LightList *manualLightList, unsigned long flags,
+            bool secondpass, bool zfail, bool twosided);
+        typedef std::vector<ShadowCaster*> ShadowCasterList;
+        ShadowCasterList mShadowCasterList;
+        SphereSceneQuery* mShadowCasterSphereQuery;
+        AxisAlignedBoxSceneQuery* mShadowCasterAABBQuery;
+        Real mShadowFarDist;
+        Real mShadowFarDistSquared;
+        Real mShadowTextureOffset; // proportion of texture offset in view direction e.g. 0.4
+        Real mShadowTextureFadeStart; // as a proportion e.g. 0.6
+        Real mShadowTextureFadeEnd; // as a proportion e.g. 0.9
+		bool mShadowTextureSelfShadow;
+		Pass* mShadowTextureCustomCasterPass;
+		Pass* mShadowTextureCustomReceiverPass;
+		String mShadowTextureCustomCasterVertexProgram;
+		String mShadowTextureCustomReceiverVertexProgram;
+		GpuProgramParametersSharedPtr mShadowTextureCustomCasterVPParams;
+		GpuProgramParametersSharedPtr mShadowTextureCustomReceiverVPParams;
+		bool mShadowTextureCasterVPDirty;
+		bool mShadowTextureReceiverVPDirty;
+
+
+        GpuProgramParametersSharedPtr mInfiniteExtrusionParams;
+        GpuProgramParametersSharedPtr mFiniteExtrusionParams;
+
+        /// Inner class to use as callback for shadow caster scene query
+        class _OgreExport ShadowCasterSceneQueryListener : public SceneQueryListener
+        {
+        protected:
+			SceneManager* mSceneMgr;
+            ShadowCasterList* mCasterList;
+            bool mIsLightInFrustum;
+            const PlaneBoundedVolumeList* mLightClipVolumeList;
+            const Camera* mCamera;
+            const Light* mLight;
+            Real mFarDistSquared;
+        public:
+            ShadowCasterSceneQueryListener(SceneManager* sm) : mSceneMgr(sm),
+				mCasterList(0), mIsLightInFrustum(false), mLightClipVolumeList(0), 
+                mCamera(0) {}
+            // Prepare the listener for use with a set of parameters  
+            void prepare(bool lightInFrustum, 
+                const PlaneBoundedVolumeList* lightClipVolumes, 
+                const Light* light, const Camera* cam, ShadowCasterList* casterList, 
+                Real farDistSquared) 
+            {
+                mCasterList = casterList;
+                mIsLightInFrustum = lightInFrustum;
+                mLightClipVolumeList = lightClipVolumes;
+                mCamera = cam;
+                mLight = light;
+                mFarDistSquared = farDistSquared;
+            }
+            bool queryResult(MovableObject* object);
+            bool queryResult(SceneQuery::WorldFragment* fragment);
+        };
+
+        ShadowCasterSceneQueryListener* mShadowCasterQueryListener;
+
+        /** Internal method for locating a list of shadow casters which 
+            could be affecting the frustum for a given light. 
+        @remarks
+            Custom scene managers are encouraged to override this method to add optimisations, 
+            and to add their own custom shadow casters (perhaps for world geometry)
+        */
+        virtual const ShadowCasterList& findShadowCastersForLight(const Light* light, 
+            const Camera* camera);
+		/** Render the objects in a given queue group 
+		*/
+		virtual void renderQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group in the ordinary way */
+        virtual void renderBasicQueueGroupObjects(RenderQueueGroup* pGroup);
+		/** Render a group with the added complexity of additive stencil shadows. */
+		virtual void renderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup* group);
+		/** Render a group with the added complexity of additive stencil shadows. */
+		virtual void renderModulativeStencilShadowedQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group rendering only shadow casters. */
+        virtual void renderTextureShadowCasterQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group rendering only shadow receivers. */
+        virtual void renderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup* group);
+        /** Render a group with the added complexity of additive stencil shadows. */
+        virtual void renderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup* group);
+		/** Render a set of objects, see renderSingleObject for param definitions */
+		virtual void renderObjects(const RenderPriorityGroup::SolidRenderablePassMap& objs, 
+            bool doLightIteration, const LightList* manualLightList = 0);
+        /** Render a set of objects, see renderSingleObject for param definitions */
+		virtual void renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs, 
+            bool doLightIteration, const LightList* manualLightList = 0);
+		/** Render those objects in the transparent pass list which have shadow casting forced on
+		@remarks
+			This function is intended to be used to render the shadows of transparent objects which have
+			transparency_casts_shadows set to 'on' in their material
+		*/
+		virtual void renderTransparentShadowCasterObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs, 
+			bool doLightIteration, const LightList* manualLightList = 0);
+
+    public:
+        /** Default constructor.
+        */
+        SceneManager();
+
+        /** Default destructor.
+        */
+        virtual ~SceneManager();
+
+        /** Creates a camera to be managed by this scene manager.
+            @remarks
+                This camera must be added to the scene at a later time using
+                the attachObject method of the SceneNode class.
+            @param
+                name Name to give the new camera.
+        */
+        virtual Camera* createCamera(const String& name);
+
+        /** Retrieves a pointer to the named camera.
+        */
+        virtual Camera* getCamera(const String& name);
+
+        /** Removes a camera from the scene.
+            @remarks
+                This method removes a previously added camera from the scene.
+                The camera is deleted so the caller must ensure no references
+                to it's previous instance (e.g. in a SceneNode) are used.
+            @param
+                cam Pointer to the camera to remove
+        */
+        virtual void removeCamera(Camera *cam);
+
+        /** Removes a camera from the scene.
+            @remarks
+                This method removes an camera from the scene based on the
+                camera's name rather than a pointer.
+        */
+        virtual void removeCamera(const String& name);
+
+        /** Removes (and destroys) all cameras from the scene.
+        */
+        virtual void removeAllCameras(void);
+
+        /** Creates a light for use in the scene.
+            @remarks
+                Lights can either be in a fixed position and independent of the
+                scene graph, or they can be attached to SceneNodes so they derive
+                their position from the parent node. Either way, they are created
+                using this method so that the SceneManager manages their
+                existence.
+            @param
+                name The name of the new light, to identify it later.
+        */
+        virtual Light* createLight(const String& name);
+
+        /** Returns a pointer to the named Light which has previously been added to the scene.
+        */
+        virtual Light* getLight(const String& name);
+
+        /** Removes the named light from the scene and destroys it.
+            @remarks
+                Any pointers held to this light after calling this method will be invalid.
+        */
+        virtual void removeLight(const String& name);
+
+        /** Removes the light from the scene and destroys it based on a pointer.
+            @remarks
+                Any pointers held to this light after calling this method will be invalid.
+        */
+        virtual void removeLight(Light* light);
+        /** Removes and destroys all lights in the scene.
+        */
+        virtual void removeAllLights(void);
+
+        /** Populate a light list with an ordered set of the lights which are closest
+        to the position specified.
+        @remarks
+            Note that since directional lights have no position, they are always considered
+            closer than any point lights and as such will always take precedence. 
+        @par
+            Subclasses of the default SceneManager may wish to take into account other issues
+            such as possible visibility of the light if that information is included in their
+            data structures. This basic scenemanager simply orders by distance, eliminating 
+            those lights which are out of range.
+        @par
+            The number of items in the list max exceed the maximum number of lights supported
+            by the renderer, but the extraneous ones will never be used. In fact the limit will
+            be imposed by Pass::getMaxSimultaneousLights.
+        @param position The position at which to evaluate the list of lights
+        @param radius The bounding radius to test
+        @param destList List to be populated with ordered set of lights; will be cleared by 
+            this method before population.
+        */
+        virtual void _populateLightList(const Vector3& position, Real radius, LightList& destList);
+
+
+        /** Creates an instance of a SceneNode.
+            @remarks
+                Note that this does not add the SceneNode to the scene hierarchy.
+                This method is for convenience, since it allows an instance to
+                be created for which the SceneManager is responsible for
+                allocating and releasing memory, which is convenient in complex
+                scenes.
+            @par
+                To include the returned SceneNode in the scene, use the addChild
+                method of the SceneNode which is to be it's parent.
+            @par
+                Note that this method takes no parameters, and the node created is unnamed (it is
+                actually given a generated name, which you can retrieve if you want).
+                If you wish to create a node with a specific name, call the alternative method
+                which takes a name parameter.
+        */
+        virtual SceneNode* createSceneNode(void);
+
+        /** Creates an instance of a SceneNode with a given name.
+            @remarks
+                Note that this does not add the SceneNode to the scene hierarchy.
+                This method is for convenience, since it allows an instance to
+                be created for which the SceneManager is responsible for
+                allocating and releasing memory, which is convenient in complex
+                scenes.
+            @par
+                To include the returned SceneNode in the scene, use the addChild
+                method of the SceneNode which is to be it's parent.
+            @par
+                Note that this method takes a name parameter, which makes the node easier to
+                retrieve directly again later.
+        */
+        virtual SceneNode* createSceneNode(const String& name);
+
+        /** Destroys a SceneNode with a given name.
+        @remarks
+            This allows you to physically delete an individual SceneNode if you want to.
+            Note that this is not normally recommended, it's better to allow SceneManager
+            to delete the nodes when the scene is cleared.
+        */
+        virtual void destroySceneNode(const String& name);
+
+        /** Gets the SceneNode at the root of the scene hierarchy.
+            @remarks
+                The entire scene is held as a hierarchy of nodes, which
+                allows things like relative transforms, general changes in
+                rendering state etc (See the SceneNode class for more info).
+                In this basic SceneManager class, the application using
+                Ogre is free to structure this hierarchy however it likes,
+                since it has no real significance apart from making transforms
+                relative to each node (more specialised subclasses will
+                provide utility methods for building specific node structures
+                e.g. loading a BSP tree).
+            @par
+                However, in all cases there is only ever one root node of
+                the hierarchy, and this method returns a pointer to it.
+        */
+        virtual SceneNode* getRootSceneNode(void) const;
+
+        /** Retrieves a named SceneNode from the scene graph.
+        @remarks
+            If you chose to name a SceneNode as you created it, or if you
+            happened to make a note of the generated name, you can look it
+            up wherever it is in the scene graph using this method.
+        */
+        virtual SceneNode* getSceneNode(const String& name) const;
+
+        /** Create an Entity (instance of a discrete mesh).
+            @param
+                entityName The name to be given to the entity (must be unique).
+            @param
+                meshName The name of the Mesh it is to be based on (e.g. 'knot.oof'). The
+                mesh will be loaded if it is not already.
+        */
+        virtual Entity* createEntity(const String& entityName, const String& meshName);
+
+        /** Prefab shapes available without loading a model.
+            @note
+                Minimal implementation at present.
+            @todo
+                Add more prefabs (teapots, teapots!!!)
+        */
+        enum PrefabType {
+            PT_PLANE
+        };
+
+        /** Create an Entity (instance of a discrete mesh) from a range of prefab shapes.
+            @param
+                entityName The name to be given to the entity (must be unique).
+            @param
+                ptype The prefab type.
+        */
+        virtual Entity* createEntity(const String& entityName, PrefabType ptype);
+        /** Retrieves a pointer to the named Entity. */
+        virtual Entity* getEntity(const String& name);
+
+        /** Removes & destroys an Entity from the SceneManager.
+            @warning
+                Must only be done if the Entity is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene if you are unsure use clearScene.
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeEntity(Entity* ent);
+
+        /** Removes & destroys an Entity from the SceneManager by name.
+            @warning
+                Must only be done if the Entity is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene if you are unsure use clearScene.
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeEntity(const String& name);
+
+        /** Removes & destroys all Entities.
+            @warning
+                Again, use caution since no Entity must be referred to
+                elsewhere e.g. attached to a SceneNode otherwise a crash
+                is likely. Use clearScene if you are unsure (it clears SceneNode
+                entries too.)
+            @see
+                SceneManager::clearScene
+        */
+        virtual void removeAllEntities(void);
+
+        /** Empties the entire scene, inluding all SceneNodes, Entities, Lights, 
+            BillboardSets etc. Cameras are not deleted at this stage since
+            they are still referenced by viewports, which are not destroyed during
+            this process.
+        */
+        virtual void clearScene(void);
+
+        /** Sets the ambient light level to be used for the scene.
+            @remarks
+                This sets the colour and intensity of the ambient light in the scene, i.e. the
+                light which is 'sourceless' and illuminates all objects equally.
+                The colour of an object is affected by a combination of the light in the scene,
+                and the amount of light that object reflects (in this case based on the Material::ambient
+                property).
+            @remarks
+                By default the ambient light in the scene is ColourValue::Black, i.e. no ambient light. This
+                means that any objects rendered with a Material which has lighting enabled (see Material::setLightingEnabled)
+                will not be visible unless you have some dynamic lights in your scene.
+        */
+        void setAmbientLight(const ColourValue& colour);
+
+        /** Returns the ambient light level to be used for the scene.
+        */
+        const ColourValue& getAmbientLight(void) const;
+
+        /** Sets the source of the 'world' geometry, i.e. the large, mainly static geometry
+            making up the world e.g. rooms, landscape etc.
+            @remarks
+                Depending on the type of SceneManager (subclasses will be specialised
+                for particular world geometry types) you have requested via the Root or
+                SceneManagerEnumerator classes, you can pass a filename to this method and it
+                will attempt to load the world-level geometry for use. If you try to load
+                an inappropriate type of world data an exception will be thrown. The default
+                SceneManager cannot handle any sort of world geometry and so will always
+                throw an exception. However subclasses like BspSceneManager can load
+                particular types of world geometry e.g. "q3dm1.bsp".
+            @par
+                World geometry will be loaded via the 'common' resource paths and archives set in the
+                ResourceManager class.
+        */
+        virtual void setWorldGeometry(const String& filename);
+
+        /** Estimate the number of loading stages required to load the named
+            world geometry. 
+        @remarks
+            This method should be overridden by SceneManagers that provide
+            custom world geometry that can take some time to load. They should
+            return from this method a count of the number of stages of progress
+            they can report on whilst loading. During real loading (setWorldGeomtry),
+            they should call ResourceGroupManager::_notifyWorldGeometryProgress exactly
+            that number of times when loading the geometry for real.
+        @note 
+            The default is to return 0, ie to not report progress. 
+        */
+        virtual size_t estimateWorldGeometry(const String& filename) { return 0; }
+
+        /** Asks the SceneManager to provide a suggested viewpoint from which the scene should be viewed.
+            @remarks
+                Typically this method returns the origin unless a) world geometry has been loaded using
+                SceneManager::setWorldGeometry and b) that world geometry has suggested 'start' points.
+                If there is more than one viewpoint which the scene manager can suggest, it will always suggest
+                the first one unless the random parameter is true.
+            @param
+                random If true, and there is more than one possible suggestion, a random one will be used. If false
+                the same one will always be suggested.
+            @return
+                On success, true is returned.
+            @par
+                On failiure, false is returned.
+        */
+        virtual ViewPoint getSuggestedViewpoint(bool random = false);
+
+        /** Method for setting a specific option of the Scene Manager. These options are usually
+            specific for a certain implemntation of the Scene Manager class, and may (and probably
+            will) not exist across different implementations.
+            @param
+                strKey The name of the option to set
+            @param
+                pValue A pointer to the value - the size should be calculated by the scene manager
+                based on the key
+            @return
+                On success, true is returned.
+            @par
+                On failiure, false is returned.
+        */
+        virtual bool setOption( const String& strKey, const void* pValue ) { return false; }
+
+        /** Method for getting the value of an implementation-specific Scene Manager option.
+            @param
+                strKey The name of the option
+            @param
+                pDestValue A pointer to a memory location where the value will
+                be copied. Currently, the memory will be allocated by the
+                scene manager, but this may change
+            @return
+                On success, true is returned and pDestValue points to the value of the given
+                option.
+            @par
+                On failiure, false is returned and pDestValue is set to NULL.
+        */
+        virtual bool getOption( const String& strKey, void* pDestValue ) { return false; }
+
+        /** Method for verifying wether the scene manager has an implementation-specific
+            option.
+            @param
+                strKey The name of the option to check for.
+            @return
+                If the scene manager contains the given option, true is returned.
+            @remarks
+                If it does not, false is returned.
+        */
+        virtual bool hasOption( const String& strKey ) const { return false; }
+        /** Method for getting all possible values for a specific option. When this list is too large
+            (i.e. the option expects, for example, a float), the return value will be true, but the
+            list will contain just one element whose size will be set to 0.
+            Otherwise, the list will be filled with all the possible values the option can
+            accept.
+            @param
+                strKey The name of the option to get the values for.
+            @param
+                refValueList A reference to a list that will be filled with the available values.
+            @return
+                On success (the option exists), true is returned.
+            @par
+                On failure, false is returned.
+        */
+        virtual bool getOptionValues( const String& strKey, StringVector& refValueList ) { return false; }
+
+        /** Method for getting all the implementation-specific options of the scene manager.
+            @param
+                refKeys A reference to a list that will be filled with all the available options.
+            @return
+                On success, true is returned. On failiure, false is returned.
+        */
+        virtual bool getOptionKeys( StringVector& refKeys ) { return false; }
+
+        /** Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class.
+            @remarks
+                This must be done before issuing objects to the rendering pipeline, since derived transformations from
+                parent nodes are not updated until required. This SceneManager is a basic implementation which simply
+                updates all nodes from the root. This ensures the scene is up to date but requires all the nodes
+                to be updated even if they are not visible. Subclasses could trim this such that only potentially visible
+                nodes are updated.
+        */
+        virtual void _updateSceneGraph(Camera* cam);
+
+        /** Internal method which parses the scene to find visible objects to render.
+            @remarks
+                If you're implementing a custom scene manager, this is the most important method to
+                override since it's here you can apply your custom world partitioning scheme. Once you
+                have added the appropriate objects to the render queue, you can let the default
+                SceneManager objects _renderVisibleObjects handle the actual rendering of the objects
+                you pick.
+            @par
+                Any visible objects will be added to a rendering queue, which is indexed by material in order
+                to ensure objects with the same material are rendered together to minimise render state changes.
+        */
+        virtual void _findVisibleObjects(Camera* cam, bool onlyShadowCasters);
+
+        /** Internal method for applying animations to scene nodes.
+        @remarks
+            Uses the internally stored AnimationState objects to apply animation to SceneNodes.
+        */
+        virtual void _applySceneAnimations(void);
+
+        /** Sends visible objects found in _findVisibleObjects to the rendering engine.
+        */
+        virtual void _renderVisibleObjects(void);
+
+        /** Prompts the class to send its contents to the renderer.
+            @remarks
+                This method prompts the scene manager to send the
+                contents of the scene it manages to the rendering
+                pipeline, possibly preceded by some sorting, culling
+                or other scene management tasks. Note that this method is not normally called
+                directly by the user application; it is called automatically
+                by the Ogre rendering loop.
+            @param camera Pointer to a camera from whose viewpoint the scene is to
+                be rendered.
+            @param vp The target viewport
+            @param includeOverlays Whether or not overlay objects should be rendered
+        */
+        virtual void _renderScene(Camera* camera, Viewport* vp, bool includeOverlays);
+
+        /** Internal method for queueing the sky objects with the params as 
+            previously set through setSkyBox, setSkyPlane and setSkyDome.
+        */
+        virtual void _queueSkiesForRendering(Camera* cam);
+
+
+
+        /** Notifies the scene manager of its destination render system
+            @remarks
+                Called automatically by RenderSystem::addSceneManager
+                this method simply notifies the manager of the render
+                system to which its output must be directed.
+            @param
+                sys Pointer to the RenderSystem subclass to be used as a render target.
+        */
+        virtual void _setDestinationRenderSystem(RenderSystem* sys);
+
+        /** Enables / disables a 'sky plane' i.e. a plane at constant
+            distance from the camera representing the sky.
+            @remarks
+                You can create sky planes yourself using the standard mesh and
+                entity methods, but this creates a plane which the camera can
+                never get closer or further away from - it moves with the camera.
+                (NB you could create this effect by creating a world plane which
+                was attached to the same SceneNode as the Camera too, but this
+                would only apply to a single camera whereas this plane applies to
+                any camera using this scene manager).
+            @note
+                To apply scaling, scrolls etc to the sky texture(s) you
+                should use the TextureUnitState class methods.
+            @param
+                enable True to enable the plane, false to disable it
+            @param
+                plane Details of the plane, i.e. it's normal and it's
+                distance from the camera.
+            @param
+                materialName The name of the material the plane will use
+            @param
+                scale The scaling applied to the sky plane - higher values
+                mean a bigger sky plane - you may want to tweak this
+                depending on the size of plane.d and the other
+                characteristics of your scene
+            @param
+                tiling How many times to tile the texture across the sky.
+                Applies to all texture layers. If you need finer control use
+                the TextureUnitState texture coordinate transformation methods.
+            @param
+                drawFirst If true, the plane is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the plane.d value is large enough that no objects
+                will 'poke through' the sky plane when it is rendered.
+			@param
+				bow If zero, the plane will be completely flat (like previous
+				versions.  If above zero, the plane will be curved, allowing
+				the sky to appear below camera level.  Curved sky planes are 
+				simular to skydomes, but are more compatable with fog.
+            @param xsegments, ysegments
+                Determines the number of segments the plane will have to it. This
+                is most important when you are bowing the plane, but may also be useful
+                if you need tesselation on the plane to perform per-vertex effects.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyPlane(
+            bool enable,
+            const Plane& plane, const String& materialName, Real scale = 1000,
+            Real tiling = 10, bool drawFirst = true, Real bow = 0, 
+            int xsegments = 1, int ysegments = 1, 
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Enables / disables a 'sky box' i.e. a 6-sided box at constant
+            distance from the camera representing the sky.
+            @remarks
+                You could create a sky box yourself using the standard mesh and
+                entity methods, but this creates a plane which the camera can
+                never get closer or further away from - it moves with the camera.
+                (NB you could create this effect by creating a world box which
+                was attached to the same SceneNode as the Camera too, but this
+                would only apply to a single camera whereas this skybox applies
+                to any camera using this scene manager).
+            @par
+                The material you use for the skybox can either contain layers
+                which are single textures, or they can be cubic textures, i.e.
+                made up of 6 images, one for each plane of the cube. See the
+                TextureUnitState class for more information.
+            @param
+                enable True to enable the skybox, false to disable it
+            @param
+                materialName The name of the material the box will use
+            @param
+                distance Distance in world coorinates from the camera to
+                each plane of the box. The default is normally OK.
+            @param
+                drawFirst If true, the box is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the distance value is large enough that no
+                objects will 'poke through' the sky box when it is rendered.
+            @param
+                orientation Optional parameter to specify the orientation
+                of the box. By default the 'top' of the box is deemed to be
+                in the +y direction, and the 'front' at the -z direction.
+                You can use this parameter to rotate the sky if you want.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyBox(
+            bool enable, const String& materialName, Real distance = 5000,
+            bool drawFirst = true, const Quaternion& orientation = Quaternion::IDENTITY,
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Enables / disables a 'sky dome' i.e. an illusion of a curved sky.
+            @remarks
+                A sky dome is actually formed by 5 sides of a cube, but with
+                texture coordinates generated such that the surface appears
+                curved like a dome. Sky domes are appropriate where you need a
+                realistic looking sky where the scene is not going to be
+                'fogged', and there is always a 'floor' of some sort to prevent
+                the viewer looking below the horizon (the distortion effect below
+                the horizon can be pretty horrible, and there is never anyhting
+                directly below the viewer). If you need a complete wrap-around
+                background, use the setSkyBox method instead. You can actually
+                combine a sky box and a sky dome if you want, to give a positional
+                backdrop with an overlayed curved cloud layer.
+            @par
+                Sky domes work well with 2D repeating textures like clouds. You
+                can change the apparant 'curvature' of the sky depending on how
+                your scene is viewed - lower curvatures are better for 'open'
+                scenes like landscapes, whilst higher curvatures are better for
+                say FPS levels where you don't see a lot of the sky at once and
+                the exaggerated curve looks good.
+            @param
+                enable True to enable the skydome, false to disable it
+            @param
+                materialName The name of the material the dome will use
+            @param
+                curvature The curvature of the dome. Good values are
+                between 2 and 65. Higher values are more curved leading to
+                a smoother effect, lower values are less curved meaning
+                more distortion at the horizons but a better distance effect.
+            @param
+                tiling How many times to tile the texture(s) across the
+                dome.
+            @param
+                distance Distance in world coorinates from the camera to
+                each plane of the box the dome is rendered on. The default
+                is normally OK.
+            @param
+                drawFirst If true, the dome is drawn before all other
+                geometry in the scene, without updating the depth buffer.
+                This is the safest rendering method since all other objects
+                will always appear in front of the sky. However this is not
+                the most efficient way if most of the sky is often occluded
+                by other objects. If this is the case, you can set this
+                parameter to false meaning it draws <em>after</em> all other
+                geometry which can be an optimisation - however you must
+                ensure that the distance value is large enough that no
+                objects will 'poke through' the sky when it is rendered.
+            @param
+                orientation Optional parameter to specify the orientation
+                of the dome. By default the 'top' of the dome is deemed to
+                be in the +y direction, and the 'front' at the -z direction.
+                You can use this parameter to rotate the sky if you want.
+            @param groupName
+                The name of the resource group to which to assign the plane mesh.
+        */
+        virtual void setSkyDome(
+            bool enable, const String& materialName, Real curvature = 10,
+            Real tiling = 8, Real distance = 4000, bool drawFirst = true,
+            const Quaternion& orientation = Quaternion::IDENTITY,
+            int xsegments = 16, int ysegments = 16, int ysegments_keep = -1,
+            const String& groupName = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+        /** Sets the fogging mode applied to the scene.
+            @remarks
+                This method sets up the scene-wide fogging effect. These settings
+                apply to all geometry rendered, UNLESS the material with which it
+                is rendered has it's own fog settings (see Material::setFog).
+            @param
+                mode Set up the mode of fog as described in the FogMode
+                enum, or set to FOG_NONE to turn off.
+            @param
+                colour The colour of the fog. Either set this to the same
+                as your viewport background colour, or to blend in with a
+                skydome or skybox.
+            @param
+                expDensity The density of the fog in FOG_EXP or FOG_EXP2
+                mode, as a value between 0 and 1. The default is 0.001. 
+            @param
+                linearStart Distance in world units at which linear fog starts to
+                encroach. Only applicable if mode is
+                FOG_LINEAR.
+            @param
+                linearEnd Distance in world units at which linear fog becomes completely
+                opaque. Only applicable if mode is
+                FOG_LINEAR.
+        */
+        void setFog(
+            FogMode mode = FOG_NONE, const ColourValue& colour = ColourValue::White,
+            Real expDensity = 0.001, Real linearStart = 0.0, Real linearEnd = 1.0);
+
+        /** Returns the fog mode for the scene.
+        */
+        virtual FogMode getFogMode(void) const;
+
+        /** Returns the fog colour for the scene.
+        */
+        virtual const ColourValue& getFogColour(void) const;
+
+        /** Returns the fog start distance for the scene.
+        */
+        virtual Real getFogStart(void) const;
+
+        /** Returns the fog end distance for the scene.
+        */
+        virtual Real getFogEnd(void) const;
+
+        /** Returns the fog density for the scene.
+        */
+        virtual Real getFogDensity(void) const;
+
+
+        /** Creates a new BillboardSet for use with this scene manager.
+            @remarks
+                This method creates a new BillboardSet which is registered with
+                the SceneManager. The SceneManager will destroy this object when
+                it shuts down or when the SceneManager::clearScene method is
+                called, so the caller does not have to worry about destroying
+                this object (in fact, it definitely should not do this).
+            @par
+                See the BillboardSet documentations for full details of the
+                returned class.
+            @param
+                name The name to give to this billboard set. Must be unique.
+            @param
+                poolSize The initial size of the pool of billboards (see BillboardSet for more information)
+            @see
+                BillboardSet
+        */
+        virtual BillboardSet* createBillboardSet(const String& name, unsigned int poolSize = 20);
+
+        /** Retrieves a pointer to the named BillboardSet.
+        */
+        virtual BillboardSet* getBillboardSet(const String& name);
+
+        /** Removes & destroys an BillboardSet from the SceneManager.
+            @warning
+                Must only be done if the BillboardSet is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene. If you are unsure, use clearScene.
+        */
+        virtual void removeBillboardSet(BillboardSet* set);
+
+        /** Removes & destroys an BillboardSet from the SceneManager by name.
+            @warning
+                Must only be done if the BillboardSet is not attached
+                to a SceneNode. It may be safer to wait to clear the whole
+                scene. If you are unsure, use clearScene.
+        */
+        virtual void removeBillboardSet(const String& name);
+
+        /** Removes & destroys all BillboardSets.
+        @warning
+        Again, use caution since no BillboardSet must be referred to
+        elsewhere e.g. attached to a SceneNode otherwise a crash
+        is likely. Use clearScene if you are unsure (it clears SceneNode
+        entries too.)
+        @see
+        SceneManager::clearScene
+        */
+        virtual void removeAllBillboardSets(void);
+
+        /** Tells the SceneManager whether it should render the SceneNodes which 
+            make up the scene as well as the objects in the scene.
+        @remarks
+            This method is mainly for debugging purposes. If you set this to 'true',
+            each node will be rendered as a set of 3 axes to allow you to easily see
+            the orientation of the nodes.
+        */
+        virtual void setDisplaySceneNodes(bool display);
+
+        /** Creates an animation which can be used to animate scene nodes.
+        @remarks
+            An animation is a collection of 'tracks' which over time change the position / orientation
+            of Node objects. In this case, the animation will likely have tracks to modify the position
+            / orientation of SceneNode objects, e.g. to make objects move along a path.
+        @par
+            You don't need to use an Animation object to move objects around - you can do it yourself
+            using the methods of the Node in your FrameListener class. However, when you need relatively
+            complex scripted animation, this is the class to use since it will interpolate between
+            keyframes for you and generally make the whole process easier to manage.
+        @par
+            A single animation can affect multiple Node objects (each AnimationTrack affects a single Node).
+            In addition, through animation blending a single Node can be affected by multiple animations,
+            athough this is more useful when performing skeletal animation (see Skeleton::createAnimation).
+        @par
+            Note that whilst it uses the same classes, the animations created here are kept separate from the
+            skeletal animations of meshes (each Skeleton owns those animations).
+        @param name The name of the animation, must be unique within this SceneManager.
+        @param length The total length of the animation.
+        */
+        virtual Animation* createAnimation(const String& name, Real length);
+
+        /** Looks up an Animation object previously created with createAnimation. */
+        virtual Animation* getAnimation(const String& name) const;
+
+        /** Destroys an Animation. 
+        @remarks
+            You should ensure that none of your code is referencing this animation objects since the 
+            memory will be freed.
+        */
+        virtual void destroyAnimation(const String& name);
+
+        /** Removes all animations created using this SceneManager. */
+        virtual void destroyAllAnimations(void);
+
+        /** Create an AnimationState object for managing application of animations.
+        @remarks
+            You can create Animation objects for animating SceneNode obejcts using the
+            createAnimation method. However, in order to actually apply those animations
+            you have to call methods on Node and Animation in a particular order (namely
+            Node::resetToInitialState and Animation::apply). To make this easier and to
+            help track the current time position of animations, the AnimationState object
+            is provided. </p>
+            So if you don't want to control animation application manually, call this method,
+            update the returned object as you like every frame and let SceneManager apply 
+            the animation state for you.
+        @par
+            Remember, AnimationState objects are disabled by default at creation time. 
+            Turn them on when you want them using their setEnabled method.
+        @par
+            Note that any SceneNode affected by this automatic animation will have it's state
+            reset to it's initial position before application of the animation. Unless specifically
+            modified using Node::setInitialState the Node assumes it's initial state is at the
+            origin. If you want the base state of the SceneNode to be elsewhere, make your changes
+            to the node using the standard transform methods, then call setInitialState to 
+            'bake' this reference position into the node.
+        @param animName The name of an animation created already with createAnimation.
+        */
+        virtual AnimationState* createAnimationState(const String& animName);
+
+        /** Retrieves animation state as previously created using createAnimationState */
+        virtual AnimationState* getAnimationState(const String& animName);
+
+        /** Destroys an AnimationState. 
+        @remarks
+            You should ensure that none of your code is referencing this animation 
+            state object since the memory will be freed.
+        */
+        virtual void destroyAnimationState(const String& name);
+
+        /** Removes all animation states created using this SceneManager. */
+        virtual void destroyAllAnimationStates(void);
+
+        /** Manual rendering method, for advanced users only.
+        @remarks
+            This method allows you to send rendering commands through the pipeline on
+            demand, bypassing OGRE's normal world processing. You should only use this if you
+            really know what you're doing; OGRE does lots of things for you that you really should
+            let it do. However, there are times where it may be useful to have this manual interface,
+            for example overlaying something on top of the scene rendered by OGRE.
+        @par
+            Because this is an instant rendering method, timing is important. The best 
+            time to call it is from a RenderTargetListener event handler.
+        @par
+            Don't call this method a lot, it's designed for rare (1 or 2 times per frame) use. 
+            Calling it regularly per frame will cause frame rate drops!
+        @param rend A RenderOperation object describing the rendering op
+        @param pass The Pass to use for this render
+        @param vp Pointer to the viewport to render to
+        @param worldMatrix The transform to apply from object to world space
+        @param viewMatrix The transform to apply from world to view space
+        @param projMatrix The transform to apply from view to screen space
+        @param doBeginEndFrame If true, beginFrame() and endFrame() are called, 
+            otherwise not. You should leave this as false if you are calling
+            this within the main render loop.
+        */
+        virtual void manualRender(RenderOperation* rend, Pass* pass, Viewport* vp, 
+            const Matrix4& worldMatrix, const Matrix4& viewMatrix, const Matrix4& projMatrix, 
+            bool doBeginEndFrame = false) ;
+
+        /** Registers a new RenderQueueListener which will be notified when render queues
+            are processed.
+        */
+        virtual void addRenderQueueListener(RenderQueueListener* newListener);
+
+        /** Removes a listener previously added with addRenderQueueListener. */
+        virtual void removeRenderQueueListener(RenderQueueListener* delListener);
+
+		/** Adds an item to the 'special case' render queue list.
+		@remarks
+			Normally all render queues are rendered, in their usual sequence, 
+			only varying if a RenderQueueListener nominates for the queue to be 
+			repeated or skipped. This method allows you to add a render queue to 
+			a 'special case' list, which varies the behaviour. The effect of this
+			list depends on the 'mode' in which this list is in, which might be
+			to exclude these render queues, or to include them alone (excluding
+			all other queues). This allows you to perform broad selective
+			rendering without requiring a RenderQueueListener.
+		@param qid The identifier of the queue which should be added to the
+			special case list. Nothing happens if the queue is already in the list.
+		*/
+		virtual void addSpecialCaseRenderQueue(RenderQueueGroupID qid);
+		/** Removes an item to the 'special case' render queue list.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param qid The identifier of the queue which should be removed from the
+			special case list. Nothing happens if the queue is not in the list.
+		*/
+		virtual void removeSpecialCaseRenderQueue(RenderQueueGroupID qid);
+		/** Clears the 'special case' render queue list.
+		@see SceneManager::addSpecialCaseRenderQueue
+		*/
+		virtual void clearSpecialCaseRenderQueues(void);
+		/** Sets the way the special case render queue list is processed.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param mode The mode of processing
+		*/
+		virtual void setSpecialCaseRenderQueueMode(SpecialCaseRenderQueueMode mode);
+		/** Gets the way the special case render queue list is processed. */
+		virtual SpecialCaseRenderQueueMode getSpecialCaseRenderQueueMode(void);
+		/** Returns whether or not the named queue will be rendered based on the
+			current 'special case' render queue list and mode.
+		@see SceneManager::addSpecialCaseRenderQueue
+		@param qid The identifier of the queue which should be tested
+		@returns true if the queue will be rendered, false otherwise
+		*/
+		virtual bool isRenderQueueToBeProcessed(RenderQueueGroupID qid);
+
+		/** Sets the render queue that the world geometry (if any) this SceneManager
+			renders will be associated with.
+		@remarks
+			SceneManagers which provide 'world geometry' should place it in a 
+			specialised render queue in order to make it possible to enable / 
+			disable it easily using the addSpecialCaseRenderQueue method. Even 
+			if the SceneManager does not use the render queues to render the 
+			world geometry, it should still pick a queue to represent it's manual
+			rendering, and check isRenderQueueToBeProcessed before rendering.
+		@note
+			Setting this may not affect the actual ordering of rendering the
+			world geometry, if the world geometry is being rendered manually
+			by the SceneManager. If the SceneManager feeds world geometry into
+			the queues, however, the ordering will be affected. 
+		*/
+		virtual void setWorldGeometryRenderQueue(RenderQueueGroupID qid);
+		/** Gets the render queue that the world geometry (if any) this SceneManager
+			renders will be associated with.
+		@remarks
+			SceneManagers which provide 'world geometry' should place it in a 
+			specialised render queue in order to make it possible to enable / 
+			disable it easily using the addSpecialCaseRenderQueue method. Even 
+			if the SceneManager does not use the render queues to render the 
+			world geometry, it should still pick a queue to represent it's manual
+			rendering, and check isRenderQueueToBeProcessed before rendering.
+		*/
+		virtual RenderQueueGroupID getWorldGeometryRenderQueue(void);
+
+		/** Allows all bounding boxes of scene nodes to be displayed. */
+		virtual void showBoundingBoxes(bool bShow);
+
+		/** Returns if all bounding boxes of scene nodes are to be displayed */
+		virtual bool getShowBoundingBoxes() const;
+
+        /** Internal method for notifying the manager that a SceneNode is autotracking. */
+        virtual void _notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack);
+
+        
+        /** Creates an AxisAlignedBoxSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param box Details of the box which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual AxisAlignedBoxSceneQuery* 
+            createAABBQuery(const AxisAlignedBox& box, unsigned long mask = 0xFFFFFFFF);
+        /** Creates a SphereSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            for a spherical region. See SceneQuery and SphereSceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param sphere Details of the sphere which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual SphereSceneQuery* 
+            createSphereQuery(const Sphere& sphere, unsigned long mask = 0xFFFFFFFF);
+        /** Creates a PlaneBoundedVolumeListSceneQuery for this scene manager. 
+        @remarks
+        This method creates a new instance of a query object for this scene manager, 
+        for a region enclosed by a set of planes (normals pointing inwards). 
+        See SceneQuery and PlaneBoundedVolumeListSceneQuery for full details.
+        @par
+        The instance returned from this method must be destroyed by calling
+        SceneManager::destroyQuery when it is no longer required.
+        @param volumes Details of the volumes which describe the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+        certain objects; see SceneQuery for details.
+        */
+        virtual PlaneBoundedVolumeListSceneQuery* 
+            createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, unsigned long mask = 0xFFFFFFFF);
+
+
+        /** Creates a RaySceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for this scene manager, 
+            looking for objects which fall along a ray. See SceneQuery and RaySceneQuery 
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param ray Details of the ray which describes the region for this query.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual RaySceneQuery* 
+            createRayQuery(const Ray& ray, unsigned long mask = 0xFFFFFFFF);
+        //PyramidSceneQuery* createPyramidQuery(const Pyramid& p, unsigned long mask = 0xFFFFFFFF);
+        /** Creates an IntersectionSceneQuery for this scene manager. 
+        @remarks
+            This method creates a new instance of a query object for locating
+            intersecting objects. See SceneQuery and IntersectionSceneQuery
+            for full details.
+        @par
+            The instance returned from this method must be destroyed by calling
+            SceneManager::destroyQuery when it is no longer required.
+        @param mask The query mask to apply to this query; can be used to filter out
+            certain objects; see SceneQuery for details.
+        */
+        virtual IntersectionSceneQuery* 
+            createIntersectionQuery(unsigned long mask = 0xFFFFFFFF);
+
+        /** Destroys a scene query of any type. */
+        virtual void destroyQuery(SceneQuery* query);
+
+        typedef MapIterator<SceneLightList> LightIterator;
+        typedef MapIterator<EntityList> EntityIterator;
+        typedef MapIterator<CameraList> CameraIterator;
+        typedef MapIterator<BillboardSetList> BillboardSetIterator;
+        typedef MapIterator<AnimationList> AnimationIterator;
+
+        /** Returns a specialised MapIterator over all lights in the scene. */
+        LightIterator getLightIterator(void) {
+            return LightIterator(mLights.begin(), mLights.end());
+        }
+        /** Returns a specialised MapIterator over all entities in the scene. */
+        EntityIterator getEntityIterator(void) {
+            return EntityIterator(mEntities.begin(), mEntities.end());
+        }
+        /** Returns a specialised MapIterator over all cameras in the scene. */
+        CameraIterator getCameraIterator(void) {
+            return CameraIterator(mCameras.begin(), mCameras.end());
+        }
+        /** Returns a specialised MapIterator over all BillboardSets in the scene. */
+        BillboardSetIterator getBillboardSetIterator(void) {
+            return BillboardSetIterator(mBillboardSets.begin(), mBillboardSets.end());
+        }
+        /** Returns a specialised MapIterator over all animations in the scene. */
+        AnimationIterator getAnimationIterator(void) {
+            return AnimationIterator(mAnimationsList.begin(), mAnimationsList.end());
+        }
+        /** Returns a specialised MapIterator over all animation states in the scene. */
+        AnimationStateIterator getAnimationStateIterator(void) {
+            return AnimationStateIterator(mAnimationStates.begin(), mAnimationStates.end());
+        }
+
+        /** Sets the general shadow technique to be used in this scene.
+        @remarks   
+            There are multiple ways to generate shadows in a scene, and each has 
+            strengths and weaknesses. 
+            <ul><li>Stencil-based approaches can be used to 
+            draw very long, extreme shadows without loss of precision and the 'additive'
+            version can correctly show the shadowing of complex effects like bump mapping
+            because they physically exclude the light from those areas. However, the edges
+            are very sharp and stencils cannot handle transparency, and they involve a 
+            fair amount of CPU work in order to calculate the shadow volumes, especially
+            when animated objects are involved.</li>
+            <li>Texture-based approaches are good for handling transparency (they can, for
+            example, correctly shadow a mesh which uses alpha to represent holes), and they
+            require little CPU overhead, and can happily shadow geometry which is deformed
+            by a vertex program, unlike stencil shadows. However, they have a fixed precision 
+            which can introduce 'jaggies' at long range and have fillrate issues of their own.</li>
+            </ul>
+        @par
+            We support 2 kinds of stencil shadows, and 2 kinds of texture-based shadows, and one
+            simple decal approach. The 2 stencil approaches differ in the amount of multipass work 
+            that is required - the modulative approach simply 'darkens' areas in shadow after the 
+            main render, which is the least expensive, whilst the additive approach has to perform 
+            a render per light and adds the cumulative effect, whcih is more expensive but more 
+            accurate. The texture based shadows both work in roughly the same way, the only difference is
+            that the shadowmap approach is slightly more accurate, but requires a more recent
+            graphics card.
+        @par
+            Note that because mixing many shadow techniques can cause problems, only one technique
+            is supported at once. Also, you should call this method at the start of the 
+            scene setup. 
+        @param technique The shadowing technique to use for the scene.
+        */
+        virtual void setShadowTechnique(ShadowTechnique technique);
+        
+        /** Gets the current shadow technique. */
+        virtual ShadowTechnique getShadowTechnique(void) const { return mShadowTechnique; }
+
+        /** Enables / disables the rendering of debug information for shadows. */
+        virtual void setShowDebugShadows(bool debug) { mDebugShadows = debug; }
+        /** Are debug shadows shown? */
+        virtual bool getShowDebugShadows(void ) const { return mDebugShadows; }
+
+        /** Set the colour used to modulate areas in shadow. 
+        @remarks This is only applicable for shadow techniques which involve 
+            darkening the area in shadow, as opposed to masking out the light. 
+            This colour provided is used as a modulative value to darken the
+            areas.
+        */
+        virtual void setShadowColour(const ColourValue& colour);
+        /** Get the colour used to modulate areas in shadow. 
+        @remarks This is only applicable for shadow techniques which involve 
+        darkening the area in shadow, as opposed to masking out the light. 
+        This colour provided is used as a modulative value to darken the
+        areas.
+        */
+        virtual const ColourValue& getShadowColour(void) const;
+        /** Sets the distance a shadow volume is extruded for a directional light.
+        @remarks
+            Although directional lights are essentially infinite, there are many
+            reasons to limit the shadow extrusion distance to a finite number, 
+            not least of which is compatibility with older cards (which do not
+            support infinite positions), and shadow caster elimination.
+        @par
+            The default value is 10,000 world units. This does not apply to
+            point lights or spotlights, since they extrude up to their 
+            attenuation range.
+        */
+        virtual void setShadowDirectionalLightExtrusionDistance(Real dist); 
+        /** Gets the distance a shadow volume is extruded for a directional light.
+        */
+        virtual Real getShadowDirectionalLightExtrusionDistance(void) const;
+        /** Sets the maximum distance away from the camera that shadows
+        will be visible.
+        @remarks
+        Shadow techniques can be expensive, therefore it is a good idea
+        to limit them to being rendered close to the camera if possible,
+        and to skip the expense of rendering shadows for distance objects.
+        This method allows you to set the distance at which shadows will no
+        longer be rendered.
+        @note
+        Each shadow technique can interpret this subtely differently.
+        For example, one technique may use this to eliminate casters,
+        another might use it to attenuate the shadows themselves.
+        You should tweak this value to suit your chosen shadow technique
+        and scene setup.
+        */
+        virtual void setShadowFarDistance(Real distance);
+        /** Gets the maximum distance away from the camera that shadows
+        will be visible.
+        */
+        virtual Real getShadowFarDistance(void) const
+        { return mShadowFarDist; }
+
+		/** Sets the maximum size of the index buffer used to render shadow
+		 	primitives.
+		@remarks
+			This method allows you to tweak the size of the index buffer used
+			to render shadow primitives (including stencil shadow volumes). The
+			default size is 51,200 entries, which is 100k of GPU memory, or
+			enough to render approximately 17,000 triangles. You can reduce this
+			as long as you do not have any models / world geometry chunks which 
+			could require more than the amount you set.
+		@par
+			The maximum number of triangles required to render a single shadow 
+			volume (including light and dark caps when needed) will be 3x the 
+			number of edges on the light silhouette, plus the number of 
+			light-facing triangles.	On average, half the 
+			triangles will be facing toward the light, but the number of 
+			triangles in the silhouette entirely depends on the mesh - 
+			angular meshes will have a higher silhouette tris/mesh tris
+			ratio than a smooth mesh. You can estimate the requirements for
+			your particular mesh by rendering it alone in a scene with shadows
+			enabled and a single light - rotate it or the light and make a note
+			of how high the triangle count goes (remembering to subtract the 
+			mesh triangle count)
+		@param size The number of indexes; divide this by 3 to determine the
+			number of triangles.
+		*/
+		virtual void setShadowIndexBufferSize(size_t size);
+        /// Get the size of the shadow index buffer
+		virtual size_t getShadowIndexBufferSize(void) const
+		{ return mShadowIndexBufferSize; }
+        /** Set the size of the texture used for texture-based shadows.
+        @remarks
+            The larger the shadow texture, the better the detail on 
+            texture based shadows, but obviously this takes more memory.
+            The default size is 512. Sizes must be a power of 2.
+        */
+        virtual void setShadowTextureSize(unsigned short size);
+        /// Get the size of the texture used for texture based shadows
+        unsigned short getShadowTextureSize(void) const {return mShadowTextureSize; }
+        /** Set the pixel format of the textures used for texture-based shadows.
+        @remarks
+			By default, a colour texture is used (PF_X8R8G8B8) for texture shadows,
+			but if you want to use more advanced texture shadow types you can 
+			alter this. If you do, you will have to also call
+			setShadowTextureCasterMaterial and setShadowTextureReceiverMaterial
+			to provide shader-based materials to use these customised shadow
+			texture formats.
+        */
+        virtual void setShadowTexturePixelFormat(PixelFormat fmt);
+        /// Get the format of the textures used for texture based shadows
+        PixelFormat getShadowTexturePixelFormat(void) const {return mShadowTextureFormat; }
+        /** Set the number of textures allocated for texture-based shadows.
+        @remarks
+            The default number of textures assigned to deal with texture based
+            shadows is 1; however this means you can only have one light casting
+            shadows at the same time. You can increase this number in order to 
+            make this more flexible, but be aware of the texture memory it will use.
+        */
+        virtual void setShadowTextureCount(unsigned short count);
+        /// Get the number of the textures allocated for texture based shadows
+        unsigned short getShadowTextureCount(void) const {return mShadowTextureCount; }
+        /** Sets the size and count of textures used in texture-based shadows. 
+        @remarks
+            @see setShadowTextureSize and setShadowTextureCount for details, this
+            method just allows you to change both at once, which can save on 
+            reallocation if the textures have already been created.
+        */
+        virtual void setShadowTextureSettings(unsigned short size, unsigned short count, 
+			PixelFormat fmt = PF_X8R8G8B8);
+        /** Sets the proportional distance which a texture shadow which is generated from a
+            directional light will be offset into the camera view to make best use of texture space.
+        @remarks
+            When generating a shadow texture from a directional light, an approximation is used
+            since it is not possible to render the entire scene to one texture. 
+            The texture is projected onto an area centred on the camera, and is
+            the shadow far distance * 2 in length (it is square). This wastes
+            a lot of texture space outside the frustum though, so this offset allows
+            you to move the texture in front of the camera more. However, be aware
+            that this can cause a little shadow 'jittering' during rotation, and
+            that if you move it too far then you'll start to get artefacts close 
+            to the camera. The value is represented as a proportion of the shadow
+            far distance, and the default is 0.6.
+        */
+        virtual void setShadowDirLightTextureOffset(Real offset) { mShadowTextureOffset = offset;}
+        /** Sets the proportional distance at which texture shadows begin to fade out.
+        @remarks
+            To hide the edges where texture shadows end (in directional lights)
+            Ogre will fade out the shadow in the distance. This value is a proportional
+            distance of the entire shadow visibility distance at which the shadow
+            begins to fade out. The default is 0.7
+        */
+        virtual void setShadowTextureFadeStart(Real fadeStart) 
+        { mShadowTextureFadeStart = fadeStart; }
+        /** Sets the proportional distance at which texture shadows finish to fading out.
+        @remarks
+        To hide the edges where texture shadows end (in directional lights)
+        Ogre will fade out the shadow in the distance. This value is a proportional
+        distance of the entire shadow visibility distance at which the shadow
+        is completely invisible. The default is 0.9.
+        */
+        virtual void setShadowTextureFadeEnd(Real fadeEnd) 
+        { mShadowTextureFadeEnd = fadeEnd; }
+
+		/** Sets whether or not texture shadows should attempt to self-shadow.
+		@remarks
+			The default implementation of texture shadows uses a fixed-function 
+			colour texture projection approach for maximum compatibility, and 
+			as such cannot support self-shadowing. However, if you decide to 
+			implement a more complex shadowing technique using the 
+			setShadowTextureCasterMaterial and setShadowTextureReceiverMaterial 
+			there is a possibility you may be able to support 
+			self-shadowing (e.g by implementing a shader-based shadow map). In 
+			this case you might want to enable this option.
+		@param selfShadow Whether to attempt self-shadowing with texture shadows
+		*/
+		virtual void setShadowTextureSelfShadow(bool selfShadow) 
+		{ mShadowTextureSelfShadow = selfShadow; }
+		/// Gets whether or not texture shadows attempt to self-shadow.
+		virtual bool getShadowTextureSelfShadow(void) const 
+		{ return mShadowTextureSelfShadow; }
+		/** Sets the default material to use for rendering shadow casters.
+		@remarks
+			By default shadow casters are rendered into the shadow texture using
+			an automatically generated fixed-function pass. This allows basic
+			projective texture shadows, but it's possible to use more advanced
+			shadow techniques by overriding the caster and receiver materials, for
+			example providing vertex and fragment programs to implement shadow
+			maps.
+		@par
+			You can rely on the ambient light in the scene being set to the 
+			requested texture shadow colour, if that's useful. 
+		@note
+			Individual objects may also override the vertex program in
+			your default material if their materials include 
+			shadow_caster_vertex_program_ref shadow_receiver_vertex_program_ref
+			entries, so if you use both make sure they are compatible.
+		@note
+			Only a single pass is allowed in your material, although multiple
+			techniques may be used for hardware fallback.
+		*/
+		virtual void setShadowTextureCasterMaterial(const String& name);
+		/** Sets the default material to use for rendering shadow receivers.
+		@remarks
+			By default shadow receivers are rendered as a post-pass using basic
+			modulation. This allows basic projective texture shadows, but it's 
+			possible to use more advanced shadow techniques by overriding the 
+			caster and receiver materials, for example providing vertex and 
+			fragment programs to implement shadow maps.
+		@par
+			You can rely on texture unit 0 containing the shadow texture, and 
+			for the unit to be set to use projective texturing from the light 
+			(only useful if you're using fixed-function, which is unlikely; 
+			otherwise you should rely on the texture_viewproj_matrix auto binding)
+		@note
+			Individual objects may also override the vertex program in
+			your default material if their materials include 
+			shadow_caster_vertex_program_ref shadow_receiver_vertex_program_ref
+			entries, so if you use both make sure they are compatible.
+		@note
+			Only a single pass is allowed in your material, although multiple
+			techniques may be used for hardware fallback.
+		*/
+		virtual void setShadowTextureReceiverMaterial(const String& name);
+
+		/** Sets whether we should use an inifinite camera far plane
+			when rendering stencil shadows.
+		@remarks
+			Stencil shadow coherency is very reliant on the shadow volume
+			not being clipped by the far plane. If this clipping happens, you
+			get a kind of 'negative' shadow effect. The best way to achieve
+			coherency is to move the far plane of the camera out to infinity,
+			thus preventing the far plane from clipping the shadow volumes.
+			When combined with vertex program extrusion of the volume to 
+			infinity, which	Ogre does when available, this results in very
+			robust shadow volumes. For this reason, when you enable stencil 
+			shadows, Ogre automatically changes your camera settings to 
+			project to infinity if the card supports it. You can disable this
+			behaviour if you like by calling this method; although you can 
+			never enable infinite projection if the card does not support it.
+		@par	
+			If you disable infinite projection, or it is not available, 
+			you need to be far more careful with your light attenuation /
+			directional light extrusion distances to avoid clipping artefacts
+			at the far plane.
+		@note
+			Recent cards will generally support infinite far plane projection.
+			However, we have found some cases where they do not, especially
+			on Direct3D. There is no standard capability we can check to 
+			validate this, so we use some heuristics based on experience:
+			<UL>
+			<LI>OpenGL always seems to support it no matter what the card</LI>
+			<LI>Direct3D on non-vertex program capable systems (including 
+			vertex program capable cards on Direct3D7) does not
+			support it</LI>
+			<LI>Direct3D on GeForce3 and GeForce4 Ti does not seem to support
+			infinite projection<LI>
+			</UL>
+			Therefore in the RenderSystem implementation, we may veto the use
+			of an infinite far plane based on these heuristics. 
+		*/
+        virtual void setShadowUseInfiniteFarPlane(bool enable) {
+            mShadowUseInfiniteFarPlane = enable; }
+
+		/** Creates a StaticGeometry instance suitable for use with this
+			SceneManager.
+		@remarks
+			StaticGeometry is a way of batching up geometry into a more 
+			efficient form at the expense of being able to move it. Please 
+			read the StaticGeometry class documentation for full information.
+		@param name The name to give the new object
+		@returns The new StaticGeometry instance
+		*/
+		virtual StaticGeometry* createStaticGeometry(const String& name);
+		/** Retrieve a previously created StaticGeometry instance. */
+		virtual StaticGeometry* getStaticGeometry(const String& name) const;
+		/** Remove & destroy a StaticGeometry instance. */
+		virtual void removeStaticGeometry(StaticGeometry* geom);
+		/** Remove & destroy a StaticGeometry instance. */
+		virtual void removeStaticGeometry(const String& name);
+		/** Remove & destroy all StaticGeometry instances. */
+		virtual void removeAllStaticGeometry(void);
+
+		
+    };
+
+    /** Default implementation of IntersectionSceneQuery. */
+    class _OgreExport DefaultIntersectionSceneQuery : 
+        public IntersectionSceneQuery
+    {
+    public:
+        DefaultIntersectionSceneQuery(SceneManager* creator);
+        ~DefaultIntersectionSceneQuery();
+
+        /** See IntersectionSceneQuery. */
+        void execute(IntersectionSceneQueryListener* listener);
+    };
+
+    /** Default implementation of RaySceneQuery. */
+	class _OgreExport DefaultRaySceneQuery : public RaySceneQuery
+    {
+    public:
+        DefaultRaySceneQuery(SceneManager* creator);
+        ~DefaultRaySceneQuery();
+
+        /** See RayScenQuery. */
+        void execute(RaySceneQueryListener* listener);
+    };
+    /** Default implementation of SphereSceneQuery. */
+	class _OgreExport DefaultSphereSceneQuery : public SphereSceneQuery
+    {
+    public:
+        DefaultSphereSceneQuery(SceneManager* creator);
+        ~DefaultSphereSceneQuery();
+
+        /** See SceneQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    /** Default implementation of PlaneBoundedVolumeListSceneQuery. */
+    class _OgreExport DefaultPlaneBoundedVolumeListSceneQuery : public PlaneBoundedVolumeListSceneQuery
+    {
+    public:
+        DefaultPlaneBoundedVolumeListSceneQuery(SceneManager* creator);
+        ~DefaultPlaneBoundedVolumeListSceneQuery();
+
+        /** See SceneQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    /** Default implementation of AxisAlignedBoxSceneQuery. */
+	class _OgreExport DefaultAxisAlignedBoxSceneQuery : public AxisAlignedBoxSceneQuery
+    {
+    public:
+        DefaultAxisAlignedBoxSceneQuery(SceneManager* creator);
+        ~DefaultAxisAlignedBoxSceneQuery();
+
+        /** See RayScenQuery. */
+        void execute(SceneQueryListener* listener);
+    };
+    
+
+
+} // Namespace
+
+
+
+#endif
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 158)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 158)
@@ -0,0 +1,644 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+#include "OgreSceneNode.h"
+
+#include "OgreException.h"
+#include "OgreEntity.h"
+#include "OgreCamera.h"
+#include "OgreLight.h"
+#include "OgreMath.h"
+#include "OgreSceneManager.h"
+#include "OgreMovableObject.h"
+#include "OgreWireBoundingBox.h"
+
+namespace Ogre {
+    //-----------------------------------------------------------------------
+    SceneNode::SceneNode(SceneManager* creator) 
+    : Node(), mLightListDirty(true), mWireBoundingBox(0), 
+	mShowBoundingBox(false), mCreator(creator), 
+	mYawFixed(false), mAutoTrackTarget(0), mIsInSceneGraph(false)
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false), mLastRendered(-1)
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    {
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::SceneNode(SceneManager* creator, const String& name) 
+    : Node(name), mLightListDirty(true), mWireBoundingBox(0), 
+	mShowBoundingBox(false), mCreator(creator), mYawFixed(false), 
+	mAutoTrackTarget(0), mIsInSceneGraph(false)
+	#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false)
+	#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    {
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::~SceneNode()
+    {
+        // Detach all objects, do this manually to avoid needUpdate() call 
+        // which can fail because of deleted items
+		ObjectMap::iterator itr;
+		MovableObject* ret;
+		for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
+		{
+		  ret = itr->second;
+		  ret->_notifyAttached((SceneNode*)0);
+		}
+        mObjectsByName.clear();
+
+        if (mWireBoundingBox) {
+			delete mWireBoundingBox;
+		}
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_update(bool updateChildren, bool parentHasChanged)
+    {
+        Node::_update(updateChildren, parentHasChanged);
+        _updateBounds();
+        mLightListDirty = true;
+
+    }
+    //-----------------------------------------------------------------------
+	void SceneNode::setParent(Node* parent)
+	{
+		Node::setParent(parent);
+
+		if (parent)
+		{
+			SceneNode* sceneParent = static_cast<SceneNode*>(parent);
+			setInSceneGraph(sceneParent->isInSceneGraph());
+		}
+		else
+		{
+			setInSceneGraph(false);
+		}
+	}
+    //-----------------------------------------------------------------------
+	void SceneNode::setInSceneGraph(bool inGraph)
+	{
+		if (inGraph != mIsInSceneGraph)
+		{
+			mIsInSceneGraph = inGraph;
+			// Tell children
+	        ChildNodeMap::iterator child;
+    	    for (child = mChildren.begin(); child != mChildren.end(); ++child)
+        	{
+            	SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+				sceneChild->setInSceneGraph(inGraph);
+			}
+		}
+	}
+    //-----------------------------------------------------------------------
+    void SceneNode::attachObject(MovableObject* obj)
+    {
+        obj->_notifyAttached(this);
+
+        // Also add to name index
+        std::pair<ObjectMap::iterator, bool> insresult = 
+            mObjectsByName.insert(ObjectMap::value_type(obj->getName(), obj));
+        assert(insresult.second && "Object was not attached because an object of the "
+            "same name was already attached to this node.");
+
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    unsigned short SceneNode::numAttachedObjects(void) const
+    {
+        return static_cast< unsigned short >( mObjectsByName.size() );
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::getAttachedObject(unsigned short index)
+    {
+        if (index < mObjectsByName.size())
+        {
+            ObjectMap::iterator i = mObjectsByName.begin();
+            // Increment (must do this one at a time)            
+            while (index--)++i;
+
+            return i->second;
+        }
+        else
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttachedObject");
+        }
+        return 0;
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::getAttachedObject(const String& name)
+    {
+        // Look up 
+        ObjectMap::iterator i = mObjectsByName.find(name);
+
+        if (i == mObjectsByName.end())
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Attached object " + 
+                name + " not found.", "SceneNode::getAttachedObject");
+        }
+
+        return i->second;
+
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::detachObject(unsigned short index)
+    {
+        MovableObject* ret;
+        if (index < mObjectsByName.size())
+        {
+
+            ObjectMap::iterator i = mObjectsByName.begin();
+            // Increment (must do this one at a time)            
+            while (index--)++i;
+
+            ret = i->second;
+            mObjectsByName.erase(i);
+            ret->_notifyAttached((SceneNode*)0);
+
+            // Make sure bounds get updated (must go right to the top)
+            needUpdate();
+
+            return ret;
+
+        }
+        else
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttchedEntity");
+        }
+        return 0;
+
+    }
+    //-----------------------------------------------------------------------
+    MovableObject* SceneNode::detachObject(const String& name)
+    {
+        ObjectMap::iterator it = mObjectsByName.find(name);
+        if (it == mObjectsByName.end())
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Object " + name + " is not attached "
+                "to this node.", "SceneNode::detachObject");
+        }
+        MovableObject* ret = it->second;
+        mObjectsByName.erase(it);
+        ret->_notifyAttached((SceneNode*)0);
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+        
+        return ret;
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::detachObject(MovableObject* obj)
+    {
+        ObjectMap::iterator i, iend;
+        iend = mObjectsByName.end();
+        for (i = mObjectsByName.begin(); i != iend; ++i)
+        {
+            if (i->second == obj)
+            {
+                mObjectsByName.erase(i);
+                break;
+            }
+        }
+        obj->_notifyAttached((SceneNode*)0);
+
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::detachAllObjects(void)
+    {
+		ObjectMap::iterator itr;
+		MovableObject* ret;
+		for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
+		{
+		  ret = itr->second;
+		  ret->_notifyAttached((SceneNode*)0);
+		}
+        mObjectsByName.clear();
+        // Make sure bounds get updated (must go right to the top)
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_updateBounds(void)
+    {
+        // Reset bounds first
+        mWorldAABB.setNull();
+
+        // Update bounds from own attached objects
+        ObjectMap::iterator i;
+        for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
+        {
+            // Merge world bounds of each object
+            mWorldAABB.merge(i->second->getWorldBoundingBox(true));
+        }
+
+        // Merge with children
+        ChildNodeMap::iterator child;
+        for (child = mChildren.begin(); child != mChildren.end(); ++child)
+        {
+            SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+            mWorldAABB.merge(sceneChild->mWorldAABB);
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, 
+        bool includeChildren, bool displayNodes, bool onlyShadowCasters)
+    {
+        // Check self visible
+        if (!cam->isVisible(mWorldAABB))
+            return;
+
+        // Add all entities
+        ObjectMap::iterator iobj;
+        ObjectMap::iterator iobjend = mObjectsByName.end();
+        for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj)
+        {
+            // Tell attached objects about camera position (incase any extra processing they want to do)
+            iobj->second->_notifyCurrentCamera(cam);
+            if (iobj->second->isVisible() && 
+                (!onlyShadowCasters || iobj->second->getCastShadows()))
+            {
+                iobj->second->_updateRenderQueue(queue);
+            }
+        }
+
+        if (includeChildren)
+        {
+            ChildNodeMap::iterator child, childend;
+            childend = mChildren.end();
+            for (child = mChildren.begin(); child != childend; ++child)
+            {
+                SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
+                sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
+            }
+        }
+
+        if (displayNodes)
+        {
+            // Include self in the render queue
+            queue->addRenderable(this);
+        }
+
+		// Check if the bounding box should be shown.
+		// See if our flag is set or if the scene manager flag is set.
+		if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes())) 
+		{ 
+			_addBoundingBoxToQueue(queue);
+		}
+
+
+    }
+
+
+	void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
+		// Create a WireBoundingBox if needed.
+		if (mWireBoundingBox == NULL) {
+			mWireBoundingBox = new WireBoundingBox();
+		}
+		mWireBoundingBox->setupBoundingBox(mWorldAABB);
+		queue->addRenderable(mWireBoundingBox);
+	}
+
+	void SceneNode::showBoundingBox(bool bShow) {
+		mShowBoundingBox = bShow;
+	}
+
+	bool SceneNode::getShowBoundingBox() const {
+		return mShowBoundingBox;
+	}
+
+
+    //-----------------------------------------------------------------------
+    Node* SceneNode::createChildImpl(void)
+    {
+        assert(mCreator);
+        return mCreator->createSceneNode();
+    }
+    //-----------------------------------------------------------------------
+    Node* SceneNode::createChildImpl(const String& name)
+    {
+        assert(mCreator);
+        return mCreator->createSceneNode(name);
+    }
+    //-----------------------------------------------------------------------
+    AxisAlignedBox SceneNode::_getWorldAABB(void) const
+    {
+        return mWorldAABB;
+    }
+    //-----------------------------------------------------------------------
+    SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void)
+    {
+        return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
+    }
+	//-----------------------------------------------------------------------
+	SceneNode::ConstObjectIterator SceneNode::getAttachedObjectIterator(void) const
+	{
+		return ConstObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
+	}
+    //-----------------------------------------------------------------------
+    SceneManager* SceneNode::getCreator(void) const
+    {
+        return mCreator;
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyChild(const String& name)
+    {
+        SceneNode* pChild = static_cast<SceneNode*>(getChild(name));
+        pChild->removeAndDestroyAllChildren();
+
+        removeChild(name);
+        pChild->getCreator()->destroySceneNode(name);
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyChild(unsigned short index)
+    {
+        SceneNode* pChild = static_cast<SceneNode*>(getChild(index));
+        pChild->removeAndDestroyAllChildren();
+
+        removeChild(index);
+        pChild->getCreator()->destroySceneNode(pChild->getName());
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::removeAndDestroyAllChildren(void)
+    {
+        ChildNodeMap::iterator i, iend;
+        iend = mChildren.end();
+        for (i = mChildren.begin(); i != iend; ++i)
+        {
+            SceneNode* sn = static_cast<SceneNode*>(i->second);
+            sn->removeAndDestroyAllChildren();
+            sn->getCreator()->destroySceneNode(sn->getName());
+        }
+	    mChildren.clear();
+        needUpdate();
+    }
+    //-----------------------------------------------------------------------
+	SceneNode* SceneNode::createChildSceneNode(const Vector3& translate, 
+        const Quaternion& rotate)
+	{
+		return static_cast<SceneNode*>(this->createChild(translate, rotate));
+	}
+    //-----------------------------------------------------------------------
+    SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate, 
+		const Quaternion& rotate)
+	{
+		return static_cast<SceneNode*>(this->createChild(name, translate, rotate));
+	}
+    //-----------------------------------------------------------------------
+    const LightList& SceneNode::findLights(Real radius) const
+    {
+        // TEMP FIX
+        // If a scene node is static and lights have moved, light list won't change
+        // can't use a simple global boolean flag since this is only called for
+        // visible nodes, so temporarily visible nodes will not be updated
+        // Since this is only called for visible nodes, skip the check for now
+        //if (mLightListDirty)
+        if (mCreator)
+        {
+            // Use SceneManager to calculate
+            mCreator->_populateLightList(this->_getDerivedPosition(), radius, mLightList);
+            mLightListDirty = false;
+        }
+        return mLightList;
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setAutoTracking(bool enabled, SceneNode* target, 
+        const Vector3& localDirectionVector,
+        const Vector3& offset)
+    {
+        if (enabled)
+        {
+            mAutoTrackTarget = target;
+            mAutoTrackOffset = offset;
+            mAutoTrackLocalDirection = localDirectionVector;
+        }
+        else
+        {
+            mAutoTrackTarget = 0;
+        }
+        if (mCreator)
+            mCreator->_notifyAutotrackingSceneNode(this, enabled);
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
+    {
+        mYawFixed = useFixed;
+        mYawFixedAxis = fixedAxis;
+    }
+
+	//-----------------------------------------------------------------------
+	void SceneNode::yaw(const Radian& angle, TransformSpace relativeTo)
+	{
+		if (mYawFixed)
+		{
+			rotate(mYawFixedAxis, angle, relativeTo);
+		}
+		else
+		{
+			rotate(Vector3::UNIT_Y, angle, relativeTo);
+		}
+
+	}
+    //-----------------------------------------------------------------------
+    void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        setDirection(Vector3(x,y,z), relativeTo, localDirectionVector);
+    }
+
+    //-----------------------------------------------------------------------
+    void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        // Do nothing if given a zero vector
+        if (vec == Vector3::ZERO) return;
+
+        // Adjust vector so that it is relative to local Z
+        Vector3 zAdjustVec;
+        if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
+        {
+            zAdjustVec = -vec;
+        }
+        else
+        {
+            Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
+            zAdjustVec = localToUnitZ * vec;
+        }
+        zAdjustVec.normalise();
+
+        Quaternion targetOrientation;
+        if( mYawFixed )
+        {
+            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
+            xVec.normalise();
+
+            Vector3 yVec = zAdjustVec.crossProduct( xVec );
+            yVec.normalise();
+            
+            targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
+        }
+        else
+        {
+
+            // Get axes from current quaternion
+            Vector3 axes[3];
+            _getDerivedOrientation().ToAxes(axes);
+            Quaternion rotQuat;
+            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f)
+            {
+                // Oops, a 180 degree turn (infinite possible rotation axes)
+                // Default to yaw i.e. use current UP
+                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
+            }
+            else
+            {
+                // Derive shortest arc to new direction
+                rotQuat = axes[2].getRotationTo(zAdjustVec);
+
+            }
+            targetOrientation = rotQuat * mOrientation;
+        }
+
+        if (relativeTo == TS_LOCAL || !mParent)
+        {
+            setOrientation(targetOrientation);
+        }
+        else
+        {
+            if (relativeTo == TS_PARENT)
+            {
+                setOrientation(targetOrientation * mParent->getOrientation().Inverse());
+            }
+            else if (relativeTo == TS_WORLD)
+            {
+                setOrientation(targetOrientation * mParent->_getDerivedOrientation().Inverse());
+            }
+        }
+
+
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        this->setDirection(targetPoint - _getDerivedPosition(), relativeTo, 
+            localDirectionVector);
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::_autoTrack(void)
+    {
+        // NB assumes that all scene nodes have been updated
+        if (mAutoTrackTarget)
+        {
+            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset, 
+                TS_WORLD, mAutoTrackLocalDirection);
+            // update self & children
+            _update(true, true);
+        }
+    }
+    //-----------------------------------------------------------------------
+    SceneNode* SceneNode::getParentSceneNode(void) const
+    {
+        return static_cast<SceneNode*>(getParent());
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::setVisible(bool visible, bool cascade)
+    {
+        ObjectMap::iterator oi, oiend;
+        oiend = mObjectsByName.end();
+        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
+        {
+            oi->second->setVisible(visible);
+        }
+
+        if (cascade)
+        {
+            ChildNodeMap::iterator i, iend;
+            iend = mChildren.end();
+            for (i = mChildren.begin(); i != iend; ++i)
+            {
+                static_cast<SceneNode*>(i->second)->setVisible(visible, cascade);
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::flipVisibility(bool cascade)
+    {
+        ObjectMap::iterator oi, oiend;
+        oiend = mObjectsByName.end();
+        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
+        {
+            oi->second->setVisible(!oi->second->isVisible());
+        }
+
+        if (cascade)
+        {
+            ChildNodeMap::iterator i, iend;
+            iend = mChildren.end();
+            for (i = mChildren.begin(); i != iend; ++i)
+            {
+                static_cast<SceneNode*>(i->second)->flipVisibility(cascade);
+            }
+        }
+    }
+	#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//-----------------------------------------------------------------------	
+	int SceneNode::lastVisited(void)
+	{
+		return mLastVisited;
+	}
+	//-----------------------------------------------------------------------
+	void SceneNode::setLastVisited(int frameid)
+	{
+		mLastVisited = frameid;
+	}
+	//-----------------------------------------------------------------------	
+	void SceneNode::setNodeVisible(bool visible)
+	{
+		mVisible = visible;
+	}
+	//-----------------------------------------------------------------------	
+	bool SceneNode::isNodeVisible(void)
+	{
+		return mVisible;
+	}
+	//-----------------------------------------------------------------------	
+	int SceneNode::lastRendered(void)
+	{
+		return mLastRendered;
+	}
+	//-----------------------------------------------------------------------
+	void SceneNode::setLastRendered(int frameid)
+	{
+		mLastRendered = frameid;
+	}
+	#endif //GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp	(revision 316)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp	(revision 316)
@@ -0,0 +1,419 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+// RenderSystem implementation
+// Note that most of this class is abstract since
+//  we cannot know how to implement the behaviour without
+//  being aware of the 3D API. However there are a few
+//  simple functions which can have a base implementation
+
+#include "OgreRenderSystem.h"
+
+#include "OgreRoot.h"
+#include "OgreViewport.h"
+#include "OgreException.h"
+#include "OgreRenderTarget.h"
+#include "OgreRenderWindow.h"
+#include "OgreMeshManager.h"
+#include "OgreMaterial.h"
+#include "OgreTimer.h"
+
+namespace Ogre {
+
+    const PlaneList Renderable::msDummyPlaneList; // FIX ME: temporary
+
+    //-----------------------------------------------------------------------
+    RenderSystem::RenderSystem()
+    {
+        mActiveViewport = 0;
+		mActiveRenderTarget = NULL;
+        mTextureManager = 0;
+        mCapabilities = 0;
+        mVSync = true;
+		mWBuffer = false;
+
+
+        // This means CULL clockwise vertices, i.e. front of poly is counter-clockwise
+        // This makes it the same as OpenGL and other right-handed systems
+        mCullingMode = CULL_CLOCKWISE;
+        mInvertVertexWinding = false;
+
+        // instanciate RenderSystemCapabilities
+        mCapabilities = new RenderSystemCapabilities();
+    }
+
+    //-----------------------------------------------------------------------
+    RenderSystem::~RenderSystem()
+    {
+        shutdown();
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_initRenderTargets(void)
+    {
+
+        // Init stats
+        for(
+            RenderTargetMap::iterator it = mRenderTargets.begin();
+            it != mRenderTargets.end();
+            ++it )
+        {
+            it->second->resetStatistics();
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_updateAllRenderTargets(void)
+    {
+        // Update all in order of priority
+        // This ensures render-to-texture targets get updated before render windows
+		RenderTargetPriorityMap::iterator itarg, itargend;
+		itargend = mPrioritisedRenderTargets.end();
+		for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg )
+		{
+			if( itarg->second->isActive() && itarg->second->isAutoUpdated())
+				itarg->second->update();
+		}
+    }
+    //-----------------------------------------------------------------------
+    RenderWindow* RenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
+    {
+        // Have I been registered by call to Root::setRenderSystem?
+		/** Don't do this anymore, just allow via Root
+        RenderSystem* regPtr = Root::getSingleton().getRenderSystem();
+        if (!regPtr || regPtr != this)
+            // Register self - library user has come to me direct
+            Root::getSingleton().setRenderSystem(this);
+		*/
+
+
+        // Subclasses should take it from here
+        // They should ALL call this superclass method from
+        //   their own initialise() implementations.
+
+        return 0;
+    }
+    //---------------------------------------------------------------------------------------------
+    void RenderSystem::destroyRenderWindow(const String& name)
+    {
+        destroyRenderTarget(name);
+    }
+    //---------------------------------------------------------------------------------------------
+    void RenderSystem::destroyRenderTexture(const String& name)
+    {
+        destroyRenderTarget(name);
+    }
+    //---------------------------------------------------------------------------------------------
+    void RenderSystem::destroyRenderTarget(const String& name)
+    {
+        RenderTarget* rt = detachRenderTarget(name);
+        delete rt;
+    }
+    //---------------------------------------------------------------------------------------------
+    void RenderSystem::attachRenderTarget( RenderTarget &target )
+    {
+		assert( target.getPriority() < OGRE_NUM_RENDERTARGET_GROUPS );
+
+        mRenderTargets.insert( RenderTargetMap::value_type( target.getName(), &target ) );
+        mPrioritisedRenderTargets.insert(
+            RenderTargetPriorityMap::value_type(target.getPriority(), &target ));
+    }
+
+    //---------------------------------------------------------------------------------------------
+    RenderTarget * RenderSystem::getRenderTarget( const String &name )
+    {
+        RenderTargetMap::iterator it = mRenderTargets.find( name );
+        RenderTarget *ret = NULL;
+
+        if( it != mRenderTargets.end() )
+        {
+            ret = it->second;
+        }
+
+        return ret;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    RenderTarget * RenderSystem::detachRenderTarget( const String &name )
+    {
+        RenderTargetMap::iterator it = mRenderTargets.find( name );
+        RenderTarget *ret = NULL;
+
+        if( it != mRenderTargets.end() )
+        {
+            ret = it->second;
+			
+			/* Remove the render target from the priority groups. */
+            RenderTargetPriorityMap::iterator itarg, itargend;
+            itargend = mPrioritisedRenderTargets.end();
+			for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg )
+            {
+				if( itarg->second == ret ) {
+					mPrioritisedRenderTargets.erase( itarg );
+					break;
+				}
+            }
+
+            mRenderTargets.erase( it );
+        }
+
+        return ret;
+    }
+    //-----------------------------------------------------------------------
+    Viewport* RenderSystem::_getViewport(void)
+    {
+        return mActiveViewport;
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_setTextureUnitSettings(size_t texUnit, TextureUnitState& tl)
+    {
+        // This method is only ever called to set a texture unit to valid details
+        // The method _disableTextureUnit is called to turn a unit off
+
+        // Texture name
+		if (tl.isBlank())
+		{
+			_setTexture(texUnit, true, StringUtil::BLANK);
+		}
+		else
+		{
+			_setTexture(texUnit, true, tl.getTextureName());
+		}
+
+        // Set texture coordinate set
+        _setTextureCoordSet(texUnit, tl.getTextureCoordSet());
+
+        // Set texture layer filtering
+        _setTextureUnitFiltering(texUnit, 
+            tl.getTextureFiltering(FT_MIN), 
+            tl.getTextureFiltering(FT_MAG), 
+            tl.getTextureFiltering(FT_MIP));
+
+        // Set texture layer filtering
+        _setTextureLayerAnisotropy(texUnit, tl.getTextureAnisotropy());
+
+		// Set blend modes
+		// Note, colour before alpha is important
+        _setTextureBlendMode(texUnit, tl.getColourBlendMode());
+        _setTextureBlendMode(texUnit, tl.getAlphaBlendMode());
+
+        // Texture addressing mode
+        _setTextureAddressingMode(texUnit, tl.getTextureAddressingMode() );
+
+        // Set texture effects
+        TextureUnitState::EffectMap::iterator effi;
+        // Iterate over new effects
+        bool anyCalcs = false;
+        for (effi = tl.mEffects.begin(); effi != tl.mEffects.end(); ++effi)
+        {
+            switch (effi->second.type)
+            {
+            case TextureUnitState::ET_ENVIRONMENT_MAP:
+                if (effi->second.subtype == TextureUnitState::ENV_CURVED)
+                {
+                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP);
+                    anyCalcs = true;
+                }
+                else if (effi->second.subtype == TextureUnitState::ENV_PLANAR)
+                {
+                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_PLANAR);
+                    anyCalcs = true;
+                }
+                else if (effi->second.subtype == TextureUnitState::ENV_REFLECTION)
+                {
+                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_REFLECTION);
+                    anyCalcs = true;
+                }
+                else if (effi->second.subtype == TextureUnitState::ENV_NORMAL)
+                {
+                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_NORMAL);
+                    anyCalcs = true;
+                }
+                break;
+            case TextureUnitState::ET_SCROLL:
+            case TextureUnitState::ET_ROTATE:
+            case TextureUnitState::ET_TRANSFORM:
+                break;
+            case TextureUnitState::ET_PROJECTIVE_TEXTURE:
+                _setTextureCoordCalculation(texUnit, TEXCALC_PROJECTIVE_TEXTURE, 
+                    effi->second.frustum);
+                anyCalcs = true;
+                break;
+            }
+        }
+        // Ensure any previous texcoord calc settings are reset if there are now none
+        if (!anyCalcs)
+        {
+            _setTextureCoordCalculation(texUnit, TEXCALC_NONE);
+            _setTextureCoordSet(texUnit, tl.getTextureCoordSet());
+        }
+
+        // Change tetxure matrix 
+        _setTextureMatrix(texUnit, tl.getTextureTransform());
+
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_disableTextureUnit(size_t texUnit)
+    {
+        _setTexture(texUnit, false, "");
+        _setTextureMatrix(texUnit, Matrix4::IDENTITY);
+    }
+    //---------------------------------------------------------------------
+    void RenderSystem::_disableTextureUnitsFrom(size_t texUnit)
+    {
+        for (size_t i = texUnit; i < mCapabilities->getNumTextureUnits(); ++i)
+        {
+            _disableTextureUnit(i);
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_setTextureUnitFiltering(size_t unit, FilterOptions minFilter,
+            FilterOptions magFilter, FilterOptions mipFilter)
+    {
+        _setTextureUnitFiltering(unit, FT_MIN, minFilter);
+        _setTextureUnitFiltering(unit, FT_MAG, magFilter);
+        _setTextureUnitFiltering(unit, FT_MIP, mipFilter);
+    }
+    //-----------------------------------------------------------------------
+    CullingMode RenderSystem::_getCullingMode(void) const
+    {
+        return mCullingMode;
+    }
+    //-----------------------------------------------------------------------
+    bool RenderSystem::getWaitForVerticalBlank(void) const
+    {
+        return mVSync;
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::setWaitForVerticalBlank(bool enabled)
+    {
+        mVSync = enabled;
+    }
+    bool RenderSystem::getWBufferEnabled(void) const
+    {
+        return mWBuffer;
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::setWBufferEnabled(bool enabled)
+    {
+        mWBuffer = enabled;
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::shutdown(void)
+    {
+        // Remove all the render targets.
+		// (destroy primary target last since others may depend on it)
+		RenderTarget* primary = 0;
+		for (RenderTargetMap::iterator it = mRenderTargets.begin(); it != mRenderTargets.end(); ++it)
+		{
+			if (!primary && it->second->isPrimary())
+				primary = it->second;
+			else
+				delete it->second;
+		}
+		delete primary;
+		mRenderTargets.clear();
+
+		mPrioritisedRenderTargets.clear();
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_beginGeometryCount(void)
+    {
+        mFaceCount = mVertexCount = 0;
+
+    }
+    //-----------------------------------------------------------------------
+    unsigned int RenderSystem::_getFaceCount(void) const
+    {
+        return static_cast< unsigned int >( mFaceCount );
+    }
+    //-----------------------------------------------------------------------
+    unsigned int RenderSystem::_getVertexCount(void) const
+    {
+        return static_cast< unsigned int >( mVertexCount );
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_setWorldMatrices(const Matrix4* m, unsigned short count)
+    {
+        // Save these matrices for software blending later
+        for (unsigned short i = 0; i < count; ++i)
+        {
+            mWorldMatrices[i] = m[i];
+        }
+        // Set hardware matrix to nothing
+        _setWorldMatrix(Matrix4::IDENTITY);
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_render(const RenderOperation& op)
+    {
+        // Update stats
+        size_t val;
+
+        if (op.useIndexes)
+            val = op.indexData->indexCount;
+        else
+            val = op.vertexData->vertexCount;
+
+        switch(op.operationType)
+        {
+		case RenderOperation::OT_TRIANGLE_LIST:
+            mFaceCount += val / 3;
+            break;
+        case RenderOperation::OT_TRIANGLE_STRIP:
+        case RenderOperation::OT_TRIANGLE_FAN:
+            mFaceCount += val - 2;
+            break;
+	    case RenderOperation::OT_POINT_LIST:
+	    case RenderOperation::OT_LINE_LIST:
+	    case RenderOperation::OT_LINE_STRIP:
+	        break;
+	    }
+
+        mVertexCount += op.vertexData->vertexCount;
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::setInvertVertexWinding(bool invert)
+    {
+        mInvertVertexWinding = invert;
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::setClipPlane (ushort index, const Plane &p)
+    {
+        setClipPlane (index, p.normal.x, p.normal.y, p.normal.z, p.d);
+    }
+    //-----------------------------------------------------------------------
+    void RenderSystem::_notifyCameraRemoved(const Camera* cam)
+    {
+        RenderTargetMap::iterator i, iend;
+        iend = mRenderTargets.end();
+        for (i = mRenderTargets.begin(); i != iend; ++i)
+        {
+            RenderTarget* target = i->second;
+            target->_notifyCameraRemoved(cam);
+        }
+    }
+}
+
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreFrustum.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreFrustum.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreFrustum.cpp	(revision 193)
@@ -0,0 +1,856 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+#include "OgreFrustum.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreSceneNode.h"
+#include "OgreSphere.h"
+#include "OgreLogManager.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreCamera.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+#include "OgreMaterialManager.h"
+#include "OgreRenderSystem.h"
+
+namespace Ogre {
+
+    String Frustum::msMovableType = "Frustum";
+    const Real Frustum::INFINITE_FAR_PLANE_ADJUST = 0.00001;
+    //-----------------------------------------------------------------------
+    Frustum::Frustum() : 
+        mProjType(PT_PERSPECTIVE), 
+        mFOVy(Radian(Math::PI/4.0)), 
+        mFarDist(100000.0f), 
+        mNearDist(100.0f), 
+        mAspect(1.33333333333333f), 
+        mProjMatrix(Matrix4::ZERO), 
+        mViewMatrix(Matrix4::ZERO), 
+        mRecalcFrustum(true), 
+        mRecalcView(true), 
+        mReflect(false), 
+        mReflectMatrix(Matrix4::ZERO), 
+        mLinkedReflectPlane(0),
+        mObliqueDepthProjection(false), 
+        mLinkedObliqueProjPlane(0)
+    {
+        // Initialise vertex & index data
+        mVertexData.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
+        mVertexData.vertexCount = 32;
+        mVertexData.vertexStart = 0;
+        mVertexData.vertexBufferBinding->setBinding( 0,
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+                sizeof(float)*3, 32, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY) );
+
+        // Initialise material
+        mMaterial = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
+        
+        // Alter superclass members
+        mVisible = false;
+        mParentNode = 0;
+
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        mLastLinkedObliqueProjPlane.normal = Vector3::ZERO;
+
+
+        updateView();
+    }
+
+    //-----------------------------------------------------------------------
+    Frustum::~Frustum()
+    {
+        // Do nothing
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFOVy(const Radian& fov)
+    {
+        mFOVy = fov;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const Radian& Frustum::getFOVy(void) const
+    {
+        return mFOVy;
+    }
+
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFarClipDistance(Real farPlane)
+    {
+        mFarDist = farPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getFarClipDistance(void) const
+    {
+        return mFarDist;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setNearClipDistance(Real nearPlane)
+    {
+        if (nearPlane <= 0)
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.",
+                "Frustum::setNearClipDistance");
+        mNearDist = nearPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getNearClipDistance(void) const
+    {
+        return mNearDist;
+    }
+
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getStandardProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mStandardProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getViewMatrix(void) const
+    {
+        updateView();
+
+        return mViewMatrix;
+
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane& Frustum::getFrustumPlane(unsigned short plane) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        return mFrustumPlanes[plane];
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
+    {
+        // Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // Get corners of the box
+        const Vector3* pCorners = bound.getAllCorners();
+
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            if (mFrustumPlanes[plane].getSide(pCorners[0]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[1]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[2]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[3]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[4]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[5]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[6]) == Plane::NEGATIVE_SIDE &&
+                mFrustumPlanes[plane].getSide(pCorners[7]) == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // For each plane, see if sphere is on negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+
+            // If the distance from sphere center to plane is negative, and 'more negative' 
+            // than the radius of the sphere, sphere is outside frustum
+            if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius())
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustum(void) const
+    {
+        if (isFrustumOutOfDate())
+        {
+            // Common calcs
+            Radian thetaY (mFOVy * 0.5f);
+            Real tanThetaY = Math::Tan(thetaY);
+            Real tanThetaX = tanThetaY * mAspect;
+            Real vpTop = tanThetaY * mNearDist;
+            Real vpRight = tanThetaX * mNearDist;
+            Real vpBottom = -vpTop;
+            Real vpLeft = -vpRight;
+
+            RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
+            // Recalc if frustum params changed
+            if (mProjType == PT_PERSPECTIVE)
+            {
+
+                // PERSPECTIVE transform, API specific
+                renderSystem->_makeProjectionMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mProjMatrix);
+
+                // PERSPECTIVE transform, API specific for Gpu Programs
+                renderSystem->_makeProjectionMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
+
+                if (mObliqueDepthProjection)
+                {
+                    // Translate the plane into view space
+                    Plane viewSpaceNear = mViewMatrix * mObliqueProjPlane;
+                    renderSystem->_applyObliqueDepthProjection(
+                        mProjMatrix, viewSpaceNear, false);
+                    renderSystem->_applyObliqueDepthProjection(
+                        mStandardProjMatrix, viewSpaceNear, true);
+                }
+            }
+            else if (mProjType == PT_ORTHOGRAPHIC)
+            {
+                // ORTHOGRAPHIC projection, API specific 
+                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mProjMatrix);
+
+                // ORTHOGRAPHIC projection, non-API specific 
+                Root::getSingleton().getRenderSystem()->_makeOrthoMatrix(mFOVy, 
+                    mAspect, mNearDist, mFarDist, mStandardProjMatrix, true);
+
+
+            }
+
+            
+            // Calculate bounding box (local)
+            // Box is from 0, down -Z, max dimensions as determined from far plane
+            // If infinite view frustum just pick a far value
+            Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+            Real farTop = tanThetaY * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real farRight = tanThetaX * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real farBottom = -farTop;
+            Real farLeft = -farRight;
+            Vector3 min(-farRight, -farTop, 0);
+            Vector3 max(farRight, farTop, -farDist);
+            mBoundingBox.setExtents(min, max);
+
+            // Calculate vertex positions (local)
+            // 0 is the origin
+            // 1, 2, 3, 4 are the points on the near plane, top left first, clockwise
+            // 5, 6, 7, 8 are the points on the far plane, top left first, clockwise
+            HardwareVertexBufferSharedPtr vbuf = mVertexData.vertexBufferBinding->getBuffer(0);
+            float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
+
+            // near plane (remember frustum is going in -Z direction)
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            // far plane (remember frustum is going in -Z direction)
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            // Sides of the pyramid
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            // Sides of the box
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;  *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+
+            vbuf->unlock();
+
+            mRecalcFrustum = false;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isViewOutOfDate(void) const
+    {
+        bool returnVal = false;
+        // Attached to node?
+        if (mParentNode)
+        {
+            if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation &&
+                mParentNode->_getDerivedPosition() == mLastParentPosition)
+            {
+                returnVal = false;
+            }
+            else
+            {
+                // Ok, we're out of date with SceneNode we're attached to
+                mLastParentOrientation = mParentNode->_getDerivedOrientation();
+                mLastParentPosition = mParentNode->_getDerivedPosition();
+                returnVal = true;
+            }
+        }
+        // Deriving reflection from linked plane?
+        if (mReflect && mLinkedReflectPlane && 
+            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
+        {
+            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+            returnVal = true;
+        }
+
+        return mRecalcView || returnVal;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isFrustumOutOfDate(void) const
+    {
+        // Deriving custom near plane from linked plane?
+        bool returnVal = false;
+        if (mObliqueDepthProjection)
+        {
+            // Always out of date since plane needs to be in view space
+            returnVal = true;
+            // Update derived plane
+            if (mLinkedObliqueProjPlane && 
+                !(mLastLinkedObliqueProjPlane == mLinkedObliqueProjPlane->_getDerivedPlane()))
+            {
+                mObliqueProjPlane = mLinkedObliqueProjPlane->_getDerivedPlane();
+                mLastLinkedObliqueProjPlane = mObliqueProjPlane;
+            }
+        }
+
+        return mRecalcFrustum || returnVal;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::updateView(void) const
+    {
+        if (isViewOutOfDate())
+        {
+            // ----------------------
+            // Update the view matrix
+            // ----------------------
+
+            // View matrix is:
+            //
+            //  [ Lx  Uy  Dz  Tx  ]
+            //  [ Lx  Uy  Dz  Ty  ]
+            //  [ Lx  Uy  Dz  Tz  ]
+            //  [ 0   0   0   1   ]
+            //
+            // Where T = -(Transposed(Rot) * Pos)
+
+            // This is most efficiently done using 3x3 Matrices
+
+            // Get orientation from quaternion
+
+			Matrix3 rot;
+            const Quaternion& orientation = getOrientationForViewUpdate();
+            const Vector3& position = getPositionForViewUpdate();
+			orientation.ToRotationMatrix(rot);
+
+            // Make the translation relative to new axes
+            Matrix3 rotT = rot.Transpose();
+            Vector3 trans = -rotT * position;
+
+            // Make final matrix
+            mViewMatrix = Matrix4::IDENTITY;
+            mViewMatrix = rotT; // fills upper 3x3
+            mViewMatrix[0][3] = trans.x;
+            mViewMatrix[1][3] = trans.y;
+            mViewMatrix[2][3] = trans.z;
+
+            // Deal with reflections
+            if (mReflect)
+            {
+                mViewMatrix = mViewMatrix * mReflectMatrix;
+            }
+
+            // -------------------------
+            // Update the frustum planes
+            // -------------------------
+            updateFrustum();
+
+			Vector3 newpos = position;
+			if (mReflect)
+			{
+				newpos = mReflectMatrix * newpos;
+			}
+            Matrix4 combo = mStandardProjMatrix * mViewMatrix;
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
+            mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
+            mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
+            mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
+            mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
+
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
+            mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
+			mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.normalise();
+			mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = 
+				-(mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.dotProduct(newpos) + mNearDist);
+
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
+            mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
+			mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.normalise();
+			mFrustumPlanes[FRUSTUM_PLANE_FAR].d = 
+				-(mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.dotProduct(newpos) - mFarDist);
+
+            // Renormalise any normals which were not unit length (not near & far)
+            for(int i=2; i<6; i++ ) 
+            {
+                float length = mFrustumPlanes[i].normal.normalise();
+                mFrustumPlanes[i].d /= length;
+            }
+
+            // Update worldspace corners
+            Matrix4 eyeToWorld = mViewMatrix.inverse();
+            // Get worldspace frustum corners
+            // Treat infinite fardist as some arbitrary far value
+            Real farDist = (mFarDist == 0)? 100000 : mFarDist;
+            Real y = Math::Tan(mFOVy * 0.5);
+            Real x = mAspect * y;
+            Real neary = y * mNearDist;
+            Real fary = y * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            Real nearx = x * mNearDist;
+            Real farx = x * (mProjType == PT_ORTHOGRAPHIC? mNearDist : farDist);
+            // near
+            mWorldSpaceCorners[0] = eyeToWorld * Vector3( nearx,  neary, -mNearDist);
+            mWorldSpaceCorners[1] = eyeToWorld * Vector3(-nearx,  neary, -mNearDist);
+            mWorldSpaceCorners[2] = eyeToWorld * Vector3(-nearx, -neary, -mNearDist);
+            mWorldSpaceCorners[3] = eyeToWorld * Vector3( nearx, -neary, -mNearDist);
+            // far
+            mWorldSpaceCorners[4] = eyeToWorld * Vector3( farx,  fary, -farDist);
+            mWorldSpaceCorners[5] = eyeToWorld * Vector3(-farx,  fary, -farDist);
+            mWorldSpaceCorners[6] = eyeToWorld * Vector3(-farx, -fary, -farDist);
+            mWorldSpaceCorners[7] = eyeToWorld * Vector3( farx, -fary, -farDist);
+
+
+            mRecalcView = false;
+
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getAspectRatio(void) const
+    {
+        return mAspect;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setAspectRatio(Real r)
+    {
+        mAspect = r;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const AxisAlignedBox& Frustum::getBoundingBox(void) const
+    {
+        return mBoundingBox;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::_updateRenderQueue(RenderQueue* queue)
+    {
+        // Add self 
+        queue->addRenderable(this);
+    }
+    //-----------------------------------------------------------------------
+    const String& Frustum::getMovableType(void) const
+    {
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+	Real Frustum::getBoundingRadius(void) const
+	{
+        return (mFarDist == 0)? 100000 : mFarDist;
+	}
+    //-----------------------------------------------------------------------
+    const MaterialPtr& Frustum::getMaterial(void) const
+    {
+        return mMaterial;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::getRenderOperation(RenderOperation& op) 
+    {
+        updateView();
+        updateFrustum();
+        op.operationType = RenderOperation::OT_LINE_LIST;
+        op.useIndexes = false;
+        op.vertexData = &mVertexData;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::getWorldTransforms(Matrix4* xform) const 
+    {
+        if (mParentNode)
+            mParentNode->getWorldTransforms(xform);
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Frustum::getWorldOrientation(void) const 
+    {
+        if (mParentNode)
+            return mParentNode->_getDerivedOrientation();
+        else
+            return Quaternion::IDENTITY;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Frustum::getWorldPosition(void) const 
+    {
+        if (mParentNode)
+            return mParentNode->_getDerivedPosition();
+        else
+            return Vector3::ZERO;
+    }
+    //-----------------------------------------------------------------------
+    Real Frustum::getSquaredViewDepth(const Camera* cam) const 
+    {
+        // Calc from centre
+        if (mParentNode)
+            return (cam->getDerivedPosition() 
+                - mParentNode->_getDerivedPosition()).squaredLength();
+        else
+            return 0;
+    }
+    //-----------------------------------------------------------------------
+    const LightList& Frustum::getLights(void) const 
+    {
+        // N/A
+        static LightList ll;
+        return ll;
+    }
+    //-----------------------------------------------------------------------
+    const String& Frustum::getName(void) const
+    {
+        // NA
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::_notifyCurrentCamera(Camera* cam)
+    {
+        // NA
+    }
+
+    // -------------------------------------------------------------------
+    void Frustum::invalidateFrustum() const
+    {
+        mRecalcFrustum = true;
+    }
+    // -------------------------------------------------------------------
+    void Frustum::invalidateView() const
+    {
+        mRecalcView = true;
+    }
+    // -------------------------------------------------------------------
+    const Vector3* Frustum::getWorldSpaceCorners(void) const
+    {
+        updateView();
+
+        return mWorldSpaceCorners;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::setProjectionType(ProjectionType pt)
+    {
+        mProjType = pt;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    ProjectionType Frustum::getProjectionType(void) const
+    {
+        return mProjType;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Frustum::getPositionForViewUpdate(void) const
+    {
+        return mLastParentPosition;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Frustum::getOrientationForViewUpdate(void) const
+    {
+        return mLastParentOrientation;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const Plane& p)
+    {
+        mReflect = true;
+        mReflectPlane = p;
+        mLinkedReflectPlane = 0;
+        mReflectMatrix = Math::buildReflectionMatrix(p);
+        invalidateView();
+
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const MovablePlane* p)
+    {
+        mReflect = true;
+        mLinkedReflectPlane = p;
+        mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+        mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+        mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+        invalidateView();
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::disableReflection(void)
+    {
+        mReflect = false;
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        invalidateView();
+    }
+    //---------------------------------------------------------------------
+    bool Frustum::projectSphere(const Sphere& sphere, 
+        Real* left, Real* top, Real* right, Real* bottom) const
+    {
+        // initialise
+        *left = *bottom = -1.0f;
+        *right = *top = 1.0f;
+
+        // Transform light position into camera space
+        Vector3 eyeSpacePos = getViewMatrix() * sphere.getCenter();
+
+        if (eyeSpacePos.z < 0)
+        {
+            Real r = sphere.getRadius();
+            // early-exit
+            if (eyeSpacePos.squaredLength() <= r * r)
+                return false;
+
+            Vector3 screenSpacePos = getStandardProjectionMatrix() * eyeSpacePos;
+
+
+            // perspective attenuate
+            Vector3 spheresize(r, r, eyeSpacePos.z);
+            spheresize = getStandardProjectionMatrix() * spheresize;
+
+            Real possLeft = screenSpacePos.x - spheresize.x;
+            Real possRight = screenSpacePos.x + spheresize.x;
+            Real possTop = screenSpacePos.y + spheresize.y;
+            Real possBottom = screenSpacePos.y - spheresize.y;
+
+            *left = std::max(static_cast<Real>(-1.0), possLeft);
+            *right = std::min(static_cast<Real>(1.0), possRight);
+            *top = std::min(static_cast<Real>(1.0), possTop);
+            *bottom = std::max(static_cast<Real>(-1.0), possBottom);
+
+        }
+
+        return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f);
+
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const MovablePlane* plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = plane;
+        mObliqueProjPlane = plane->_getDerivedPlane();
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const Plane& plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = 0;
+        mObliqueProjPlane = plane;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::disableCustomNearClipPlane(void)
+    {
+        mObliqueDepthProjection = false;
+        mLinkedObliqueProjPlane = 0;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+	//added by matt: 050405
+    bool Frustum::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
+	{
+		intersects = false;
+
+		// Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Make any pending updates to the calculated frustum
+        updateView();
+
+        // Get corners of the box
+        const Vector3* pCorners = bound.getAllCorners();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (mFarDist == 0 && plane == FRUSTUM_PLANE_FAR)
+                continue;
+			
+			int corner = 0;
+			bool visible = false;
+
+			while((corner < 8) && (!visible || ((plane == FRUSTUM_PLANE_NEAR) && !intersects)))
+			{
+				if(mFrustumPlanes[plane].getSide(pCorners[corner++]) == Plane::NEGATIVE_SIDE)
+				{
+					if(plane == FRUSTUM_PLANE_NEAR)
+						intersects = true;
+				}
+				else
+				{
+					visible = true;
+				}
+			}
+            
+			if(!visible)
+			{
+				// ALL corners on negative side therefore out of view
+				if (culledBy)
+					*culledBy = (FrustumPlane)plane;
+				return false;
+            }
+		}
+
+        return true;
+    }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+} // namespace Ogre
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderQueueSortingGrouping.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderQueueSortingGrouping.cpp	(revision 343)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderQueueSortingGrouping.cpp	(revision 343)
@@ -0,0 +1,339 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+#include "OgreRenderQueueSortingGrouping.h"
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::destroySolidPassMap(SolidRenderablePassMap& passmap)
+    {
+        // destroy all the pass map entries
+        SolidRenderablePassMap::iterator i, iend;
+        iend = passmap.end();
+        for (i = passmap.begin(); i != iend; ++i)
+        {
+            // Free the list associated with this pass
+            delete i->second;
+        }
+        passmap.clear();
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::removeSolidPassEntry(Pass* p)
+    {
+        SolidRenderablePassMap::iterator i;
+
+        i = mSolidPasses.find(p);
+        if (i != mSolidPasses.end())
+        {
+            // free memory
+            delete i->second;
+            // erase from map
+            mSolidPasses.erase(i);
+        }
+
+        i = mSolidPassesDiffuseSpecular.find(p);
+        if (i != mSolidPassesDiffuseSpecular.end())
+        {
+            // free memory
+            delete i->second;
+            // erase from map
+            mSolidPassesDiffuseSpecular.erase(i);
+        }
+        i = mSolidPassesDecal.find(p);
+        if (i != mSolidPassesDecal.end())
+        {
+            // free memory
+            delete i->second;
+            // erase from map
+            mSolidPassesDecal.erase(i);
+        }
+        i = mSolidPassesNoShadow.find(p);
+        if (i != mSolidPassesNoShadow.end())
+        {
+            // free memory
+            delete i->second;
+            // erase from map
+            mSolidPassesNoShadow.erase(i);
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::clearSolidPassMap(SolidRenderablePassMap& passmap)
+    {
+        SolidRenderablePassMap::iterator i, iend;
+        iend = passmap.end();
+        for (i = passmap.begin(); i != iend; ++i)
+        {
+            // Clear the list associated with this pass, but leave the pass entry
+            i->second->clear();
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addRenderable(Renderable* rend)
+    {
+        // Check material & technique supplied (the former since the default implementation
+        // of getTechnique is based on it for backwards compatibility
+        Technique* pTech;
+        if(rend->getMaterial().isNull() || !rend->getTechnique())
+        {
+            // Use default base white
+			MaterialPtr baseWhite = MaterialManager::getSingleton().getByName("BaseWhite");
+            pTech = baseWhite->getTechnique(0);
+        }
+        else
+        {
+            // Get technique
+            pTech = rend->getTechnique();
+        }
+
+        // Transparent and depth settings mean depth sorting is required?
+        if (pTech->isTransparent() && 
+            !(pTech->isDepthWriteEnabled() && pTech->isDepthCheckEnabled()) )
+        {
+            addTransparentRenderable(pTech, rend);
+        }
+        else
+        {
+            if (mSplitNoShadowPasses && !pTech->getParent()->getReceiveShadows())
+            {
+                // Add solid renderable and add passes to no-shadow group
+                addSolidRenderable(pTech, rend, true);
+            }
+            else
+            {
+                if (mSplitPassesByLightingType)
+                {
+                    addSolidRenderableSplitByLightType(pTech, rend);
+                }
+                else
+                {
+                    addSolidRenderable(pTech, rend, false);
+                }
+            }
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addSolidRenderable(Technique* pTech, 
+        Renderable* rend, bool addToNoShadow)
+    {
+        Technique::PassIterator pi = pTech->getPassIterator();
+
+        SolidRenderablePassMap* passMap;
+        if (addToNoShadow)
+        {
+            passMap = &mSolidPassesNoShadow;
+        }
+        else
+        {
+            passMap = &mSolidPasses;
+        }
+
+
+        while (pi.hasMoreElements())
+        {
+            // Insert into solid list
+            Pass* p = pi.getNext();
+            SolidRenderablePassMap::iterator i = passMap->find(p);
+            if (i == passMap->end())
+            {
+                std::pair<SolidRenderablePassMap::iterator, bool> retPair;
+                // Create new pass entry, build a new list
+                // Note that this pass and list are never destroyed until the engine
+                // shuts down, although the lists will be cleared
+                retPair = passMap->insert(
+                    SolidRenderablePassMap::value_type(p, new RenderableList() ) );
+                assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap");
+                i = retPair.first;
+            }
+            // Insert renderable
+            i->second->push_back(rend);
+
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend)
+    {
+        // Divide the passes into the 3 categories
+        Technique::IlluminationPassIterator pi = 
+            pTech->getIlluminationPassIterator();
+
+        while (pi.hasMoreElements())
+        {
+            // Insert into solid list
+            IlluminationPass* p = pi.getNext();
+            SolidRenderablePassMap* passMap;
+            switch(p->stage)
+            {
+            case IS_AMBIENT:
+                passMap = &mSolidPasses;
+                break;
+            case IS_PER_LIGHT:
+                passMap = &mSolidPassesDiffuseSpecular;
+                break;
+            case IS_DECAL:
+                passMap = &mSolidPassesDecal;
+                break;
+            };
+
+            SolidRenderablePassMap::iterator i = passMap->find(p->pass);
+            if (i == passMap->end())
+            {
+                std::pair<SolidRenderablePassMap::iterator, bool> retPair;
+                // Create new pass entry, build a new list
+                // Note that this pass and list are never destroyed until the engine
+                // shuts down, although the lists will be cleared
+                retPair = passMap->insert(
+                    SolidRenderablePassMap::value_type(p->pass, new RenderableList() ) );
+                assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap");
+                i = retPair.first;
+            }
+            // Insert renderable
+            i->second->push_back(rend);
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addTransparentRenderable(Technique* pTech, Renderable* rend)
+    {
+        Technique::PassIterator pi = pTech->getPassIterator();
+
+        while (pi.hasMoreElements())
+        {
+            // Insert into transparent list
+            mTransparentPasses.push_back(RenderablePass(rend, pi.getNext()));
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::sort(const Camera* cam)
+    {
+        TransparentQueueItemLess transFunctor;
+        transFunctor.camera = cam;
+
+        std::stable_sort(mTransparentPasses.begin(), mTransparentPasses.end(), 
+            transFunctor);
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::clear(void)
+    {
+        SolidRenderablePassMap::iterator i, iend;
+        // Delete queue groups which are using passes which are to be
+        // deleted, we won't need these any more and they clutter up 
+        // the list and can cause problems with future clones
+        const Pass::PassSet& graveyardList = Pass::getPassGraveyard();
+        Pass::PassSet::const_iterator gi, giend;
+        giend = graveyardList.end();
+        for (gi = graveyardList.begin(); gi != giend; ++gi)
+        {
+            removeSolidPassEntry(*gi);
+        }
+
+        // Now remove any dirty passes, these will have their hashes recalculated
+        // by the parent queue after all groups have been processed
+        // If we don't do this, the std::map will become inconsistent for new insterts
+        const Pass::PassSet& dirtyList = Pass::getDirtyHashList();
+        Pass::PassSet::const_iterator di, diend;
+        diend = dirtyList.end();
+        for (di = dirtyList.begin(); di != diend; ++di)
+        {
+            removeSolidPassEntry(*di);
+        }
+        // NB we do NOT clear the graveyard or the dirty list here, because 
+        // it needs to be acted on for all groups, the parent queue takes 
+        // care of this afterwards
+
+        // We do not clear the unchanged solid pass maps, only the contents of each list
+        // This is because we assume passes are reused a lot and it saves resorting
+        clearSolidPassMap(mSolidPasses);
+        clearSolidPassMap(mSolidPassesDecal);
+        clearSolidPassMap(mSolidPassesDiffuseSpecular);
+        clearSolidPassMap(mSolidPassesNoShadow);
+
+        // Always empty the transparents list
+        mTransparentPasses.clear();
+
+    }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE	
+	//-----------------------------------------------------------------------
+    void RenderPriorityGroup::clear(const int leavePassesInQueue)
+    {
+		//-- standard method if no passes are left in queue
+		if (leavePassesInQueue == 0)
+		{
+			clear();
+			return;
+		}
+
+        // We do not clear the unchanged solid pass maps, only the contents of each list
+        // This is because we assume passes are reused a lot and it saves resorting
+		if (!(leavePassesInQueue & SOLID_PASSES))
+			destroySolidPassMap(mSolidPasses);
+		if (!(leavePassesInQueue & SOLID_PASSES_DECAL))
+			destroySolidPassMap(mSolidPassesDecal);
+		if (!(leavePassesInQueue & SOLID_PASSES_DIFFUSE_SPECULAR))
+			destroySolidPassMap(mSolidPassesDiffuseSpecular);
+		if (!(leavePassesInQueue & SOLID_PASSES_NOSHADOW))
+			destroySolidPassMap(mSolidPassesNoShadow);
+
+        if (!(leavePassesInQueue & TRANSPARENT_PASSES))
+			mTransparentPasses.clear();
+    }
+	//-----------------------------------------------------------------------
+    void RenderPriorityGroup::destroyPassMaps(const int leavePassesInQueue)
+    {
+		/*    
+        const Pass::PassSet& graveyardList = Pass::getPassGraveyard();
+        Pass::PassSet::const_iterator gi, giend;
+        giend = graveyardList.end();
+        for (gi = graveyardList.begin(); gi != giend; ++gi)
+        {
+            removeSolidPassEntry(*gi);
+        }
+
+        const Pass::PassSet& dirtyList = Pass::getDirtyHashList();
+        Pass::PassSet::const_iterator di, diend;
+        diend = dirtyList.end();
+        for (di = dirtyList.begin(); di != diend; ++di)
+        {
+            removeSolidPassEntry(*di);
+		}
+		*/
+
+        // We do not clear the unchanged solid pass maps, only the contents of each list
+        // This is because we assume passes are reused a lot and it saves resorting
+		if (!(leavePassesInQueue & SOLID_PASSES))
+			destroySolidPassMap(mSolidPasses);
+		if (!(leavePassesInQueue & SOLID_PASSES_DECAL))
+			destroySolidPassMap(mSolidPassesDecal);
+		if (!(leavePassesInQueue & SOLID_PASSES_DIFFUSE_SPECULAR))
+			destroySolidPassMap(mSolidPassesDiffuseSpecular);
+		if (!(leavePassesInQueue & SOLID_PASSES_NOSHADOW))
+			destroySolidPassMap(mSolidPassesNoShadow);
+    }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE		
+//-----------------------------------------------------------------------
+
+}
+
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 343)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 343)
@@ -0,0 +1,4269 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStableHeaders.h"
+
+#include "OgreSceneManager.h"
+
+#include "OgreCamera.h"
+#include "OgreRenderSystem.h"
+#include "OgreMeshManager.h"
+#include "OgreMesh.h"
+#include "OgreSubMesh.h"
+#include "OgreEntity.h"
+#include "OgreSubEntity.h"
+#include "OgreLight.h"
+#include "OgreMath.h"
+#include "OgreControllerManager.h"
+#include "OgreMaterialManager.h"
+#include "OgreAnimation.h"
+#include "OgreAnimationTrack.h"
+#include "OgreRenderQueueSortingGrouping.h"
+#include "OgreOverlay.h"
+#include "OgreOverlayManager.h"
+#include "OgreStringConverter.h"
+#include "OgreRenderQueueListener.h"
+#include "OgreBillboardSet.h"
+#include "OgrePass.h"
+#include "OgreTechnique.h"
+#include "OgreTextureUnitState.h"
+#include "OgreException.h"
+#include "OgreLogManager.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreRoot.h"
+#include "OgreSpotShadowFadePng.h"
+#include "OgreGpuProgramManager.h"
+#include "OgreGpuProgram.h"
+#include "OgreShadowVolumeExtrudeProgram.h"
+#include "OgreDataStream.h"
+#include "OgreStaticGeometry.h"
+
+// This class implements the most basic scene manager
+
+#include <cstdio>
+
+namespace Ogre {
+
+//-----------------------------------------------------------------------
+unsigned long SceneManager::WORLD_GEOMETRY_QUERY_MASK = 0x80000000;
+//-----------------------------------------------------------------------
+SceneManager::SceneManager() :
+mRenderQueue(0),
+mSkyPlaneEntity(0),
+mSkyPlaneNode(0),
+mSkyDomeNode(0),
+mSkyBoxNode(0),
+mSkyPlaneEnabled(false),
+mSkyBoxEnabled(false),
+mSkyDomeEnabled(false),
+mFogMode(FOG_NONE),
+mSpecialCaseQueueMode(SCRQM_EXCLUDE),
+mWorldGeometryRenderQueue(RENDER_QUEUE_WORLD_GEOMETRY_1),
+mShadowCasterPlainBlackPass(0),
+mShadowReceiverPass(0),
+mDisplayNodes(false),
+mShowBoundingBoxes(false),
+mShadowTechnique(SHADOWTYPE_NONE),
+mDebugShadows(false),
+mShadowColour(ColourValue(0.25, 0.25, 0.25)),
+mShadowDebugPass(0),
+mShadowStencilPass(0),
+mShadowModulativePass(0),
+mShadowMaterialInitDone(false),
+mShadowIndexBufferSize(51200),
+mFullScreenQuad(0),
+mShadowDirLightExtrudeDist(10000),
+mIlluminationStage(IRS_NONE),
+mShadowTextureSize(512),
+mShadowTextureCount(1),
+mShadowTextureFormat(PF_X8R8G8B8),
+mShadowUseInfiniteFarPlane(true),
+mShadowCasterSphereQuery(0),
+mShadowCasterAABBQuery(0),
+mShadowFarDist(0),
+mShadowFarDistSquared(0),
+mShadowTextureOffset(0.6), 
+mShadowTextureFadeStart(0.7), 
+mShadowTextureFadeEnd(0.9),
+mShadowTextureSelfShadow(false),
+mShadowTextureCustomCasterPass(0),
+mShadowTextureCustomReceiverPass(0),
+mShadowTextureCasterVPDirty(false),
+mShadowTextureReceiverVPDirty(false)
+{
+    // Root scene node
+    mSceneRoot = new SceneNode(this, "root node");
+	mSceneRoot->_notifyRootNode();
+
+    // init sky
+    size_t i;
+    for (i = 0; i < 6; ++i)
+    {
+        mSkyBoxEntity[i] = 0;
+    }
+    for (i = 0; i < 5; ++i)
+    {
+        mSkyDomeEntity[i] = 0;
+    }
+
+	mShadowCasterQueryListener = new ShadowCasterSceneQueryListener(this);
+
+    Root *root = Root::getSingletonPtr();
+    if (root)
+        _setDestinationRenderSystem(root->getRenderSystem());
+}
+//-----------------------------------------------------------------------
+SceneManager::~SceneManager()
+{
+    clearScene();
+    removeAllCameras();
+	delete mShadowCasterQueryListener;
+    delete mSceneRoot;
+    delete mFullScreenQuad;
+    delete mShadowCasterSphereQuery;
+    delete mShadowCasterAABBQuery;
+    delete mRenderQueue;
+}
+//-----------------------------------------------------------------------
+RenderQueue* SceneManager::getRenderQueue(void)
+{
+    if (!mRenderQueue)
+    {
+        initRenderQueue();
+    }
+    return mRenderQueue;
+}
+//-----------------------------------------------------------------------
+void SceneManager::initRenderQueue(void)
+{
+    mRenderQueue = new RenderQueue();
+    // init render queues that do not need shadows
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_BACKGROUND)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_OVERLAY)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_EARLY)->setShadowsEnabled(false);
+    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_LATE)->setShadowsEnabled(false);
+}
+//-----------------------------------------------------------------------
+void SceneManager::addSpecialCaseRenderQueue(RenderQueueGroupID qid)
+{
+	mSpecialCaseQueueList.insert(qid);
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeSpecialCaseRenderQueue(RenderQueueGroupID qid)
+{
+	mSpecialCaseQueueList.erase(qid);
+}
+//-----------------------------------------------------------------------
+void SceneManager::clearSpecialCaseRenderQueues(void)
+{
+	mSpecialCaseQueueList.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSpecialCaseRenderQueueMode(SceneManager::SpecialCaseRenderQueueMode mode)
+{
+	mSpecialCaseQueueMode = mode;
+}
+//-----------------------------------------------------------------------
+SceneManager::SpecialCaseRenderQueueMode SceneManager::getSpecialCaseRenderQueueMode(void)
+{
+	return mSpecialCaseQueueMode;
+}
+//-----------------------------------------------------------------------
+bool SceneManager::isRenderQueueToBeProcessed(RenderQueueGroupID qid)
+{
+	bool inList = mSpecialCaseQueueList.find(qid) != mSpecialCaseQueueList.end();
+	return (inList && mSpecialCaseQueueMode == SCRQM_INCLUDE)
+		|| (!inList && mSpecialCaseQueueMode == SCRQM_EXCLUDE);
+}
+//-----------------------------------------------------------------------
+void SceneManager::setWorldGeometryRenderQueue(RenderQueueGroupID qid)
+{
+	mWorldGeometryRenderQueue = qid;
+}
+//-----------------------------------------------------------------------
+RenderQueueGroupID SceneManager::getWorldGeometryRenderQueue(void)
+{
+	return mWorldGeometryRenderQueue;
+}
+//-----------------------------------------------------------------------
+Camera* SceneManager::createCamera(const String& name)
+{
+    // Check name not used
+    if (mCameras.find(name) != mCameras.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A camera with the name " + name + " already exists",
+            "SceneManager::createCamera" );
+    }
+
+    Camera *c = new Camera(name, this);
+    mCameras.insert(CameraList::value_type(name, c));
+
+
+    return c;
+}
+
+//-----------------------------------------------------------------------
+Camera* SceneManager::getCamera(const String& name)
+{
+    CameraList::iterator i = mCameras.find(name);
+    if (i == mCameras.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Camera with name " + name,
+            "SceneManager::getCamera");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeCamera(Camera *cam)
+{
+    // Find in list
+    CameraList::iterator i = mCameras.begin();
+    for (; i != mCameras.end(); ++i)
+    {
+        if (i->second == cam)
+        {
+            mCameras.erase(i);
+            // notify render targets
+            mDestRenderSystem->_notifyCameraRemoved(cam);
+            delete cam;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeCamera(const String& name)
+{
+    // Find in list
+    CameraList::iterator i = mCameras.find(name);
+    if (i != mCameras.end())
+    {
+        // Notify render system
+        mDestRenderSystem->_notifyCameraRemoved(i->second);
+        delete i->second;
+        mCameras.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllCameras(void)
+{
+
+    CameraList::iterator i = mCameras.begin();
+    for (; i != mCameras.end(); ++i)
+    {
+        // Notify render system
+        mDestRenderSystem->_notifyCameraRemoved(i->second);
+        delete i->second;
+    }
+    mCameras.clear();
+}
+
+//-----------------------------------------------------------------------
+Light* SceneManager::createLight(const String& name)
+{
+    // Check name not used
+    if (mLights.find(name) != mLights.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A light with the name " + name + " already exists",
+            "SceneManager::createLight" );
+    }
+
+    Light *l = new Light(name);
+    mLights.insert(SceneLightList::value_type(name, l));
+    return l;
+}
+
+//-----------------------------------------------------------------------
+Light* SceneManager::getLight(const String& name)
+{
+    SceneLightList::iterator i = mLights.find(name);
+    if (i == mLights.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Light with name " + name,
+            "SceneManager::getLight");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeLight(Light *l)
+{
+    // Find in list
+    SceneLightList::iterator i = mLights.begin();
+    for (; i != mLights.end(); ++i)
+    {
+        if (i->second == l)
+        {
+            mLights.erase(i);
+            delete l;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeLight(const String& name)
+{
+    // Find in list
+    SceneLightList::iterator i = mLights.find(name);
+    if (i != mLights.end())
+    {
+        delete i->second;
+        mLights.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllLights(void)
+{
+
+    SceneLightList::iterator i = mLights.begin();
+    for (; i != mLights.end(); ++i)
+    {
+        delete i->second;
+    }
+    mLights.clear();
+}
+//-----------------------------------------------------------------------
+bool SceneManager::lightLess::operator()(const Light* a, const Light* b) const
+{
+    return a->tempSquareDist < b->tempSquareDist;
+}
+//-----------------------------------------------------------------------
+void SceneManager::_populateLightList(const Vector3& position, Real radius, LightList& destList)
+{
+    // Really basic trawl of the lights, then sort
+    // Subclasses could do something smarter
+    destList.clear();
+    Real squaredRadius = radius * radius;
+
+    SceneLightList::iterator i, iend;
+    iend = mLights.end();
+    for (i = mLights.begin(); i != iend; ++i)
+    {
+        Light* lt = i->second;
+        if (lt->isVisible())
+        {
+            if (lt->getType() == Light::LT_DIRECTIONAL)
+            {
+                // No distance
+                lt->tempSquareDist = 0.0f;
+                destList.push_back(lt);
+            }
+            else
+            {
+                // Calc squared distance
+                lt->tempSquareDist = (lt->getDerivedPosition() - position).squaredLength();
+                // only add in-range lights
+                Real range = lt->getAttenuationRange();
+                if ((lt->tempSquareDist - squaredRadius) <= (range * range))
+                {
+                    destList.push_back(lt);
+                }
+            }
+        }
+    }
+
+    // Sort (stable to guarantee ordering on directional lights)
+    std::stable_sort(destList.begin(), destList.end(), lightLess());
+
+
+}
+//-----------------------------------------------------------------------
+Entity* SceneManager::createEntity(const String& entityName, PrefabType ptype)
+{
+    switch (ptype)
+    {
+    case PT_PLANE:
+        return createEntity(entityName, "Prefab_Plane");
+
+        break;
+    }
+
+    OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+        "Unknown prefab type for entity " + entityName,
+        "SceneManager::createEntity");
+}
+
+//-----------------------------------------------------------------------
+Entity* SceneManager::createEntity(
+                                   const String& entityName,
+                                   const String& meshName )
+{
+    // Check name not used
+    EntityList::iterator it = mEntities.find( entityName );
+    if( it != mEntities.end() )
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "An entity with the name " + entityName + " already exists",
+            "SceneManager::createEntity" );
+    }
+
+    // Get mesh (load if required)
+    MeshPtr pMesh = MeshManager::getSingleton().load( 
+        meshName, 
+        // note that you can change the group by pre-loading the mesh 
+        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
+
+    // Create entity
+    Entity* e = new Entity( entityName, pMesh, this );
+
+    // Add to internal list
+    mEntities[entityName] = e; //.insert(EntityList::value_type(entityName, e));
+
+    return e;
+}
+
+//-----------------------------------------------------------------------
+Entity* SceneManager::getEntity(const String& name)
+{
+    EntityList::iterator i = mEntities.find(name);
+    if (i == mEntities.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find Entity with name " + name,
+            "SceneManager::getEntity");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeEntity(Entity *cam)
+{
+    // Find in list
+    EntityList::iterator i = mEntities.begin();
+    for (; i != mEntities.end(); ++i)
+    {
+        if (i->second == cam)
+        {
+            mEntities.erase(i);
+            delete cam;
+            break;
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeEntity(const String& name)
+{
+    // Find in list
+    EntityList::iterator i = mEntities.find(name);
+    if (i != mEntities.end())
+    {
+        delete i->second;
+        mEntities.erase(i);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllEntities(void)
+{
+
+    EntityList::iterator i = mEntities.begin();
+    for (; i != mEntities.end(); ++i)
+    {
+        delete i->second;
+    }
+    mEntities.clear();
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::removeAllBillboardSets(void)
+{
+    // Delete all BillboardSets
+    for (BillboardSetList::iterator bi = mBillboardSets.begin();
+        bi != mBillboardSets.end(); ++bi)
+    {
+        delete bi->second;
+    }
+    mBillboardSets.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::clearScene(void)
+{
+	removeAllStaticGeometry();
+    removeAllEntities();
+    removeAllBillboardSets();
+    removeAllLights();
+
+	// Clear root node of all children
+	mSceneRoot->removeAllChildren();
+	mSceneRoot->detachAllObjects();
+
+    // Delete all SceneNodes, except root that is
+    for (SceneNodeList::iterator i = mSceneNodes.begin();
+        i != mSceneNodes.end(); ++i)
+    {
+        delete i->second;
+    }
+    mSceneNodes.clear();
+    mAutoTrackingSceneNodes.clear();
+
+
+
+    // Clear animations
+    destroyAllAnimations();
+
+    // Remove sky nodes since they've been deleted
+    mSkyBoxNode = mSkyPlaneNode = mSkyDomeNode = 0;
+    mSkyBoxEnabled = mSkyPlaneEnabled = mSkyDomeEnabled = false; 
+
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::createSceneNode(void)
+{
+    SceneNode* sn = new SceneNode(this);
+    assert(mSceneNodes.find(sn->getName()) == mSceneNodes.end());
+    mSceneNodes[sn->getName()] = sn;
+    return sn;
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::createSceneNode(const String& name)
+{
+    // Check name not used
+    if (mSceneNodes.find(name) != mSceneNodes.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A scene node with the name " + name + " already exists",
+            "SceneManager::createSceneNode" );
+    }
+
+    SceneNode* sn = new SceneNode(this, name);
+    mSceneNodes[sn->getName()] = sn;
+    return sn;
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroySceneNode(const String& name)
+{
+    SceneNodeList::iterator i = mSceneNodes.find(name);
+
+    if (i == mSceneNodes.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
+            "SceneManager::destroySceneNode");
+    }
+
+    // Find any scene nodes which are tracking this node, and turn them off
+    AutoTrackingSceneNodes::iterator ai, aiend;
+    aiend = mAutoTrackingSceneNodes.end();
+    for (ai = mAutoTrackingSceneNodes.begin(); ai != aiend; ++ai)
+    {
+        SceneNode* n = *ai;
+        // Tracking this node
+        if (n->getAutoTrackTarget() == i->second)
+        {
+            // turn off, this will notify SceneManager to remove
+            n->setAutoTracking(false);
+            // no need to reset iterator since set erase does not invalidate
+        }
+        // node is itself a tracker
+        else if (n == i->second)
+        {
+            mAutoTrackingSceneNodes.erase(ai);
+        }
+    }
+
+	// detach from parent (don't do this in destructor since bulk destruction
+	// behaves differently)
+	Node* parentNode = i->second->getParent();
+	if (parentNode)
+	{
+		parentNode->removeChild(i->second);
+	}
+    delete i->second;
+    mSceneNodes.erase(i);
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::getRootSceneNode(void) const
+{
+    return mSceneRoot;
+}
+//-----------------------------------------------------------------------
+SceneNode* SceneManager::getSceneNode(const String& name) const
+{
+    SceneNodeList::const_iterator i = mSceneNodes.find(name);
+
+    if (i == mSceneNodes.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
+            "SceneManager::getSceneNode");
+    }
+
+    return i->second;
+
+}
+//-----------------------------------------------------------------------
+Pass* SceneManager::setPass(Pass* pass)
+{
+    static bool lastUsedVertexProgram = false;
+    static bool lastUsedFragmentProgram = false;
+
+    if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
+    {
+        // Derive a special shadow caster pass from this one
+        pass = deriveShadowCasterPass(pass);
+    }
+    else if (mIlluminationStage == IRS_RENDER_MODULATIVE_PASS)
+    {
+        pass = deriveShadowReceiverPass(pass);
+    }
+
+    // TEST
+    /*
+    LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) + 
+    " of " + pass->getParent()->getParent()->getName());
+    */
+    bool passSurfaceAndLightParams = true;
+
+    if (pass->hasVertexProgram())
+    {
+        mDestRenderSystem->bindGpuProgram(pass->getVertexProgram()->_getBindingDelegate());
+        // bind parameters later since they can be per-object
+        lastUsedVertexProgram = true;
+        // does the vertex program want surface and light params passed to rendersystem?
+        passSurfaceAndLightParams = pass->getVertexProgram()->getPassSurfaceAndLightStates();
+    }
+    else
+    {
+        // Unbind program?
+        if (lastUsedVertexProgram)
+        {
+            mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+            lastUsedVertexProgram = false;
+        }
+        // Set fixed-function vertex parameters
+    }
+
+    if (passSurfaceAndLightParams)
+    {
+        // Set surface reflectance properties, only valid if lighting is enabled
+        if (pass->getLightingEnabled())
+        {
+            mDestRenderSystem->_setSurfaceParams( 
+                pass->getAmbient(), 
+                pass->getDiffuse(), 
+                pass->getSpecular(), 
+                pass->getSelfIllumination(), 
+                pass->getShininess(),
+		pass->getVertexColourTracking() );
+        }
+
+        // Dynamic lighting enabled?
+        mDestRenderSystem->setLightingEnabled(pass->getLightingEnabled());
+    }
+
+    // Using a fragment program?
+    if (pass->hasFragmentProgram())
+    {
+        mDestRenderSystem->bindGpuProgram(
+            pass->getFragmentProgram()->_getBindingDelegate());
+        // bind parameters later since they can be per-object
+        lastUsedFragmentProgram = true;
+    }
+    else
+    {
+        // Unbind program?
+        if (lastUsedFragmentProgram)
+        {
+            mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+            lastUsedFragmentProgram = false;
+        }
+
+        // Set fixed-function fragment settings
+
+        // Fog (assumes we want pixel fog which is the usual)
+        // New fog params can either be from scene or from material
+        FogMode newFogMode;
+        ColourValue newFogColour;
+        Real newFogStart, newFogEnd, newFogDensity;
+        if (pass->getFogOverride())
+        {
+            // New fog params from material
+            newFogMode = pass->getFogMode();
+            newFogColour = pass->getFogColour();
+            newFogStart = pass->getFogStart();
+            newFogEnd = pass->getFogEnd();
+            newFogDensity = pass->getFogDensity();
+        }
+        else
+        {
+            // New fog params from scene
+            newFogMode = mFogMode;
+            newFogColour = mFogColour;
+            newFogStart = mFogStart;
+            newFogEnd = mFogEnd;
+            newFogDensity = mFogDensity;
+        }
+        mDestRenderSystem->_setFog(
+            newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
+
+    }
+
+    // The rest of the settings are the same no matter whether we use programs or not
+
+    // Set scene blending
+    mDestRenderSystem->_setSceneBlending(
+        pass->getSourceBlendFactor(), pass->getDestBlendFactor());
+
+
+    // Texture unit settings
+
+    Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
+    size_t unit = 0;
+    while(texIter.hasMoreElements())
+    {
+        TextureUnitState* pTex = texIter.getNext();
+        mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
+        ++unit;
+    }
+    // Disable remaining texture units
+    mDestRenderSystem->_disableTextureUnitsFrom(pass->getNumTextureUnitStates());
+
+    // Set up non-texture related material settings
+    // Depth buffer settings
+    mDestRenderSystem->_setDepthBufferFunction(pass->getDepthFunction());
+    mDestRenderSystem->_setDepthBufferCheckEnabled(pass->getDepthCheckEnabled());
+    mDestRenderSystem->_setDepthBufferWriteEnabled(pass->getDepthWriteEnabled());
+    mDestRenderSystem->_setDepthBias(pass->getDepthBias());
+	// Alpha-reject settings
+	mDestRenderSystem->_setAlphaRejectSettings(
+		pass->getAlphaRejectFunction(), pass->getAlphaRejectValue());
+    // Set colour write mode
+    // Right now we only use on/off, not per-channel
+    bool colWrite = pass->getColourWriteEnabled();
+    mDestRenderSystem->_setColourBufferWriteEnabled(colWrite, colWrite, colWrite, colWrite);
+    // Culling mode
+    mDestRenderSystem->_setCullingMode(pass->getCullingMode());
+    // Shading
+    mDestRenderSystem->setShadingType(pass->getShadingMode());
+
+    return pass;
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
+{
+	Root::getSingleton()._setCurrentSceneManager(this);
+    // Prep Pass for use in debug shadows
+    initShadowVolumeMaterials();
+    // Perform a quick pre-check to see whether we should override far distance
+    // When using stencil volumes we have to use infinite far distance
+    // to prevent dark caps getting clipped
+    if ((mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE ||
+        mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE) && 
+        camera->getFarClipDistance() != 0 && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE) && 
+        mShadowUseInfiniteFarPlane)
+    {
+        // infinite far distance
+        camera->setFarClipDistance(0);
+    }
+
+    mCameraInProgress = camera;
+    mCamChanged = true;
+
+
+    // Update the scene, only do this once per frame
+    static unsigned long lastFrameNumber = 0;
+    unsigned long thisFrameNumber = Root::getSingleton().getCurrentFrameNumber();
+    if (thisFrameNumber != lastFrameNumber)
+    {
+        // Update animations
+        _applySceneAnimations();
+        // Update controllers 
+        ControllerManager::getSingleton().updateAllControllers();
+        lastFrameNumber = thisFrameNumber;
+    }
+
+    // Update scene graph for this camera (can happen multiple times per frame)
+    _updateSceneGraph(camera);
+
+    // Auto-track nodes
+    AutoTrackingSceneNodes::iterator atsni, atsniend;
+    atsniend = mAutoTrackingSceneNodes.end();
+    for (atsni = mAutoTrackingSceneNodes.begin(); atsni != atsniend; ++atsni)
+    {
+        (*atsni)->_autoTrack();
+    }
+    // Auto-track camera if required
+    camera->_autoTrack();
+
+
+    // Are we using any shadows at all?
+    if (mShadowTechnique != SHADOWTYPE_NONE && 
+        mIlluminationStage != IRS_RENDER_TO_TEXTURE)
+    {
+        // Locate any lights which could be affecting the frustum
+        findLightsAffectingFrustum(camera);
+        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+        {
+            // *******
+            // WARNING
+            // *******
+            // This call will result in re-entrant calls to this method
+            // therefore anything which comes before this is NOT 
+            // guaranteed persistent. Make sure that anything which 
+            // MUST be specific to this camera / target is done 
+            // AFTER THIS POINT
+            prepareShadowTextures(camera, vp);
+            // reset the cameras because of the re-entrant call
+            mCameraInProgress = camera;
+            mCamChanged = true;
+        }
+    }
+
+    // Invert vertex winding?
+    if (camera->isReflected())
+    {
+        mDestRenderSystem->setInvertVertexWinding(true);
+    }
+    else
+    {
+        mDestRenderSystem->setInvertVertexWinding(false);
+    }
+
+    // Set the viewport
+    setViewport(vp);
+
+    // Tell params about camera
+    mAutoParamDataSource.setCurrentCamera(camera);
+    // Set autoparams for finite dir light extrusion
+    mAutoParamDataSource.setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist);
+
+    // Tell params about current ambient light
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+	// Tell rendersystem
+	mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
+
+    // Tell params about render target
+    mAutoParamDataSource.setCurrentRenderTarget(vp->getTarget());
+
+
+    // Set camera window clipping planes (if any)
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES))
+    {
+        if (camera->isWindowSet())  
+        {
+            const std::vector<Plane>& planeList = 
+                camera->getWindowPlanes();
+            for (ushort i = 0; i < 4; ++i)
+            {
+                mDestRenderSystem->enableClipPlane(i, true);
+                mDestRenderSystem->setClipPlane(i, planeList[i]);
+            }
+        }
+        else
+        {
+            for (ushort i = 0; i < 4; ++i)
+            {
+                mDestRenderSystem->enableClipPlane(i, false);
+            }
+        }
+    }
+
+    // Clear the render queue
+    getRenderQueue()->clear();
+
+    // Parse the scene and tag visibles
+    _findVisibleObjects(camera, 
+        mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
+    // Add overlays, if viewport deems it
+    if (vp->getOverlaysEnabled())
+    {
+        OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp);
+    }
+    // Queue skies
+    _queueSkiesForRendering(camera);
+
+
+    // Don't do view / proj here anymore
+    // Checked per renderable now, although only changed when required
+    //mDestRenderSystem->_setViewMatrix(camera->getViewMatrix());
+    //mDestRenderSystem->_setProjectionMatrix(camera->getProjectionMatrix());
+
+    mDestRenderSystem->_beginGeometryCount();
+    // Begin the frame
+    mDestRenderSystem->_beginFrame();
+
+    // Set rasterisation mode
+    mDestRenderSystem->_setRasterisationMode(camera->getDetailLevel());
+
+    // Render scene content 
+    _renderVisibleObjects();
+
+    // End frame
+    mDestRenderSystem->_endFrame();
+
+    // Notify camera or vis faces
+    camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
+
+
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::_setDestinationRenderSystem(RenderSystem* sys)
+{
+    mDestRenderSystem = sys;
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::setWorldGeometry(const String& filename)
+{
+    // This default implementation cannot handle world geometry
+    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+        "World geometry is not supported by the generic SceneManager.",
+        "SceneManager::setWorldGeometry");
+}
+
+//-----------------------------------------------------------------------
+bool SceneManager::materialLess::operator() (const Material* x, const Material* y) const
+{
+    // If x transparent and y not, x > y (since x has to overlap y)
+    if (x->isTransparent() && !y->isTransparent())
+    {
+        return false;
+    }
+    // If y is transparent and x not, x < y
+    else if (!x->isTransparent() && y->isTransparent())
+    {
+        return true;
+    }
+    else
+    {
+        // Otherwise don't care (both transparent or both solid)
+        // Just arbitrarily use pointer
+        return x < y;
+    }
+
+}
+
+//-----------------------------------------------------------------------
+void SceneManager::setSkyPlane(
+                               bool enable,
+                               const Plane& plane,
+                               const String& materialName,
+                               Real gscale,
+                               Real tiling,
+                               bool drawFirst,
+                               Real bow, 
+                               int xsegments, int ysegments, 
+                               const String& groupName)
+{
+    if (enable)
+    {
+        String meshName = "SkyPlane";
+        mSkyPlane = plane;
+
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky plane material '" + materialName + "' not found.",
+                "SceneManager::setSkyPlane");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+
+        mSkyPlaneDrawFirst = drawFirst;
+
+        // Set up the plane
+        MeshPtr planeMesh = MeshManager::getSingleton().getByName(meshName);
+        if (!planeMesh.isNull())
+        {
+            // Destroy the old one
+            MeshManager::getSingleton().remove(planeMesh->getHandle());
+        }
+
+        // Create up vector
+        Vector3 up = plane.normal.crossProduct(Vector3::UNIT_X);
+        if (up == Vector3::ZERO)
+            up = plane.normal.crossProduct(-Vector3::UNIT_Z);
+
+        // Create skyplane
+        if( bow > 0 )
+        {
+            // Build a curved skyplane
+            planeMesh = MeshManager::getSingleton().createCurvedPlane(
+                meshName, groupName, plane, gscale * 100, gscale * 100, gscale * bow * 100, 
+                xsegments, ysegments, false, 1, tiling, tiling, up);
+        }
+        else
+        {
+            planeMesh = MeshManager::getSingleton().createPlane(
+                meshName, groupName, plane, gscale * 100, gscale * 100, xsegments, ysegments, false, 
+                1, tiling, tiling, up);
+        }
+
+        // Create entity 
+        if (mSkyPlaneEntity)
+        {
+            // destroy old one, do it by name for speed
+            removeEntity(meshName);
+        }
+        // Create, use the same name for mesh and entity
+        mSkyPlaneEntity = createEntity(meshName, meshName);
+        mSkyPlaneEntity->setMaterialName(materialName);
+        mSkyPlaneEntity->setCastShadows(false);
+
+        // Create node and attach
+        if (!mSkyPlaneNode)
+        {
+            mSkyPlaneNode = createSceneNode(meshName + "Node");
+        }
+        else
+        {
+            mSkyPlaneNode->detachAllObjects();
+        }
+        mSkyPlaneNode->attachObject(mSkyPlaneEntity);
+
+    }
+	mSkyPlaneEnabled = enable;
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSkyBox(
+                             bool enable,
+                             const String& materialName,
+                             Real distance,
+                             bool drawFirst,
+                             const Quaternion& orientation,
+                             const String& groupName)
+{
+    if (enable)
+    {
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky box material '" + materialName + "' not found.",
+                "SceneManager::setSkyBox");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+        // Also clamp texture, don't wrap (otherwise edges can get filtered)
+        m->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+
+
+        mSkyBoxDrawFirst = drawFirst;
+
+        // Create node 
+        if (!mSkyBoxNode)
+        {
+            mSkyBoxNode = createSceneNode("SkyBoxNode");
+        }
+        else
+        {
+            mSkyBoxNode->detachAllObjects();
+        }
+
+        MaterialManager& matMgr = MaterialManager::getSingleton();
+        // Set up the box (6 planes)
+        for (int i = 0; i < 6; ++i)
+        {
+            MeshPtr planeMesh = createSkyboxPlane((BoxPlane)i, distance, orientation, groupName);
+            String entName = "SkyBoxPlane" + StringConverter::toString(i);
+
+            // Create entity 
+            if (mSkyBoxEntity[i])
+            {
+                // destroy old one, do it by name for speed
+                removeEntity(entName);
+            }
+            mSkyBoxEntity[i] = createEntity(entName, planeMesh->getName());
+            mSkyBoxEntity[i]->setCastShadows(false);
+            // Have to create 6 materials, one for each frame
+            // Used to use combined material but now we're using queue we can't split to change frame
+            // This doesn't use much memory because textures aren't duplicated
+            MaterialPtr boxMat = matMgr.getByName(entName);
+            if (boxMat.isNull())
+            {
+                // Create new by clone
+                boxMat = m->clone(entName);
+                boxMat->load();
+            }
+            else
+            {
+                // Copy over existing
+                m->copyDetailsTo(boxMat);
+                boxMat->load();
+            }
+            // Set active frame
+            boxMat->getBestTechnique()->getPass(0)->getTextureUnitState(0)
+                ->setCurrentFrame(i);
+
+            mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
+
+            // Attach to node
+            mSkyBoxNode->attachObject(mSkyBoxEntity[i]);
+        } // for each plane
+
+    }
+	mSkyBoxEnabled = enable;
+}
+//-----------------------------------------------------------------------
+void SceneManager::setSkyDome(
+                              bool enable,
+                              const String& materialName,
+                              Real curvature,
+                              Real tiling,
+                              Real distance,
+                              bool drawFirst,
+                              const Quaternion& orientation,
+                              int xsegments, int ysegments, int ySegmentsToKeep,
+                              const String& groupName)
+{
+    if (enable)
+    {
+        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
+        if (m.isNull())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+                "Sky dome material '" + materialName + "' not found.",
+                "SceneManager::setSkyDome");
+        }
+        // Make sure the material doesn't update the depth buffer
+        m->setDepthWriteEnabled(false);
+        // Ensure loaded
+        m->load();
+
+        mSkyDomeDrawFirst = drawFirst;
+
+        // Create node 
+        if (!mSkyDomeNode)
+        {
+            mSkyDomeNode = createSceneNode("SkyDomeNode");
+        }
+        else
+        {
+            mSkyDomeNode->detachAllObjects();
+        }
+
+        // Set up the dome (5 planes)
+        for (int i = 0; i < 5; ++i)
+        {
+            MeshPtr planeMesh = createSkydomePlane((BoxPlane)i, curvature, 
+                tiling, distance, orientation, xsegments, ysegments, 
+                i!=BP_UP ? ySegmentsToKeep : -1, groupName);
+
+            String entName = "SkyDomePlane" + StringConverter::toString(i);
+
+            // Create entity 
+            if (mSkyDomeEntity[i])
+            {
+                // destroy old one, do it by name for speed
+                removeEntity(entName);
+            }
+            mSkyDomeEntity[i] = createEntity(entName, planeMesh->getName());
+            mSkyDomeEntity[i]->setMaterialName(m->getName());
+            mSkyDomeEntity[i]->setCastShadows(false);
+
+            // Attach to node
+            mSkyDomeNode->attachObject(mSkyDomeEntity[i]);
+        } // for each plane
+
+    }
+	mSkyDomeEnabled = enable;
+}
+//-----------------------------------------------------------------------
+MeshPtr SceneManager::createSkyboxPlane(
+                                      BoxPlane bp,
+                                      Real distance,
+                                      const Quaternion& orientation,
+                                      const String& groupName)
+{
+    Plane plane;
+    String meshName;
+    Vector3 up;
+
+    meshName = "SkyBoxPlane_";
+    // Set up plane equation
+    plane.d = distance;
+    switch(bp)
+    {
+    case BP_FRONT:
+        plane.normal = Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Front";
+        break;
+    case BP_BACK:
+        plane.normal = -Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Back";
+        break;
+    case BP_LEFT:
+        plane.normal = Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Left";
+        break;
+    case BP_RIGHT:
+        plane.normal = -Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Right";
+        break;
+    case BP_UP:
+        plane.normal = -Vector3::UNIT_Y;
+        up = Vector3::UNIT_Z;
+        meshName += "Up";
+        break;
+    case BP_DOWN:
+        plane.normal = Vector3::UNIT_Y;
+        up = -Vector3::UNIT_Z;
+        meshName += "Down";
+        break;
+    }
+    // Modify by orientation
+    plane.normal = orientation * plane.normal;
+    up = orientation * up;
+
+
+    // Check to see if existing plane
+    MeshManager& mm = MeshManager::getSingleton();
+    MeshPtr planeMesh = mm.getByName(meshName);
+    if(!planeMesh.isNull())
+    {
+        // destroy existing
+        mm.remove(planeMesh->getHandle());
+    }
+    // Create new
+    Real planeSize = distance * 2;
+    const int BOX_SEGMENTS = 1;
+    planeMesh = mm.createPlane(meshName, groupName, plane, planeSize, planeSize, 
+        BOX_SEGMENTS, BOX_SEGMENTS, false, 1, 1, 1, up);
+
+    //planeMesh->_dumpContents(meshName);
+
+    return planeMesh;
+
+}
+//-----------------------------------------------------------------------
+MeshPtr SceneManager::createSkydomePlane(
+                                       BoxPlane bp,
+                                       Real curvature,
+                                       Real tiling,
+                                       Real distance,
+                                       const Quaternion& orientation,
+                                       int xsegments, int ysegments, int ysegments_keep, 
+                                       const String& groupName)
+{
+
+    Plane plane;
+    String meshName;
+    Vector3 up;
+
+    meshName = "SkyDomePlane_";
+    // Set up plane equation
+    plane.d = distance;
+    switch(bp)
+    {
+    case BP_FRONT:
+        plane.normal = Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Front";
+        break;
+    case BP_BACK:
+        plane.normal = -Vector3::UNIT_Z;
+        up = Vector3::UNIT_Y;
+        meshName += "Back";
+        break;
+    case BP_LEFT:
+        plane.normal = Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Left";
+        break;
+    case BP_RIGHT:
+        plane.normal = -Vector3::UNIT_X;
+        up = Vector3::UNIT_Y;
+        meshName += "Right";
+        break;
+    case BP_UP:
+        plane.normal = -Vector3::UNIT_Y;
+        up = Vector3::UNIT_Z;
+        meshName += "Up";
+        break;
+    case BP_DOWN:
+        // no down
+        return MeshPtr();
+    }
+    // Modify by orientation
+    plane.normal = orientation * plane.normal;
+    up = orientation * up;
+
+    // Check to see if existing plane
+    MeshManager& mm = MeshManager::getSingleton();
+    MeshPtr planeMesh = mm.getByName(meshName);
+    if(!planeMesh.isNull())
+    {
+        // destroy existing
+        mm.remove(planeMesh->getHandle());
+    }
+    // Create new
+    Real planeSize = distance * 2;
+    planeMesh = mm.createCurvedIllusionPlane(meshName, groupName, plane, 
+        planeSize, planeSize, curvature, 
+        xsegments, ysegments, false, 1, tiling, tiling, up, 
+        orientation, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
+        false, false, ysegments_keep);
+
+    //planeMesh->_dumpContents(meshName);
+
+    return planeMesh;
+
+}
+
+
+//-----------------------------------------------------------------------
+void SceneManager::_updateSceneGraph(Camera* cam)
+{
+    // Cascade down the graph updating transforms & world bounds
+    // In this implementation, just update from the root
+    // Smarter SceneManager subclasses may choose to update only
+    //   certain scene graph branches
+    mSceneRoot->_update(true, false);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
+{
+    // Tell nodes to find, cascade down all nodes
+    mSceneRoot->_findVisibleObjects(cam, getRenderQueue(), true, 
+        mDisplayNodes, onlyShadowCasters);
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderVisibleObjects(void)
+{
+    // Render each separate queue
+    RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
+
+    // NB only queues which have been created are rendered, no time is wasted
+    //   parsing through non-existent queues (even though there are 10 available)
+
+    while (queueIt.hasMoreElements())
+    {
+        // Get queue group id
+        RenderQueueGroupID qId = queueIt.peekNextKey();
+		RenderQueueGroup* pGroup = queueIt.getNext();
+		// Skip this one if not to be processed
+		if (!isRenderQueueToBeProcessed(qId))
+			continue;
+
+
+        bool repeatQueue = false;
+        do // for repeating queues
+        {
+            // Fire queue started event
+            if (fireRenderQueueStarted(qId))
+            {
+                // Someone requested we skip this queue
+                continue;
+            }
+
+            renderQueueGroupObjects(pGroup);
+
+            // Fire queue ended event
+            if (fireRenderQueueEnded(qId))
+            {
+                // Someone requested we repeat this queue
+                repeatQueue = true;
+            }
+            else
+            {
+                repeatQueue = false;
+            }
+        } while (repeatQueue);
+
+    } // for each queue group
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+    LightList lightList;
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Clear light list
+        lightList.clear();
+
+        // Render all the ambient passes first, no light iteration, no lights
+        mIlluminationStage = IRS_AMBIENT;
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &lightList);
+        // Also render any objects which have receive shadows disabled
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+
+
+        // Now iterate per light
+        mIlluminationStage = IRS_PER_LIGHT;
+
+        // Iterate over lights, render all volumes to stencil
+        LightList::const_iterator li, liend;
+        liend = mLightsAffectingFrustum.end();
+
+        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
+        {
+            Light* l = *li;
+            // Set light state
+
+            if (l->getCastShadows())
+            {
+                // Clear stencil
+                mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
+                renderShadowVolumesToStencil(l, mCameraInProgress);
+                // turn stencil check on
+                mDestRenderSystem->setStencilCheckEnabled(true);
+                // NB we render where the stencil is equal to zero to render lit areas
+                mDestRenderSystem->setStencilBufferParams(CMPF_EQUAL, 0);
+            }
+
+            // render lighting passes for this light
+            if (lightList.empty())
+                lightList.push_back(l);
+            else
+                lightList[0] = l;
+            renderObjects(pPriorityGrp->_getSolidPassesDiffuseSpecular(), false, &lightList);
+
+            // Reset stencil params
+            mDestRenderSystem->setStencilBufferParams();
+            mDestRenderSystem->setStencilCheckEnabled(false);
+            mDestRenderSystem->_setDepthBufferParams();
+
+        }// for each light
+
+
+        // Now render decal passes, no need to set lights as lighting will be disabled
+        mIlluminationStage = IRS_DECAL;
+        renderObjects(pPriorityGrp->_getSolidPassesDecal(), false);
+
+
+    }// for each priority
+
+    // reset lighting stage
+    mIlluminationStage = IRS_NONE;
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
+    while (groupIt2.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderModulativeStencilShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    /* For each light, we need to render all the solids from each group, 
+    then do the modulative shadows, then render the transparents from
+    each group.
+    Now, this means we are going to reorder things more, but that it required
+    if the shadows are to look correct. The overall order is preserved anyway,
+    it's just that all the transparents are at the end instead of them being
+    interleaved as in the normal rendering loop. 
+    */
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do (shadowable) solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+    }
+
+
+    // Iterate over lights, render all volumes to stencil
+    LightList::const_iterator li, liend;
+    liend = mLightsAffectingFrustum.end();
+
+    for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
+    {
+        Light* l = *li;
+        if (l->getCastShadows())
+        {
+            // Clear stencil
+            mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
+            renderShadowVolumesToStencil(l, mCameraInProgress);
+            // render full-screen shadow modulator for all lights
+            setPass(mShadowModulativePass);
+            // turn stencil check on
+            mDestRenderSystem->setStencilCheckEnabled(true);
+            // NB we render where the stencil is not equal to zero to render shadows, not lit areas
+            mDestRenderSystem->setStencilBufferParams(CMPF_NOT_EQUAL, 0);
+            renderSingleObject(mFullScreenQuad, mShadowModulativePass, false);
+            // Reset stencil params
+            mDestRenderSystem->setStencilBufferParams();
+            mDestRenderSystem->setStencilCheckEnabled(false);
+            mDestRenderSystem->_setDepthBufferParams();
+        }
+
+    }// for each light
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
+    while (groupIt2.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
+
+        // Do non-shadowable solids
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+
+    }// for each priority
+
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
+    while (groupIt3.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTextureShadowCasterQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    static LightList nullLightList;
+    // This is like the basic group render, except we skip all transparents
+    // and we also render any non-shadowed objects
+    // Note that non-shadow casters will have already been eliminated during
+    // _findVisibleObjects
+
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    // Override auto param ambient to force vertex programs and fixed function to 
+    // use shadow colour
+    mAutoParamDataSource.setAmbientLightColour(mShadowColour);
+    mDestRenderSystem->setAmbientLight(mShadowColour.r, mShadowColour.g, mShadowColour.b);
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids, override light list incase any vertex programs use them
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &nullLightList);
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), false, &nullLightList);
+		// Do transparents that cast shadows
+		renderTransparentShadowCasterObjects(
+				pPriorityGrp->_getTransparentPasses(), false, &nullLightList);
+
+
+    }// for each priority
+
+    // reset ambient light
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    /* For each light, we need to render all the solids from each group, 
+    then do the modulative shadows, then render the transparents from
+    each group.
+    Now, this means we are going to reorder things more, but that it required
+    if the shadows are to look correct. The overall order is preserved anyway,
+    it's just that all the transparents are at the end instead of them being
+    interleaved as in the normal rendering loop. 
+    */
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+        renderObjects(pPriorityGrp->_getSolidPassesNoShadow(), true);
+    }
+
+
+    // Iterate over lights, render received shadows
+    // only perform this if we're in the 'normal' render stage, to avoid
+    // doing it during the render to texture
+    if (mIlluminationStage == IRS_NONE)
+    {
+        mIlluminationStage = IRS_RENDER_MODULATIVE_PASS;
+
+        LightList::iterator i, iend;
+        ShadowTextureList::iterator si, siend;
+        iend = mLightsAffectingFrustum.end();
+        siend = mShadowTextures.end();
+        for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
+            i != iend && si != siend; ++i)
+        {
+            Light* l = *i;
+
+            if (!l->getCastShadows())
+                continue;
+
+            mCurrentShadowTexture = *si;
+            // Hook up receiver texture
+            mShadowReceiverPass->getTextureUnitState(0)->setTextureName(
+                mCurrentShadowTexture->getName());
+            // Hook up projection frustum
+            mShadowReceiverPass->getTextureUnitState(0)->setProjectiveTexturing(
+                true, mCurrentShadowTexture->getViewport(0)->getCamera());
+            mAutoParamDataSource.setTextureProjector(
+                mCurrentShadowTexture->getViewport(0)->getCamera());
+            // if this light is a spotlight, we need to add the spot fader layer
+            if (l->getType() == Light::LT_SPOTLIGHT)
+            {
+                // Add spot fader if not present already
+                if (mShadowReceiverPass->getNumTextureUnitStates() == 1)
+                {
+                    TextureUnitState* t = 
+                        mShadowReceiverPass->createTextureUnitState("spot_shadow_fade.png");
+                    t->setProjectiveTexturing(
+                        true, mCurrentShadowTexture->getViewport(0)->getCamera());
+                    t->setColourOperation(LBO_ADD);
+                    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+                }
+                else
+                {
+                    // Just set projector
+                    TextureUnitState* t = 
+                        mShadowReceiverPass->getTextureUnitState(1);
+                    t->setProjectiveTexturing(
+                        true, mCurrentShadowTexture->getViewport(0)->getCamera());
+                }
+            }
+            else if (mShadowReceiverPass->getNumTextureUnitStates() > 1)
+            {
+                // remove spot fader layer
+                mShadowReceiverPass->removeTextureUnitState(1);
+
+            }
+            mShadowReceiverPass->_load();
+
+            if (l->getCastShadows() && pGroup->getShadowsEnabled())
+            {
+                renderTextureShadowReceiverQueueGroupObjects(pGroup);
+            }
+
+            ++si;
+
+        }// for each light
+
+        mIlluminationStage = IRS_NONE;
+
+    }
+
+    // Iterate again - variable name changed to appease gcc.
+    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
+    while (groupIt3.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
+
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+    }// for each priority
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    static LightList nullLightList;
+
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    // Override auto param ambient to force vertex programs to go full-bright
+    mAutoParamDataSource.setAmbientLightColour(ColourValue::White);
+    mDestRenderSystem->setAmbientLight(1, 1, 1);
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Do solids, override light list incase any vertex programs use them
+        renderObjects(pPriorityGrp->_getSolidPasses(), false, &nullLightList);
+
+        // Don't render transparents or passes which have shadow receipt disabled
+
+    }// for each priority
+
+    // reset ambient
+    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
+    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
+
+}
+//-----------------------------------------------------------------------
+bool SceneManager::validatePassForRendering(Pass* pass)
+{
+    // Bypass if we're doing a texture shadow render and 
+    // this pass is after the first (only 1 pass needed for shadow texture)
+    if ((mIlluminationStage == IRS_RENDER_TO_TEXTURE ||
+        mIlluminationStage == IRS_RENDER_MODULATIVE_PASS) && 
+        pass->getIndex() > 0)
+    {
+        return false;
+    }
+
+    return true;
+}
+//-----------------------------------------------------------------------
+bool SceneManager::validateRenderableForRendering(Pass* pass, Renderable* rend)
+{
+    // Skip this renderable if we're doing texture shadows, it casts shadows
+    // and we're doing the render receivers pass and we're not self-shadowing
+    if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE && 
+        mIlluminationStage == IRS_RENDER_MODULATIVE_PASS && 
+        rend->getCastsShadows() && !mShadowTextureSelfShadow)
+    {
+        return false;
+    }
+
+    return true;
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderObjects(
+                                 const RenderPriorityGroup::SolidRenderablePassMap& objs, bool doLightIteration, 
+                                 const LightList* manualLightList)
+{
+    // ----- SOLIDS LOOP -----
+    RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
+    ipassend = objs.end();
+    for (ipass = objs.begin(); ipass != ipassend; ++ipass)
+    {
+        // Fast bypass if this group is now empty
+        if (ipass->second->empty()) continue;
+
+        // Give SM a chance to eliminate this pass
+        if (!validatePassForRendering(ipass->first))
+            continue;
+
+        // For solids, we try to do each pass in turn
+        Pass* usedPass = setPass(ipass->first);
+        RenderPriorityGroup::RenderableList* rendList = ipass->second;
+        RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
+        irendend = rendList->end();
+        for (irend = rendList->begin(); irend != irendend; ++irend)
+        {
+            // Give SM a chance to eliminate
+            if (!validateRenderableForRendering(ipass->first, *irend))
+                continue;
+            // Render a single object, this will set up auto params if required
+            renderSingleObject(*irend, usedPass, doLightIteration, manualLightList);
+        }
+    } 
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderObjects(
+                                 const RenderPriorityGroup::TransparentRenderablePassList& objs, bool doLightIteration,
+                                 const LightList* manualLightList)
+{
+    // ----- TRANSPARENT LOOP -----
+    // This time we render by Z, not by pass
+    // The mTransparentObjects set needs to be ordered first
+    // Render each non-transparent entity in turn, grouped by material
+    RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
+
+    itransend = objs.end();
+    for (itrans = objs.begin(); 
+        itrans != itransend; ++itrans)
+    {
+        // For transparents, we have to accept that we can't sort entirely by pass
+        setPass(itrans->pass);
+        renderSingleObject(itrans->renderable, itrans->pass, doLightIteration, 
+            manualLightList);
+    }
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    if (pGroup->getShadowsEnabled() && 
+        mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
+    {
+        // Additive stencil shadows in use
+        renderAdditiveStencilShadowedQueueGroupObjects(pGroup);
+    }
+    else if (pGroup->getShadowsEnabled() && 
+        mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
+    {
+        // Modulative stencil shadows in use
+        renderModulativeStencilShadowedQueueGroupObjects(pGroup);
+    }
+    else if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+    {
+        // Modulative texture shadows in use
+        if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
+        {
+            // Shadow caster pass
+            if (pGroup->getShadowsEnabled())
+                renderTextureShadowCasterQueueGroupObjects(pGroup);
+        }
+        else
+        {
+            // Ordinary pass
+            renderModulativeTextureShadowedQueueGroupObjects(pGroup);
+        }
+    }
+    else
+    {
+        // No shadows, ordinary pass
+        renderBasicQueueGroupObjects(pGroup);
+    }
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup)
+{
+    // Basic render loop
+    // Iterate through priorities
+    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
+
+    while (groupIt.hasMoreElements())
+    {
+        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
+
+        // Sort the queue first
+        pPriorityGrp->sort(mCameraInProgress);
+
+        // Do solids
+        renderObjects(pPriorityGrp->_getSolidPasses(), true);
+        // Do transparents
+        renderObjects(pPriorityGrp->_getTransparentPasses(), true);
+
+
+    }// for each priority
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderTransparentShadowCasterObjects(
+	const RenderPriorityGroup::TransparentRenderablePassList& objs, bool doLightIteration,
+	const LightList* manualLightList)
+{
+	// ----- TRANSPARENT LOOP as in renderObjects above, but changed a bit -----
+	RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
+
+	itransend = objs.end();
+	for (itrans = objs.begin(); 
+		itrans != itransend; ++itrans)
+	{
+		Renderable *r = itrans->renderable;
+		Pass *p = itrans->pass;
+
+		// only render this pass if it's being forced to cast shadows
+		if (p->getParent()->getParent()->getTransparencyCastsShadows())
+		{
+			setPass(p);
+			renderSingleObject(itrans->renderable, p, doLightIteration, manualLightList);
+		}
+	}
+}
+//-----------------------------------------------------------------------
+void SceneManager::renderSingleObject(Renderable* rend, Pass* pass, 
+                                      bool doLightIteration, const LightList* manualLightList)
+{
+    static Matrix4 xform[256];
+    unsigned short numMatrices;
+    static bool normalisedNormals = false;
+    SceneDetailLevel camDetailLevel = mCameraInProgress->getDetailLevel();
+    static SceneDetailLevel lastDetailLevel = camDetailLevel;
+    static RenderOperation ro;
+    static LightList localLightList;
+
+    if (pass->isProgrammable())
+    {
+        // Tell auto params object about the renderable change
+        mAutoParamDataSource.setCurrentRenderable(rend);
+        pass->_updateAutoParamsNoLights(mAutoParamDataSource);
+    }
+
+    // Set world transformation
+    rend->getWorldTransforms(xform);
+    numMatrices = rend->getNumWorldTransforms();
+    if (numMatrices > 1)
+    {
+        mDestRenderSystem->_setWorldMatrices(xform, numMatrices);
+    }
+    else
+    {
+        mDestRenderSystem->_setWorldMatrix(*xform);
+    }
+
+    // Issue view / projection changes if any
+    useRenderableViewProjMode(rend);
+
+    // Reissue any texture gen settings which are dependent on view matrix
+    Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
+    size_t unit = 0;
+    while(texIter.hasMoreElements())
+    {
+        TextureUnitState* pTex = texIter.getNext();
+        if (pTex->hasViewRelativeTextureCoordinateGeneration())
+        {
+            mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
+        }
+        ++unit;
+    }
+
+
+    // Sort out normalisation
+    bool thisNormalise = rend->getNormaliseNormals();
+    if (thisNormalise != normalisedNormals)
+    {
+        mDestRenderSystem->setNormaliseNormals(thisNormalise);
+        normalisedNormals = thisNormalise;
+    }
+
+    // Set up the solid / wireframe override
+    SceneDetailLevel reqDetail = rend->getRenderDetail();
+    if (rend->getRenderDetailOverrideable())
+    {
+        // check camera detial only when render detail is overridable
+        if (reqDetail > camDetailLevel)
+        {
+            // only downgrade detail; if cam says wireframe we don't go up to solid
+            reqDetail = camDetailLevel;
+        }
+    }
+    if (reqDetail != lastDetailLevel)
+    {
+        mDestRenderSystem->_setRasterisationMode(reqDetail);
+        lastDetailLevel = reqDetail;
+
+    }
+
+    mDestRenderSystem->setClipPlanes(rend->getClipPlanes());
+
+    // Set up rendering operation
+    rend->getRenderOperation(ro);
+    ro.srcRenderable = rend;
+
+    if (doLightIteration)
+    {
+        // Here's where we issue the rendering operation to the render system
+        // Note that we may do this once per light, therefore it's in a loop
+        // and the light parameters are updated once per traversal through the
+        // loop
+        const LightList& rendLightList = rend->getLights();
+        bool iteratePerLight = pass->getRunOncePerLight();
+        size_t numIterations = iteratePerLight ? rendLightList.size() : 1;
+        const LightList* pLightListToUse;
+        for (size_t i = 0; i < numIterations; ++i)
+        {
+            // Determine light list to use
+            if (iteratePerLight)
+            {
+                // Change the only element of local light list to be
+                // the light at index i
+                localLightList.clear();
+                // Check whether we need to filter this one out
+                if (pass->getRunOnlyForOneLightType() && 
+                    pass->getOnlyLightType() != rendLightList[i]->getType())
+                {
+                    // Skip
+                    continue;
+                }
+
+                localLightList.push_back(rendLightList[i]);
+                pLightListToUse = &localLightList;
+            }
+            else
+            {
+                // Use complete light list
+                pLightListToUse = &rendLightList;
+            }
+
+            // Do we need to update GPU program parameters?
+            if (pass->isProgrammable())
+            {
+                // Update any automatic gpu params for lights
+                // Other bits of information will have to be looked up
+                mAutoParamDataSource.setCurrentLightList(pLightListToUse);
+                pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
+                // NOTE: We MUST bind parameters AFTER updating the autos
+                // TEST
+                if (pass->hasVertexProgram())
+                {
+                    mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
+                        pass->getVertexProgramParameters());
+                }
+                if (pass->hasFragmentProgram())
+                {
+                    mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, 
+                        pass->getFragmentProgramParameters());
+                }
+            }
+            // Do we need to update light states? 
+            // Only do this if fixed-function vertex lighting applies
+            if (pass->getLightingEnabled() &&
+                (!pass->hasVertexProgram() || pass->getVertexProgram()->getPassSurfaceAndLightStates()))
+            {
+                mDestRenderSystem->_useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
+            }
+            // issue the render op		
+            mDestRenderSystem->_render(ro);
+        } // possibly iterate per light
+    }
+    else // no automatic light processing
+    {
+        // Do we need to update GPU program parameters?
+        if (pass->isProgrammable())
+        {
+            // Do we have a manual light list?
+            if (manualLightList)
+            {
+                // Update any automatic gpu params for lights
+                mAutoParamDataSource.setCurrentLightList(manualLightList);
+                pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
+            }
+
+            if (pass->hasVertexProgram())
+            {
+                mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
+                    pass->getVertexProgramParameters());
+            }
+            if (pass->hasFragmentProgram())
+            {
+                mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, 
+                    pass->getFragmentProgramParameters());
+            }
+        }
+
+        // Use manual lights if present, and fixed-function vertex lighting applies
+        if (manualLightList && 
+            pass->getLightingEnabled() &&
+            (!pass->hasVertexProgram() || pass->getVertexProgram()->getPassSurfaceAndLightStates()))
+        {
+            mDestRenderSystem->_useLights(*manualLightList, pass->getMaxSimultaneousLights());
+        }
+        // issue the render op		
+        mDestRenderSystem->_render(ro);
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::setAmbientLight(const ColourValue& colour)
+{
+    mAmbientLight = colour;
+    mDestRenderSystem->setAmbientLight(colour.r, colour.g, colour.b);
+}
+//-----------------------------------------------------------------------
+const ColourValue& SceneManager::getAmbientLight(void) const
+{
+    return mAmbientLight;
+}
+//-----------------------------------------------------------------------
+ViewPoint SceneManager::getSuggestedViewpoint(bool random)
+{
+    // By default return the origin
+    ViewPoint vp;
+    vp.position = Vector3::ZERO;
+    vp.orientation = Quaternion::IDENTITY;
+    return vp;
+}
+//-----------------------------------------------------------------------
+void SceneManager::setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
+{
+    mFogMode = mode;
+    mFogColour = colour;
+    mFogStart = start;
+    mFogEnd = end;
+    mFogDensity = density;
+}
+//-----------------------------------------------------------------------
+FogMode SceneManager::getFogMode(void) const
+{
+    return mFogMode;
+}
+//-----------------------------------------------------------------------
+const ColourValue& SceneManager::getFogColour(void) const
+{
+    return mFogColour;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogStart(void) const
+{
+    return mFogStart;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogEnd(void) const
+{
+    return mFogEnd;
+}
+//-----------------------------------------------------------------------
+Real SceneManager::getFogDensity(void) const
+{
+    return mFogDensity;
+}
+//-----------------------------------------------------------------------
+BillboardSet* SceneManager::createBillboardSet(const String& name, unsigned int poolSize)
+{
+    // Check name not used
+    if (mBillboardSets.find(name) != mBillboardSets.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "A billboard set with the name " + name + " already exists",
+            "SceneManager::createBillboardSet" );
+    }
+
+    BillboardSet* set = new BillboardSet( name, poolSize );
+    mBillboardSets[name] = set;//.insert(BillboardSetList::value_type(name, set));
+
+    return set;
+}
+//-----------------------------------------------------------------------
+BillboardSet* SceneManager::getBillboardSet(const String& name)
+{
+    BillboardSetList::iterator i = mBillboardSets.find(name);
+    if (i == mBillboardSets.end())
+    {
+        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find BillboardSet with name " + name,
+            "SceneManager::getBillboardSet");
+    }
+    else
+    {
+        return i->second;
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeBillboardSet(BillboardSet* set)
+{
+    // Find in list
+    BillboardSetList::iterator i = mBillboardSets.begin();
+    for (; i != mBillboardSets.end(); ++i)
+    {
+        if (i->second == set)
+        {
+            mBillboardSets.erase(i);
+            delete set;
+            break;
+        }
+    }
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::removeBillboardSet(const String& name)
+{
+    // Find in list
+    BillboardSetList::iterator i = mBillboardSets.find(name);
+    if (i != mBillboardSets.end())
+    {
+        delete i->second;
+        mBillboardSets.erase(i);
+    }
+}
+//-----------------------------------------------------------------------
+void SceneManager::setDisplaySceneNodes(bool display)
+{
+    mDisplayNodes = display;
+}
+//-----------------------------------------------------------------------
+Animation* SceneManager::createAnimation(const String& name, Real length)
+{
+    // Check name not used
+    if (mAnimationsList.find(name) != mAnimationsList.end())
+    {
+        OGRE_EXCEPT(
+            Exception::ERR_DUPLICATE_ITEM,
+            "An animation with the name " + name + " already exists",
+            "SceneManager::createAnimation" );
+    }
+
+    Animation* pAnim = new Animation(name, length);
+    mAnimationsList[name] = pAnim;
+    return pAnim;
+}
+//-----------------------------------------------------------------------
+Animation* SceneManager::getAnimation(const String& name) const
+{
+    AnimationList::const_iterator i = mAnimationsList.find(name);
+    if (i == mAnimationsList.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find animation with name " + name, 
+            "SceneManager::getAnimation");
+    }
+    return i->second;
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAnimation(const String& name)
+{
+    // Also destroy any animation states referencing this animation
+    AnimationStateSet::iterator si, siend;
+    siend = mAnimationStates.end();
+    for (si = mAnimationStates.begin(); si != siend; )
+    {
+        if (si->second.getAnimationName() == name)
+        {
+            // erase, post increment to avoid the invalidated iterator
+            mAnimationStates.erase(si++);
+        }
+        else
+        {
+            ++si;
+        }
+    }
+
+    AnimationList::iterator i = mAnimationsList.find(name);
+    if (i == mAnimationsList.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot find animation with name " + name, 
+            "SceneManager::getAnimation");
+    }
+
+    // Free memory
+    delete i->second;
+
+    mAnimationsList.erase(i);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAllAnimations(void)
+{
+    // Destroy all states too, since they cannot reference destroyed animations
+    destroyAllAnimationStates();
+
+    AnimationList::iterator i;
+    for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
+    {
+        // destroy
+        delete i->second;
+    }
+    mAnimationsList.clear();
+}
+//-----------------------------------------------------------------------
+AnimationState* SceneManager::createAnimationState(const String& animName)
+{
+    if (mAnimationStates.find(animName) != mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
+            "Cannot create, AnimationState already exists: "+animName, 
+            "SceneManager::createAnimationState");
+    }
+
+    // Get animation, this will throw an exception if not found
+    Animation* anim = getAnimation(animName);
+
+    // Create new state
+    AnimationState newState(animName, 0, anim->getLength());
+
+    // Record it
+    std::pair<AnimationStateSet::iterator, bool> retPair = 
+        mAnimationStates.insert(AnimationStateSet::value_type(animName, newState));
+
+    // Check boolean return
+    if (retPair.second)
+    {
+        // insert was OK
+        // Get pointer from iterator in pair
+        return &(retPair.first->second);
+    }
+    else
+    {
+        // Problem
+        // Not because of duplicate item, that's checked for above
+        OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Unexpected error creating new animation state.",
+            "SceneManager::createAnimationState");
+    }
+
+
+}
+//-----------------------------------------------------------------------
+AnimationState* SceneManager::getAnimationState(const String& animName) 
+{
+    AnimationStateSet::iterator i = mAnimationStates.find(animName);
+
+    if (i == mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot locate animation state for animation " + animName,
+            "SceneManager::getAnimationState");
+    }
+
+    return &(i->second);
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAnimationState(const String& name)
+{
+    AnimationStateSet::iterator i = mAnimationStates.find(name);
+
+    if (i == mAnimationStates.end())
+    {
+        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+            "Cannot locate animation state for animation " + name,
+            "SceneManager::destroyAnimationState");
+    }
+
+    mAnimationStates.erase(i);
+
+
+}
+//-----------------------------------------------------------------------
+void SceneManager::destroyAllAnimationStates(void)
+{
+    mAnimationStates.clear();
+}
+//-----------------------------------------------------------------------
+void SceneManager::_applySceneAnimations(void)
+{
+    AnimationStateSet::const_iterator i, iend;
+
+    i = mAnimationStates.begin();
+    iend = mAnimationStates.end();
+
+    for (;i != iend; ++i)
+    {
+        if (i->second.getEnabled())
+        {
+            Animation* anim = getAnimation(i->second.getAnimationName());
+
+            // Reset any nodes involved
+            // NB this excludes blended animations
+            const Animation::TrackList& trackList = anim->_getTrackList();
+            Animation::TrackList::const_iterator ti, tend;
+            ti = trackList.begin();
+            tend = trackList.end();
+            for (;ti != tend; ++ti)
+            {
+                Node* nd = ti->second->getAssociatedNode();
+                nd->resetToInitialState();
+            }
+
+
+            // Apply the animation
+            anim->apply(i->second.getTimePosition(), i->second.getWeight());
+        }
+    }
+
+
+}
+//---------------------------------------------------------------------
+void SceneManager::manualRender(RenderOperation* rend, 
+                                Pass* pass, Viewport* vp, const Matrix4& worldMatrix, 
+                                const Matrix4& viewMatrix, const Matrix4& projMatrix, 
+                                bool doBeginEndFrame) 
+{
+    mDestRenderSystem->_setViewport(vp);
+    mDestRenderSystem->_setWorldMatrix(worldMatrix);
+    mDestRenderSystem->_setViewMatrix(viewMatrix);
+    mDestRenderSystem->_setProjectionMatrix(projMatrix);
+
+    if (doBeginEndFrame)
+        mDestRenderSystem->_beginFrame();
+
+    setPass(pass);
+    mDestRenderSystem->_render(*rend);
+
+    if (doBeginEndFrame)
+        mDestRenderSystem->_endFrame();
+
+}
+//---------------------------------------------------------------------
+void SceneManager::useRenderableViewProjMode(Renderable* pRend)
+{
+    // Check view matrix
+    static bool lastViewWasIdentity = false;
+    bool useIdentityView = pRend->useIdentityView();
+    if (useIdentityView && (mCamChanged || !lastViewWasIdentity))
+    {
+        // Using identity view now, change it
+        mDestRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
+        lastViewWasIdentity = true;
+    }
+    else if (!useIdentityView && (mCamChanged || lastViewWasIdentity))
+    {
+        // Coming back to normal from identity view
+        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix());
+        lastViewWasIdentity = false;
+    }
+
+    static bool lastProjWasIdentity = false;
+    bool useIdentityProj = pRend->useIdentityProjection();
+
+    if (useIdentityProj && (mCamChanged || !lastProjWasIdentity))
+    {
+        mDestRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY);
+
+        lastProjWasIdentity = true;
+    }
+    else if (!useIdentityProj && (mCamChanged || lastProjWasIdentity))
+    {
+        // Coming back from flat projection
+        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrix());
+        lastProjWasIdentity = false;
+    }
+
+    mCamChanged = false;
+
+}
+
+//---------------------------------------------------------------------
+void SceneManager::_queueSkiesForRendering(Camera* cam)
+{
+    // Update nodes
+    // Translate the box by the camera position (constant distance)
+    if (mSkyPlaneNode)
+    {
+        // The plane position relative to the camera has already been set up
+        mSkyPlaneNode->setPosition(cam->getDerivedPosition());
+    }
+
+    if (mSkyBoxNode)
+    {
+        mSkyBoxNode->setPosition(cam->getDerivedPosition());
+    }
+
+    if (mSkyDomeNode)
+    {
+        mSkyDomeNode->setPosition(cam->getDerivedPosition());
+    }
+
+    RenderQueueGroupID qid;
+    if (mSkyPlaneEnabled)
+    {
+        qid = mSkyPlaneDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+        getRenderQueue()->addRenderable(mSkyPlaneEntity->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+    }
+
+    uint plane;
+    if (mSkyBoxEnabled)
+    {
+        qid = mSkyBoxDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+
+        for (plane = 0; plane < 6; ++plane)
+        {
+            getRenderQueue()->addRenderable(
+                mSkyBoxEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+        }
+    }
+
+    if (mSkyDomeEnabled)
+    {
+        qid = mSkyDomeDrawFirst? 
+RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
+
+        for (plane = 0; plane < 5; ++plane)
+        {
+            getRenderQueue()->addRenderable(
+                mSkyDomeEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
+        }
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::addRenderQueueListener(RenderQueueListener* newListener)
+{
+    mRenderQueueListeners.push_back(newListener);
+}
+//---------------------------------------------------------------------
+void SceneManager::removeRenderQueueListener(RenderQueueListener* delListener)
+{
+    RenderQueueListenerList::iterator i, iend;
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        if (*i == delListener)
+        {
+            mRenderQueueListeners.erase(i);
+            break;
+        }
+    }
+
+}
+//---------------------------------------------------------------------
+bool SceneManager::fireRenderQueueStarted(RenderQueueGroupID id)
+{
+    RenderQueueListenerList::iterator i, iend;
+    bool skip = false;
+
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        (*i)->renderQueueStarted(id, skip);
+    }
+    return skip;
+}
+//---------------------------------------------------------------------
+bool SceneManager::fireRenderQueueEnded(RenderQueueGroupID id)
+{
+    RenderQueueListenerList::iterator i, iend;
+    bool repeat = false;
+
+    iend = mRenderQueueListeners.end();
+    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
+    {
+        (*i)->renderQueueEnded(id, repeat);
+    }
+    return repeat;
+}
+//---------------------------------------------------------------------
+void SceneManager::setViewport(Viewport* vp)
+{
+    mCurrentViewport = vp;
+    // Set viewport in render system
+    mDestRenderSystem->_setViewport(vp);
+}
+//---------------------------------------------------------------------
+void SceneManager::showBoundingBoxes(bool bShow) 
+{
+    mShowBoundingBoxes = bShow;
+}
+//---------------------------------------------------------------------
+bool SceneManager::getShowBoundingBoxes() const
+{
+    return mShowBoundingBoxes;
+}
+//---------------------------------------------------------------------
+void SceneManager::_notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack)
+{
+    if (autoTrack)
+    {
+        mAutoTrackingSceneNodes.insert(node);
+    }
+    else
+    {
+        mAutoTrackingSceneNodes.erase(node);
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTechnique(ShadowTechnique technique)
+{
+    mShadowTechnique = technique;
+    if (technique == SHADOWTYPE_STENCIL_ADDITIVE || 
+        technique == SHADOWTYPE_STENCIL_MODULATIVE)
+    {
+        // Firstly check that we  have a stencil
+        // Otherwise forget it
+        if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_HWSTENCIL))
+        {
+            LogManager::getSingleton().logMessage(
+                "WARNING: Stencil shadows were requested, but this device does not "
+                "have a hardware stencil. Shadows disabled.");
+            mShadowTechnique = SHADOWTYPE_NONE;
+        }
+        else if (mShadowIndexBuffer.isNull())
+        {
+            // Create an estimated sized shadow index buffer
+            mShadowIndexBuffer = HardwareBufferManager::getSingleton().
+                createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 
+                mShadowIndexBufferSize, 
+                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
+                false);
+            // tell all meshes to prepare shadow volumes
+            MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(true);
+        }
+    }
+
+    if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
+    {
+        // Additive stencil, we need to split everything by illumination stage
+        getRenderQueue()->setSplitPassesByLightingType(true);
+    }
+    else
+    {
+        getRenderQueue()->setSplitPassesByLightingType(false);
+    }
+
+    if (mShadowTechnique != SHADOWTYPE_NONE)
+    {
+        // Tell render queue to split off non-shadowable materials
+        getRenderQueue()->setSplitNoShadowPasses(true);
+    }
+    else
+    {
+        getRenderQueue()->setSplitNoShadowPasses(false);
+    }
+
+    if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+    {
+        createShadowTextures(mShadowTextureSize, mShadowTextureCount, mShadowTextureFormat);
+    }
+
+}
+//---------------------------------------------------------------------
+void SceneManager::findLightsAffectingFrustum(const Camera* camera)
+{
+    // Basic iteration for this SM
+    mLightsAffectingFrustum.clear();
+    SceneLightList::iterator i, iend;
+    iend = mLights.end();
+    Sphere sphere;
+    for (i = mLights.begin(); i != iend; ++i)
+    {
+        Light* l = i->second;
+		if (l->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);
+				}
+
+			}
+		}
+    }
+
+}
+//---------------------------------------------------------------------
+bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
+    MovableObject* object)
+{
+    if (object->getCastShadows() && object->isVisible() && 
+		mSceneMgr->isRenderQueueToBeProcessed(object->getRenderQueueGroup()))
+    {
+        if (mFarDistSquared)
+        {
+            // Check object is within the shadow far distance
+            Vector3 toObj = object->getParentNode()->_getDerivedPosition() 
+                - mCamera->getDerivedPosition();
+            Real radius = object->getWorldBoundingSphere().getRadius();
+            Real dist =  toObj.squaredLength();               
+            if (dist - (radius * radius) > mFarDistSquared)
+            {
+                // skip, beyond max range
+                return true;
+            }
+        }
+
+        // If the object is in the frustum, we can always see the shadow
+        if (mCamera->isVisible(object->getWorldBoundingBox()))
+        {
+            mCasterList->push_back(object);
+            return true;
+        }
+
+        // Otherwise, object can only be casting a shadow into our view if
+        // the light is outside the frustum (or it's a directional light, 
+        // which are always outside), and the object is intersecting
+        // on of the volumes formed between the edges of the frustum and the
+        // light
+        if (!mIsLightInFrustum || mLight->getType() == Light::LT_DIRECTIONAL)
+        {
+            // Iterate over volumes
+            PlaneBoundedVolumeList::const_iterator i, iend;
+            iend = mLightClipVolumeList->end();
+            for (i = mLightClipVolumeList->begin(); i != iend; ++i)
+            {
+                if (i->intersects(object->getWorldBoundingBox()))
+                {
+                    mCasterList->push_back(object);
+                    return true;
+                }
+
+            }
+
+        }
+    }
+    return true;
+}
+//---------------------------------------------------------------------
+bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
+    SceneQuery::WorldFragment* fragment)
+{
+    // don't deal with world geometry
+    return true;
+}
+//---------------------------------------------------------------------
+const SceneManager::ShadowCasterList& SceneManager::findShadowCastersForLight(
+    const Light* light, const Camera* camera)
+{
+    mShadowCasterList.clear();
+
+    if (light->getType() == Light::LT_DIRECTIONAL)
+    {
+        // Basic AABB query encompassing the frustum and the extrusion of it
+        AxisAlignedBox aabb;
+        const Vector3* corners = camera->getWorldSpaceCorners();
+        Vector3 min, max;
+        Vector3 extrude = light->getDirection() * -mShadowDirLightExtrudeDist;
+        // do first corner
+        min = max = corners[0];
+        min.makeFloor(corners[0] + extrude);
+        max.makeCeil(corners[0] + extrude);
+        for (size_t c = 1; c < 8; ++c)
+        {
+            min.makeFloor(corners[c]);
+            max.makeCeil(corners[c]);
+            min.makeFloor(corners[c] + extrude);
+            max.makeCeil(corners[c] + extrude);
+        }
+        aabb.setExtents(min, max);
+
+        if (!mShadowCasterAABBQuery)
+            mShadowCasterAABBQuery = createAABBQuery(aabb);
+        else
+            mShadowCasterAABBQuery->setBox(aabb);
+        // Execute, use callback
+        mShadowCasterQueryListener->prepare(false, 
+            &(light->_getFrustumClipVolumes(camera)), 
+            light, camera, &mShadowCasterList, mShadowFarDistSquared);
+        mShadowCasterAABBQuery->execute(mShadowCasterQueryListener);
+
+
+    }
+    else
+    {
+        Sphere s(light->getPosition(), light->getAttenuationRange());
+        // eliminate early if camera cannot see light sphere
+        if (camera->isVisible(s))
+        {
+            if (!mShadowCasterSphereQuery)
+                mShadowCasterSphereQuery = createSphereQuery(s);
+            else
+                mShadowCasterSphereQuery->setSphere(s);
+
+            // Determine if light is inside or outside the frustum
+            bool lightInFrustum = camera->isVisible(light->getDerivedPosition());
+            const PlaneBoundedVolumeList* volList = 0;
+            if (!lightInFrustum)
+            {
+                // Only worth building an external volume list if
+                // light is outside the frustum
+                volList = &(light->_getFrustumClipVolumes(camera));
+            }
+
+            // Execute, use callback
+            mShadowCasterQueryListener->prepare(lightInFrustum, 
+                volList, light, camera, &mShadowCasterList, mShadowFarDistSquared);
+            mShadowCasterSphereQuery->execute(mShadowCasterQueryListener);
+
+        }
+
+    }
+
+
+    return mShadowCasterList;
+}
+//---------------------------------------------------------------------
+void SceneManager::initShadowVolumeMaterials(void)
+{
+    /* This should have been set in the SceneManager constructor, but if you
+       created the SceneManager BEFORE the Root object, you will need to call
+       SceneManager::_setDestinationRenderSystem manually.
+     */
+    assert( mDestRenderSystem );
+
+    if (mShadowMaterialInitDone)
+        return;
+
+    if (!mShadowDebugPass)
+    {
+        MaterialPtr matDebug = 
+            MaterialManager::getSingleton().getByName("Ogre/Debug/ShadowVolumes");
+        if (matDebug.isNull())
+        {
+            // Create
+            matDebug = MaterialManager::getSingleton().create(
+                "Ogre/Debug/ShadowVolumes", 
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
+            mShadowDebugPass->setSceneBlending(SBT_ADD); 
+            mShadowDebugPass->setLightingEnabled(false);
+            mShadowDebugPass->setDepthWriteEnabled(false);
+            TextureUnitState* t = mShadowDebugPass->createTextureUnitState();
+            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, 
+                ColourValue(0.7, 0.0, 0.2));
+            mShadowDebugPass->setCullingMode(CULL_NONE);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(
+                RSC_VERTEX_PROGRAM))
+            {
+                ShadowVolumeExtrudeProgram::initialise();
+
+                // Enable the (infinite) point light extruder for now, just to get some params
+                mShadowDebugPass->setVertexProgram(
+                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT]);
+                mInfiniteExtrusionParams = 
+                    mShadowDebugPass->getVertexProgramParameters();
+                mInfiniteExtrusionParams->setAutoConstant(0, 
+                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+                mInfiniteExtrusionParams->setAutoConstant(4, 
+                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
+            }	
+            matDebug->compile();
+
+        }
+        else
+        {
+            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
+        }
+    }
+
+    if (!mShadowStencilPass)
+    {
+
+        MaterialPtr matStencil = MaterialManager::getSingleton().getByName(
+            "Ogre/StencilShadowVolumes");
+        if (matStencil.isNull())
+        {
+            // Init
+            matStencil = MaterialManager::getSingleton().create(
+                "Ogre/StencilShadowVolumes",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(
+                RSC_VERTEX_PROGRAM))
+            {
+
+                // Enable the finite point light extruder for now, just to get some params
+                mShadowStencilPass->setVertexProgram(
+                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT_FINITE]);
+                mFiniteExtrusionParams = 
+                    mShadowStencilPass->getVertexProgramParameters();
+                mFiniteExtrusionParams->setAutoConstant(0, 
+                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
+                mFiniteExtrusionParams->setAutoConstant(4, 
+                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
+                // Note extra parameter
+                mFiniteExtrusionParams->setAutoConstant(5, 
+                    GpuProgramParameters::ACT_SHADOW_EXTRUSION_DISTANCE);
+            }
+            matStencil->compile();
+            // Nothing else, we don't use this like a 'real' pass anyway,
+            // it's more of a placeholder
+        }
+        else
+        {
+            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
+        }
+    }
+
+
+
+
+    if (!mShadowModulativePass)
+    {
+
+        MaterialPtr matModStencil = MaterialManager::getSingleton().getByName(
+            "Ogre/StencilShadowModulationPass");
+        if (matModStencil.isNull())
+        {
+            // Init
+            matModStencil = MaterialManager::getSingleton().create(
+                "Ogre/StencilShadowModulationPass",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
+            mShadowModulativePass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO); 
+            mShadowModulativePass->setLightingEnabled(false);
+            mShadowModulativePass->setDepthWriteEnabled(false);
+            mShadowModulativePass->setDepthCheckEnabled(false);
+            TextureUnitState* t = mShadowModulativePass->createTextureUnitState();
+            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, 
+                mShadowColour);
+            mShadowModulativePass->setCullingMode(CULL_NONE);
+        }
+        else
+        {
+            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
+        }
+    }
+
+    // Also init full screen quad while we're at it
+    if (!mFullScreenQuad)
+    {
+        mFullScreenQuad = new Rectangle2D();
+        mFullScreenQuad->setCorners(-1,1,1,-1);
+    }
+
+    // Also init shadow caster material for texture shadows
+    if (!mShadowCasterPlainBlackPass)
+    {
+        MaterialPtr matPlainBlack = MaterialManager::getSingleton().getByName(
+            "Ogre/TextureShadowCaster");
+        if (matPlainBlack.isNull())
+        {
+            matPlainBlack = MaterialManager::getSingleton().create(
+                "Ogre/TextureShadowCaster",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
+            // Lighting has to be on, because we need shadow coloured objects
+            // Note that because we can't predict vertex programs, we'll have to
+            // bind light values to those, and so we bind White to ambient
+            // reflectance, and we'll set the ambient colour to the shadow colour
+            mShadowCasterPlainBlackPass->setAmbient(ColourValue::White);
+            mShadowCasterPlainBlackPass->setDiffuse(ColourValue::Black);
+            mShadowCasterPlainBlackPass->setSelfIllumination(ColourValue::Black);
+            mShadowCasterPlainBlackPass->setSpecular(ColourValue::Black);
+			// Override fog
+			mShadowCasterPlainBlackPass->setFog(true, FOG_NONE);
+            // no textures or anything else, we will bind vertex programs
+            // every so often though
+        }
+        else
+        {
+            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
+        }
+    }
+
+    if (!mShadowReceiverPass)
+    {
+        MaterialPtr matShadRec = MaterialManager::getSingleton().getByName(
+            "Ogre/TextureShadowReceiver");
+        if (matShadRec.isNull())			
+        {
+            matShadRec = MaterialManager::getSingleton().create(
+                "Ogre/TextureShadowReceiver",
+                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
+            mShadowReceiverPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
+            // No lighting, one texture unit 
+            // everything else will be bound as needed during the receiver pass
+            mShadowReceiverPass->setLightingEnabled(false);
+            TextureUnitState* t = mShadowReceiverPass->createTextureUnitState();
+            t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+        }
+        else
+        {
+            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
+        }
+    }
+
+    // Set up spot shadow fade texture (loaded from code data block)
+    TexturePtr spotShadowFadeTex = 
+        TextureManager::getSingleton().getByName("spot_shadow_fade.png");
+    if (spotShadowFadeTex.isNull())
+    {
+        // Load the manual buffer into an image (don't destroy memory!
+        DataStreamPtr stream(
+			new MemoryDataStream(SPOT_SHADOW_FADE_PNG, SPOT_SHADOW_FADE_PNG_SIZE, false));
+        Image img;
+        img.load(stream, "png");
+        spotShadowFadeTex = 
+            TextureManager::getSingleton().loadImage(
+			"spot_shadow_fade.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
+			img, TEX_TYPE_2D);
+    }
+
+    mShadowMaterialInitDone = true;
+}
+//---------------------------------------------------------------------
+Pass* SceneManager::deriveShadowCasterPass(Pass* pass)
+{
+    switch (mShadowTechnique)
+    {
+    case SHADOWTYPE_TEXTURE_MODULATIVE:
+		if (mShadowTextureCustomCasterPass)
+		{
+			// Caster pass has been customised
+
+			if (!pass->getShadowCasterVertexProgramName().empty())
+			{
+				// Have to merge the shadow caster vertex program in
+				mShadowTextureCustomCasterPass->setVertexProgram(
+					pass->getShadowCasterVertexProgramName());
+				const GpuProgramPtr& prg = mShadowTextureCustomCasterPass->getVertexProgram();
+				// Load this program if not done already
+				if (!prg->isLoaded())
+					prg->load();
+				// Copy params
+				mShadowTextureCustomCasterPass->setVertexProgramParameters(
+					pass->getShadowCasterVertexProgramParameters());
+				// mark that we've overridden the standard
+				mShadowTextureCasterVPDirty = true;
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowTextureCasterVPDirty)
+			{
+				// reset
+				mShadowTextureCustomCasterPass->setVertexProgram(
+					mShadowTextureCustomCasterVertexProgram);
+				if(mShadowTextureCustomCasterPass->hasVertexProgram())
+				{
+					mShadowTextureCustomCasterPass->setVertexProgramParameters(
+						mShadowTextureCustomCasterVPParams);
+
+				}
+				mShadowTextureCasterVPDirty = false;
+			}
+			return mShadowTextureCustomCasterPass;
+		}
+		else
+		{
+			// Standard pass
+			if (pass->hasVertexProgram())
+			{
+				// Have to merge the shadow caster vertex program in
+				// This may in fact be blank, in which case it falls back on 
+				// fixed function
+				mShadowCasterPlainBlackPass->setVertexProgram(
+					pass->getShadowCasterVertexProgramName());
+				// Did this result in a new vertex program?
+				if (mShadowCasterPlainBlackPass->hasVertexProgram())
+				{
+					const GpuProgramPtr& prg = mShadowCasterPlainBlackPass->getVertexProgram();
+					// Load this program if not done already
+					if (!prg->isLoaded())
+						prg->load();
+					// Copy params
+					mShadowCasterPlainBlackPass->setVertexProgramParameters(
+						pass->getShadowCasterVertexProgramParameters());
+				}
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowCasterPlainBlackPass->hasVertexProgram())
+			{
+				// reset
+				mShadowCasterPlainBlackPass->setVertexProgram("");
+			}
+			return mShadowCasterPlainBlackPass;
+		}
+    default:
+        return pass;
+    };
+
+}
+//---------------------------------------------------------------------
+Pass* SceneManager::deriveShadowReceiverPass(Pass* pass)
+{
+
+    switch (mShadowTechnique)
+    {
+    case SHADOWTYPE_TEXTURE_MODULATIVE:
+		if (mShadowTextureCustomReceiverPass)
+		{
+			// Receiver pass has been customised
+
+			if (!pass->getShadowReceiverVertexProgramName().empty())
+			{
+				// Have to merge the shadow Receiver vertex program in
+				mShadowTextureCustomReceiverPass->setVertexProgram(
+					pass->getShadowReceiverVertexProgramName());
+				const GpuProgramPtr& prg = mShadowTextureCustomReceiverPass->getVertexProgram();
+				// Load this program if not done already
+				if (!prg->isLoaded())
+					prg->load();
+				// Copy params
+				mShadowTextureCustomReceiverPass->setVertexProgramParameters(
+					pass->getShadowReceiverVertexProgramParameters());
+				// mark that we've overridden the standard
+				mShadowTextureReceiverVPDirty = true;
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowTextureReceiverVPDirty)
+			{
+				// reset
+				mShadowTextureCustomReceiverPass->setVertexProgram(
+					mShadowTextureCustomReceiverVertexProgram);
+				if(mShadowTextureCustomReceiverPass->hasVertexProgram())
+				{
+					mShadowTextureCustomReceiverPass->setVertexProgramParameters(
+						mShadowTextureCustomReceiverVPParams);
+
+				}
+				mShadowTextureReceiverVPDirty = false;
+			}
+			return mShadowTextureCustomReceiverPass;
+		}
+		else
+		{
+			if (pass->hasVertexProgram())
+			{
+				// Have to merge the receiver vertex program in
+				// This may return "" which means fixed function will be used
+				mShadowReceiverPass->setVertexProgram(
+					pass->getShadowReceiverVertexProgramName());
+				// Did this result in a new vertex program?
+				if (mShadowReceiverPass->hasVertexProgram())
+				{
+					const GpuProgramPtr& prg = mShadowReceiverPass->getVertexProgram();
+					// Load this program if required
+					if (!prg->isLoaded())
+						prg->load();
+					// Copy params
+					mShadowReceiverPass->setVertexProgramParameters(
+						pass->getShadowReceiverVertexProgramParameters());
+				}
+				// Also have to hack the light autoparams, that is done later
+			}
+			else if (mShadowReceiverPass->hasVertexProgram())
+			{
+				// reset
+				mShadowReceiverPass->setVertexProgram("");
+
+			}
+		}
+
+        return mShadowReceiverPass;
+    default:
+        return pass;
+    };
+
+}
+//---------------------------------------------------------------------
+void SceneManager::renderShadowVolumesToStencil(const Light* light, const Camera* camera)
+{
+    // Get the shadow caster list
+    const ShadowCasterList& casters = findShadowCastersForLight(light, camera);
+    // Check there are some shadow casters to render
+    if (casters.empty())
+    {
+        // No casters, just do nothing
+        return;
+    }
+
+    // Set up scissor test (point & spot lights only)
+    bool scissored = false;
+    if (light->getType() != Light::LT_DIRECTIONAL && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_SCISSOR_TEST))
+    {
+        // Project the sphere onto the camera
+        Real left, right, top, bottom;
+        Sphere sphere(light->getDerivedPosition(), light->getAttenuationRange());
+        if (camera->projectSphere(sphere, &left, &top, &right, &bottom))
+        {
+            scissored = true;
+            // Turn normalised device coordinates into pixels
+            int iLeft, iTop, iWidth, iHeight;
+            mCurrentViewport->getActualDimensions(iLeft, iTop, iWidth, iHeight);
+            size_t szLeft, szRight, szTop, szBottom;
+
+            szLeft = (size_t)(iLeft + ((left + 1) * 0.5 * iWidth));
+            szRight = (size_t)(iLeft + ((right + 1) * 0.5 * iWidth));
+            szTop = (size_t)(iTop + ((-top + 1) * 0.5 * iHeight));
+            szBottom = (size_t)(iTop + ((-bottom + 1) * 0.5 * iHeight));
+
+            mDestRenderSystem->setScissorTest(true, szLeft, szTop, szRight, szBottom);
+        }
+    }
+
+    mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+
+    // Can we do a 2-sided stencil?
+    bool stencil2sided = false;
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_TWO_SIDED_STENCIL) && 
+        mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
+    {
+        // enable
+        stencil2sided = true;
+    }
+
+    // Do we have access to vertex programs?
+    bool extrudeInSoftware = true;
+    bool finiteExtrude = !mShadowUseInfiniteFarPlane || 
+        !mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE);
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
+    {
+        extrudeInSoftware = false;
+        // attach the appropriate extrusion vertex program
+        // Note we never unset it because support for vertex programs is constant
+        mShadowStencilPass->setVertexProgram(
+            ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, false)
+            , false);
+        // Set params
+        if (finiteExtrude)
+        {
+            mShadowStencilPass->setVertexProgramParameters(mFiniteExtrusionParams);
+        }
+        else
+        {
+            mShadowStencilPass->setVertexProgramParameters(mInfiniteExtrusionParams);
+        }
+        if (mDebugShadows)
+        {
+            mShadowDebugPass->setVertexProgram(
+                ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, true)
+                , false);
+            // Set params
+            if (finiteExtrude)
+            {
+                mShadowDebugPass->setVertexProgramParameters(mFiniteExtrusionParams);
+            }
+            else
+            {
+                mShadowDebugPass->setVertexProgramParameters(mInfiniteExtrusionParams);
+            }
+        }
+
+        mDestRenderSystem->bindGpuProgram(mShadowStencilPass->getVertexProgram()->_getBindingDelegate());
+
+    }
+    else
+    {
+        mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+    }
+
+    // Add light to internal list for use in render call
+    LightList lightList;
+    // const_cast is forgiveable here since we pass this const
+    lightList.push_back(const_cast<Light*>(light));
+
+    // Turn off colour writing and depth writing
+    mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
+	mDestRenderSystem->_disableTextureUnitsFrom(0);
+    mDestRenderSystem->_setDepthBufferParams(true, false, CMPF_LESS);
+    mDestRenderSystem->setStencilCheckEnabled(true);
+
+    // Calculate extrusion distance
+    // Use direction light extrusion distance now, just form optimize code
+    // generate a little, point/spot light will up to date later
+    Real extrudeDist = mShadowDirLightExtrudeDist;
+
+    // Figure out the near clip volume
+    const PlaneBoundedVolume& nearClipVol = 
+        light->_getNearClipVolume(camera);
+
+    // Now iterate over the casters and render
+    ShadowCasterList::const_iterator si, siend;
+    siend = casters.end();
+
+
+	// Now iterate over the casters and render
+	for (si = casters.begin(); si != siend; ++si)
+	{
+        ShadowCaster* caster = *si;
+		bool zfailAlgo = false;
+		unsigned long flags = 0;
+
+        if (light->getType() != Light::LT_DIRECTIONAL)
+        {
+            extrudeDist = caster->getPointExtrusionDistance(light); 
+        }
+
+        if (!extrudeInSoftware && !finiteExtrude)
+        {
+            // hardware extrusion, to infinity (and beyond!)
+            flags |= SRF_EXTRUDE_TO_INFINITY;
+        }
+
+		// Determine whether zfail is required
+        if (nearClipVol.intersects(caster->getWorldBoundingBox()))
+        {
+            // We use zfail for this object only because zfail
+	        // compatible with zpass algorithm
+			zfailAlgo = true;
+            // We need to include the light and / or dark cap
+            // But only if they will be visible
+            if(camera->isVisible(caster->getLightCapBounds()))
+            {
+                flags |= SRF_INCLUDE_LIGHT_CAP;
+            }
+			// zfail needs dark cap 
+			// UNLESS directional lights using hardware extrusion to infinity
+			// since that extrudes to a single point
+			if(!((flags & SRF_EXTRUDE_TO_INFINITY) && 
+				light->getType() == Light::LT_DIRECTIONAL) &&
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+        }
+		else
+		{
+			// In zpass we need a dark cap if
+			// 1: infinite extrusion on point/spotlight sources in modulative shadows
+			//    mode, since otherwise in areas where there is no depth (skybox)
+			//    the infinitely projected volume will leave a dark band
+			// 2: finite extrusion on any light source since glancing angles
+			//    can peek through the end and shadow objects behind incorrectly
+			if ((flags & SRF_EXTRUDE_TO_INFINITY) && 
+				light->getType() != Light::LT_DIRECTIONAL && 
+				mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE && 
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+			else if (!(flags & SRF_EXTRUDE_TO_INFINITY) && 
+				camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
+			{
+				flags |= SRF_INCLUDE_DARK_CAP;
+			}
+
+		}
+
+        // Get shadow renderables			
+        ShadowCaster::ShadowRenderableListIterator iShadowRenderables =
+            caster->getShadowVolumeRenderableIterator(mShadowTechnique,
+            light, &mShadowIndexBuffer, extrudeInSoftware, 
+            extrudeDist, flags);
+
+        // Render a shadow volume here
+        //  - if we have 2-sided stencil, one render with no culling
+        //  - otherwise, 2 renders, one with each culling method and invert the ops
+        setShadowVolumeStencilState(false, zfailAlgo, stencil2sided);
+        renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
+            false, zfailAlgo, stencil2sided);
+        if (!stencil2sided)
+        {
+            // Second pass
+            setShadowVolumeStencilState(true, zfailAlgo, false);
+            renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
+                true, zfailAlgo, false);
+        }
+
+        // Do we need to render a debug shadow marker?
+        if (mDebugShadows)
+        {
+            // reset stencil & colour ops
+            mDestRenderSystem->setStencilBufferParams();
+            mShadowDebugPass->getTextureUnitState(0)->
+                setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
+                zfailAlgo ? ColourValue(0.7, 0.0, 0.2) : ColourValue(0.0, 0.7, 0.2));
+            setPass(mShadowDebugPass);
+            renderShadowVolumeObjects(iShadowRenderables, mShadowDebugPass, &lightList, flags,
+                true, false, false);
+            mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
+            mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+        }
+    }
+
+    // revert colour write state
+    mDestRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
+    // revert depth state
+    mDestRenderSystem->_setDepthBufferParams();
+
+    mDestRenderSystem->setStencilCheckEnabled(false);
+
+    mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+
+    if (scissored)
+    {
+        // disable scissor test
+        mDestRenderSystem->setScissorTest(false);
+    }
+
+}
+//---------------------------------------------------------------------
+void SceneManager::renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
+                                             Pass* pass,
+                                             const LightList *manualLightList,
+                                             unsigned long flags,
+                                             bool secondpass, bool zfail, bool twosided)
+{
+    // ----- SHADOW VOLUME LOOP -----
+    // Render all shadow renderables with same stencil operations
+    while (iShadowRenderables.hasMoreElements())
+    {
+        ShadowRenderable* sr = iShadowRenderables.getNext();
+
+        // omit hidden renderables
+        if (sr->isVisible())
+        {
+            // render volume, including dark and (maybe) light caps
+            renderSingleObject(sr, pass, false, manualLightList);
+
+            // optionally render separate light cap
+            if (sr->isLightCapSeparate() && (flags & SRF_INCLUDE_LIGHT_CAP))
+            {
+                ShadowRenderable* lightCap = sr->getLightCapRenderable();
+                assert(lightCap && "Shadow renderable is missing a separate light cap renderable!");
+
+                // We must take care with light caps when we could 'see' the back facing
+                // triangles directly:
+                //   1. The front facing light caps must render as always fail depth
+                //      check to avoid 'depth fighting'.
+                //   2. The back facing light caps must use normal depth function to
+                //      avoid break the standard depth check
+                //
+                // TODO:
+                //   1. Separate light caps rendering doesn't need for the 'closed'
+                //      mesh that never touch the near plane, because in this instance,
+                //      we couldn't 'see' any back facing triangles directly. The
+                //      'closed' mesh must determinate by edge list builder.
+                //   2. There still exists 'depth fighting' bug with coplane triangles
+                //      that has opposite facing. This usually occur when use two side
+                //      material in the modeling tools and the model exporting tools
+                //      exporting double triangles to represent this model. This bug
+                //      can't fixed in GPU only, there must has extra work on edge list
+                //      builder and shadow volume generater to fix it.
+                //
+                if (twosided)
+                {
+                    // select back facing light caps to render
+                    mDestRenderSystem->_setCullingMode(CULL_ANTICLOCKWISE);
+                    // use normal depth function for back facing light caps
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // select front facing light caps to render
+                    mDestRenderSystem->_setCullingMode(CULL_CLOCKWISE);
+                    // must always fail depth check for front facing light caps
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // reset depth function
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+                    // reset culling mode
+                    mDestRenderSystem->_setCullingMode(CULL_NONE);
+                }
+                else if ((secondpass || zfail) && !(secondpass && zfail))
+                {
+                    // use normal depth function for back facing light caps
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+                }
+                else
+                {
+                    // must always fail depth check for front facing light caps
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
+                    renderSingleObject(lightCap, pass, false, manualLightList);
+
+                    // reset depth function
+                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
+                }
+            }
+        }
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided)
+{
+    // Determinate the best stencil operation
+    StencilOperation incrOp, decrOp;
+    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
+    {
+        incrOp = SOP_INCREMENT_WRAP;
+        decrOp = SOP_DECREMENT_WRAP;
+    }
+    else
+    {
+        incrOp = SOP_INCREMENT;
+        decrOp = SOP_DECREMENT;
+    }
+
+    // First pass, do front faces if zpass
+    // Second pass, do back faces if zpass
+    // Invert if zfail
+    // this is to ensure we always increment before decrement
+    // When two-sided stencil, always pass front face stencil
+    // operation parameters and the inverse of them will happen
+    // for back faces
+    if ( !twosided && ((secondpass || zfail) && !(secondpass && zfail)) )
+    {
+        mDestRenderSystem->_setCullingMode(
+            twosided? CULL_NONE : CULL_ANTICLOCKWISE);
+        mDestRenderSystem->setStencilBufferParams(
+            CMPF_ALWAYS_PASS, // always pass stencil check
+            0, // no ref value (no compare)
+            0xFFFFFFFF, // no mask
+            SOP_KEEP, // stencil test will never fail
+            zfail ? incrOp : SOP_KEEP, // back face depth fail
+            zfail ? SOP_KEEP : decrOp, // back face pass
+            twosided
+            );
+    }
+    else
+    {
+        mDestRenderSystem->_setCullingMode(
+            twosided? CULL_NONE : CULL_CLOCKWISE);
+        mDestRenderSystem->setStencilBufferParams(
+            CMPF_ALWAYS_PASS, // always pass stencil check
+            0, // no ref value (no compare)
+            0xFFFFFFFF, // no mask
+            SOP_KEEP, // stencil test will never fail
+            zfail ? decrOp : SOP_KEEP, // front face depth fail
+            zfail ? SOP_KEEP : incrOp, // front face pass
+            twosided
+            );
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowColour(const ColourValue& colour)
+{
+    mShadowColour = colour;
+
+    // Prep materials first
+    initShadowVolumeMaterials();
+
+    mShadowModulativePass->getTextureUnitState(0)->setColourOperationEx(
+        LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, colour);
+}
+//---------------------------------------------------------------------
+const ColourValue& SceneManager::getShadowColour(void) const
+{
+    return mShadowColour;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowFarDistance(Real distance)
+{
+    mShadowFarDist = distance;
+    mShadowFarDistSquared = distance * distance;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowDirectionalLightExtrusionDistance(Real dist)
+{
+    mShadowDirLightExtrudeDist = dist;
+}
+//---------------------------------------------------------------------
+Real SceneManager::getShadowDirectionalLightExtrusionDistance(void) const
+{
+    return mShadowDirLightExtrudeDist;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowIndexBufferSize(size_t size)
+{
+    if (!mShadowIndexBuffer.isNull() && size != mShadowIndexBufferSize)
+    {
+        // re-create shadow buffer with new size
+        mShadowIndexBuffer = HardwareBufferManager::getSingleton().
+            createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 
+            mShadowIndexBufferSize, 
+            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
+            false);
+    }
+    mShadowIndexBufferSize = size;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureSize(unsigned short size)
+{
+    // possibly recreate
+    createShadowTextures(size, mShadowTextureCount, mShadowTextureFormat);
+    mShadowTextureSize = size;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureCount(unsigned short count)
+{
+    // possibly recreate
+    createShadowTextures(mShadowTextureSize, count, mShadowTextureFormat);
+    mShadowTextureCount = count;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTexturePixelFormat(PixelFormat fmt)
+{
+	// possibly recreate
+	createShadowTextures(mShadowTextureSize, mShadowTextureCount, fmt);
+	mShadowTextureFormat = fmt;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureSettings(unsigned short size, 
+	unsigned short count, PixelFormat fmt)
+{
+    if (!mShadowTextures.empty() && 
+        (count != mShadowTextureCount ||
+        size != mShadowTextureSize ||
+		fmt != mShadowTextureFormat))
+    {
+        // recreate
+        createShadowTextures(size, count, fmt);
+    }
+    mShadowTextureCount = count;
+    mShadowTextureSize = size;
+	mShadowTextureFormat = fmt;
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureCasterMaterial(const String& name)
+{
+	if (name.empty())
+	{
+		mShadowTextureCustomCasterPass = 0;
+	}
+	else
+	{
+		MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
+		if (mat.isNull())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+				"Cannot locate material called '" + name + "'", 
+				"SceneManager::setShadowTextureCasterMaterial");
+		}
+		mat->load();
+		mShadowTextureCustomCasterPass = mat->getBestTechnique()->getPass(0);
+		if (mShadowTextureCustomCasterPass->hasVertexProgram())
+		{
+			// Save vertex program and params in case we have to swap them out
+			mShadowTextureCustomCasterVertexProgram = 
+				mShadowTextureCustomCasterPass->getVertexProgramName();
+			mShadowTextureCustomCasterVPParams = 
+				mShadowTextureCustomCasterPass->getVertexProgramParameters();
+			mShadowTextureCasterVPDirty = false;
+
+		}
+	}
+}
+//---------------------------------------------------------------------
+void SceneManager::setShadowTextureReceiverMaterial(const String& name)
+{
+	if (name.empty())
+	{
+		mShadowTextureCustomReceiverPass = 0;
+	}
+	else
+	{
+		MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
+		if (mat.isNull())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+				"Cannot locate material called '" + name + "'", 
+				"SceneManager::setShadowTextureReceiverMaterial");
+		}
+		mat->load();
+		mShadowTextureCustomReceiverPass = mat->getBestTechnique()->getPass(0);
+		if (mShadowTextureCustomReceiverPass->hasVertexProgram())
+		{
+			// Save vertex program and params in case we have to swap them out
+			mShadowTextureCustomReceiverVertexProgram = 
+				mShadowTextureCustomReceiverPass->getVertexProgramName();
+			mShadowTextureCustomReceiverVPParams = 
+				mShadowTextureCustomReceiverPass->getVertexProgramParameters();
+			mShadowTextureReceiverVPDirty = false;
+
+		}
+	}
+}
+//---------------------------------------------------------------------
+void SceneManager::createShadowTextures(unsigned short size,
+	unsigned short count, PixelFormat fmt)
+{
+    static const String baseName = "Ogre/ShadowTexture";
+
+    if (mShadowTechnique != SHADOWTYPE_TEXTURE_MODULATIVE ||
+        !mShadowTextures.empty() && 
+        count == mShadowTextureCount &&
+        size == mShadowTextureSize && 
+		fmt == mShadowTextureFormat)
+    {
+        // no change
+        return;
+    }
+
+
+    // destroy existing
+    ShadowTextureList::iterator i, iend;
+    iend = mShadowTextures.end();
+    for (i = mShadowTextures.begin(); i != iend; ++i)
+    {
+        RenderTexture* r = *i;
+        // remove camera and destroy texture
+        removeCamera(r->getViewport(0)->getCamera());
+        mDestRenderSystem->destroyRenderTexture(r->getName());
+    }
+    mShadowTextures.clear();
+
+    // Recreate shadow textures
+    for (unsigned short t = 0; t < count; ++t)
+    {
+        String targName = baseName + StringConverter::toString(t);
+        String matName = baseName + "Mat" + StringConverter::toString(t);
+        String camName = baseName + "Cam" + StringConverter::toString(t);
+
+        RenderTexture* shadowTex;
+        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+        {
+            shadowTex = mDestRenderSystem->createRenderTexture( 
+                targName, size, size, TEX_TYPE_2D, mShadowTextureFormat);
+        }
+
+        // Create a camera to go with this texture
+        Camera* cam = createCamera(camName);
+        cam->setAspectRatio(1.0f);
+        // Create a viewport
+        Viewport *v = shadowTex->addViewport(cam);
+        v->setClearEveryFrame(true);
+        // remove overlays
+        v->setOverlaysEnabled(false);
+        // Don't update automatically - we'll do it when required
+        shadowTex->setAutoUpdated(false);
+        mShadowTextures.push_back(shadowTex);
+
+        // Also create corresponding Material used for rendering this shadow
+        MaterialPtr mat = MaterialManager::getSingleton().getByName(matName);
+        if (mat.isNull())
+        {
+            mat = MaterialManager::getSingleton().create(
+                matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+        }
+        else
+        {
+            mat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
+        }
+        // create texture unit referring to render target texture
+        TextureUnitState* texUnit = 
+            mat->getTechnique(0)->getPass(0)->createTextureUnitState(targName);
+        // set projective based on camera
+        texUnit->setProjectiveTexturing(true, cam);
+        texUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
+        mat->touch();
+
+    }
+}
+//---------------------------------------------------------------------
+void SceneManager::prepareShadowTextures(Camera* cam, Viewport* vp)
+{
+    // Set the illumination stage, prevents recursive calls
+    IlluminationRenderStage savedStage = mIlluminationStage;
+    mIlluminationStage = IRS_RENDER_TO_TEXTURE;
+
+    // Determine far shadow distance
+    Real shadowDist = mShadowFarDist;
+    if (!shadowDist)
+    {
+        // need a shadow distance, make one up
+        shadowDist = cam->getNearClipDistance() * 300;
+    }
+    // set fogging to hide the shadow edge
+    Real shadowOffset = shadowDist * mShadowTextureOffset;
+    Real shadowEnd = shadowDist + shadowOffset;
+    mShadowReceiverPass->setFog(true, FOG_LINEAR, ColourValue::White, 
+        0, shadowEnd * mShadowTextureFadeStart, shadowEnd * mShadowTextureFadeEnd);
+
+    // Iterate over the lights we've found, max out at the limit of light textures
+
+    LightList::iterator i, iend;
+    ShadowTextureList::iterator si, siend;
+    iend = mLightsAffectingFrustum.end();
+    siend = mShadowTextures.end();
+    for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
+        i != iend && si != siend; ++i)
+    {
+        Light* light = *i;
+        RenderTexture* shadowTex = *si;
+        // Skip non-shadowing lights
+        if (!light->getCastShadows())
+            continue;
+
+        // Directional lights 
+        if (light->getType() == Light::LT_DIRECTIONAL)
+        {
+
+            // set up the shadow texture
+            Camera* texCam = shadowTex->getViewport(0)->getCamera();
+            // Set ortho projection
+            texCam->setProjectionType(PT_ORTHOGRAPHIC);
+            // set easy FOV and near dist so that texture covers far dist
+            texCam->setFOVy(Degree(90));
+            texCam->setNearClipDistance(shadowDist);
+
+            // Set size of projection
+
+            // Calculate look at position
+            // We want to look at a spot shadowOffset away from near plane
+            // 0.5 is a litle too close for angles
+            Vector3 target = cam->getDerivedPosition() + 
+                (cam->getDerivedDirection() * shadowOffset);
+
+            // Calculate position
+            // We want to be in the -ve direction of the light direction
+            // far enough to project for the dir light extrusion distance
+            Vector3 pos = target + 
+                (light->getDerivedDirection() * -mShadowDirLightExtrudeDist);
+
+            // Calculate orientation
+            Vector3 dir = (pos - target); // backwards since point down -z
+            dir.normalise();
+            /*
+            // Next section (camera oriented shadow map) abandoned
+            // Always point in the same direction, if we don't do this then
+            // we get 'shadow swimming' as camera rotates
+            // As it is, we get swimming on moving but this is less noticeable
+
+            // calculate up vector, we want it aligned with cam direction
+            Vector3 up = cam->getDerivedDirection();
+            // Check it's not coincident with dir
+            if (up.dotProduct(dir) >= 1.0f)
+            {
+            // Use camera up
+            up = cam->getUp();
+            }
+            */
+            Vector3 up = Vector3::UNIT_Y;
+            // Check it's not coincident with dir
+            if (up.dotProduct(dir) >= 1.0f)
+            {
+                // Use camera up
+                up = Vector3::UNIT_Z;
+            }
+            // cross twice to rederive, only direction is unaltered
+            Vector3 left = dir.crossProduct(up);
+            left.normalise();
+            up = dir.crossProduct(left);
+            up.normalise();
+            // Derive quaternion from axes
+            Quaternion q;
+            q.FromAxes(left, up, dir);
+            texCam->setOrientation(q);
+
+            // Round local x/y position based on a world-space texel; this helps to reduce
+            // jittering caused by the projection moving with the camera
+            // Viewport is 2 * near clip distance across (90 degree fov)
+            Real worldTexelSize = (texCam->getNearClipDistance() * 20) / mShadowTextureSize;
+            pos.x -= fmod(pos.x, worldTexelSize);
+            pos.y -= fmod(pos.y, worldTexelSize);
+            pos.z -= fmod(pos.z, worldTexelSize);
+            // Finally set position
+            texCam->setPosition(pos);
+
+            if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+                shadowTex->getViewport(0)->setBackgroundColour(ColourValue::White);
+
+            // Update target
+            shadowTex->update();
+
+            ++si;
+        }
+        // Spotlight
+        else if (light->getType() == Light::LT_SPOTLIGHT)
+        {
+
+            // set up the shadow texture
+            Camera* texCam = shadowTex->getViewport(0)->getCamera();
+            // Set perspective projection
+            texCam->setProjectionType(PT_PERSPECTIVE);
+            // set FOV slightly larger than the spotlight range to ensure coverage
+            texCam->setFOVy(light->getSpotlightOuterAngle()*1.2);
+            texCam->setPosition(light->getDerivedPosition());
+            texCam->setDirection(light->getDerivedDirection());
+            // set near clip the same as main camera, since they are likely
+            // to both reflect the nature of the scene
+            texCam->setNearClipDistance(cam->getNearClipDistance());
+
+            if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE)
+                shadowTex->getViewport(0)->setBackgroundColour(ColourValue::White);
+
+            // Update target
+            shadowTex->update();
+
+            ++si;
+        }
+    }
+    // Set the illumination stage, prevents recursive calls
+    mIlluminationStage = savedStage;
+}
+//---------------------------------------------------------------------
+StaticGeometry* SceneManager::createStaticGeometry(const String& name)
+{
+	// Check not existing
+	if (mStaticGeometryList.find(name) != mStaticGeometryList.end())
+	{
+		OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
+			"StaticGeometry with name '" + name + "' already exists!", 
+			"SceneManager::createStaticGeometry");
+	}
+	StaticGeometry* ret = new StaticGeometry(this, name);
+	mStaticGeometryList[name] = ret;
+	return ret;
+}
+//---------------------------------------------------------------------
+StaticGeometry* SceneManager::getStaticGeometry(const String& name) const
+{
+	StaticGeometryList::const_iterator i = mStaticGeometryList.find(name);
+	if (i == mStaticGeometryList.end())
+	{
+		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+			"StaticGeometry with name '" + name + "' not found", 
+			"SceneManager::createStaticGeometry");
+	}
+	return i->second;
+}
+//---------------------------------------------------------------------
+void SceneManager::removeStaticGeometry(StaticGeometry* geom)
+{
+	removeStaticGeometry(geom->getName());
+}
+//---------------------------------------------------------------------
+void SceneManager::removeStaticGeometry(const String& name)
+{
+	StaticGeometryList::iterator i = mStaticGeometryList.find(name);
+	if (i != mStaticGeometryList.end())
+	{
+		delete i->second;
+		mStaticGeometryList.erase(i);
+	}
+
+}
+//---------------------------------------------------------------------
+void SceneManager::removeAllStaticGeometry(void)
+{
+	StaticGeometryList::iterator i, iend;
+	iend = mStaticGeometryList.end();
+	for (i = mStaticGeometryList.begin(); i != iend; ++i)
+	{
+		delete i->second;
+	}
+	mStaticGeometryList.clear();
+}
+//---------------------------------------------------------------------
+AxisAlignedBoxSceneQuery* 
+SceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
+{
+    DefaultAxisAlignedBoxSceneQuery* q = new DefaultAxisAlignedBoxSceneQuery(this);
+    q->setBox(box);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+SphereSceneQuery* 
+SceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
+{
+    DefaultSphereSceneQuery* q = new DefaultSphereSceneQuery(this);
+    q->setSphere(sphere);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+PlaneBoundedVolumeListSceneQuery* 
+SceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, 
+                                            unsigned long mask)
+{
+    DefaultPlaneBoundedVolumeListSceneQuery* q = new DefaultPlaneBoundedVolumeListSceneQuery(this);
+    q->setVolumes(volumes);
+    q->setQueryMask(mask);
+    return q;
+}
+
+//---------------------------------------------------------------------
+RaySceneQuery* 
+SceneManager::createRayQuery(const Ray& ray, unsigned long mask)
+{
+    DefaultRaySceneQuery* q = new DefaultRaySceneQuery(this);
+    q->setRay(ray);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+IntersectionSceneQuery* 
+SceneManager::createIntersectionQuery(unsigned long mask)
+{
+
+    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+void SceneManager::destroyQuery(SceneQuery* query)
+{
+    delete query;
+}
+//---------------------------------------------------------------------
+DefaultIntersectionSceneQuery::DefaultIntersectionSceneQuery(SceneManager* creator)
+: IntersectionSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultIntersectionSceneQuery::~DefaultIntersectionSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator a, b, theEnd;
+    theEnd = mParentSceneMgr->mEntities.end();
+    int numEntities;
+    // Loop a from first to last-1
+    a = mParentSceneMgr->mEntities.begin();
+    numEntities = (uint)mParentSceneMgr->mEntities.size();
+    for (int i = 0; i < (numEntities - 1); ++i, ++a)
+    {
+        // Skip if a does not pass the mask
+        if (!(a->second->getQueryFlags() & mQueryMask) ||
+			!a->second->isInScene())
+            continue;
+
+        // Loop b from a+1 to last
+        b = a;
+        for (++b; b != theEnd; ++b)
+        {
+            // Apply mask to b (both must pass)
+            if ((b->second->getQueryFlags() & mQueryMask) && b->second->isInScene())
+            {
+                const AxisAlignedBox& box1 = a->second->getWorldBoundingBox();
+                const AxisAlignedBox& box2 = b->second->getWorldBoundingBox();
+
+                if (box1.intersects(box2))
+                {
+                    if (!listener->queryResult(a->second, b->second)) return;
+                }
+            }
+
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultAxisAlignedBoxSceneQuery::
+DefaultAxisAlignedBoxSceneQuery(SceneManager* creator)
+: AxisAlignedBoxSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultAxisAlignedBoxSceneQuery::~DefaultAxisAlignedBoxSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultAxisAlignedBoxSceneQuery::execute(SceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        if ((i->second->getQueryFlags() & mQueryMask) && 
+			i->second->isInScene() &&
+			mAABB.intersects(i->second->getWorldBoundingBox()))
+        {
+            if (!listener->queryResult(i->second)) return;
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultRaySceneQuery::
+DefaultRaySceneQuery(SceneManager* creator) : RaySceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultRaySceneQuery::~DefaultRaySceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultRaySceneQuery::execute(RaySceneQueryListener* listener)
+{
+    // Note that becuase we have no scene partitioning, we actually
+    // perform a complete scene search even if restricted results are
+    // requested; smarter scene manager queries can utilise the paritioning 
+    // of the scene in order to reduce the number of intersection tests 
+    // required to fulfil the query
+
+    // TODO: BillboardSets? Will need per-billboard collision most likely
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        if( (i->second->getQueryFlags() & mQueryMask) &&
+			i->second->isInScene())
+        {
+            // Do ray / box test
+            std::pair<bool, Real> result =
+                mRay.intersects(i->second->getWorldBoundingBox());
+
+            if (result.first)
+            {
+                if (!listener->queryResult(i->second, result.second)) return;
+            }
+        }
+    }
+
+}
+//---------------------------------------------------------------------
+DefaultSphereSceneQuery::
+DefaultSphereSceneQuery(SceneManager* creator) : SphereSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultSphereSceneQuery::~DefaultSphereSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultSphereSceneQuery::execute(SceneQueryListener* listener)
+{
+    // TODO: BillboardSets? Will need per-billboard collision most likely
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    Sphere testSphere;
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        // Skip unattached
+        if (!i->second->isInScene() || 
+			!(i->second->getQueryFlags() & mQueryMask))
+            continue;
+
+        // Do sphere / sphere test
+        testSphere.setCenter(i->second->getParentNode()->_getDerivedPosition());
+        testSphere.setRadius(i->second->getBoundingRadius());
+        if (mSphere.intersects(testSphere))
+        {
+            if (!listener->queryResult(i->second)) return;
+        }
+    }
+}
+//---------------------------------------------------------------------
+DefaultPlaneBoundedVolumeListSceneQuery::
+DefaultPlaneBoundedVolumeListSceneQuery(SceneManager* creator) 
+: PlaneBoundedVolumeListSceneQuery(creator)
+{
+    // No world geometry results supported
+    mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
+}
+//---------------------------------------------------------------------
+DefaultPlaneBoundedVolumeListSceneQuery::~DefaultPlaneBoundedVolumeListSceneQuery()
+{
+}
+//---------------------------------------------------------------------
+void DefaultPlaneBoundedVolumeListSceneQuery::execute(SceneQueryListener* listener)
+{
+    // Entities only for now
+    SceneManager::EntityList::const_iterator i, iEnd;
+    iEnd = mParentSceneMgr->mEntities.end();
+    Sphere testSphere;
+    for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
+    {
+        PlaneBoundedVolumeList::iterator pi, piend;
+        piend = mVolumes.end();
+        for (pi = mVolumes.begin(); pi != piend; ++pi)
+        {
+            PlaneBoundedVolume& vol = *pi;
+            // Do AABB / plane volume test
+            if ((i->second->getQueryFlags() & mQueryMask) && 
+				i->second->isInScene() && 
+				vol.intersects(i->second->getWorldBoundingBox()))
+            {
+                if (!listener->queryResult(i->second)) return;
+                break;
+            }
+        }
+    }
+}
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//-----------------------------------------------------------------------
+Pass* SceneManager::setPassWrapper(Pass* pass)
+{
+	return setPass(pass);
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderSceneNode(Camera *cam, SceneNode *node, const int leavePassesInQueue)
+{
+	// delete previously rendered objects from renderqueue
+	_deleteRenderedQueueGroups(leavePassesInQueue);
+
+	node->_findVisibleObjects(cam, getRenderQueue(), false, mDisplayNodes, false);
+	SceneManager::_renderVisibleObjects();
+}
+//-----------------------------------------------------------------------
+void SceneManager::_deleteRenderedQueueGroups(const int leavePassesInQueue)
+{
+	RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
+
+	// find currently processed queue groups and delelete them from render queue
+	while (queueIt.hasMoreElements())
+	{
+		RenderQueueGroupID qId = queueIt.peekNextKey();
+		RenderQueueGroup* pGroup = queueIt.getNext();
+
+		if (isRenderQueueToBeProcessed(qId))
+		{
+			pGroup->destroyPasses(leavePassesInQueue);
+		}
+	}
+	
+	// Now trigger the pending pass updates
+	// 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 int leavePassesInQueue)
+{
+	// delete previously rendered objects from renderqueue
+	_deleteRenderedQueueGroups(leavePassesInQueue);
+
+	mov->_updateRenderQueue(getRenderQueue());
+	SceneManager::_renderVisibleObjects();
+}
+//-----------------------------------------------------------------------
+void SceneManager::_renderSingleRenderable(Renderable *rend)
+{
+	Pass *pass = rend->getTechnique()->getPass(0);
+	setPass(pass);
+	renderSingleObject(rend, pass, false);
+}
+//-----------------------------------------------------------------------
+void SceneManager::useRenderableViewProjModeWrapper(Renderable* pRend)
+{
+	useRenderableViewProjMode(pRend);
+}
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h	(revision 347)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctree.h	(revision 347)
@@ -0,0 +1,215 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octree.h  -  description
+-------------------
+begin                : Mon Sep 30 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+***************************************************************************/
+
+#ifndef OCTREE_H
+#define OCTREE_H
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+#include "OgreTerrainPrerequisites.h"
+#endif
+#include <OgreAxisAlignedBox.h>
+#include <OgreWireBoundingBox.h>
+
+#include <list>
+
+namespace Ogre
+{
+
+class OctreeNode;
+
+typedef std::list < OctreeNode * > NodeList;
+
+
+/** Octree datastructure for managing scene nodes.
+@remarks
+This is a loose octree implementation, meaning that each
+octant child of the octree actually overlaps it's siblings by a factor
+of .5.  This guarantees that any thing that is half the size of the parent will
+fit completely into a child, with no splitting necessary.
+*/
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+class _OgreTerrainExport Octree
+#else
+class Octree
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+{
+public:
+    Octree( Octree * p );
+    ~Octree();
+
+    /** Adds an Octree scene node to this octree level.
+    @remarks
+    This is called by the OctreeSceneManager after
+    it has determined the correct Octree to insert the node into.
+    */
+    void _addNode( OctreeNode * );
+
+    /** Removes an Octree scene node to this octree level.
+    */
+    void _removeNode( OctreeNode * );
+
+    /** Returns the number of scene nodes attached to this octree
+    */
+    int numNodes()
+    {
+        return mNumNodes;
+    };
+
+    /** The bounding box of the octree
+    @remarks
+    This is used for octant index determination and rendering, but not culling
+    */
+    AxisAlignedBox mBox;
+    WireBoundingBox* mWireBoundingBox;
+    
+    /** Creats the wire frame bounding box for this octant
+    */
+    WireBoundingBox* getWireBoundingBox();
+
+    /** Vector containing the dimensions of this octree / 2
+    */
+    Vector3 mHalfSize;
+
+    /** 3D array of children of this octree.
+    @remarks
+    Children are dynamically created as needed when nodes are inserted in the Octree.
+    If, later, the all the nodes are removed from the child, it is still kept arround.
+    */
+    Octree * mChildren[ 2 ][ 2 ][ 2 ];
+
+    /** Determines if this octree is twice as big as the given box.
+    @remarks
+    This method is used by the OctreeSceneManager to determine if the given
+    box will fit into a child of this octree.
+    */
+    bool _isTwiceSize( AxisAlignedBox &box );
+
+    /**  Returns the appropriate indexes for the child of this octree into which the box will fit.
+    @remarks
+    This is used by the OCtreeSceneManager to determine which child to traverse next when
+    finding the appropriate octree to insert the box.  Since it is a loose octree, only the
+    center of the box is checked to determine the octant.
+    */
+    void _getChildIndexes( AxisAlignedBox &, int *x, int *y, int *z );
+
+    /** Creates the AxisAlignedBox used for culling this octree.
+    @remarks
+    Since it's a loose octree, the culling bounds can be different than the actual bounds of the octree.
+    */
+    void _getCullBounds( AxisAlignedBox * );
+
+
+    /** Public list of SceneNodes attached to this particular octree
+    */
+    NodeList mNodes;
+
+protected:
+
+    /** Increments the overall node count of this octree and all it's parents
+    */
+    inline void _ref()
+    {
+        mNumNodes++;
+
+        if ( mParent != 0 ) mParent -> _ref();
+    };
+
+    /** Decrements the overall node count of this octree and all it's parents
+    */
+    inline void _unref()
+    {
+        mNumNodes--;
+
+        if ( mParent != 0 ) mParent -> _unref();
+    };
+
+    ///number of SceneNodes in this octree and all it's children.
+    int mNumNodes;
+
+    ///parent octree
+    Octree * mParent;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+public:
+	/** Returns last visited frame id. */
+	int lastVisited(void);
+	/** Set to current frame id.
+    @param current frame id.
+    */
+	void setLastVisited(int frameid);
+	/** Makes this octree become visible / invisble.
+    @param visible Whether this node is to be made visible or invisible
+    */
+	void setOctreeVisible(bool visible);
+	/** Returns true if this node is marked visible, false otherwise. 
+	*/
+	bool isOctreeVisible(void);
+	/** Gets this node's parent (NULL if this is the root).
+	*/
+	Octree *getParent();
+	/** Frame id when this octree was last rendered. 
+	@return last rendered frame id
+	*/	
+	int lastRendered(void);
+	/** Sets frame id when this octree was last rendered. 
+	@param last rendered frame id
+	*/
+	void setLastRendered(int frameid);
+	
+	/** Returns real extent of the octree, i.e., the merged extent of the bounding boxes. 
+	*/
+	AxisAlignedBox _getWorldAABB(void) const;
+
+	/** Updates bounds of real aabb of octree. 
+	*/
+	void _updateBounds();
+
+protected:
+	
+	/** the real extent of the octree. */
+	AxisAlignedBox mWorldAABB;
+
+	int mLastRendered;
+	int mLastVisited;
+	bool mVisible;
+	
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+};
+
+}
+
+#endif
+
+
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeNode.h
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeNode.h	(revision 193)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeNode.h	(revision 193)
@@ -0,0 +1,151 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreenode.h  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+***************************************************************************/
+
+#ifndef OCTREENODE_H
+#define OCTREENODE_H
+
+#include <OgreSceneNode.h>
+
+#include <OgreOctreeSceneManager.h>
+
+namespace Ogre
+{
+
+/** Specialized SceneNode that is customized for working within an Octree. Each node
+* maintains it's own bounding box, rather than merging it with all the children.
+*
+*/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+class _OgreTerrainExport OctreeNode : public SceneNode
+#else
+class OctreeNode : public SceneNode
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+{
+public:
+    /** Standard constructor */
+    OctreeNode( SceneManager* creator );
+    /** Standard constructor */
+    OctreeNode( SceneManager* creator, const String& name );
+    /** Standard destructor */
+    ~OctreeNode();
+
+    /** Overridden from Node to remove any reference to octants */
+    Node * removeChild( unsigned short index );
+    
+    /** Overridden from Node to remove any reference to octants */
+    Node * removeChild( const String & name );
+
+    /** Overridden from Node to remove any reference to octants */
+    Node * removeChild( Node* child);
+
+    /** Returns the Octree in which this OctreeNode resides
+    */
+    Octree * getOctant()
+    {
+        return mOctant;
+    };
+
+    /** Sets the Octree in which this OctreeNode resides
+    */
+    void setOctant( Octree *o )
+    {
+        mOctant = o;
+    };
+
+    /** Determines if the center of this node is within the given box
+    */
+    bool _isIn( AxisAlignedBox &box );
+
+    /** Adds all the attached scenenodes to the render queue
+    */
+    virtual void _addToRenderQueue( Camera* cam, RenderQueue * q, bool onlyShadowCasters );
+
+    /** Sets up the LegacyRenderOperation for rendering this scene node as geometry.
+    @remarks
+    This will render the scenenode as a bounding box.
+    */
+    virtual void getRenderOperation( RenderOperation& op );
+
+    /** Returns the local bounding box of this OctreeNode.
+    @remarks
+    This is used to render the bounding box, rather then the global.
+    */
+    AxisAlignedBox & _getLocalAABB()
+    {
+        return mLocalAABB;
+    };
+
+
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/// scale for node visualization
+	static void setVizScale(Real scale);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+protected:
+
+    /** Internal method for updating the bounds for this OctreeNode.
+    @remarks
+    This method determines the bounds solely from the attached objects, not
+    any children. If the node has changed it's bounds, it is removed from its
+    current octree, and reinserted into the tree.
+    */
+    void _updateBounds( void );
+
+    void _removeNodeAndChildren( );
+
+    ///local bounding box
+    AxisAlignedBox mLocalAABB;
+
+    ///Octree this node is attached to.
+    Octree *mOctant;
+
+    ///preallocated corners for rendering
+    Real mCorners[ 24 ];
+    ///shared colors for rendering
+    static unsigned long mColors[ 8 ];
+    ///shared indexes for rendering
+    static unsigned short mIndexes[ 24 ];
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	// scale for node visualization
+	static Real msVizScale;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+};
+
+}
+
+
+#endif
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 316)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 316)
@@ -0,0 +1,442 @@
+/*
+-----------------------------------------------------------------------------
+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
+
+#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 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
+        {
+#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 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;}
+
+#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:
+		// 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
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        int mRenderLevel[MAX_RENDERLEVEL_INDEX];
+#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
+        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
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 193)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 193)
@@ -0,0 +1,91 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreecamera.h  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+***************************************************************************/
+
+#ifndef OCTREECAMERA_H
+#define OCTREECAMERA_H
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+#include "OgreTerrainPrerequisites.h"
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+#include <OgreCamera.h>
+#include <OgreHardwareBufferManager.h>
+#include <OgreSimpleRenderable.h>
+
+/**
+*@author Jon Anderson
+*/
+
+namespace Ogre
+{
+
+class Octree;
+
+
+/** Specialized viewpoint from which an Octree can be rendered.
+@remarks
+This class contains several speciliazations of the Ogre::Camera class. It
+implements the getRenderOperation method inorder to return displayable geometry
+for debuggin purposes. It also implements a visibility function that is more granular
+than the default.
+*/
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+class _OgreTerrainExport OctreeCamera : public Camera
+#else
+class OctreeCamera : public Camera
+#endif
+{
+public:
+
+    /** Visibility types */
+    enum Visibility
+    {
+        NONE,
+        PARTIAL,
+        FULL
+    };
+
+    /* Standard Constructor */
+    OctreeCamera( const String& name, SceneManager* sm );
+    /* Standard destructor */
+    ~OctreeCamera();
+
+    /** Returns the visiblity of the box
+    */
+    OctreeCamera::Visibility getVisibility( const AxisAlignedBox &bound );
+
+};
+
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 316)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 316)
@@ -0,0 +1,275 @@
+/***************************************************************************
+octreescenemanager.h  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+***************************************************************************/
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef OCTREESCENEMANAGER_H
+#define OCTREESCENEMANAGER_H
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+#include "OgreTerrainPrerequisites.h"
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+#include "OgreSceneManager.h"
+#include "OgreRenderOperation.h"
+#include "OgreSphere.h"
+
+#include <list>
+#include <algorithm>
+
+#include <OgreOctree.h>
+
+
+namespace Ogre
+{
+
+class OctreeNode;
+
+class OctreeCamera;
+class OctreeIntersectionSceneQuery;
+class OctreeRaySceneQuery;
+class OctreeSphereSceneQuery;
+class OctreeAxisAlignedBoxSceneQuery;
+class OctreePlaneBoundedVolumeListSceneQuery;
+
+
+typedef std::list < WireBoundingBox * > BoxList;
+typedef std::list < unsigned long > ColorList;
+//typedef std::list < SceneNode * > SceneNodeList;
+
+
+/** Specialized SceneManager that divides the geometry into an octree in order to faciliate spatial queries.
+@remarks
+For debugging purposes, a special "CullCamera" can be defined.  To use it, call setUseCallCamera( true ),
+and create a camera named "CullCamera".  All culling will be performed using that camera, instead of the viewport
+camera, allowing you to fly around and examine culling.
+*/
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+class _OgreTerrainExport OctreeSceneManager : public SceneManager
+#else
+class OctreeSceneManager : public SceneManager
+#endif GTP_VISIBILITY_MODIFIED_OGRE
+{
+    friend class OctreeIntersectionSceneQuery;
+    friend class OctreeRaySceneQuery;
+    friend class OctreeSphereSceneQuery;
+    friend class OctreeAxisAlignedBoxSceneQuery;
+    friend class OctreePlaneBoundedVolumeListSceneQuery;
+
+public:
+    static int intersect_call;
+    /** Standard Constructor.  Initializes the octree to -500,-500,-500 to 500,500,500 with unlimited depth. */
+    OctreeSceneManager( );
+    /** Standard Constructor */
+    OctreeSceneManager( AxisAlignedBox &box, int max_depth );
+    /** Standard desctructor */
+    ~OctreeSceneManager();
+
+    /** Initializeds the manager to the given box and depth.
+    */
+    void init( AxisAlignedBox &box, int d );
+
+    /** Creates a specialized OctreeNode */
+    virtual	SceneNode * createSceneNode ( void );
+    /** Creates a specialized OctreeNode */
+    virtual SceneNode * createSceneNode ( const String &name );
+    /** Creates a specialized OctreeCamera */
+    virtual Camera * createCamera( const String &name );
+
+    /** Deletes a scene node */
+    virtual void destroySceneNode( const String &name );
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/** Renders one octant of an octree, i.e., renders current octant
+		node and does not traverse deeper into the tree.
+
+		@remark Note that OctreeNode instances are NOT part of the octree 
+		hierarchy, instead one octant of an Octree contains many OctreeNode instances.
+		
+		@param cam current camera
+		@param octree the octant to be rendered (without children)
+		@param onlyShadowCasters if only shadow casters are rendered
+		@param passes if passes should be left in queue for later processing
+	*/
+	void _renderOctant(Camera* cam, Octree *octree, bool onlyShadowCasters, 
+		const int leavePassesInQueue = 0);
+
+	/** Returns stored list of boxes */
+	BoxList *getBoxes();
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+
+    /** Does nothing more */
+    virtual void _updateSceneGraph( Camera * cam );
+    /** Recurses through the octree determining which nodes are visible. */
+    virtual void _findVisibleObjects ( Camera * cam, bool onlyShadowCasters );
+
+    /** Alerts each unculled object, notifying it that it will be drawn.
+     * Useful for doing calculations only on nodes that will be drawn, prior
+     * to drawing them...
+     */
+    virtual void _alertVisibleObjects( void );
+
+    /** Walks through the octree, adding any visible objects to the render queue.
+    @remarks
+    If any octant in the octree if completely within the the view frustum,
+    all subchildren are automatically added with no visibility tests.
+    */
+    void walkOctree( OctreeCamera *, RenderQueue *, Octree *, bool foundvisible,
+                     bool onlyShadowCasters);
+
+    /** Checks the given OctreeNode, and determines if it needs to be moved
+    * to a different octant.
+    */
+    void _updateOctreeNode( OctreeNode * );
+    /** Removes the given octree node */
+    void _removeOctreeNode( OctreeNode * );
+    /** Adds the Octree Node, starting at the given octree, and recursing at max to the specified depth.
+    */
+    void _addOctreeNode( OctreeNode *, Octree *octree, int depth = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the box into the given list.
+    It ignores the exclude scene node.
+    */
+    void findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the sphere into the given list.
+    It ignores the exclude scene node.
+    */
+    void findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude = 0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the volume into the given list.
+      It ignores the exclude scene node.
+      */
+    void findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude=0 );
+
+    /** Recurses the octree, adding any nodes intersecting with the ray into the given list.
+      It ignores the exclude scene node.
+      */
+    void findNodesIn( const Ray &ray, std::list < SceneNode * > &list, SceneNode *exclude=0 );
+
+    /** Sets the box visibility flag */
+    void setShowBoxes( bool b )
+    {
+        mShowBoxes = b;
+    };
+
+    /** Sets the cull camera flag */
+    void setUseCullCamera( bool b )
+    {
+        mCullCamera = b;
+    };
+
+    void setLooseOctree( bool b )
+    {
+        mLoose = b;
+    };
+
+
+    /** Resizes the octree to the given size */
+    void resize( const AxisAlignedBox &box );
+
+    /** Sets the given option for the SceneManager
+               @remarks
+        Options are:
+        "Size", AxisAlignedBox *;
+        "CullCamera", bool *;
+        "Depth", int *;
+        "ShowOctree", bool *;
+    */
+
+    virtual bool setOption( const String &, const void * );
+    /** Gets the given option for the Scene Manager.
+        @remarks
+        See setOption
+    */
+    virtual bool getOption( const String &, void * );
+
+    bool getOptionValues( const String & key, StringVector &refValueList );
+    bool getOptionKeys( StringVector &refKeys );
+    /** Overridden from SceneManager */
+    void clearScene(void);
+
+    AxisAlignedBoxSceneQuery* OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask);
+    SphereSceneQuery* OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask);
+    PlaneBoundedVolumeListSceneQuery* createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes, unsigned long mask);
+    RaySceneQuery* createRayQuery(const Ray& ray, unsigned long mask);
+    IntersectionSceneQuery* createIntersectionQuery(unsigned long mask);
+
+
+protected:
+
+
+    NodeList mVisible;
+
+    /// The root octree
+    Octree *mOctree;
+
+    /// list of boxes to be rendered
+    BoxList mBoxes;
+
+    /// number of rendered objs
+    int mNumObjects;
+
+    /// max depth for the tree.
+    int mMaxDepth;
+    /// Size of the octree
+    AxisAlignedBox mBox;
+
+    /// box visibility flag
+    bool mShowBoxes;
+
+    /// cull camera flag
+    bool mCullCamera;
+
+
+    bool mLoose;
+
+    Real mCorners[ 24 ];
+    static unsigned long mColors[ 8 ];
+    static unsigned short mIndexes[ 24 ];
+
+    Matrix4 mScaleFactor;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/** The number of nodes in the octree.
+		@remark counts the octree hierarchy nodes in the tree.
+	*/
+	int mNumOctants;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+};
+
+
+}
+
+#endif
+
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp	(revision 350)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp	(revision 350)
@@ -0,0 +1,266 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octree.cpp  -  description
+-------------------
+begin                : Mon Sep 30 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+
+#include <OgreOctree.h>
+#include <OgreOctreeNode.h>
+
+namespace Ogre
+{
+
+/** Returns true is the box will fit in a child.
+*/
+bool Octree::_isTwiceSize( AxisAlignedBox &box )
+{
+    const Vector3 * pts1 = mBox.getAllCorners();
+    const Vector3 * pts2 = box.getAllCorners();
+
+    return ( ( pts2[ 4 ].x -pts2[ 0 ].x ) <= ( pts1[ 4 ].x - pts1[ 0 ].x ) / 2 ) &&
+           ( ( pts2[ 4 ].y - pts2[ 0 ].y ) <= ( pts1[ 4 ].y - pts1[ 0 ].y ) / 2 ) &&
+           ( ( pts2[ 4 ].z - pts2[ 0 ].z ) <= ( pts1[ 4 ].z - pts1[ 0 ].z ) / 2 ) ;
+
+}
+
+/** It's assumed the the given box has already been proven to fit into
+* a child.  Since it's a loose octree, only the centers need to be
+* compared to find the appropriate node.
+*/
+void Octree::_getChildIndexes( AxisAlignedBox &box, int *x, int *y, int *z )
+{
+    Vector3 max = mBox.getMaximum();
+    Vector3 min = box.getMinimum();
+
+    Vector3 center = mBox.getMaximum().midPoint( mBox.getMinimum() );
+
+    Vector3 ncenter = box.getMaximum().midPoint( box.getMinimum() );
+
+    if ( ncenter.x > center.x )
+        * x = 1;
+    else
+        *x = 0;
+
+    if ( ncenter.y > center.y )
+        * y = 1;
+    else
+        *y = 0;
+
+    if ( ncenter.z > center.z )
+        * z = 1;
+    else
+        *z = 0;
+
+}
+
+Octree::Octree( Octree * parent ) 
+    : mWireBoundingBox(0),
+      mHalfSize( 0, 0, 0 )
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	, mLastVisited(0), mVisible(false), mLastRendered(-1)
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+{
+    //initialize all children to null.
+    for ( int i = 0; i < 2; i++ )
+    {
+        for ( int j = 0; j < 2; j++ )
+        {
+            for ( int k = 0; k < 2; k++ )
+            {
+                mChildren[ i ][ j ][ k ] = 0;
+            }
+        }
+    }
+
+    mParent = parent;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	// update bounds because we want tight octree
+	_updateBounds();
+	
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+    mNumNodes = 0;
+}
+
+Octree::~Octree()
+{
+    //initialize all children to null.
+    for ( int i = 0; i < 2; i++ )
+    {
+        for ( int j = 0; j < 2; j++ )
+        {
+            for ( int k = 0; k < 2; k++ )
+            {
+                if ( mChildren[ i ][ j ][ k ] != 0 )
+                    delete mChildren[ i ][ j ][ k ];
+            }
+        }
+    }
+
+    if(mWireBoundingBox)
+        delete mWireBoundingBox;
+
+    mParent = 0;
+
+}
+
+void Octree::_addNode( OctreeNode * n )
+{
+    mNodes.push_back( n );
+    n -> setOctant( this );
+
+    //update total counts.
+    _ref();
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	_updateBounds();
+#endif
+
+}
+
+void Octree::_removeNode( OctreeNode * n )
+{
+    mNodes.erase( std::find( mNodes.begin(), mNodes.end(), n ) );
+    n -> setOctant( 0 );
+
+    //update total counts.
+    _unref();
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	_updateBounds();
+#endif
+}
+
+void Octree::_getCullBounds( AxisAlignedBox *b )
+{
+    const Vector3 * corners = mBox.getAllCorners();
+    b -> setExtents( corners[ 0 ] - mHalfSize, corners[ 4 ] + mHalfSize );
+}
+
+WireBoundingBox* Octree::getWireBoundingBox()
+{
+	// Create a WireBoundingBox if needed
+    if(mWireBoundingBox == 0)
+        mWireBoundingBox = new WireBoundingBox();
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	mWireBoundingBox->setupBoundingBox(mWorldAABB);
+#else
+	mWireBoundingBox->setupBoundingBox(mBox);
+#endif	
+
+    return mWireBoundingBox;
+}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//-----------------------------------------------------------------------	
+int Octree::lastVisited()
+{
+	return mLastVisited;
+}
+//-----------------------------------------------------------------------
+void Octree::setLastVisited(int frameid)
+{
+	mLastVisited = frameid;
+}
+//-----------------------------------------------------------------------	
+int Octree::lastRendered()
+{
+	return mLastRendered;
+}
+//-----------------------------------------------------------------------
+void Octree::setLastRendered(int frameid)
+{
+	mLastRendered = frameid;
+}
+//-----------------------------------------------------------------------	
+void Octree::setOctreeVisible(bool visible)
+{
+	mVisible = visible;
+}
+//-----------------------------------------------------------------------	
+bool Octree::isOctreeVisible()
+{
+	return mVisible;
+}
+//-----------------------------------------------------------------------	
+Octree *Octree::getParent()
+{
+	return mParent;
+}
+//-----------------------------------------------------------------------	
+AxisAlignedBox Octree::_getWorldAABB(void) const
+{
+	return mWorldAABB;
+}
+//-----------------------------------------------------------------------
+void Octree::_updateBounds()
+{
+	// Reset bounds first
+    mWorldAABB.setNull();
+  
+    // Update bounds from own attached objects
+	NodeList::iterator it, it_end;
+	it_end = mNodes.end();
+
+    for (it = mNodes.begin(); it != it_end; ++it)
+    {
+        // Merge world bounds of each object
+		mWorldAABB.merge((*it)->_getWorldAABB());
+    }
+
+    // Merge with children
+	for (int i = 0; i < 2; ++i)
+    {
+        for (int j = 0; j < 2; ++j)
+        {
+            for (int k = 0; k < 2; ++k)
+            {
+                if (mChildren[i][j][k])
+				{
+					mWorldAABB.merge(mChildren[i][j][k]->_getWorldAABB());
+				}
+            }
+        }
+	}
+	// HACK: clamp to bounds
+	AxisAlignedBox box;
+	_getCullBounds(&box);
+	mWorldAABB = mWorldAABB.intersection(box); 
+	
+	// recursively update parent bounds
+	if (mParent)
+	{
+		mParent->_updateBounds();
+	}
+ }
+
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeNode.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeNode.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeNode.cpp	(revision 193)
@@ -0,0 +1,237 @@
+/*
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreenode.cpp  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+
+#include <OgreRoot.h>
+
+#include <OgreOctreeNode.h>
+#include <OgreOctreeSceneManager.h>
+#include <OgreMeshManager.h>
+#include <OgreSubMesh.h>
+
+namespace Ogre
+{
+unsigned long green = 0xFFFFFFFF;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+Real OctreeNode::msVizScale = 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+unsigned short OctreeNode::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
+        0, 6, 6, 5, 5, 1,             //left
+        3, 7, 7, 4, 4, 2,             //right
+        6, 7, 5, 4 };          //front
+unsigned long OctreeNode::mColors[ 8 ] = {green, green, green, green, green, green, green, green };
+
+OctreeNode::OctreeNode( SceneManager* creator ) : SceneNode( creator )
+{
+    mOctant = 0;
+}
+
+OctreeNode::OctreeNode( SceneManager* creator, const String& name ) : SceneNode( creator, name )
+{
+    mOctant = 0;
+}
+
+OctreeNode::~OctreeNode()
+{}
+void OctreeNode::_removeNodeAndChildren( )
+{
+    static_cast< OctreeSceneManager * > ( mCreator ) -> _removeOctreeNode( this ); 
+    //remove all the children nodes as well from the octree.
+    ChildNodeMap::iterator it = mChildren.begin();
+    while( it != mChildren.end() )
+    {
+        static_cast<OctreeNode *>( it->second ) -> _removeNodeAndChildren();
+        ++it;
+    }
+}
+Node * OctreeNode::removeChild( unsigned short index )
+{
+    OctreeNode *on = static_cast<OctreeNode* >( SceneNode::removeChild( index ) );
+    on -> _removeNodeAndChildren(); 
+    return on; 
+}
+Node * OctreeNode::removeChild( Node* child )
+{
+    OctreeNode *on = static_cast<OctreeNode* >( SceneNode::removeChild( child ) );
+    on -> _removeNodeAndChildren(); 
+    return on; 
+}
+    
+Node * OctreeNode::removeChild( const String & name )
+{
+    OctreeNode *on = static_cast< OctreeNode * >( SceneNode::removeChild(  name ) );
+    on -> _removeNodeAndChildren( ); 
+    return on; 
+}
+
+//same as SceneNode, only it doesn't care about children...
+void OctreeNode::_updateBounds( void )
+{
+    mWorldAABB.setNull();
+    mLocalAABB.setNull();
+
+    // Update bounds from own attached objects
+    ObjectMap::iterator i = mObjectsByName.begin();
+    AxisAlignedBox bx;
+
+    while ( i != mObjectsByName.end() )
+    {
+
+        // Get local bounds of object
+        bx = i->second ->getBoundingBox();
+
+        mLocalAABB.merge( bx );
+
+        mWorldAABB.merge( i->second ->getWorldBoundingBox(true) );
+        ++i;
+    }
+
+
+    //update the OctreeSceneManager that things might have moved.
+    // if it hasn't been added to the octree, add it, and if has moved
+    // enough to leave it's current node, we'll update it.
+    if ( ! mWorldAABB.isNull() )
+    {
+        static_cast < OctreeSceneManager * > ( mCreator ) -> _updateOctreeNode( this );
+    }
+
+}
+
+/** Since we are loose, only check the center.
+*/
+bool OctreeNode::_isIn( AxisAlignedBox &box )
+{
+	// Always fail if not in the scene graph
+	if (!mIsInSceneGraph) return false;
+
+    Vector3 center = mWorldAABB.getMaximum().midPoint( mWorldAABB.getMinimum() );
+
+    Vector3 bmin = box.getMinimum();
+    Vector3 bmax = box.getMaximum();
+
+    return ( bmax > center && bmin < center );
+
+}
+
+/** Addes the attached objects of this OctreeScene node into the queue. */
+void OctreeNode::_addToRenderQueue( Camera* cam, RenderQueue *queue, bool onlyShadowCasters )
+{
+    ObjectMap::iterator mit = mObjectsByName.begin();
+
+    while ( mit != mObjectsByName.end() )
+    {
+        MovableObject * mo = mit->second;
+
+        mo->_notifyCurrentCamera(cam);
+        if ( mo->isVisible() &&
+            (!onlyShadowCasters || mo->getCastShadows()))
+        {
+            mo -> _updateRenderQueue( queue );
+        }
+
+        ++mit;
+    }
+
+}
+
+
+void OctreeNode::getRenderOperation( RenderOperation& rend )
+{
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	/*static SubMesh* pSubMesh = 0;
+
+	if (!pSubMesh)
+	{
+		MeshPtr pMesh = MeshManager::getSingleton().load("axis.mesh", 
+			ResourceGroupManager::BOOTSTRAP_RESOURCE_GROUP_NAME);
+		pSubMesh = pMesh->getSubMesh(0);
+	}
+	pSubMesh->_getRenderOperation(rend);*/
+
+	// HACK. render scaled box
+	if (mWireBoundingBox == NULL) 
+	{
+		mWireBoundingBox = new WireBoundingBox();
+	}
+
+	//LogManager::getSingleton().logMessage("hagaaggaagag");
+	AxisAlignedBox box = mLocalAABB;
+	
+	// HACK: scale should not be done here
+	box.scale(Vector3(msVizScale, msVizScale, msVizScale));
+
+	mWireBoundingBox->setupBoundingBox(box);
+	mWireBoundingBox->getRenderOperation(rend);
+
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    /* TODO
+    rend.useIndexes = true;
+    rend.numTextureCoordSets = 0; // no textures
+    rend.vertexOptions = LegacyRenderOperation::VO_DIFFUSE_COLOURS;
+    rend.operationType = LegacyRenderOperation::OT_LINE_LIST;
+    rend.numVertices = 8;
+    rend.numIndexes = 24;
+
+    rend.pVertices = mCorners;
+    rend.pIndexes = mIndexes;
+    rend.pDiffuseColour = mColors;
+
+    const Vector3 * corners = _getLocalAABB().getAllCorners();
+
+    int index = 0;
+
+    for ( int i = 0; i < 8; i++ )
+    {
+        rend.pVertices[ index ] = corners[ i ].x;
+        index++;
+        rend.pVertices[ index ] = corners[ i ].y;
+        index++;
+        rend.pVertices[ index ] = corners[ i ].z;
+        index++;
+    }
+    */
+
+
+}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+void OctreeNode::setVizScale(Real scale)
+{
+	msVizScale = scale;
+}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreTerrainRenderable.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreTerrainRenderable.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreTerrainRenderable.cpp	(revision 193)
@@ -0,0 +1,1528 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreTerrainRenderable.h"
+#include "OgreSceneNode.h"
+#include "OgreRenderQueue.h"
+#include "OgreRenderOperation.h"
+#include "OgreCamera.h"
+#include "OgreRoot.h"
+#include "OgreTerrainSceneManager.h"
+#include "OgreLogManager.h"
+#include "OgreStringConverter.h"
+#include "OgreViewport.h"
+#include "OgreException.h"
+
+namespace Ogre
+{
+    //-----------------------------------------------------------------------
+    #define MAIN_BINDING 0
+    #define DELTA_BINDING 1
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+    TerrainBufferCache TerrainRenderable::msIndexCache;
+    String TerrainRenderable::mType = "TerrainMipMap";
+    LevelArray TerrainRenderable::mLevelIndex;
+    bool TerrainRenderable::mLevelInit = false;
+    const TerrainOptions* TerrainRenderable::msOptions = 0;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	int TerrainRenderable::msCurrentRenderLevelIndex = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+
+    //-----------------------------------------------------------------------
+    TerrainRenderable::TerrainRenderable(const String& name)
+        : Renderable(), mTerrain(0), mName(name),  mDeltaBuffers(0), mPositionBuffer(0)
+    {
+        mForcedRenderLevel = -1;
+        mLastNextLevel = -1;
+        // Default query flags to top bit so users can exclude it if they wish
+        mQueryFlags = SceneManager::WORLD_GEOMETRY_QUERY_MASK;
+
+        mMinLevelDistSqr = 0;
+
+        mInit = false;
+		MovableObject::mCastShadows = false;
+
+        for ( int i = 0; i < 4; i++ )
+        {
+            mNeighbors[ i ] = 0;
+        }
+
+		_initLevelIndexes();
+
+    }
+    //-----------------------------------------------------------------------
+    TerrainRenderable::~TerrainRenderable()
+    {
+
+        deleteGeometry();
+        _destroyLevelIndexes();
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::deleteGeometry()
+    {
+        if(mTerrain)
+            delete mTerrain;
+
+        if (mPositionBuffer)
+            delete [] mPositionBuffer;
+
+        if (mDeltaBuffers)
+            delete [] mDeltaBuffers;
+
+        if ( mMinLevelDistSqr != 0 )
+            delete [] mMinLevelDistSqr;
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::initialise(int startx, int startz,  
+        Real* pageHeightData)
+    {
+        if (!msOptions)
+            msOptions = &(TerrainSceneManager::getOptions());
+
+        if ( msOptions->maxGeoMipMapLevel != 0 )
+        {
+            int i = ( int ) 1 << ( msOptions->maxGeoMipMapLevel - 1 ) ;
+
+            if ( ( i + 1 ) > msOptions->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 = msOptions->tileSize * msOptions->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 (TerrainSceneManager::getOptions().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 (TerrainSceneManager::getOptions().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 (msOptions->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[ msOptions->maxGeoMipMapLevel ];
+
+        int endx = startx + msOptions->tileSize;
+
+        int endz = startz + msOptions->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 * msOptions->pageSize + i];
+                height = height * msOptions->scale.y; // scale height 
+
+                *pSysPos++ = *pPos++ = ( float ) i * msOptions->scale.x; //x
+                *pSysPos++ = *pPos++ = height; // y
+                *pSysPos++ = *pPos++ = ( float ) j * msOptions->scale.z; //z
+
+                *pTex0++ = ( float ) i / ( float ) ( msOptions->pageSize - 1 );
+                *pTex0++ = ( float ) j / ( float ) ( msOptions->pageSize - 1 );
+
+                *pTex1++ = ( ( float ) i / ( float ) ( msOptions->tileSize - 1 ) ) * msOptions->detailTile;
+                *pTex1++ = ( ( float ) j / ( float ) ( msOptions->tileSize - 1 ) ) * msOptions->detailTile;
+
+                if ( height < min )
+                    min = ( Real ) height;
+
+                if ( height > max )
+                    max = ( Real ) height;
+
+                pBase += mMainBuffer->getVertexSize();
+            }
+        }
+
+        mMainBuffer->unlock();
+
+        mBounds.setExtents( 
+            ( Real ) startx * msOptions->scale.x, 
+            min, 
+            ( Real ) startz * msOptions->scale.z,
+            ( Real ) ( endx - 1 ) * msOptions->scale.x, 
+            max, 
+            ( Real ) ( endz - 1 ) * msOptions->scale.z );
+
+
+        mCenter = Vector3( ( startx * msOptions->scale.x + (endx - 1) * msOptions->scale.x ) / 2,
+            ( min + max ) / 2,
+            ( startz * msOptions->scale.z + (endz - 1) * msOptions->scale.z ) / 2 );
+
+        // Create delta buffer list if required to morph
+        if (msOptions->lodMorph)
+        {
+            // Create delta buffer for all except the lowest mip
+            mDeltaBuffers = new HardwareVertexBufferSharedPtr[msOptions->maxGeoMipMapLevel - 1];
+        }
+
+        Real C = _calculateCFactor();
+
+        _calculateMinLevelDist2( C );
+
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_getNormalAt( float x, float z, Vector3 * result )
+    {
+
+        assert(msOptions->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 TerrainRenderable::_calculateNormals()
+    {
+
+        Vector3 norm;
+
+        assert (msOptions->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 ( size_t j = 0; j < msOptions->tileSize; j++ )
+        {
+            for ( size_t i = 0; i < msOptions->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 TerrainRenderable::_notifyCurrentCamera( Camera* 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();
+        Vector3 diff = mCenter - cpos;
+
+        Real L = diff.squaredLength();
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            mRenderLevel[msCurrentRenderLevelIndex] = -1;;
+#else
+			mRenderLevel = -1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        for ( int i = 0; i < msOptions->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] = msOptions->maxGeoMipMapLevel - 1;
+#else
+		if ( mRenderLevel < 0 )
+            mRenderLevel = msOptions->maxGeoMipMapLevel - 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        if (msOptions->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 - msOptions->lodMorphStart);
+                    mLODMorphFactor = std::max((percent - msOptions->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 TerrainRenderable::_updateRenderQueue( RenderQueue* queue )
+    {
+        queue->addRenderable( this );
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::getRenderOperation( RenderOperation& op )
+    {
+        //setup indexes for vertices and uvs...
+
+        assert( mInit && "Uninitialized" );
+
+        op.useIndexes = true;
+        op.operationType = msOptions->useTriStrips ? 
+            RenderOperation::OT_TRIANGLE_STRIP : RenderOperation::OT_TRIANGLE_LIST;
+        op.vertexData = mTerrain;
+        op.indexData = getIndexData();
+
+
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::getWorldTransforms( Matrix4* xform ) const
+    {
+        *xform = mParentNode->_getFullTransform();
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& TerrainRenderable::getWorldOrientation(void) const
+    {
+        return mParentNode->_getDerivedOrientation();
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& TerrainRenderable::getWorldPosition(void) const
+    {
+        return mParentNode->_getDerivedPosition();
+    }
+    //-----------------------------------------------------------------------
+    bool TerrainRenderable::_checkSize( int n )
+    {
+        for ( int i = 0; i < 10; i++ )
+        {
+            if ( ( ( 1 << i ) + 1 ) == n )
+                return true;
+        }
+
+        return false;
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_calculateMinLevelDist2( Real C )
+    {
+        //level 0 has no delta.
+        mMinLevelDistSqr[ 0 ] = 0;
+
+        int i, j;
+
+        for ( int level = 1; level < msOptions->maxGeoMipMapLevel; level++ )
+        {
+            mMinLevelDistSqr[ level ] = 0;
+
+            int step = 1 << level;
+            // The step of the next higher LOD
+            int higherstep = step >> 1;
+
+            float* pDeltas = 0;
+            if (msOptions->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 < msOptions->tileSize - step; j += step )
+            {
+                for ( i = 0; i < msOptions->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 (!msOptions->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 == (msOptions->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 == (msOptions->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 (msOptions->lodMorph && 
+                                fulldetailx != 0  && fulldetailx != (msOptions->tileSize - 1) && 
+                                fulldetailz != 0  && fulldetailz != (msOptions->tileSize - 1) )
+                            {
+                                // Save height difference 
+                                pDeltas[fulldetailx + (fulldetailz * msOptions->tileSize)] = 
+                                    interp_h - actual_h;
+                            }
+
+                        }
+
+                    }
+                }
+            }
+
+            // Unlock morph deltas if required
+            if (msOptions->lodMorph)
+            {
+                mDeltaBuffers[level - 1]->unlock();
+            }
+        }
+
+
+
+        // Post validate the whole set
+        for ( i = 1; i < msOptions->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 = msOptions->maxGeoMipMapLevel - 1; i >= 0; --i)
+        {
+            if (i == msOptions->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 TerrainRenderable::_initLevelIndexes()
+    {
+        if ( mLevelInit )
+            return ;
+
+
+	    if ( mLevelIndex.size() == 0 )
+        {
+            for ( int i = 0; i < 16; i++ )
+            {
+
+				mLevelIndex.push_back( new IndexMap() );
+
+            }
+
+        }
+	
+        mLevelInit = true;
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_destroyLevelIndexes()
+    {
+        if ( mLevelInit )
+        {
+            for ( int i = 0; i < 16; i++ )
+            {
+                delete mLevelIndex[i];
+            }
+            mLevelIndex.clear();
+            mLevelInit = false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_adjustRenderLevel( int i )
+    {
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        mRenderLevel[msCurrentRenderLevelIndex] = i;
+#else
+		mRenderLevel = i;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    }
+    //-----------------------------------------------------------------------
+    Real TerrainRenderable::_calculateCFactor()
+    {
+        Real A, T;
+
+        const TerrainOptions& opts = TerrainSceneManager::getOptions();
+        if (!opts.primaryCamera)
+        {
+            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+                "You have not created a camera yet!", 
+                "TerrainRenderable::_calculateCFactor");
+        }
+
+        //A = 1 / Math::Tan(Math::AngleUnitsToRadians(opts.primaryCamera->getFOVy()));
+        // Turn off detail compression at higher FOVs
+        A = 1.0f;
+
+        int vertRes = opts.primaryCamera->getViewport()->getActualHeight();
+
+        T = 2 * ( Real ) opts.maxPixelError / ( Real ) vertRes;
+
+        return A / T;
+    }
+    //-----------------------------------------------------------------------
+    float TerrainRenderable::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( msOptions->tileSize - 1, msOptions->tileSize - 1, 0 );
+        end.y = _vertex( msOptions->tileSize - 1, msOptions->tileSize - 1, 1 );
+        end.z = _vertex( msOptions->tileSize - 1, msOptions->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 ) ( msOptions->tileSize - 1 );
+        float z_pt = z_pct * ( float ) ( msOptions->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 == msOptions->tileSize - 1)
+        {
+            --x_index;
+            x_pct = 1.0f;
+        }
+        else
+        {
+            // get remainder
+            x_pct = x_pt - x_index;
+        }
+        if (z_index == msOptions->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 TerrainRenderable::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 TerrainRenderable::_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 < msOptions->tileSize; i++ )
+        {
+            for ( size_t j = 0; j < msOptions->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 TerrainRenderable::getSquaredViewDepth(const Camera* cam) const
+    {
+        Vector3 diff = mCenter - cam->getDerivedPosition();
+        // Use squared length to avoid square root
+        return diff.squaredLength();
+    }
+
+    //-----------------------------------------------------------------------
+    const LightList& TerrainRenderable::getLights(void) const
+    {
+        return getParentSceneNode()->findLights(this->getBoundingRadius());
+    }
+    //-----------------------------------------------------------------------
+    IndexData* TerrainRenderable::getIndexData(void)
+    {
+        unsigned int stitchFlags = 0;
+
+        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;
+        }
+
+        // Check preexisting
+        IndexMap::iterator ii = mLevelIndex[ getRenderLevel() ]->find( stitchFlags );
+        IndexData* indexData;
+        if ( ii == mLevelIndex[ getRenderLevel() ]->end())
+        {
+            // Create
+            if (msOptions->useTriStrips)
+            {
+                indexData = generateTriStripIndexes(stitchFlags);
+            }
+            else
+            {
+                indexData = generateTriListIndexes(stitchFlags);
+            }
+            mLevelIndex[ getRenderLevel() ]->insert(
+                IndexMap::value_type(stitchFlags, indexData));
+        }
+        else
+        {
+            indexData = ii->second;
+        }
+
+
+        return indexData;
+
+
+    }
+    //-----------------------------------------------------------------------
+    IndexData* TerrainRenderable::generateTriStripIndexes(unsigned int stitchFlags)
+    {
+        // The step used for the current level
+        int step = 1 << getRenderLevel();
+        // The step used for the lower level
+        int lowstep = 1 << (getRenderLevel() + 1);
+
+        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 = (((msOptions->tileSize-1) / step) * 2) + 3;
+        // Num indexes is number of tris + 2
+        int new_length = numTrisAcross * ((msOptions->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);
+
+        msIndexCache.mCache.push_back( indexData );
+
+        unsigned short* pIdx = static_cast<unsigned short*>(
+            indexData->indexBuffer->lock(0, 
+            indexData->indexBuffer->getSizeInBytes(), 
+            HardwareBuffer::HBL_DISCARD));
+
+        // Stripified mesh
+        for ( int j = 0; j < msOptions->tileSize - 1; j += step )
+        {
+            int i;
+            // Forward strip
+            // We just do the |/ here, final | done after
+            for ( i = 0; i < msOptions->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 == (msOptions->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 == msOptions->tileSize - 1 - step)
+                {
+                    // Emit extra index to finish row
+                    *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    if (j < msOptions->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 = msOptions->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 == (msOptions->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 == msOptions->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 == msOptions->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 < msOptions->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* TerrainRenderable::generateTriListIndexes(unsigned int stitchFlags)
+    {
+
+        int numIndexes = 0;
+        int step = 1 << getRenderLevel();
+
+        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 = ( msOptions->tileSize / step ) * ( msOptions->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);
+
+        msIndexCache.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 ( int j = north; j < msOptions->tileSize - 1 - south; j += step )
+        {
+            for ( int i = west; i < msOptions->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 )
+        {
+            numIndexes += stitchEdge(NORTH, getRenderLevel(), mNeighbors[NORTH]->getRenderLevel(),
+                west > 0, east > 0, &pIdx);
+        }
+        // East stitching
+        if ( east > 0 )
+        {
+            numIndexes += stitchEdge(EAST, getRenderLevel(), mNeighbors[EAST]->getRenderLevel(),
+                north > 0, south > 0, &pIdx);
+        }
+        // South stitching
+        if ( south > 0 )
+        {
+            numIndexes += stitchEdge(SOUTH, getRenderLevel(), mNeighbors[SOUTH]->getRenderLevel(),
+                east > 0, west > 0, &pIdx);
+        }
+        // West stitching
+        if ( west > 0 )
+        {
+            numIndexes += stitchEdge(WEST, getRenderLevel(), mNeighbors[WEST]->getRenderLevel(),
+                south > 0, north > 0, &pIdx);
+        }
+
+
+        indexData->indexBuffer->unlock();
+        indexData->indexCount = numIndexes;
+        indexData->indexStart = 0;
+
+        return indexData;
+    }
+    //-----------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr TerrainRenderable::createDeltaBuffer(void)
+    {
+        // Delta buffer is a 1D float buffer of height offsets
+        HardwareVertexBufferSharedPtr buf = 
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+            VertexElement::getTypeSize(VET_FLOAT1), 
+            msOptions->tileSize * msOptions->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, msOptions->tileSize * msOptions->tileSize * sizeof(float));
+        buf->unlock();
+
+        return buf;
+
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_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 TerrainRenderable::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 = msOptions->tileSize - 1;
+            rowstep = step;
+            horizontal = true;
+            break;
+        case SOUTH:
+            // invert x AND y direction, helps to keep same winding
+            startx = starty = msOptions->tileSize - 1;
+            endx = 0;
+            rowstep = -step;
+            step = -step;
+            superstep = -superstep;
+            halfsuperstep = -halfsuperstep;
+            horizontal = true;
+            break;
+        case EAST:
+            startx = 0;
+            endx = msOptions->tileSize - 1;
+            starty = msOptions->tileSize - 1;
+            rowstep = -step;
+            horizontal = false;
+            break;
+        case WEST:
+            startx = msOptions->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 TerrainRenderable::ResetRenderLevelIndex() 
+	{
+		msCurrentRenderLevelIndex = 0;
+	}
+	//-----------------------------------------------------------------------
+	void TerrainRenderable::NextRenderLevelIndex()
+	{
+		if ((++ msCurrentRenderLevelIndex) > MAX_RENDERLEVEL_INDEX)
+			msCurrentRenderLevelIndex = 0;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+} //namespace
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp	(revision 61)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeCamera.cpp	(revision 61)
@@ -0,0 +1,114 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreecamera.cpp  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+
+Enhancements 2003 - 2004 (C) The OGRE Team
+
+***************************************************************************/
+#include <OgreMath.h>
+#include <OgreAxisAlignedBox.h>
+#include <OgreRoot.h>
+
+#include <OgreOctreeCamera.h>
+
+namespace Ogre
+{
+OctreeCamera::OctreeCamera( const String& name, SceneManager* sm ) : Camera( name, sm )
+{
+                                                                      
+}
+
+OctreeCamera::~OctreeCamera()
+{
+}
+
+OctreeCamera::Visibility OctreeCamera::getVisibility( const AxisAlignedBox &bound )
+{
+
+    // Null boxes always invisible
+    if ( bound.isNull() )
+        return NONE;
+
+    // Make any pending updates to the calculated frustum
+    updateView();
+
+    // Get corners of the box
+    const Vector3* pCorners = bound.getAllCorners();
+
+    // For each plane, see if all points are on the negative side
+    // If so, object is not visible.
+    // If one or more are, it's partial.
+    // If all aren't, full
+
+    int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
+
+    int planes[ 6 ] = {FRUSTUM_PLANE_TOP, FRUSTUM_PLANE_BOTTOM,
+                       FRUSTUM_PLANE_LEFT, FRUSTUM_PLANE_RIGHT,
+                       FRUSTUM_PLANE_FAR, FRUSTUM_PLANE_NEAR };
+
+    bool all_inside = true;
+
+    for ( int plane = 0; plane < 6; ++plane )
+    {
+
+        // Skip far plane if infinite view frustum
+        if (mFarDist == 0 && planes[ plane ] == FRUSTUM_PLANE_FAR)
+            continue;
+
+        bool all_outside = true;
+
+        float distance = 0;
+
+        for ( int corner = 0; corner < 8; ++corner )
+        {
+            distance = mFrustumPlanes[ planes[ plane ] ].getDistance( pCorners[ corners[ corner ] ] );
+            all_outside = all_outside && ( distance < 0 );
+            all_inside = all_inside && ( distance >= 0 );
+
+            if ( !all_outside && !all_inside )
+                break;
+        }
+
+        if ( all_outside )
+            return NONE;
+    }
+
+    if ( all_inside )
+        return FULL;
+    else
+        return PARTIAL;
+
+}
+
+}
+
+
+
+
Index: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 318)
+++ OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 318)
@@ -0,0 +1,1228 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+/***************************************************************************
+octreescenemanager.cpp  -  description
+-------------------
+begin                : Fri Sep 27 2002
+copyright            : (C) 2002 by Jon Anderson
+email                : janders@users.sf.net
+ 
+Enhancements 2003 - 2004 (C) The OGRE Team
+ 
+***************************************************************************/
+
+#include <OgreOctreeSceneManager.h>
+#include <OgreOctreeSceneQuery.h>
+#include <OgreOctreeNode.h>
+#include <OgreOctreeCamera.h>
+#include <OgreRenderSystem.h>
+
+
+extern "C"
+{
+    void findNodesInBox( Ogre::SceneManager *sm,
+                         const Ogre::AxisAlignedBox &box,
+                         std::list < Ogre::SceneNode * > &list,
+                         Ogre::SceneNode *exclude )
+    {
+        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( box, list, exclude );
+    }
+    void findNodesInSphere( Ogre::SceneManager *sm,
+                            const Ogre::Sphere &sphere,
+                            std::list < Ogre::SceneNode * > &list,
+                            Ogre::SceneNode *exclude )
+    {
+        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( sphere, list, exclude );
+    }
+}
+
+namespace Ogre
+{
+enum Intersection
+{
+    OUTSIDE=0,
+    INSIDE=1,
+    INTERSECT=2
+};
+int OctreeSceneManager::intersect_call = 0;
+
+Intersection intersect( const Ray &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    bool inside = true;
+    const Vector3* pCorners = two.getAllCorners();
+    Vector3 origin = one.getOrigin();
+    Vector3 dir = one.getDirection();
+
+    Vector3 maxT(-1, -1, -1);
+
+    int i = 0;
+    for(i=0; i<3; i++ )
+    {
+        if( origin[i] < pCorners[0][i] )
+        {
+            inside = false;
+            if( dir[i] > 0 )
+            {
+                maxT[i] = (pCorners[0][i] - origin[i])/ dir[i];
+            }
+        }
+        else if( origin[i] > pCorners[4][i] )
+        {
+            inside = false;
+            if( dir[i] < 0 )
+            {
+                maxT[i] = (pCorners[4][i] - origin[i]) / dir[i];
+            }
+        }
+    }
+
+    if( inside )
+    {
+        return INTERSECT;
+    }
+    int whichPlane = 0;
+    if( maxT[1] > maxT[whichPlane])
+        whichPlane = 1;
+    if( maxT[2] > maxT[whichPlane])
+        whichPlane = 2;
+
+    if( ((int)maxT[whichPlane]) & 0x80000000 )
+    {
+        return OUTSIDE;
+    }
+    for(i=0; i<3; i++ )
+    {
+        if( i!= whichPlane )
+        {
+            float f = origin[i] + maxT[whichPlane] * dir[i];
+            if ( f < (pCorners[0][i] - 0.00001f) ||
+                    f > (pCorners[4][i] +0.00001f ) )
+            {
+                return OUTSIDE;
+            }
+        }
+    }
+
+    return INTERSECT;
+
+}
+
+
+/** Checks how the second box intersects with the first.
+*/
+Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    // Get corners of the box
+    const Vector3* pCorners = two.getAllCorners();
+
+    // For each plane, see if all points are on the negative side
+    // If so, object is not visible.
+    // If one or more are, it's partial.
+    // If all aren't, full
+    int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
+    bool all_inside = true;
+    PlaneList::const_iterator i, iend;
+    iend = one.planes.end();
+    for (i = one.planes.begin(); i != iend; ++i)
+    {
+        const Plane& plane = *i;
+        bool all_outside = true;
+
+        float distance = 0;
+
+        for ( int corner = 0; corner < 8; ++corner )
+        {
+            distance = plane.getDistance( pCorners[ corners[ corner ] ] );
+            all_outside = all_outside && ( distance < 0 );
+            all_inside = all_inside && ( distance >= 0 );
+
+            if ( !all_outside && !all_inside )
+                break;
+        }
+
+        if ( all_outside )
+            return OUTSIDE;
+    }
+
+    if ( all_inside )
+        return INSIDE;
+    else
+        return INTERSECT;
+
+}
+
+
+/** Checks how the second box intersects with the first.
+*/
+Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (one.isNull() || two.isNull()) return OUTSIDE;
+
+    const Vector3 * outside = one.getAllCorners();
+    const Vector3 *inside = two.getAllCorners();
+
+    if ( inside[ 4 ].x < outside[ 0 ].x ||
+            inside[ 4 ].y < outside[ 0 ].y ||
+            inside[ 4 ].z < outside[ 0 ].z ||
+            inside[ 0 ].x > outside[ 4 ].x ||
+            inside[ 0 ].y > outside[ 4 ].y ||
+            inside[ 0 ].z > outside[ 4 ].z )
+    {
+        return OUTSIDE;
+    }
+
+    bool full = ( inside[ 0 ].x > outside[ 0 ].x &&
+                  inside[ 0 ].y > outside[ 0 ].y &&
+                  inside[ 0 ].z > outside[ 0 ].z &&
+                  inside[ 4 ].x < outside[ 4 ].x &&
+                  inside[ 4 ].y < outside[ 4 ].y &&
+                  inside[ 4 ].z < outside[ 4 ].z );
+
+    if ( full )
+        return INSIDE;
+    else
+        return INTERSECT;
+
+}
+
+/** Checks how the box intersects with the sphere.
+*/
+Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
+{
+    OctreeSceneManager::intersect_call++;
+    // Null box?
+    if (two.isNull()) return OUTSIDE;
+
+    float sradius = one.getRadius();
+
+    sradius *= sradius;
+
+    Vector3 scenter = one.getCenter();
+
+    const Vector3 *corners = two.getAllCorners();
+
+    float s, d = 0;
+
+    Vector3 mndistance = ( corners[ 0 ] - scenter );
+    Vector3 mxdistance = ( corners[ 4 ] - scenter );
+
+    if ( mndistance.squaredLength() < sradius &&
+            mxdistance.squaredLength() < sradius )
+    {
+        return INSIDE;
+    }
+
+    //find the square of the distance
+    //from the sphere to the box
+    for ( int i = 0 ; i < 3 ; i++ )
+    {
+        if ( scenter[ i ] < corners[ 0 ][ i ] )
+        {
+            s = scenter[ i ] - corners[ 0 ][ i ];
+            d += s * s;
+        }
+
+        else if ( scenter[ i ] > corners[ 4 ][ i ] )
+        {
+            s = scenter[ i ] - corners[ 4 ][ i ];
+            d += s * s;
+        }
+
+    }
+
+    bool partial = ( d <= sradius );
+
+    if ( !partial )
+    {
+        return OUTSIDE;
+    }
+
+    else
+    {
+        return INTERSECT;
+    }
+
+
+}
+
+unsigned long white = 0xFFFFFFFF;
+
+unsigned short OctreeSceneManager::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
+        0, 6, 6, 5, 5, 1,             //left
+        3, 7, 7, 4, 4, 2,             //right
+        6, 7, 5, 4 };          //front
+unsigned long OctreeSceneManager::mColors[ 8 ] = {white, white, white, white, white, white, white, white };
+
+
+OctreeSceneManager::OctreeSceneManager( ) : SceneManager()
+{
+    AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
+    int depth = 8; 
+    mOctree = 0;
+    init( b, depth );
+}
+
+OctreeSceneManager::OctreeSceneManager( AxisAlignedBox &box, int max_depth ) : SceneManager()
+{
+    mOctree = 0;
+    init( box, max_depth );
+}
+
+void OctreeSceneManager::init( AxisAlignedBox &box, int depth )
+{
+    delete mSceneRoot; //get rid of old root.
+
+    // -- Changes by Steve
+    // Don't do it this way, it will add it to the mSceneNodes which we don't want
+    //mSceneRoot = createSceneNode( "SceneRoot" );
+    mSceneRoot = new OctreeNode( this, "SceneRoot" );
+	mSceneRoot->_notifyRootNode();
+    // -- End changes by Steve
+
+    if ( mOctree != 0 )
+        delete mOctree;
+
+    mOctree = new Octree( 0 );
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	mNumOctants = 1; // initialise number of octants in tree
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    mMaxDepth = depth;
+    mBox = box;
+
+    mOctree -> mBox = box;
+
+    Vector3 min = box.getMinimum();
+
+    Vector3 max = box.getMaximum();
+
+    mOctree -> mHalfSize = ( max - min ) / 2;
+
+
+    mShowBoxes = false;
+
+    mCullCamera = false;
+
+    mNumObjects = 0;
+
+    Vector3 v( 1.5, 1.5, 1.5 );
+
+    mScaleFactor.setScale( v );
+
+
+
+    // setDisplaySceneNodes( true );
+    // setShowBoxes( true );
+
+    //
+    //setUseCullCamera( true );
+    //mSceneRoot isn't put into the octree since it has no volume.
+
+}
+
+OctreeSceneManager::~OctreeSceneManager()
+{
+    // -- Changed by Steve
+    // Don't do this here, SceneManager will do it
+    /*
+    if( mSceneRoot )
+    delete mSceneRoot;
+    */ 
+    // --End Changes by Steve
+
+    if ( mOctree )
+        delete mOctree;
+}
+
+Camera * OctreeSceneManager::createCamera( const String &name )
+{
+    Camera * c = new OctreeCamera( name, this );
+    mCameras.insert( CameraList::value_type( name, c ) );
+    return c;
+}
+
+void OctreeSceneManager::destroySceneNode( const String &name )
+{
+    OctreeNode * on = static_cast < OctreeNode* > ( getSceneNode( name ) );
+
+    if ( on != 0 )
+        _removeOctreeNode( on );
+
+    SceneManager::destroySceneNode( name );
+}
+
+bool OctreeSceneManager::getOptionValues( const String & key, StringVector  &refValueList )
+{
+    return SceneManager::getOptionValues( key, refValueList );
+}
+
+bool OctreeSceneManager::getOptionKeys( StringVector & refKeys )
+{
+    SceneManager::getOptionKeys( refKeys );
+    refKeys.push_back( "CullCamera" );
+    refKeys.push_back( "Size" );
+    refKeys.push_back( "ShowOctree" );
+    refKeys.push_back( "Depth" );
+
+    return true;
+}
+
+
+void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
+{
+    AxisAlignedBox box = onode -> _getWorldAABB();
+
+    if ( box.isNull() )
+        return ;
+
+
+    if ( onode -> getOctant() == 0 )
+    {
+        //if outside the octree, force into the root node.
+        if ( ! onode -> _isIn( mOctree -> mBox ) )
+            mOctree->_addNode( onode );
+        else
+            _addOctreeNode( onode, mOctree );
+        return ;
+    }
+
+    if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
+    {
+        _removeOctreeNode( onode );
+
+        //if outside the octree, force into the root node.
+        if ( ! onode -> _isIn( mOctree -> mBox ) )
+            mOctree->_addNode( onode );
+        else
+            _addOctreeNode( onode, mOctree );
+    }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	else // still update because bounding box may be different
+	{
+		onode -> getOctant() -> _updateBounds();
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
+
+/** Only removes the node from the octree.  It leaves the octree, even if it's empty.
+*/
+void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
+{
+    Octree * oct = n -> getOctant();
+
+    if ( oct )
+    {
+        oct -> _removeNode( n );
+    }
+
+    n->setOctant(0);
+}
+
+
+void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
+{
+
+    AxisAlignedBox bx = n -> _getWorldAABB();
+
+
+    //if the octree is twice as big as the scene node,
+    //we will add it to a child.
+    if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
+    {
+        int x, y, z;
+        octant -> _getChildIndexes( bx, &x, &y, &z );
+
+        if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
+        {
+            octant -> mChildren[ x ][ y ][ z ] = new Octree( octant );
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+			++ mNumOctants;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+            const Vector3 *corners = octant -> mBox.getAllCorners();
+            Vector3 min, max;
+
+            if ( x == 0 )
+            {
+                min.x = corners[ 0 ].x;
+                max.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
+            }
+
+            else
+            {
+                min.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
+                max.x = corners[ 4 ].x;
+            }
+
+            if ( y == 0 )
+            {
+                min.y = corners[ 0 ].y;
+                max.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
+            }
+
+            else
+            {
+                min.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
+                max.y = corners[ 4 ].y;
+            }
+
+            if ( z == 0 )
+            {
+                min.z = corners[ 0 ].z;
+                max.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
+            }
+
+            else
+            {
+                min.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
+                max.z = corners[ 4 ].z;
+            }
+
+            octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
+            octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
+        }
+
+        _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
+
+    }
+
+    else
+    {
+        octant -> _addNode( n );
+    }
+}
+
+
+SceneNode * OctreeSceneManager::createSceneNode( void )
+{
+    OctreeNode * on = new OctreeNode( this );
+    mSceneNodes[ on->getName() ] = on;
+    return on;
+}
+
+SceneNode * OctreeSceneManager::createSceneNode( const String &name )
+{
+    OctreeNode * on = new OctreeNode( this, name );
+    mSceneNodes[ on->getName() ] = on;
+    return on;
+}
+
+void OctreeSceneManager::_updateSceneGraph( Camera * cam )
+{
+    SceneManager::_updateSceneGraph( cam );
+}
+
+void OctreeSceneManager::_alertVisibleObjects( void )
+{
+    NodeList::iterator it = mVisible.begin();
+
+    while ( it != mVisible.end() )
+    {
+        OctreeNode * node = *it;
+
+        ++it;
+    }
+}
+
+void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
+{
+
+    getRenderQueue()->clear();
+    mBoxes.clear();
+    mVisible.clear();
+
+    if ( mCullCamera )
+    {
+        Camera * c = getCamera( "CullCamera" );
+
+        if ( c != 0 )
+            cam = getCamera( "CullCamera" );
+    }
+
+    mNumObjects = 0;
+
+    //walk the octree, adding all visible Octreenodes nodes to the render queue.
+    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
+
+
+    // Show the octree boxes & cull camera if required
+    if ( mShowBoxes || mCullCamera )
+    {
+
+
+
+        if ( mShowBoxes )
+        {
+            for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
+            {
+                getRenderQueue()->addRenderable(*it);
+            }
+        }
+
+        if ( mCullCamera )
+        {
+            OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
+
+            if ( c != 0 )
+            {
+                getRenderQueue()->addRenderable(c);
+            }
+        }
+
+    }
+
+
+
+}
+
+void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
+                                     Octree *octant, bool foundvisible, bool onlyShadowCasters )
+{
+
+    //return immediately if nothing is in the node.
+    if ( octant -> numNodes() == 0 )
+        return ;
+
+    OctreeCamera::Visibility v = OctreeCamera::NONE;
+
+    if ( foundvisible )
+    {
+        v = OctreeCamera::FULL;
+    }
+
+    else if ( octant == mOctree )
+    {
+        v = OctreeCamera::PARTIAL;
+    }
+
+    else
+    {
+        AxisAlignedBox box;
+        octant -> _getCullBounds( &box );
+        v = camera -> getVisibility( box );
+    }
+
+
+    // if the octant is visible, or if it's the root node...
+    if ( v != OctreeCamera::NONE )
+    {
+
+        //Add stuff to be rendered;
+        NodeList::iterator it = octant -> mNodes.begin();
+
+        if ( mShowBoxes )
+        {
+            mBoxes.push_back( octant->getWireBoundingBox() );
+        }
+
+        bool vis = true;
+
+        while ( it != octant -> mNodes.end() )
+        {
+            OctreeNode * sn = *it;
+
+            // if this octree is partially visible, manually cull all
+            // scene nodes attached directly to this level.
+
+            if ( v == OctreeCamera::PARTIAL )
+                vis = camera -> isVisible( sn -> _getWorldAABB() );
+
+            if ( vis )
+            {
+
+                mNumObjects++;
+                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
+
+                mVisible.push_back( sn );
+
+                if ( mDisplayNodes )
+                    queue -> addRenderable( sn );
+
+                // check if the scene manager or this node wants the bounding box shown.
+                if (sn->getShowBoundingBox() || mShowBoundingBoxes)
+                    sn->_addBoundingBoxToQueue(queue);
+            }
+
+            ++it;
+        }
+
+        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
+
+    }
+
+}
+
+// --- non template versions
+void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+
+void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
+{
+
+	if ( !full )
+	{
+		AxisAlignedBox obox;
+		octant -> _getCullBounds( &obox );
+
+		Intersection isect = intersect( t, obox );
+
+		if ( isect == OUTSIDE )
+			return ;
+
+		full = ( isect == INSIDE );
+	}
+
+
+	NodeList::iterator it = octant -> mNodes.begin();
+
+	while ( it != octant -> mNodes.end() )
+	{
+		OctreeNode * on = ( *it );
+
+		if ( on != exclude )
+		{
+			if ( full )
+			{
+				list.push_back( on );
+			}
+
+			else
+			{
+				Intersection nsect = intersect( t, on -> _getWorldAABB() );
+
+				if ( nsect != OUTSIDE )
+				{
+					list.push_back( on );
+				}
+			}
+
+		}
+
+		++it;
+	}
+
+
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
+
+	if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
+
+	if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
+
+	if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
+		_findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
+
+}
+
+void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( box, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( sphere, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( volume, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
+{
+    _findNodes( r, list, exclude, false, mOctree );
+}
+
+void OctreeSceneManager::resize( const AxisAlignedBox &box )
+{
+    std::list < SceneNode * > nodes;
+    std::list < SceneNode * > ::iterator it;
+
+    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
+
+    delete mOctree;
+
+    mOctree = new Octree( 0 );
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	mNumOctants = 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    mOctree->mBox = box;
+
+    it = nodes.begin();
+
+    while ( it != nodes.end() )
+    {
+        OctreeNode * on = static_cast < OctreeNode * > ( *it );
+        on -> setOctant( 0 );
+        _updateOctreeNode( on );
+        ++it;
+    }
+
+}
+
+bool OctreeSceneManager::setOption( const String & key, const void * val )
+{
+    if ( key == "Size" )
+    {
+        resize( * static_cast < const AxisAlignedBox * > ( val ) );
+        return true;
+    }
+
+    else if ( key == "Depth" )
+    {
+        mMaxDepth = * static_cast < const int * > ( val );
+        resize( mOctree->mBox );
+        return true;
+    }
+
+    else if ( key == "ShowOctree" )
+    {
+        mShowBoxes = * static_cast < const bool * > ( val );
+        return true;
+    }
+
+    else if ( key == "CullCamera" )
+    {
+        mCullCamera = * static_cast < const bool * > ( val );
+        return true;
+    }
+
+    return SceneManager::setOption( key, val );
+
+
+}
+
+bool OctreeSceneManager::getOption( const String & key, void *val )
+{
+    if ( key == "Size" )
+    {
+        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
+        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
+        return true;
+    }
+
+    else if ( key == "Depth" )
+    {
+        * static_cast < int * > ( val ) = mMaxDepth;
+        return true;
+    }
+
+    else if ( key == "ShowOctree" )
+    {
+
+        * static_cast < bool * > ( val ) = mShowBoxes;
+        return true;
+    }
+
+    else if ( key == "CullCamera" )
+    {
+        * static_cast < bool * > ( val ) = mCullCamera;
+        return true;
+    }
+
+    return SceneManager::getOption( key, val );
+
+}
+
+void OctreeSceneManager::clearScene(void)
+{
+    SceneManager::clearScene();
+    init(mBox, mMaxDepth);
+
+}
+
+//---------------------------------------------------------------------
+AxisAlignedBoxSceneQuery*
+OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
+{
+    OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
+    q->setBox(box);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+SphereSceneQuery*
+OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
+{
+    OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
+    q->setSphere(sphere);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+PlaneBoundedVolumeListSceneQuery*
+OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
+        unsigned long mask)
+{
+    OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
+    q->setVolumes(volumes);
+    q->setQueryMask(mask);
+    return q;
+}
+
+//---------------------------------------------------------------------
+RaySceneQuery*
+OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
+{
+    OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
+    q->setRay(ray);
+    q->setQueryMask(mask);
+    return q;
+}
+//---------------------------------------------------------------------
+IntersectionSceneQuery*
+OctreeSceneManager::createIntersectionQuery(unsigned long mask)
+{
+
+    // Octree implementation performs WORSE for < 500 objects
+    // TODO: optimise it so it's better in all cases
+    //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
+    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
+    q->setQueryMask(mask);
+    return q;
+}
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//-----------------------------------------------------------------------	
+BoxList *OctreeSceneManager::getBoxes()
+{
+	return &mBoxes;
+}
+//-----------------------------------------------------------------------
+void OctreeSceneManager::_renderOctant(Camera *cam, Octree *octant, bool onlyShadowCasters, 
+									   const int leavePassesInQueue)
+{
+	// delete previously rendered objects from the render queue
+	_deleteRenderedQueueGroups(leavePassesInQueue);
+
+	//Add stuff to be rendered;
+    NodeList::iterator it = octant->mNodes.begin();
+         
+    while(it != octant->mNodes.end())
+    {
+		OctreeNode *sn = *it;
+
+        ++mNumObjects;
+
+		// check bounding box visibility of scene nodes
+		if (cam->isVisible(sn->_getWorldAABB()))
+		{
+			sn->_addToRenderQueue(cam, getRenderQueue(), onlyShadowCasters);
+			mVisible.push_back(sn);
+
+			if (mDisplayNodes)
+			{
+				getRenderQueue()->addRenderable(sn);
+			}
+
+			// check if the scene manager or this node wants the bounding box shown.
+			if (sn->getShowBoundingBox() || mShowBoundingBoxes)
+			{
+				sn->_addBoundingBoxToQueue(getRenderQueue());
+			}
+		}
+        ++it;
+	}
+
+	if (mShowBoxes)
+	{
+		octant->getWireBoundingBox()->setMaterial("BaseWhiteNoLighting");
+
+		getRenderQueue()->addRenderable(octant->getWireBoundingBox());
+		mBoxes.push_back(octant->getWireBoundingBox());
+	}
+
+	//-- the actual rendering
+	SceneManager::_renderVisibleObjects();
+}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLTexture.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLTexture.h	(revision 153)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLTexture.h	(revision 153)
@@ -0,0 +1,169 @@
+/*
+-----------------------------------------------------------------------------
+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 __GLTEXTURE_H__
+#define __GLTEXTURE_H__
+
+#include "OgreGLPrerequisites.h"
+#include "OgrePlatform.h"
+#include "OgreRenderTexture.h"
+#include "OgreTexture.h"
+#include "OgreGLSupport.h"
+#include "OgreHardwarePixelBuffer.h"
+
+namespace Ogre {
+
+    class GLTexture : public Texture
+    {
+    public:
+        // Constructor
+        GLTexture(ResourceManager* creator, const String& name, ResourceHandle handle,
+            const String& group, bool isManual, ManualResourceLoader* loader, 
+            GLSupport& support);
+
+        virtual ~GLTexture();      
+
+        /// @copydoc Texture::createInternalResources
+        void createInternalResources(void);
+		void loadImage( const Image& img );
+        void createRenderTexture();
+			
+		/// @copydoc Texture::getBuffer
+		HardwarePixelBufferSharedPtr getBuffer(size_t face, size_t mipmap);
+
+        // Takes the OGRE texture type (1d/2d/3d/cube) and returns the appropriate GL one
+        GLenum getGLTextureTarget(void) const;
+
+        GLuint getGLID() const
+        { return mTextureID; }
+
+    protected:
+        /// @copydoc Resource::loadImpl
+        void loadImpl(void);
+        /// @copydoc Resource::unloadImpl
+        void unloadImpl(void);
+
+		/** internal method, create GLHardwarePixelBuffers for every face and
+			 mipmap level. This method must be called after the GL texture object was created,
+			the number of mipmaps was set (GL_TEXTURE_MAX_LEVEL) and glTexImageXD was called to
+			actually allocate the buffer
+		*/
+		void _createSurfaceList();
+    private:
+        GLuint mTextureID;
+        GLSupport& mGLSupport;
+		
+		/// Vector of pointers to subsurfaces
+		typedef std::vector<HardwarePixelBufferSharedPtr> SurfaceList;
+		SurfaceList	mSurfaceList;
+    };
+
+    /** Specialisation of SharedPtr to allow SharedPtr to be assigned to GLTexturePtr 
+    @note Has to be a subclass since we need operator=.
+    We could templatise this instead of repeating per Resource subclass, 
+    except to do so requires a form VC6 does not support i.e.
+    ResourceSubclassPtr<T> : public SharedPtr<T>
+    */
+    class GLTexturePtr : public SharedPtr<GLTexture> 
+    {
+    public:
+        GLTexturePtr() : SharedPtr<GLTexture>() {}
+        explicit GLTexturePtr(GLTexture* rep) : SharedPtr<GLTexture>(rep) {}
+        GLTexturePtr(const GLTexturePtr& r) : SharedPtr<GLTexture>(r) {} 
+        GLTexturePtr(const ResourcePtr& r) : SharedPtr<GLTexture>()
+        {
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<GLTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+        }
+
+        /// Operator used to convert a ResourcePtr to a GLTexturePtr
+        GLTexturePtr& operator=(const ResourcePtr& r)
+        {
+            if (pRep == static_cast<GLTexture*>(r.getPointer()))
+                return *this;
+            release();
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<GLTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+        /// Operator used to convert a TexturePtr to a GLTexturePtr
+        GLTexturePtr& operator=(const TexturePtr& r)
+        {
+            if (pRep == static_cast<GLTexture*>(r.getPointer()))
+                return *this;
+            release();
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<GLTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+    };
+
+    /// GL implementation of RenderTexture
+    class GLRenderTexture : public RenderTexture
+    {
+    public:
+        GLRenderTexture(const String& name, uint width, uint height, TextureType texType, PixelFormat format,
+			const NameValuePairList *miscParams) 
+            : RenderTexture(name, width, height, texType, format) 
+        {
+            mGLTexture = mTexture;
+        }
+
+        void _copyToTexture(void);
+
+        bool requiresTextureFlipping() const { return true; }
+        virtual void writeContentsToFile( const String & filename );
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+        GLTexturePtr mGLTexture;
+    };
+}
+
+#endif // __GLTEXTURE_H__
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLHardwareOcclusionQuery.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLHardwareOcclusionQuery.h	(revision 343)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLHardwareOcclusionQuery.h	(revision 343)
@@ -0,0 +1,133 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+/*
+The nVidia occlusion query extension is defined in glext.h so you don't 
+need anything else. You do need to look up the function, we provide a 
+GLSupport class to do this, which has platform implementations for 
+getProcAddress. Check the way that extensions like glActiveTextureARB are 
+initialised and used in glRenderSystem and copy what is done there.
+
+
+
+  To do: fix so dx7 and DX9 checks and flags if HW Occlusion is supported
+  See the openGl dito for ideas what to do.
+
+*/
+
+
+
+//GL_ActiveTextureARB_Func* glActiveTextureARB_ptr = (GL_ActiveTextureARB_Func)mGLSupport->getProcAddress("glActiveTextureARB");
+
+#ifndef __GLHARDWAREOCCLUSIONQUERY_H__
+#define __GLHARDWAREOCCLUSIONQUERY_H__
+
+#include "OgreGLPrerequisites.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+
+namespace Ogre { 
+
+
+// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
+// if the first pass resultet has too few pixels visable.
+
+// Be sure to render all occlluder first and whats out so the RenderQue don't switch places on 
+// the occluding objects and the tested objects because it thinks it's more effective..
+
+
+/**
+  * This is a class that is the base class of the query class for 
+  * hardware occlusion.
+  *
+  * @author Lee Sandberg email: lee@abcmedia.se
+  */
+
+class GLHardwareOcclusionQuery : public HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	GLHardwareOcclusionQuery();
+	/**
+	  * Object destructor
+	  */
+	~GLHardwareOcclusionQuery();
+
+	//------------------------------------------------------------------
+	// Occlusion query functions (see base class documentation for this)
+	//--
+
+	void beginOcclusionQuery();
+	void endOcclusionQuery();
+	bool pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ); 
+	unsigned int getLastQuerysPixelcount() { return mPixelCount; }
+
+	// This functions are optional, it's a simple filter that simply skipps some hardware occlusion tests on visable objects only
+	// It's easy to use if you don't have to keep track on which objects are visable (can be skipped) and what objects arn't visable..
+	// (None visable objects and object you introduce for the first time have allways to be tested allthough the cheepest possible 
+	// LOD (Level Of Detail) mesh and material wize). 
+
+	/**
+	  *   
+	  * Remarks This function allows you to set how often the hardware occlusion really sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 2 only 50% of your queries are sent. 
+	  * for all visable objects. 3 will result in 33% of all queries to acctualy be sent and so on. 
+	  * New and none visable objects will be tested all the time.
+	  * This functionality is here because this class can keep track on visable and none visable objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+	void setSkipRate( int skip ) { mSkipInterval = skip; }		// Using 2 only 50 % of the tests are actully made and 3 results in only 33% of the tests. So on.
+	int	 getSkipRate() { return mSkipInterval; } 
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool pullOcclusionQuery( unsigned int* NumOfFragments, const bool waitForResult, const HW_OCCLUSIONQUERY flag = HWOCCLUSIONQUERY_FLUSH ); 
+
+	static bool sUseArbQueries;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+//----------------------------------------------------------------------
+// Protected members
+//--
+protected:
+
+	unsigned int	mPixelCount;
+	GLuint			mQueryID;
+	bool			m_bOcclusionQuery;
+	int				mSkipCounter;
+	int				mSkipInterval;
+	bool			mHasOcclusionSupportNV;
+	bool			mHasOcclusionSupportARB;
+};
+
+}
+
+#endif 
+
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLPrerequisites.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLPrerequisites.h	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreGLPrerequisites.h	(revision 193)
@@ -0,0 +1,298 @@
+/*
+-----------------------------------------------------------------------------
+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 __GLPrerequisites_H__
+#define __GLPrerequisites_H__
+
+#include "OgrePrerequisites.h"
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#if !defined( __MINGW32__ )
+#   define NOMINMAX // required to stop windows.h messing up std::min
+#endif
+#   include <windows.h>
+#   include <wingdi.h>
+#   include <GL/gl.h>
+#   define GL_GLEXT_PROTOTYPES
+#   include "glprocs.h"
+#   include <GL/glu.h>
+// Windows library does not include glSecondaryColorPointer even though it's standard now
+#   define glSecondaryColorPointer glSecondaryColorPointerEXT
+#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
+// define GL_GLEXT_LEGACY so that Mesa headers won't try to include their own
+// glext.h file.
+#   define GL_GLEXT_LEGACY
+#   include <GL/gl.h>
+#   include <GL/glu.h>
+#   define GL_GLEXT_PROTOTYPES
+#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+#   define GL_GLEXT_PROTOTYPES
+#   ifndef APIENTRY
+#       define APIENTRY
+#   endif
+#   define GL_GLEXT_LEGACY 
+#   include <OpenGL/gl.h>
+#   include <OpenGL/glu.h>
+#endif
+#include "GL/glext.h"
+
+extern "C" {
+// Pointer to glActiveTextureARB function
+typedef void (APIENTRY *GL_ActiveTextureARB_Func)(GLenum);
+extern GL_ActiveTextureARB_Func glActiveTextureARB_ptr;
+
+// Pointer to glClientActiveTextureARB function
+typedef void (APIENTRY *GL_ClientActiveTextureARB_Func)(GLenum);
+extern GL_ClientActiveTextureARB_Func glClientActiveTextureARB_ptr;
+
+// Pointer to glSecondaryColorPointerEXT function
+typedef void (APIENTRY *GL_SecondaryColorPointerEXT_Func)(GLint, GLenum, GLsizei, const GLvoid*);
+extern GL_SecondaryColorPointerEXT_Func glSecondaryColorPointerEXT_ptr;
+
+// Pointer to glSecondaryColor3fEXT function
+typedef void (APIENTRY *GL_SecondaryColor3fEXT_Func)(GLfloat, GLfloat, GLfloat);
+extern GL_SecondaryColor3fEXT_Func glSecondaryColor3fEXT_ptr;
+
+// Pointer to glGenBuffersARB function
+typedef void (APIENTRY *GL_GenBuffersARB_Func)(GLsizei, GLuint*);
+extern GL_GenBuffersARB_Func glGenBuffersARB_ptr;
+
+// Pointer to glBindBufferARB function
+typedef void (APIENTRY *GL_BindBufferARB_Func)(GLenum, GLuint);
+extern GL_BindBufferARB_Func glBindBufferARB_ptr;
+
+// Pointer to glDeleteBuffersARB function
+typedef void (APIENTRY *GL_DeleteBuffersARB_Func)(GLsizei, const GLuint*);
+extern GL_DeleteBuffersARB_Func glDeleteBuffersARB_ptr;
+
+// Pointer to glMapBufferARB function
+typedef GLvoid* (APIENTRY *GL_MapBufferARB_Func)(GLenum, GLenum);
+extern GL_MapBufferARB_Func glMapBufferARB_ptr;
+
+// Pointer to glUnmapBufferARB function
+typedef GLboolean (APIENTRY *GL_UnmapBufferARB_Func)(GLenum);
+extern GL_UnmapBufferARB_Func glUnmapBufferARB_ptr;
+
+// Pointer to glBufferSubDataARB function
+typedef void (APIENTRY *GL_BufferSubDataARB_Func)(GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid*);
+extern GL_BufferSubDataARB_Func glBufferSubDataARB_ptr;
+
+// Pointer to glBufferDataARB function
+typedef void (APIENTRY *GL_BufferDataARB_Func)(GLenum, GLsizeiptrARB, const GLvoid* , GLenum);
+extern GL_BufferDataARB_Func glBufferDataARB_ptr;
+
+// Pointer to glGetBufferSubDataARB function
+typedef void (APIENTRY *GL_GetBufferSubDataARB_Func)(GLenum, GLintptrARB, GLsizeiptrARB, GLvoid*);
+extern GL_GetBufferSubDataARB_Func glGetBufferSubDataARB_ptr;
+
+// Pointer to glGenProgramsARB function
+typedef void (APIENTRY *GL_GenProgramsARB_Func)(GLsizei, GLuint*);
+extern GL_GenProgramsARB_Func glGenProgramsARB_ptr;
+
+// Pointer to glDeleteProgramsARB function
+typedef void (APIENTRY *GL_DeleteProgramsARB_Func)(GLsizei, const GLuint*);
+extern GL_DeleteProgramsARB_Func glDeleteProgramsARB_ptr;
+
+// Pointer to glBindProgramARB function
+typedef void (APIENTRY *GL_BindProgramARB_Func)(GLenum, GLuint);
+extern GL_BindProgramARB_Func glBindProgramARB_ptr;
+
+// Pointer to glProgramStringARB function
+typedef void (APIENTRY *GL_ProgramStringARB_Func)(GLenum, GLenum, GLsizei, const GLvoid*);
+extern GL_ProgramStringARB_Func glProgramStringARB_ptr;
+
+// Pointer to glProgramLocalParameter4fvARB function
+typedef void (APIENTRY *GL_ProgramLocalParameter4fvARB_Func)(GLenum, GLuint, const GLfloat *);
+extern GL_ProgramLocalParameter4fvARB_Func glProgramLocalParameter4fvARB_ptr;
+
+// Pointer to glProgramParameter4fvNV function
+typedef void (APIENTRY *GL_ProgramParameter4fvNV_Func)(GLenum, GLuint, const GLfloat *);
+extern GL_ProgramParameter4fvNV_Func glProgramParameter4fvNV_ptr;
+
+// Pointer to glVertexAttribPointerARB function
+typedef void (APIENTRY *GL_VertexAttribPointerARB_Func) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+extern GL_VertexAttribPointerARB_Func glVertexAttribPointerARB_ptr;
+// Pointer to glEnableVertexAttribArrayARB function
+typedef void (APIENTRY *GL_EnableVertexAttribArrayARB_Func) (GLuint);
+extern GL_EnableVertexAttribArrayARB_Func glEnableVertexAttribArrayARB_ptr;
+// Pointer to glDisableVertexAttribArrayARB function
+typedef void (APIENTRY *GL_DisableVertexAttribArrayARB_Func) (GLuint);
+extern GL_DisableVertexAttribArrayARB_Func glDisableVertexAttribArrayARB_ptr;
+
+
+
+// Pointer to glCombinerStageParameterfvNV function
+typedef void (APIENTRY *GL_CombinerStageParameterfvNV_Func)(GLenum, GLenum, const GLfloat *);
+extern GL_CombinerStageParameterfvNV_Func glCombinerStageParameterfvNV_ptr;
+
+// Pointer to glCombinerParameterfvNV function
+typedef void (APIENTRY *GL_CombinerParameterfvNV_Func)(GLenum, const GLfloat *);
+extern GL_CombinerParameterfvNV_Func glCombinerParameterfvNV_ptr;
+
+// Pointer to glCombinerParameteriNV function
+typedef void (APIENTRY *GL_CombinerParameteriNV_Func)(GLenum, GLint);
+extern GL_CombinerParameteriNV_Func glCombinerParameteriNV_ptr;
+
+// Pointer to glCombinerInputNV function
+typedef void (APIENTRY *GL_CombinerInputNV_Func)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);
+extern GL_CombinerInputNV_Func glCombinerInputNV_ptr;
+
+// Pointer to glCombinerOutputNV function
+typedef void (APIENTRY *GL_CombinerOutputNV_Func)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);
+
+extern GL_CombinerOutputNV_Func glCombinerOutputNV_ptr;
+
+// Pointer to glFinalCombinerInputNV function
+typedef void (APIENTRY *GL_FinalCombinerInputNV_Func)(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+
+extern GL_FinalCombinerInputNV_Func glFinalCombinerInputNV_ptr;
+
+// Pointer to glGetProgramivARB function
+typedef void (APIENTRY *GL_GetProgramivARB_Func)(GLenum, GLenum, GLint *);
+extern GL_GetProgramivARB_Func glGetProgramivARB_ptr;
+
+// Pointer to glLoadProgramNV function
+typedef void (APIENTRY *GL_LoadProgramNV_Func)(GLenum, GLuint, GLsizei, const GLubyte *);
+extern GL_LoadProgramNV_Func glLoadProgramNV_ptr;
+
+// Pointer to glTrackMatrixNV function
+typedef void (APIENTRY *GL_TrackMatrixNV_Func)(GLenum, GLuint, GLenum, GLenum);
+extern GL_TrackMatrixNV_Func glTrackMatrixNV_ptr;
+
+// Pointer to glActiveStencilFaceEXT function
+typedef void (APIENTRY *GL_ActiveStencilFaceEXT_Func)(GLenum);
+extern GL_ActiveStencilFaceEXT_Func glActiveStencilFaceEXT_ptr;
+
+// Pointer to glGenOcclusionQueriesNV function
+typedef void (APIENTRY *GL_GenOcclusionQueriesNV_Func) (GLsizei n, GLuint *ids);
+extern GL_GenOcclusionQueriesNV_Func glGenOcclusionQueriesNV_ptr;
+
+// Pointer to glDeleteOcclusionQueriesNV function
+typedef void (APIENTRY *GL_DeleteOcclusionQueriesNV_Func) (GLsizei n, const GLuint *ids);
+extern GL_DeleteOcclusionQueriesNV_Func glDeleteOcclusionQueriesNV_ptr;
+
+// Pointer to glIsOcclusionQueryNV function
+typedef GLboolean (APIENTRY *GL_IsOcclusionQueryNV_Func) (GLuint id);
+extern GL_IsOcclusionQueryNV_Func glIsOcclusionQueryNV_ptr;
+
+// Pointer to glBeginOcclusionQueryNV function
+typedef void (APIENTRY *GL_BeginOcclusionQueryNV_Func) (GLuint id);
+extern GL_BeginOcclusionQueryNV_Func glBeginOcclusionQueryNV_ptr;
+
+// Pointer to glEndOcclusionQueryNV function
+typedef void (APIENTRY *GL_EndOcclusionQueryNV_Func) (void);
+extern GL_EndOcclusionQueryNV_Func glEndOcclusionQueryNV_ptr;
+
+// Pointer to glGetOcclusionQueryivNV function
+typedef void (APIENTRY *GL_GetOcclusionQueryivNV_Func) (GLuint id, GLenum pname, GLint *params);
+extern GL_GetOcclusionQueryivNV_Func glGetOcclusionQueryivNV_ptr;
+
+// Pointer to glGetOcclusionQueryuivNV function
+typedef void (APIENTRY *GL_GetOcclusionQueryuivNV_Func) (GLuint id, GLenum pname, GLuint *params);
+extern GL_GetOcclusionQueryuivNV_Func glGetOcclusionQueryuivNV_ptr;
+
+extern PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB_ptr;
+extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB_ptr;
+extern PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB_ptr;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB_ptr;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB_ptr;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB_ptr;
+extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB_ptr;
+
+};
+
+// Pointer to glGenQueriesARB function
+typedef void (APIENTRY *GL_GenQueriesARB_Func) (GLuint n, GLuint *ids);
+extern GL_GenQueriesARB_Func glGenQueriesARB_ptr;
+
+// Pointer to glDeleteQueriesARB function
+typedef void (APIENTRY *GL_DeleteQueriesARB_Func) (GLuint n, const GLuint *ids);
+extern GL_DeleteQueriesARB_Func glDeleteQueriesARB_ptr;
+
+// Pointer to glBeginQueryARB function
+typedef void (APIENTRY *GL_BeginQueryARB_Func) (GLenum target, GLuint id);
+extern GL_BeginQueryARB_Func glBeginQueryARB_ptr;
+
+// Pointer to glEndQueryARB function
+typedef void (APIENTRY *GL_EndQueryARB_Func) (GLenum target);
+extern GL_EndQueryARB_Func glEndQueryARB_ptr;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+// Pointer to glGetQueryivARB function
+typedef void (APIENTRY *GL_GetQueryivARB_Func) (GLuint id, GLenum pname, GLint *params);
+extern GL_GetQueryivARB_Func glGetQueryivARB_ptr;
+
+// Pointer to glGetQueryObjectivARB function
+typedef void (APIENTRY *GL_GetQueryObjectivARB_Func) (GLuint id, GLenum pname, GLint *params);
+extern GL_GetQueryObjectivARB_Func glGetQueryObjectivARB_ptr;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+// Pointer to glGetQueryObjectuivARB function
+typedef void (APIENTRY *GL_GetQueryObjectuivARB_Func) (GLuint id, GLenum pname, GLuint *params);
+extern GL_GetQueryObjectuivARB_Func glGetQueryObjectuivARB_ptr;
+
+
+namespace Ogre {
+    // Forward declarations
+    class GLSupport;
+    class GLRenderSystem;
+    class GLTexture;
+    class GLTextureManager;
+    class GLGpuProgram;
+    class GLContext;
+}
+
+
+#ifdef  OGRE_DEBUG_MODE
+
+#ifndef GL_ERROR_EXCEPT
+
+#define OGRE_GL_GETERROR(ERROR_MSG) {const GLubyte *errString; \
+    GLenum errCode = glGetError(); \
+    if (errCode != GL_NO_ERROR) {  \
+    errString = gluErrorString (errCode);  \
+    LogManager::getSingleton().logMessage  ("[GL] :" + Ogre::String(ERROR_MSG) +  \
+    " : " + Ogre::String( (const char*) errString)); \
+        } \
+    }
+
+#else //GL_ERROR_EXCEPT
+
+#define OGRE_GL_GETERROR(ERROR_MSG) {const GLubyte *errString; \
+    GLenum errCode = glGetError(); \
+    if (errCode != GL_NO_ERROR) {  \
+    errString = gluErrorString (errCode);  \
+    OGRE_EXCEPT (Exception::ERR_INTERNAL_ERROR,  \
+    Ogre::String(ERROR_MSG) +  \
+    " : " + Ogre::String( (const char*) errString), String("")); \
+        } \
+    }
+
+#endif //GL_ERROR_EXCEPT
+
+#else //OGRE_DEBUG_MODE
+
+#define OGRE_GL_GETERROR()
+
+#endif //OGRE_DEBUG_MODE
+
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreSDLWindow.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreSDLWindow.h	(revision 154)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreSDLWindow.h	(revision 154)
@@ -0,0 +1,74 @@
+/*
+-----------------------------------------------------------------------------
+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 __SDLWindow_H__
+#define __SDLWindow_H__
+
+#include "OgreSDLPrerequisites.h"
+#include "OgreRenderWindow.h"
+
+namespace Ogre {
+    class SDLWindow : public RenderWindow
+    {
+    private:
+        SDL_Surface* mScreen;
+        bool mActive;
+        bool mClosed;
+            
+        // Process pending events
+        void processEvents(void);
+    public:
+        SDLWindow();
+        ~SDLWindow();
+
+		void create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams);
+        /** Overridden - see RenderWindow */
+        void destroy(void);
+        /** Overridden - see RenderWindow */
+        bool isActive(void) const;
+        /** Overridden - see RenderWindow */
+        bool isClosed(void) const;
+        /** Overridden - see RenderWindow */
+        void reposition(int left, int top);
+        /** Overridden - see RenderWindow */
+        void resize(unsigned int width, unsigned int height);
+        /** Overridden - see RenderWindow */
+        void swapBuffers(bool waitForVSync);
+
+        /** Overridden - see RenderTarget.
+        */
+        void writeContentsToFile(const String& filename);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy) {dimx = dimy = 0; return NULL; };
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+		bool requiresTextureFlipping() const { return false; }
+    };
+}
+
+#endif
+
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreWin32Window.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreWin32Window.h	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/include/OgreWin32Window.h	(revision 193)
@@ -0,0 +1,81 @@
+/*
+-----------------------------------------------------------------------------
+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 __Win32Window_H__
+#define __Win32Window_H__
+
+#include "OgreWin32Prerequisites.h"
+#include "OgreRenderWindow.h"
+
+namespace Ogre {
+    class Win32Window : public RenderWindow
+    {
+    public:
+        Win32Window(Win32GLSupport &glsupport);
+        ~Win32Window();
+
+       void create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams);
+        void destroy(void);
+        bool isVisible() const;
+        bool isClosed(void) const;
+        void reposition(int left, int top);
+        void resize(unsigned int width, unsigned int height);
+        void swapBuffers(bool waitForVSync);
+
+        /** Overridden - see RenderTarget.
+        */
+        void writeContentsToFile(const String& filename);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+		bool requiresTextureFlipping() const { return false; }
+
+		HWND getWindowHandle() const { return mHWnd; }
+		HDC getHDC() const { return mHDC; }
+		
+		// Method for dealing with resize / move & 3d library
+		virtual void windowMovedOrResized(void);
+		
+		void getCustomAttribute( const String& name, void* pData );
+
+	protected:
+		Win32GLSupport &mGLSupport;
+		HWND	mHWnd;					// Win32 Window handle
+		HDC		mHDC;
+		HGLRC	mGlrc;
+        bool    mIsExternal;
+        bool    mSizing;
+		bool	mClosed;
+        int     mDisplayFrequency;      // fullscreen only, to restore display
+        Win32Context *mContext;
+
+		static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+    };
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp	(revision 193)
@@ -0,0 +1,467 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreGLTexture.h"
+#include "OgreGLSupport.h"
+#include "OgreGLPixelFormat.h"
+#include "OgreGLHardwarePixelBuffer.h"
+
+#include "OgreTextureManager.h"
+#include "OgreImage.h"
+#include "OgreLogManager.h"
+#include "OgreCamera.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreCodec.h"
+#include "OgreImageCodec.h"
+#include "OgreStringConverter.h"
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#   include <windows.h>
+#   include <wingdi.h>
+#endif
+
+namespace Ogre {
+
+    unsigned int mostSignificantBitSet(unsigned int value)
+	{
+		unsigned int result = 0;
+		while (value != 0) {
+			++result;
+			value >>= 1;
+		}
+		return result-1;
+	}
+
+    GLTexture::GLTexture(ResourceManager* creator, const String& name, 
+        ResourceHandle handle, const String& group, bool isManual, 
+        ManualResourceLoader* loader, GLSupport& support) 
+        : Texture(creator, name, handle, group, isManual, loader),
+        mTextureID(0), mGLSupport(support)
+    {
+    }
+
+
+    GLTexture::~GLTexture()
+    {
+        // have to call this here reather than in Resource destructor
+        // since calling virtual methods in base destructors causes crash
+        unload(); 
+    }
+
+    GLenum GLTexture::getGLTextureTarget(void) const
+    {
+        switch(mTextureType)
+        {
+            case TEX_TYPE_1D:
+                return GL_TEXTURE_1D;
+            case TEX_TYPE_2D:
+                return GL_TEXTURE_2D;
+            case TEX_TYPE_3D:
+                return GL_TEXTURE_3D;
+            case TEX_TYPE_CUBE_MAP:
+                return GL_TEXTURE_CUBE_MAP;
+            default:
+                return 0;
+        };
+    }
+
+	//* Creation / loading methods ********************************************
+	void GLTexture::createInternalResources(void)
+    {
+		// Adjust requested parameters to capabilities
+
+		// Check power-of-two size if required
+        unsigned int newWidth = (1 << mostSignificantBitSet(mWidth));
+        if (newWidth != mWidth)
+            newWidth <<= 1;
+
+        unsigned int newHeight = (1 << mostSignificantBitSet(mHeight));
+        if (newHeight != mHeight)
+            newHeight <<= 1;
+
+		unsigned int newDepth = (1 << mostSignificantBitSet(mDepth));
+        if (newDepth != mDepth)
+            newDepth <<= 1;
+
+        if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_NON_POWER_OF_2_TEXTURES))
+		{
+			mHeight = newHeight;
+			mWidth = newWidth;
+			mDepth = newDepth;
+		}
+		
+		// Check compressed texture support
+		// if a compressed format not supported, revert to PF_A8R8G8B8
+		if(PixelUtil::isCompressed(mFormat) &&
+		 !Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_COMPRESSION_DXT ))
+		{
+			mFormat = PF_A8R8G8B8;
+		}
+		// if floating point textures not supported, revert to PF_A8R8G8B8
+		if(PixelUtil::isFloatingPoint(mFormat) &&
+		 !Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_FLOAT ))
+		{
+			mFormat = PF_A8R8G8B8;
+		}
+		
+		// Check requested number of mipmaps
+		// Zero means create mip levels until 1x1
+		size_t maxMips = GLPixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
+		if(mNumMipmaps>maxMips)
+			mNumMipmaps = maxMips;
+		
+		// Generate texture name
+        glGenTextures( 1, &mTextureID );
+		
+		// Set texture type
+		glBindTexture( getGLTextureTarget(), mTextureID );
+        
+		// This needs to be set otherwise the texture doesn't get rendered
+        glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
+		
+		// If we can do automip generation and the user desires this, do so
+		if((mUsage & TU_AUTOMIPMAP) &&
+		    mNumMipmaps &&
+		 	Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP))
+        {
+            glTexParameteri( getGLTextureTarget(), GL_GENERATE_MIPMAP, GL_TRUE );
+        }
+		
+		// Allocate internal buffer so that glTexSubImageXD can be used
+		// Internal format
+		GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
+		size_t width = mWidth;
+		size_t height = mHeight;
+		size_t depth = mDepth;
+		if(PixelUtil::isCompressed(mFormat))
+		{
+			// Compressed formats
+			size_t size = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+			// Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
+			// accept a 0 pointer like normal glTexImageXD
+			// Run through this process for every mipmap to pregenerate mipmap piramid
+			uint8 *tmpdata = new uint8[size];
+			memset(tmpdata, 0, size);
+			
+			for(int mip=0; mip<=mNumMipmaps; mip++)
+			{
+			//int mip = 0;
+				size = PixelUtil::getMemorySize(width, height, depth, mFormat);
+				switch(mTextureType)
+				{
+					case TEX_TYPE_1D:
+						glCompressedTexImage1DARB_ptr(GL_TEXTURE_1D, mip, format, 
+							width, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_2D:
+						glCompressedTexImage2DARB_ptr(GL_TEXTURE_2D, mip, format,
+							width, height, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_3D:
+						glCompressedTexImage3DARB_ptr(GL_TEXTURE_3D, mip, format,
+							width, height, depth, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_CUBE_MAP:
+						for(int face=0; face<6; face++) {
+							glCompressedTexImage2DARB_ptr(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
+								width, height, 0, 
+								size, tmpdata);
+						}
+						break;
+				};
+				if(width>1)		width = width/2;
+				if(height>1)	height = height/2;
+				if(depth>1)		depth = depth/2;
+			}
+			delete [] tmpdata;
+		}
+		else
+		{
+			// Run through this process to pregenerate mipmap piramid
+			for(int mip=0; mip<=mNumMipmaps; mip++)
+			{
+				// Normal formats
+				switch(mTextureType)
+				{
+					case TEX_TYPE_1D:
+						glTexImage1D(GL_TEXTURE_1D, mip, format,
+							width, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+	
+						break;
+					case TEX_TYPE_2D:
+						glTexImage2D(GL_TEXTURE_2D, mip, format,
+							width, height, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						break;
+					case TEX_TYPE_3D:
+						glTexImage3D(GL_TEXTURE_3D, mip, format,
+							width, height, depth, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						break;
+					case TEX_TYPE_CUBE_MAP:
+						for(int face=0; face<6; face++) {
+							glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
+								width, height, 0, 
+								GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						}
+						break;
+				};
+				if(width>1)		width = width/2;
+				if(height>1)	height = height/2;
+				if(depth>1)		depth = depth/2;
+			}
+		}
+		_createSurfaceList();
+		// Get final internal format
+		mFormat = getBuffer(0,0)->getFormat();
+		mIsLoaded = true;
+	}
+	
+    void GLTexture::createRenderTexture(void)
+    {
+        if (this->getTextureType() != TEX_TYPE_2D)
+            OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, "**** Create render texture implemented only for 2D textures!!! ****", "GLTexture::createRenderTexture" );
+
+        // Create the GL texture
+		// This already does everything neccessary
+        createInternalResources();
+    }
+	
+	void GLTexture::loadImage( const Image& img )
+    {
+        std::vector<const Image*> images;
+		
+        images.push_back(&img);
+        _loadImages(images);
+        images.clear();
+    }
+
+    void GLTexture::loadImpl()
+    {
+        if( mUsage & TU_RENDERTARGET )
+        {
+            createRenderTexture();
+            mIsLoaded = true;     
+        }
+        else
+        {
+            if(mTextureType == TEX_TYPE_1D || mTextureType == TEX_TYPE_2D || 
+                mTextureType == TEX_TYPE_3D)
+            {
+                Image img;
+                img.load(mName, mGroup);
+
+				// If this is a cube map, set the texture type flag accordingly.
+                if (img.hasFlag(IF_CUBEMAP))
+					mTextureType = TEX_TYPE_CUBE_MAP;
+				// If this is a volumetric texture set the texture type flag accordingly.
+				if(img.getDepth() > 1)
+					mTextureType = TEX_TYPE_3D;
+
+				loadImage( img );
+            }
+            else if (mTextureType == TEX_TYPE_CUBE_MAP)
+            {
+				if(StringUtil::endsWith(getName(), ".dds"))
+				{
+					// XX HACK there should be a better way to specify wether 
+					// all faces are in the same file or not
+					Image img;
+                	img.load(mName, mGroup);
+					loadImage( img );
+				}
+				else
+				{
+					String baseName, ext;
+					std::vector<Image> images(6);
+					std::vector<const Image*> imagePtrs;
+					static const String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
+	
+					for(size_t i = 0; i < 6; i++)
+					{
+						size_t pos = mName.find_last_of(".");
+						baseName = mName.substr(0, pos);
+						ext = mName.substr(pos);
+						String fullName = baseName + suffixes[i] + ext;
+	
+						images[i].load(fullName, mGroup);
+						imagePtrs.push_back(&images[i]);
+					}
+	
+					_loadImages( imagePtrs );
+				}
+            }
+            else
+                OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, "**** Unknown texture type ****", "GLTexture::load" );
+        }
+    }
+	
+	//*************************************************************************
+    
+    void GLTexture::unloadImpl()
+    {
+		mSurfaceList.clear();
+        glDeleteTextures( 1, &mTextureID );
+    }
+
+	
+	//---------------------------------------------------------------------------------------------
+	void GLTexture::_createSurfaceList()
+	{
+		mSurfaceList.clear();
+		// Make our understanding of the number of mips matches the GL one
+		glBindTexture( getGLTextureTarget(), mTextureID );
+		GLint value;
+		glGetTexParameteriv( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, &value );
+		mNumMipmaps = value;
+		
+		// For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr
+		bool wantGeneratedMips = (mUsage & TU_AUTOMIPMAP)!=0;
+		bool canMip = Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP);
+		
+		// Do mipmapping in software? (uses GLU) For some cards, this is still needed. Of course,
+		// only when mipmap generation is desired.
+		bool doSoftware = wantGeneratedMips && !canMip && getNumMipmaps(); 
+		
+		for(int face=0; face<getNumFaces(); face++)
+		{
+			for(int mip=0; mip<=getNumMipmaps(); mip++)
+			{
+                GLHardwarePixelBuffer *buf = new GLHardwarePixelBuffer(getGLTextureTarget(), mTextureID, face, mip,
+						static_cast<HardwareBuffer::Usage>(mUsage), doSoftware && mip==0);
+				mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf));
+                
+                /// Check for error
+                if(buf->getWidth()==0 || buf->getHeight()==0 || buf->getDepth()==0)
+                {
+                    OGRE_EXCEPT(
+                        Exception::ERR_RENDERINGAPI_ERROR, 
+                        "Zero sized texture surface on texture "+getName()+
+                            " face "+StringConverter::toString(face)+
+                            " mipmap "+StringConverter::toString(mip)+
+                            ". Probably, the GL driver refused to create the texture.", 
+                            "GLTexture::_createSurfaceList");
+                }
+			}
+		}
+	}
+	
+	//---------------------------------------------------------------------------------------------
+	HardwarePixelBufferSharedPtr GLTexture::getBuffer(size_t face, size_t mipmap)
+	{
+		if(face >= getNumFaces())
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range",
+					"GLTexture::getBuffer");
+		if(mipmap > mNumMipmaps)
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Mipmap index out of range",
+					"GLTexture::getBuffer");
+		unsigned int idx = face*(mNumMipmaps+1) + mipmap;
+		assert(idx < mSurfaceList.size());
+		return mSurfaceList[idx];
+	}
+	
+	//---------------------------------------------------------------------------------------------
+    void GLRenderTexture::_copyToTexture(void)
+    {		
+        glBindTexture(GL_TEXTURE_2D, mGLTexture->getGLID());
+			
+        glCopyTexSubImage2D(GL_TEXTURE_2D, mGLTexture->getNumMipmaps(), 0, 0,
+            0, 0, mWidth, mHeight);
+
+    }
+    
+    void GLRenderTexture::writeContentsToFile( const String & filename ) 
+    {
+        ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+        
+        imgData->width = mGLTexture->getWidth();
+        imgData->height = mGLTexture->getHeight();
+		imgData->depth = 1;
+        imgData->format = PF_BYTE_RGB;
+
+        // Allocate buffer 
+        uchar* pBuffer = new uchar[imgData->width * imgData->height * 3];
+
+        // Read pixels
+        // I love GL: it does all the locking & colour conversion for us
+        glBindTexture(GL_TEXTURE_2D, mGLTexture->getGLID());
+        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+        // Wrap buffer in a chunk
+        DataStreamPtr stream(new MemoryDataStream(
+            pBuffer, imgData->width * imgData->height * 3, false));
+
+        // Need to flip the read data over in Y though
+        Image img;
+        img.loadRawData(stream, imgData->width, imgData->height, imgData->format );
+        img.flipAroundX();
+
+        MemoryDataStreamPtr streamFlipped(
+            new MemoryDataStream(img.getData(), stream->size(), false));
+
+        // Get codec 
+        size_t pos = filename.find_last_of(".");
+            String extension;
+        if( pos == String::npos )
+            OGRE_EXCEPT(
+                Exception::ERR_INVALIDPARAMS, 
+            "Unable to determine image type for '" + filename + "' - invalid extension.",
+                "GLRenderTexture::writeContentsToFile" );
+
+        while( pos != filename.length() - 1 )
+            extension += filename[++pos];
+
+        // Get the codec
+        Codec * pCodec = Codec::getCodec(extension);
+
+        // Write out
+        Codec::CodecDataPtr codecDataPtr(imgData);
+        pCodec->codeToFile(streamFlipped, filename, codecDataPtr);
+
+        delete [] pBuffer;
+    }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar *GLRenderTexture::getBufferContents(int &dimx, int &dimy)
+	{
+		dimx = mWidth;
+		dimy = mHeight;
+		
+		// Allocate buffer 
+		uchar* pBuffer = new uchar[mWidth * mHeight * 3];
+
+		// Read pixels
+		// I love GL: it does all the locking & colour conversion for us
+		glReadPixels(0, 0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+		return pBuffer;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
+
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp	(revision 343)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp	(revision 343)
@@ -0,0 +1,155 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreGLHardwareOcclusionQuery.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+bool GLHardwareOcclusionQuery::sUseArbQueries = false;
+/**
+  * This is a class that is the base class of the query class for 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg email: lee@abcmedia.se
+  *
+  * Updated on 12/7/2004 by Chris McGuirk
+  * - Implemented ARB_occlusion_query
+  */
+
+/**
+  * Default object constructor
+  * 
+  */
+GLHardwareOcclusionQuery::GLHardwareOcclusionQuery() 
+{ 
+	mPixelCount = 0; 
+	mSkipCounter = 0;
+	mSkipInterval = 0;
+
+	// Check for hardware occlusion support
+	// This is a hack to see if hw occlusion is supported. pointer is 0 if it's not supported.
+	mHasOcclusionSupportARB = (glGenQueriesARB_ptr != 0);
+	mHasOcclusionSupportNV = (glGenOcclusionQueriesNV_ptr != 0);
+
+	if (sUseArbQueries && mHasOcclusionSupportARB)
+		glGenQueriesARB_ptr(1, &mQueryID );	
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+		glGenOcclusionQueriesNV_ptr(1, &mQueryID);
+}
+
+/**
+  * Object destructor
+  */
+GLHardwareOcclusionQuery::~GLHardwareOcclusionQuery() 
+{ 
+	if (sUseArbQueries && mHasOcclusionSupportARB)
+		glDeleteQueriesARB_ptr(1, &mQueryID);
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+		glDeleteOcclusionQueriesNV_ptr(1, &mQueryID);  
+}
+
+//------------------------------------------------------------------
+// Occlusion query functions (see base class documentation for this)
+//--
+void GLHardwareOcclusionQuery::beginOcclusionQuery() 
+{ 
+	//if (mSkipCounter >= mSkipInterval)  // otherwise no query ever issued if mSkipInterval = 0 !
+	//	mSkipCounter = 0; if (mSkipCounter != 0) return;
+
+	if (sUseArbQueries && mHasOcclusionSupportARB)
+			glBeginQueryARB_ptr(GL_SAMPLES_PASSED_ARB, mQueryID);
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+			glBeginOcclusionQueryNV_ptr(mQueryID);
+}
+	
+void GLHardwareOcclusionQuery::endOcclusionQuery() 
+{ 
+	//if( mSkipCounter != 0) return;
+	if (sUseArbQueries && mHasOcclusionSupportARB)
+			glEndQueryARB_ptr(GL_SAMPLES_PASSED_ARB);
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+			glEndOcclusionQueryNV_ptr();
+//	mSkipCounter++;
+		}
+
+bool GLHardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ) 
+{
+	if (sUseArbQueries && mHasOcclusionSupportARB)
+		glGetQueryObjectuivARB_ptr(mQueryID, GL_QUERY_RESULT_ARB, NumOfFragments);
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+glGetOcclusionQueryuivNV_ptr(mQueryID, GL_PIXEL_COUNT_NV, NumOfFragments);
+	else
+		*NumOfFragments = 100000;		// Fails quietly
+
+	mPixelCount = *NumOfFragments; 
+	
+	return true;
+}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//------------------------------------------------------------------
+bool GLHardwareOcclusionQuery::pullOcclusionQuery(unsigned int * NumOfFragments, 
+												  const bool waitForResult, 
+												  const HW_OCCLUSIONQUERY flag) 
+{
+	if (sUseArbQueries && mHasOcclusionSupportARB)	
+	{
+		int isAvailable = GL_TRUE;
+
+		if (!waitForResult)
+			glGetQueryivARB_ptr(mQueryID, GL_QUERY_RESULT_AVAILABLE_ARB, &isAvailable);
+		
+		if (isAvailable == GL_TRUE)
+			glGetQueryObjectuivARB_ptr(mQueryID, GL_QUERY_RESULT_ARB, NumOfFragments);
+
+		mPixelCount = *NumOfFragments;
+
+		return isAvailable == GL_TRUE;
+	} 
+	else if (!sUseArbQueries && mHasOcclusionSupportNV)
+		{
+		unsigned int isAvailable = GL_TRUE;
+
+		if (!waitForResult)
+				glGetOcclusionQueryuivNV_ptr(mQueryID, GL_PIXEL_COUNT_AVAILABLE_NV, &isAvailable);
+
+		if (isAvailable == GL_TRUE)
+				glGetOcclusionQueryuivNV_ptr(mQueryID, GL_PIXEL_COUNT_NV, NumOfFragments);
+
+		mPixelCount = *NumOfFragments; 
+
+		return isAvailable == GL_TRUE;
+		}
+	
+		// In case hardware occlusion isn't supported, every object is set visible.
+		*NumOfFragments = 100000;		
+		mPixelCount = *NumOfFragments; 
+
+	return GL_TRUE;	
+}
+
+#endif // GTP_VIBILITY_MODIFIED_OGRE
+}
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLRenderSystem.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLRenderSystem.cpp	(revision 350)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreGLRenderSystem.cpp	(revision 350)
@@ -0,0 +1,2697 @@
+/*
+-----------------------------------------------------------------------------
+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.s
+-----------------------------------------------------------------------------
+*/
+
+
+#include "OgreGLRenderSystem.h"
+#include "OgreRenderSystem.h"
+#include "OgreLogManager.h"
+#include "OgreStringConverter.h"
+#include "OgreLight.h"
+#include "OgreCamera.h"
+#include "OgreGLTextureManager.h"
+#include "OgreGLHardwareVertexBuffer.h"
+#include "OgreGLHardwareIndexBuffer.h"
+#include "OgreGLDefaultHardwareBufferManager.h"
+#include "OgreGLUtil.h"
+#include "OgreGLGpuProgram.h"
+#include "OgreGLGpuNvparseProgram.h"
+#include "ATI_FS_GLGpuProgram.h"
+#include "OgreGLGpuProgramManager.h"
+#include "OgreException.h"
+#include "OgreGLATIFSInit.h"
+#include "OgreGLSLExtSupport.h"
+#include "OgreGLHardwareOcclusionQuery.h"
+#include "OgreGLContext.h"
+
+
+#ifdef HAVE_CONFIG_H
+#   include "config.h"
+#endif
+
+// Convenience macro from ARB_vertex_buffer_object spec
+#define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i))
+
+// Pointers to extension functions
+GL_ActiveTextureARB_Func glActiveTextureARB_ptr;
+GL_ClientActiveTextureARB_Func glClientActiveTextureARB_ptr;
+GL_SecondaryColorPointerEXT_Func glSecondaryColorPointerEXT_ptr;
+GL_SecondaryColor3fEXT_Func glSecondaryColor3fEXT_ptr;
+GL_GenBuffersARB_Func glGenBuffersARB_ptr;
+GL_BindBufferARB_Func glBindBufferARB_ptr;
+GL_DeleteBuffersARB_Func glDeleteBuffersARB_ptr;
+GL_MapBufferARB_Func glMapBufferARB_ptr;
+GL_UnmapBufferARB_Func glUnmapBufferARB_ptr;
+GL_BufferDataARB_Func glBufferDataARB_ptr;
+GL_BufferSubDataARB_Func glBufferSubDataARB_ptr;
+GL_GetBufferSubDataARB_Func glGetBufferSubDataARB_ptr;
+GL_GenProgramsARB_Func glGenProgramsARB_ptr;
+GL_DeleteProgramsARB_Func glDeleteProgramsARB_ptr;
+GL_BindProgramARB_Func glBindProgramARB_ptr;
+GL_ProgramStringARB_Func glProgramStringARB_ptr;
+GL_ProgramLocalParameter4fvARB_Func glProgramLocalParameter4fvARB_ptr;
+GL_ProgramParameter4fvNV_Func glProgramParameter4fvNV_ptr;
+GL_VertexAttribPointerARB_Func glVertexAttribPointerARB_ptr;
+GL_EnableVertexAttribArrayARB_Func glEnableVertexAttribArrayARB_ptr;
+GL_DisableVertexAttribArrayARB_Func glDisableVertexAttribArrayARB_ptr;
+GL_CombinerStageParameterfvNV_Func glCombinerStageParameterfvNV_ptr;
+GL_CombinerParameterfvNV_Func glCombinerParameterfvNV_ptr;
+GL_CombinerParameteriNV_Func glCombinerParameteriNV_ptr;
+GL_GetProgramivARB_Func glGetProgramivARB_ptr;
+GL_LoadProgramNV_Func glLoadProgramNV_ptr;
+GL_CombinerInputNV_Func glCombinerInputNV_ptr;
+GL_CombinerOutputNV_Func glCombinerOutputNV_ptr;
+GL_FinalCombinerInputNV_Func glFinalCombinerInputNV_ptr;
+GL_TrackMatrixNV_Func glTrackMatrixNV_ptr;
+PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glCompressedTexImage1DARB_ptr;
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB_ptr;
+PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glCompressedTexImage3DARB_ptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glCompressedTexSubImage1DARB_ptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glCompressedTexSubImage2DARB_ptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glCompressedTexSubImage3DARB_ptr;
+PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB_ptr;
+GL_ActiveStencilFaceEXT_Func glActiveStencilFaceEXT_ptr;
+GL_GenOcclusionQueriesNV_Func glGenOcclusionQueriesNV_ptr;	
+GL_DeleteOcclusionQueriesNV_Func glDeleteOcclusionQueriesNV_ptr;
+GL_BeginOcclusionQueryNV_Func glBeginOcclusionQueryNV_ptr;
+GL_EndOcclusionQueryNV_Func glEndOcclusionQueryNV_ptr;
+GL_GetOcclusionQueryuivNV_Func glGetOcclusionQueryuivNV_ptr;
+GL_GenQueriesARB_Func glGenQueriesARB_ptr;
+GL_DeleteQueriesARB_Func glDeleteQueriesARB_ptr;
+GL_BeginQueryARB_Func glBeginQueryARB_ptr;
+GL_EndQueryARB_Func glEndQueryARB_ptr;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+GL_GetQueryivARB_Func glGetQueryivARB_ptr;
+GL_GetQueryObjectivARB_Func glGetQueryObjectivARB_ptr;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+GL_GetQueryObjectuivARB_Func glGetQueryObjectuivARB_ptr;
+
+namespace Ogre {
+
+    // Callback function used when registering GLGpuPrograms
+    GpuProgram* createGLArbGpuProgram(ResourceManager* creator, 
+        const String& name, ResourceHandle handle, 
+        const String& group, bool isManual, ManualResourceLoader* loader,
+        GpuProgramType gptype, const String& syntaxCode)
+    {
+        GLArbGpuProgram* ret = new GLArbGpuProgram(
+            creator, name, handle, group, isManual, loader);
+        ret->setType(gptype);
+        ret->setSyntaxCode(syntaxCode);
+        return ret;
+    }
+
+    GpuProgram* createGLGpuNvparseProgram(ResourceManager* creator, 
+        const String& name, ResourceHandle handle, 
+        const String& group, bool isManual, ManualResourceLoader* loader,
+        GpuProgramType gptype, const String& syntaxCode)
+    {
+        GLGpuNvparseProgram* ret = new GLGpuNvparseProgram(
+            creator, name, handle, group, isManual, loader);
+        ret->setType(gptype);
+        ret->setSyntaxCode(syntaxCode);
+        return ret;
+    }
+
+    GpuProgram* createGL_ATI_FS_GpuProgram(ResourceManager* creator, 
+        const String& name, ResourceHandle handle, 
+        const String& group, bool isManual, ManualResourceLoader* loader,
+        GpuProgramType gptype, const String& syntaxCode)
+	{
+
+        ATI_FS_GLGpuProgram* ret = new ATI_FS_GLGpuProgram(
+            creator, name, handle, group, isManual, loader);
+        ret->setType(gptype);
+        ret->setSyntaxCode(syntaxCode);
+        return ret;
+	}
+
+    GLRenderSystem::GLRenderSystem()
+      : mDepthWrite(true), mHardwareBufferManager(0),
+        mGpuProgramManager(0)
+    {
+        size_t i;
+
+        OgreGuard( "GLRenderSystem::GLRenderSystem" );
+
+        LogManager::getSingleton().logMessage(getName() + " created.");
+
+        // Get our GLSupport
+        mGLSupport = getGLSupport();
+
+        for( i=0; i<MAX_LIGHTS; i++ )
+            mLights[i] = NULL;
+
+        mWorldMatrix = Matrix4::IDENTITY;
+        mViewMatrix = Matrix4::IDENTITY;
+        
+        initConfigOptions();
+
+        mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
+
+        for (i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
+        {
+			// Dummy value
+            mTextureCoordIndex[i] = 99;
+        }
+
+        for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
+        {
+            mTextureTypes[i] = 0;
+        }
+
+        mActiveRenderTarget = 0;
+        mCurrentContext = 0;
+        mMainContext = 0;
+
+        mGLInitialized = false;
+
+        glActiveTextureARB_ptr = 0;
+        glClientActiveTextureARB_ptr = 0;
+        glSecondaryColorPointerEXT_ptr = 0;
+        glSecondaryColor3fEXT_ptr = 0;
+        glGenBuffersARB_ptr = 0;
+        glBindBufferARB_ptr = 0;
+        glDeleteBuffersARB_ptr = 0;
+        glMapBufferARB_ptr = 0;
+        glUnmapBufferARB_ptr = 0;
+        glBufferDataARB_ptr = 0;
+        glBufferSubDataARB_ptr = 0;
+        glGetBufferSubDataARB_ptr = 0;
+        glGenProgramsARB_ptr = 0;
+        glDeleteProgramsARB_ptr = 0;
+        glBindProgramARB_ptr = 0;
+        glProgramStringARB_ptr = 0;
+        glProgramLocalParameter4fvARB_ptr = 0;
+        glProgramParameter4fvNV_ptr = 0;
+        glCombinerStageParameterfvNV_ptr = 0;
+        glCombinerParameterfvNV_ptr = 0;
+        glCombinerParameteriNV_ptr = 0;
+        glGetProgramivARB_ptr = 0;
+        glLoadProgramNV_ptr = 0;
+        glCombinerInputNV_ptr = 0;
+        glCombinerOutputNV_ptr = 0;
+        glFinalCombinerInputNV_ptr = 0;
+        glTrackMatrixNV_ptr = 0;
+        glActiveStencilFaceEXT_ptr = 0;
+        glGenOcclusionQueriesNV_ptr = 0;
+        glDeleteOcclusionQueriesNV_ptr = 0;
+        glBeginOcclusionQueryNV_ptr = 0;
+        glEndOcclusionQueryNV_ptr = 0;
+        glGetOcclusionQueryuivNV_ptr = 0;
+		glGenQueriesARB_ptr = 0;
+		glDeleteQueriesARB_ptr = 0;
+		glBeginQueryARB_ptr = 0;
+		glEndQueryARB_ptr = 0;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		glGetQueryivARB_ptr = 0;
+		glGetQueryObjectivARB_ptr = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		glGetQueryObjectuivARB_ptr = 0;
+
+        mCurrentLights = 0;
+        mMinFilter = FO_LINEAR;
+        mMipFilter = FO_POINT;
+        mCurrentVertexProgram = 0;
+        mCurrentFragmentProgram = 0;
+
+        mClipPlanes.reserve(6);
+
+        OgreUnguard();
+    }
+
+    GLRenderSystem::~GLRenderSystem()
+    {
+        shutdown();
+
+        // Destroy render windows
+        RenderTargetMap::iterator i;
+        for (i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i)
+        {
+            delete i->second;
+        }
+        mRenderTargets.clear();
+
+        if (mTextureManager)
+            delete mTextureManager;
+
+        delete mCapabilities;
+        delete mGLSupport;
+    }
+
+    const String& GLRenderSystem::getName(void) const
+    {
+        static String strName("OpenGL Rendering Subsystem");
+        return strName;
+    }
+
+    void GLRenderSystem::initConfigOptions(void)
+    {
+        OgreGuard("GLRenderSystem::initConfigOptions");
+        mGLSupport->addConfig();
+        OgreUnguard();
+    }
+    
+    ConfigOptionMap& GLRenderSystem::getConfigOptions(void)
+    {
+        return mGLSupport->getConfigOptions();
+    }
+
+    void GLRenderSystem::setConfigOption(const String &name, const String &value)
+    {
+		// set occlusion query
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		if ( name == "ArbQueries" )
+		{
+			if ( value == "No" )
+			{
+				GLHardwareOcclusionQuery::sUseArbQueries = false;
+			}
+			else if  ( value == "Yes" )
+			{
+				GLHardwareOcclusionQuery::sUseArbQueries = true;
+			}
+			return;
+		}
+#endif
+
+        mGLSupport->setConfigOption(name, value);
+    }
+
+    String GLRenderSystem::validateConfigOptions(void)
+    {
+        // XXX Return an error string if something is invalid
+        return mGLSupport->validateConfig();
+    }
+
+    RenderWindow* GLRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
+    {
+        mGLSupport->start();
+        
+		RenderWindow* autoWindow = mGLSupport->createWindow(autoCreateWindow, this, windowTitle);
+
+
+        _setCullingMode( mCullingMode );
+        
+        return autoWindow;
+    }
+
+    void GLRenderSystem::initGL(void)
+    {
+        mGLSupport->initialiseExtensions();
+
+        LogManager::getSingleton().logMessage(
+            "***************************\n"
+            "*** GL Renderer Started ***\n"
+            "***************************");
+
+
+        // Check for hardware mipmapping support.
+        // Note: This is disabled for ATI cards until they fix their drivers
+        if(mGLSupport->getGLVendor() != "ATI" && 
+            (mGLSupport->checkMinGLVersion("1.4.0") || 
+             mGLSupport->checkExtension("GL_SGIS_generate_mipmap")))
+        {
+            mCapabilities->setCapability(RSC_AUTOMIPMAP);
+        }
+
+        // Check for blending support
+        if(mGLSupport->checkMinGLVersion("1.3.0") || 
+            mGLSupport->checkExtension("GL_ARB_texture_env_combine") || 
+            mGLSupport->checkExtension("GL_EXT_texture_env_combine"))
+        {
+            mCapabilities->setCapability(RSC_BLENDING);
+        }
+
+        // Check for Multitexturing support and set number of texture units
+        if(mGLSupport->checkMinGLVersion("1.3.0") || 
+            mGLSupport->checkExtension("GL_ARB_multitexture"))
+        {
+            GLint units;
+            glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units );
+			mFixedFunctionTextureUnits = units;
+
+			if (mGLSupport->checkExtension("GL_ARB_fragment_program"))
+			{
+				// Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
+				// only increased this on the FX/6x00 series
+				GLint arbUnits;
+				glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &arbUnits );
+				if (arbUnits > units)
+					units = arbUnits;
+			}
+
+            mCapabilities->setNumTextureUnits(units);
+
+        }
+        else
+        {
+            // If no multitexture support then set one texture unit
+            mCapabilities->setNumTextureUnits(1);
+        }
+            
+        // Check for Anisotropy support
+        if(mGLSupport->checkExtension("GL_EXT_texture_filter_anisotropic"))
+        {
+            mCapabilities->setCapability(RSC_ANISOTROPY);
+        }
+
+        // Check for DOT3 support
+        if(mGLSupport->checkMinGLVersion("1.3.0") ||
+            mGLSupport->checkExtension("GL_ARB_texture_env_dot3") ||
+            mGLSupport->checkExtension("GL_EXT_texture_env_dot3"))
+        {
+            mCapabilities->setCapability(RSC_DOT3);
+        }
+
+        // Check for cube mapping
+        if(mGLSupport->checkMinGLVersion("1.3.0") || 
+            mGLSupport->checkExtension("GL_ARB_texture_cube_map") || 
+            mGLSupport->checkExtension("GL_EXT_texture_cube_map"))
+        {
+            mCapabilities->setCapability(RSC_CUBEMAPPING);
+        }
+        
+        // Check for hardware stencil support and set bit depth
+        GLint stencil;
+        glGetIntegerv(GL_STENCIL_BITS,&stencil);
+
+        if(stencil)
+        {
+            mCapabilities->setCapability(RSC_HWSTENCIL);
+            mCapabilities->setStencilBufferBitDepth(stencil);
+        }
+
+        // Check for VBO support
+        if(mGLSupport->checkExtension("GL_ARB_vertex_buffer_object"))
+        {
+            mCapabilities->setCapability(RSC_VBO);
+
+            mHardwareBufferManager = new GLHardwareBufferManager;
+        }
+        else
+        {
+            mHardwareBufferManager = new GLDefaultHardwareBufferManager;
+        }
+
+        // XXX Need to check for nv2 support and make a program manager for it
+        // XXX Probably nv1 as well for older cards
+        // GPU Program Manager setup
+        mGpuProgramManager = new GLGpuProgramManager();
+
+		if(mGLSupport->checkExtension("GL_ARB_vertex_program"))
+        {
+            mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
+
+            // Vertex Program Properties
+            mCapabilities->setMaxVertexProgramVersion("arbvp1");
+            mCapabilities->setVertexProgramConstantBoolCount(0);
+            mCapabilities->setVertexProgramConstantIntCount(0);
+            mCapabilities->setVertexProgramConstantFloatCount(
+                GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
+
+            mGpuProgramManager->_pushSyntaxCode("arbvp1");
+            mGpuProgramManager->registerProgramFactory("arbvp1", createGLArbGpuProgram);
+			if (mGLSupport->checkExtension("GL_NV_vertex_program2_option"))
+			{
+				mCapabilities->setMaxVertexProgramVersion("vp30");
+				mGpuProgramManager->_pushSyntaxCode("vp30");
+				mGpuProgramManager->registerProgramFactory("vp30", createGLArbGpuProgram);
+			}
+
+			if (mGLSupport->checkExtension("GL_NV_vertex_program3"))
+			{
+				mCapabilities->setMaxVertexProgramVersion("vp40");
+				mGpuProgramManager->_pushSyntaxCode("vp40");
+				mGpuProgramManager->registerProgramFactory("vp40", createGLArbGpuProgram);
+			}
+        }
+
+        if (mGLSupport->checkExtension("GL_NV_register_combiners2") &&
+            mGLSupport->checkExtension("GL_NV_texture_shader"))
+        {
+            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
+            mCapabilities->setMaxFragmentProgramVersion("fp20");
+
+            mGpuProgramManager->_pushSyntaxCode("fp20");
+            mGpuProgramManager->registerProgramFactory("fp20", createGLGpuNvparseProgram);
+        }
+
+
+		// NFZ - check for ATI fragment shader support
+		if (mGLSupport->checkExtension("GL_ATI_fragment_shader"))
+		{
+            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
+            mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
+            // no boolean params allowed
+            mCapabilities->setFragmentProgramConstantBoolCount(0);
+            // no integer params allowed
+            mCapabilities->setFragmentProgramConstantIntCount(0);
+
+			// only 8 Vector4 constant floats supported
+            mCapabilities->setFragmentProgramConstantFloatCount(8);
+
+            mGpuProgramManager->_pushSyntaxCode("ps_1_4");
+            mGpuProgramManager->_pushSyntaxCode("ps_1_3");
+            mGpuProgramManager->_pushSyntaxCode("ps_1_2");
+            mGpuProgramManager->_pushSyntaxCode("ps_1_1");
+
+            mGpuProgramManager->registerProgramFactory("ps_1_4", createGL_ATI_FS_GpuProgram);
+            mGpuProgramManager->registerProgramFactory("ps_1_3", createGL_ATI_FS_GpuProgram);
+            mGpuProgramManager->registerProgramFactory("ps_1_2", createGL_ATI_FS_GpuProgram);
+            mGpuProgramManager->registerProgramFactory("ps_1_1", createGL_ATI_FS_GpuProgram);
+		}
+
+
+        if (mGLSupport->checkExtension("GL_ARB_fragment_program"))
+        {
+            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
+            // Fragment Program Properties
+            mCapabilities->setMaxFragmentProgramVersion("arbfp1");
+            mCapabilities->setFragmentProgramConstantBoolCount(0);
+            mCapabilities->setFragmentProgramConstantIntCount(0);
+            mCapabilities->setFragmentProgramConstantFloatCount(
+                GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
+
+            mGpuProgramManager->_pushSyntaxCode("arbfp1");
+            mGpuProgramManager->registerProgramFactory("arbfp1", createGLArbGpuProgram);
+			if (mGLSupport->checkExtension("GL_NV_fragment_program_option"))
+			{
+				mCapabilities->setMaxFragmentProgramVersion("fp30");
+				mGpuProgramManager->_pushSyntaxCode("fp30");
+				mGpuProgramManager->registerProgramFactory("fp30", createGLArbGpuProgram);
+			}
+
+			if (mGLSupport->checkExtension("GL_NV_fragment_program2"))
+			{
+				mCapabilities->setMaxFragmentProgramVersion("fp40");
+				mGpuProgramManager->_pushSyntaxCode("fp40");
+				mGpuProgramManager->registerProgramFactory("fp40", createGLArbGpuProgram);
+			}        
+        }
+
+		// NFZ - check if GLSL is supported
+		if ( mGLSupport->checkExtension("GL_ARB_shading_language_100") &&
+			 mGLSupport->checkExtension("GL_ARB_shader_objects") &&
+			 mGLSupport->checkExtension("GL_ARB_fragment_shader") &&
+			 mGLSupport->checkExtension("GL_ARB_vertex_shader") )
+		{
+			// NFZ - check for GLSL vertex and fragment shader support successful
+            mGpuProgramManager->_pushSyntaxCode("glsl");
+			LogManager::getSingleton().logMessage("GLSL support detected");
+		}
+
+		// Check for texture compression
+        if(mGLSupport->checkMinGLVersion("1.3.0") ||
+            mGLSupport->checkExtension("GL_ARB_texture_compression"))
+        {   
+            mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
+         
+            // Check for dxt compression
+            if(mGLSupport->checkExtension("GL_EXT_texture_compression_s3tc"))
+            {
+                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
+            }
+            // Check for vtc compression
+            if(mGLSupport->checkExtension("GL_NV_texture_compression_vtc"))
+            {
+                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
+            }
+        }
+
+        // Scissor test is standard in GL 1.2 (is it emulated on some cards though?)
+        mCapabilities->setCapability(RSC_SCISSOR_TEST);
+		// As are user clipping planes
+		mCapabilities->setCapability(RSC_USER_CLIP_PLANES);
+
+        // 2-sided stencil?
+        if (mGLSupport->checkExtension("GL_EXT_stencil_two_side"))
+        {
+            mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
+        }
+        // stencil wrapping?
+        if (mGLSupport->checkExtension("GL_EXT_stencil_wrap"))
+        {
+            mCapabilities->setCapability(RSC_STENCIL_WRAP);
+        }
+
+        // Check for hardware occlusion support
+        if(mGLSupport->checkExtension("GL_NV_occlusion_query"))
+        {
+            mCapabilities->setCapability(RSC_HWOCCLUSION);		
+        }
+
+		// UBYTE4 always supported
+		mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
+
+        // Inifinite far plane always supported
+        mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
+
+        // Check for non-power-of-2 texture support
+		if(mGLSupport->checkExtension("GL_ARB_texture_non_power_of_two"))
+        {
+            mCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
+        }
+
+        // Check for Float textures
+        if(mGLSupport->checkExtension("GL_ATI_texture_float") ||
+//           mGLSupport->checkExtension("GL_NV_float_buffer") ||
+           mGLSupport->checkExtension("GL_ARB_texture_float"))
+        {
+            mCapabilities->setCapability(RSC_TEXTURE_FLOAT);
+        }
+		
+		// 3D textures should be supported by GL 1.2, which is our minimum version
+        mCapabilities->setCapability(RSC_TEXTURE_3D);
+
+		// Check for GLSupport specific extensions
+		mGLSupport->initialiseCapabilities(*mCapabilities);
+
+        // Get extension function pointers
+        glActiveTextureARB_ptr = 
+            (GL_ActiveTextureARB_Func)mGLSupport->getProcAddress("glActiveTextureARB");
+        glClientActiveTextureARB_ptr = 
+            (GL_ClientActiveTextureARB_Func)mGLSupport->getProcAddress("glClientActiveTextureARB");
+        glSecondaryColorPointerEXT_ptr = 
+            (GL_SecondaryColorPointerEXT_Func)mGLSupport->getProcAddress("glSecondaryColorPointerEXT");
+        glSecondaryColor3fEXT_ptr = 
+            (GL_SecondaryColor3fEXT_Func)mGLSupport->getProcAddress("glSecondaryColor3fEXT");
+        glGenBuffersARB_ptr = 
+            (GL_GenBuffersARB_Func)mGLSupport->getProcAddress("glGenBuffersARB");
+        glBindBufferARB_ptr = 
+            (GL_BindBufferARB_Func)mGLSupport->getProcAddress("glBindBufferARB");
+        glDeleteBuffersARB_ptr = 
+            (GL_DeleteBuffersARB_Func)mGLSupport->getProcAddress("glDeleteBuffersARB");
+        glMapBufferARB_ptr = 
+            (GL_MapBufferARB_Func)mGLSupport->getProcAddress("glMapBufferARB");
+        glUnmapBufferARB_ptr = 
+            (GL_UnmapBufferARB_Func)mGLSupport->getProcAddress("glUnmapBufferARB");
+        glBufferDataARB_ptr = 
+            (GL_BufferDataARB_Func)mGLSupport->getProcAddress("glBufferDataARB");
+        glBufferSubDataARB_ptr = 
+            (GL_BufferSubDataARB_Func)mGLSupport->getProcAddress("glBufferSubDataARB");
+        glGetBufferSubDataARB_ptr = 
+            (GL_GetBufferSubDataARB_Func)mGLSupport->getProcAddress("glGetBufferSubDataARB");
+        glGenProgramsARB_ptr =
+            (GL_GenProgramsARB_Func)mGLSupport->getProcAddress("glGenProgramsARB");
+        glDeleteProgramsARB_ptr =
+            (GL_DeleteProgramsARB_Func)mGLSupport->getProcAddress("glDeleteProgramsARB");
+        glBindProgramARB_ptr =
+            (GL_BindProgramARB_Func)mGLSupport->getProcAddress("glBindProgramARB");
+        glProgramStringARB_ptr =
+            (GL_ProgramStringARB_Func)mGLSupport->getProcAddress("glProgramStringARB");
+        glProgramLocalParameter4fvARB_ptr =
+            (GL_ProgramLocalParameter4fvARB_Func)mGLSupport->getProcAddress("glProgramLocalParameter4fvARB");
+         glProgramParameter4fvNV_ptr =
+            (GL_ProgramParameter4fvNV_Func)mGLSupport->getProcAddress("glProgramParameter4fvNV");
+         glVertexAttribPointerARB_ptr =
+             (GL_VertexAttribPointerARB_Func)mGLSupport->getProcAddress("glVertexAttribPointerARB");
+         glEnableVertexAttribArrayARB_ptr =
+             (GL_EnableVertexAttribArrayARB_Func)mGLSupport->getProcAddress("glEnableVertexAttribArrayARB");
+         glDisableVertexAttribArrayARB_ptr =
+             (GL_DisableVertexAttribArrayARB_Func)mGLSupport->getProcAddress("glDisableVertexAttribArrayARB");
+         glCombinerStageParameterfvNV_ptr =
+            (GL_CombinerStageParameterfvNV_Func)mGLSupport->getProcAddress("glCombinerStageParameterfvNV");
+        glCombinerParameterfvNV_ptr = 
+            (GL_CombinerParameterfvNV_Func)mGLSupport->getProcAddress("glCombinerParameterfvNV");
+         glCombinerParameteriNV_ptr = (GL_CombinerParameteriNV_Func)mGLSupport->getProcAddress("glCombinerParameteriNV");
+        glGetProgramivARB_ptr = 
+            (GL_GetProgramivARB_Func)mGLSupport->getProcAddress("glGetProgramivARB");
+        glLoadProgramNV_ptr = 
+            (GL_LoadProgramNV_Func)mGLSupport->getProcAddress("glLoadProgramNV");
+        glCombinerInputNV_ptr =
+            (GL_CombinerInputNV_Func)mGLSupport->getProcAddress("glCombinerInputNV");
+        glCombinerOutputNV_ptr =
+            (GL_CombinerOutputNV_Func)mGLSupport->getProcAddress("glCombinerOutputNV");
+        glFinalCombinerInputNV_ptr = 
+            (GL_FinalCombinerInputNV_Func)mGLSupport->getProcAddress("glFinalCombinerInputNV");
+        glTrackMatrixNV_ptr = 
+            (GL_TrackMatrixNV_Func)mGLSupport->getProcAddress("glTrackMatrixNV");
+		glCompressedTexImage1DARB_ptr =
+            (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)mGLSupport->getProcAddress("glCompressedTexImage1DARB");
+        glCompressedTexImage2DARB_ptr =
+            (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)mGLSupport->getProcAddress("glCompressedTexImage2DARB");
+		glCompressedTexImage3DARB_ptr =
+            (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)mGLSupport->getProcAddress("glCompressedTexImage3DARB");
+        glCompressedTexSubImage1DARB_ptr =
+            (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)mGLSupport->getProcAddress("glCompressedTexSubImage1DARB");
+        glCompressedTexSubImage2DARB_ptr =
+            (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)mGLSupport->getProcAddress("glCompressedTexSubImage2DARB");
+        glCompressedTexSubImage3DARB_ptr =
+            (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)mGLSupport->getProcAddress("glCompressedTexSubImage3DARB");
+		glGetCompressedTexImageARB_ptr =
+			(PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)mGLSupport->getProcAddress("glGetCompressedTexImageARB");
+        InitATIFragmentShaderExtensions(*mGLSupport);
+		InitGLShaderLanguageExtensions(*mGLSupport);
+        glActiveStencilFaceEXT_ptr = 
+            (GL_ActiveStencilFaceEXT_Func)mGLSupport->getProcAddress("glActiveStencilFaceEXT");
+        glGenOcclusionQueriesNV_ptr =
+            (GL_GenOcclusionQueriesNV_Func)mGLSupport->getProcAddress("glGenOcclusionQueriesNV");
+        glDeleteOcclusionQueriesNV_ptr =
+            (GL_DeleteOcclusionQueriesNV_Func)mGLSupport->getProcAddress("glDeleteOcclusionQueriesNV");
+        glBeginOcclusionQueryNV_ptr =
+            (GL_BeginOcclusionQueryNV_Func)mGLSupport->getProcAddress("glBeginOcclusionQueryNV");
+        glEndOcclusionQueryNV_ptr =
+            (GL_EndOcclusionQueryNV_Func)mGLSupport->getProcAddress("glEndOcclusionQueryNV");
+        glGetOcclusionQueryuivNV_ptr =
+            (GL_GetOcclusionQueryuivNV_Func)mGLSupport->getProcAddress("glGetOcclusionQueryuivNV");
+
+		glGenQueriesARB_ptr = 
+			 (GL_GenQueriesARB_Func)mGLSupport->getProcAddress("glGenQueriesARB");
+		glDeleteQueriesARB_ptr =
+			(GL_DeleteQueriesARB_Func)mGLSupport->getProcAddress("glDeleteQueriesARB");
+		glBeginQueryARB_ptr =
+			 (GL_BeginQueryARB_Func)mGLSupport->getProcAddress("glBeginQueryARB");
+		glEndQueryARB_ptr =
+			 (GL_EndQueryARB_Func)mGLSupport->getProcAddress("glEndQueryARB");
+	#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		glGetQueryivARB_ptr = 
+			(GL_GetQueryivARB_Func)mGLSupport->getProcAddress("glGetQueryivARB");
+		glGetQueryObjectivARB_ptr = 
+			 (GL_GetQueryObjectivARB_Func)mGLSupport->getProcAddress("glGetQueryObjectivARB");
+	#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		glGetQueryObjectuivARB_ptr = 
+			 (GL_GetQueryObjectuivARB_Func)mGLSupport->getProcAddress("glGetQueryObjectuivARB");
+
+        mCapabilities->log(LogManager::getSingleton().getDefaultLog());
+        mGLInitialized = true;
+    }
+
+    void GLRenderSystem::reinitialise(void)
+    {
+        this->shutdown();
+        this->initialise(true);
+    }
+
+    void GLRenderSystem::shutdown(void)
+    {
+        RenderSystem::shutdown();
+
+        // Deleting the GPU program manager and hardware buffer manager.  Has to be done before the mGLSupport->stop().
+		if (mGpuProgramManager)
+        {
+        	delete mGpuProgramManager;
+        	mGpuProgramManager = 0;
+        }
+
+        if (mHardwareBufferManager)
+        {
+            delete mHardwareBufferManager;
+            mHardwareBufferManager = 0;
+        }
+
+
+        mGLSupport->stop();
+        mStopRendering = true;
+    }
+
+    void GLRenderSystem::setAmbientLight(float r, float g, float b)
+    {
+        GLfloat lmodel_ambient[] = {r, g, b, 1.0};
+        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+    }
+
+    void GLRenderSystem::setShadingType(ShadeOptions so)
+    {
+        switch(so)
+        {
+        case SO_FLAT:
+            glShadeModel(GL_FLAT);
+            break;
+        default:
+            glShadeModel(GL_SMOOTH);
+            break;
+        }
+    }
+
+	RenderWindow* GLRenderSystem::createRenderWindow(const String &name, 
+		unsigned int width, unsigned int height, bool fullScreen,
+		const NameValuePairList *miscParams)
+    {
+        if (mRenderTargets.find(name) != mRenderTargets.end())
+        {
+            OGRE_EXCEPT(
+                Exception::ERR_INVALIDPARAMS, 
+                "Window with name '" + name + "' already exists",
+                "GLRenderSystem::createRenderWindow" );
+        }
+		// Log a message
+		std::stringstream ss;
+		ss << "GLRenderSystem::createRenderWindow \"" << name << "\", " <<
+			width << "x" << height << " ";
+		if(fullScreen)
+			ss << "fullscreen ";
+		else
+			ss << "windowed ";
+		if(miscParams)
+		{
+			ss << " miscParams: ";
+			NameValuePairList::const_iterator it;
+			for(it=miscParams->begin(); it!=miscParams->end(); ++it)
+			{
+				ss << it->first << "=" << it->second << " ";
+			}
+			LogManager::getSingleton().logMessage(ss.str());
+		}
+
+        // Create the window
+        RenderWindow* win = mGLSupport->newWindow(name, width, height, 
+            fullScreen, miscParams);
+
+        attachRenderTarget( *win );
+
+        if (!mGLInitialized) 
+        {
+            // Initialise GL after the first window has been created
+            initGL();
+            mTextureManager = new GLTextureManager(*mGLSupport);
+            // Set main and current context
+            ContextMap::iterator i = mContextMap.find(win);
+            if(i != mContextMap.end()) {
+                mCurrentContext = i->second;
+                mMainContext =  i->second;
+                mCurrentContext->setCurrent();
+            }
+            // Initialise the main context
+            _oneTimeContextInitialization();
+        }
+
+
+        // XXX Do more?
+
+        return win;
+    }
+
+	RenderTexture * GLRenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height,
+		TextureType texType, PixelFormat internalFormat, const NameValuePairList *miscParams ) 
+    {
+		// Log a message
+		std::stringstream ss;
+		ss << "GLRenderSystem::createRenderTexture \"" << name << "\", " <<
+			width << "x" << height << " texType=" << texType <<
+			" internalFormat=" << PixelUtil::getFormatName(internalFormat) << " ";
+		if(miscParams)
+		{
+			ss << "miscParams: ";
+			NameValuePairList::const_iterator it;
+			for(it=miscParams->begin(); it!=miscParams->end(); ++it)
+			{
+				ss << it->first << "=" << it->second << " ";
+			}
+			LogManager::getSingleton().logMessage(ss.str());
+		}
+		// Pass on the create call
+        RenderTexture *rt = mGLSupport->createRenderTexture(name, width, height, texType, internalFormat, miscParams);
+        attachRenderTarget( *rt );
+        return rt;
+    }
+
+    //-----------------------------------------------------------------------
+    void GLRenderSystem::destroyRenderWindow(RenderWindow* pWin)
+    {
+        // Find it to remove from list
+        RenderTargetMap::iterator i = mRenderTargets.begin();
+
+        while (i != mRenderTargets.end())
+        {
+            if (i->second == pWin)
+            {
+                mRenderTargets.erase(i);
+                delete pWin;
+                break;
+            }
+        }
+    }
+
+	//---------------------------------------------------------------------
+    void GLRenderSystem::_useLights(const LightList& lights, unsigned short limit)
+    {
+        // Save previous modelview
+        glMatrixMode(GL_MODELVIEW);
+        glPushMatrix();
+        // just load view matrix (identity world)
+        GLfloat mat[16];
+        makeGLMatrix(mat, mViewMatrix);
+        glLoadMatrixf(mat);
+
+        LightList::const_iterator i, iend;
+        iend = lights.end();
+        unsigned short num = 0;
+        for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
+        {
+            setGLLight(num, *i);
+            mLights[num] = *i;
+        }
+        // Disable extra lights
+        for (; num < mCurrentLights; ++num)
+        {
+            setGLLight(num, NULL);
+            mLights[num] = NULL;
+        }
+        mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
+
+        setLights();
+
+        // restore previous
+        glPopMatrix();
+
+    }
+
+    void GLRenderSystem::setGLLight(size_t index, Light* lt)
+    {
+        GLenum gl_index = GL_LIGHT0 + index;
+
+        if (!lt)
+        {
+            // Disable in the scene
+            glDisable(gl_index);
+        }
+        else
+        {
+            switch (lt->getType())
+            {
+            case Light::LT_SPOTLIGHT:
+                glLightf( gl_index, GL_SPOT_CUTOFF, 0.5f * lt->getSpotlightOuterAngle().valueDegrees() );
+                break;
+            default:
+                glLightf( gl_index, GL_SPOT_CUTOFF, 180.0 );
+                break;
+            }
+
+            // Color
+            ColourValue col;
+            col = lt->getDiffuseColour();
+
+
+            GLfloat f4vals[4] = {col.r, col.g, col.b, col.a};
+            glLightfv(gl_index, GL_DIFFUSE, f4vals);
+            
+            col = lt->getSpecularColour();
+            f4vals[0] = col.r;
+            f4vals[1] = col.g;
+            f4vals[2] = col.b;
+            f4vals[3] = col.a;
+            glLightfv(gl_index, GL_SPECULAR, f4vals);
+
+
+            // Disable ambient light for movables;
+            f4vals[0] = 0;
+            f4vals[1] = 0;
+            f4vals[2] = 0;
+            f4vals[3] = 1;
+            glLightfv(gl_index, GL_AMBIENT, f4vals);
+
+            setGLLightPositionDirection(lt, gl_index);
+
+
+            // Attenuation
+            glLightf(gl_index, GL_CONSTANT_ATTENUATION, lt->getAttenuationConstant());
+            glLightf(gl_index, GL_LINEAR_ATTENUATION, lt->getAttenuationLinear());
+            glLightf(gl_index, GL_QUADRATIC_ATTENUATION, lt->getAttenuationQuadric());
+            // Enable in the scene
+            glEnable(gl_index);
+
+        }
+
+    }
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m)
+    {
+        size_t x = 0;
+        for (size_t i = 0; i < 4; i++)
+        {
+            for (size_t j = 0; j < 4; j++)
+            {
+                gl_matrix[x] = m[j][i];
+                x++;
+            }
+        }
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setWorldMatrix( const Matrix4 &m )
+    {
+        GLfloat mat[16];
+        mWorldMatrix = m;
+        makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
+        glMatrixMode(GL_MODELVIEW);
+        glLoadMatrixf(mat);
+    }
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setViewMatrix( const Matrix4 &m )
+    {
+        mViewMatrix = m;
+
+        GLfloat mat[16];
+		makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
+        glMatrixMode(GL_MODELVIEW);
+        glLoadMatrixf(mat);
+
+        setGLClipPlanes();
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setProjectionMatrix(const Matrix4 &m)
+    {
+        GLfloat mat[16];
+        makeGLMatrix(mat, m);
+        if (mActiveRenderTarget->requiresTextureFlipping())
+        {
+            // Invert y
+            mat[5] = -mat[5];
+        }
+        glMatrixMode(GL_PROJECTION);
+        glLoadMatrixf(mat);
+        glMatrixMode(GL_MODELVIEW);
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setSurfaceParams(const ColourValue &ambient,
+        const ColourValue &diffuse, const ColourValue &specular,
+        const ColourValue &emissive, Real shininess,
+        TrackVertexColourType tracking)
+    {
+        // XXX Cache previous values?
+        // XXX Front or Front and Back?
+
+        GLfloat f4val[4] = {diffuse.r, diffuse.g, diffuse.b, diffuse.a};
+        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f4val);
+        f4val[0] = ambient.r;
+        f4val[1] = ambient.g;
+        f4val[2] = ambient.b;
+        f4val[3] = ambient.a;
+        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f4val);
+        f4val[0] = specular.r;
+        f4val[1] = specular.g;
+        f4val[2] = specular.b;
+        f4val[3] = specular.a;
+        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f4val);
+        f4val[0] = emissive.r;
+        f4val[1] = emissive.g;
+        f4val[2] = emissive.b;
+        f4val[3] = emissive.a;
+        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, f4val);
+        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
+        
+        // Track vertex colour
+        if(tracking != TVC_NONE) 
+        {
+            GLenum gt = GL_DIFFUSE;
+            // There are actually 15 different combinations for tracking, of which
+            // GL only supports the most used 5. This means that we have to do some
+            // magic to find the best match. NOTE: 
+            //  GL_AMBIENT_AND_DIFFUSE != GL_AMBIENT | GL__DIFFUSE
+            if(tracking & TVC_AMBIENT) 
+            {
+                if(tracking & TVC_DIFFUSE)
+                {
+                    gt = GL_AMBIENT_AND_DIFFUSE;
+                } 
+                else 
+                {
+                    gt = GL_AMBIENT;
+                }
+            }
+            else if(tracking & TVC_DIFFUSE) 
+            {
+                gt = GL_DIFFUSE;
+            }
+            else if(tracking & TVC_SPECULAR) 
+            {
+                gt = GL_SPECULAR;              
+            }
+            else if(tracking & TVC_EMISSIVE) 
+            {
+                gt = GL_EMISSION;
+            }
+            glColorMaterial(GL_FRONT_AND_BACK, gt);
+            
+            glEnable(GL_COLOR_MATERIAL);
+        } 
+        else 
+        {
+            glDisable(GL_COLOR_MATERIAL);          
+        }
+    }
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTexture(size_t stage, bool enabled, const String &texname)
+    {
+        GLTexturePtr tex = TextureManager::getSingleton().getByName(texname);
+
+        GLenum lastTextureType = mTextureTypes[stage];
+
+		glActiveTextureARB_ptr( GL_TEXTURE0 + stage );
+		if (enabled)
+        {
+            if (!tex.isNull())
+            {
+                // note used
+                tex->touch();
+                mTextureTypes[stage] = tex->getGLTextureTarget();
+            }
+            else
+                // assume 2D
+                mTextureTypes[stage] = GL_TEXTURE_2D;
+
+            if(lastTextureType != mTextureTypes[stage] && lastTextureType != 0)
+            {
+				if (stage < mFixedFunctionTextureUnits)
+				{
+                glDisable( lastTextureType );
+            }
+            }
+
+			if (stage < mFixedFunctionTextureUnits)
+			{
+			glEnable( mTextureTypes[stage] );
+			}
+
+			if(!tex.isNull())
+				glBindTexture( mTextureTypes[stage], tex->getGLID() );
+
+        }
+        else
+        {
+			if (stage < mFixedFunctionTextureUnits)
+			{
+            if (lastTextureType != 0)
+            {
+                glDisable( mTextureTypes[stage] );
+            }
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        }
+        }
+
+        glActiveTextureARB_ptr( GL_TEXTURE0 );
+
+    }
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTextureCoordSet(size_t stage, size_t index)
+    {
+        mTextureCoordIndex[stage] = index;
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m, 
+        const Frustum* frustum)
+    {
+		if (stage >= mFixedFunctionTextureUnits)
+		{
+			// Can't do this
+			return;
+		}
+
+		
+        GLfloat M[16];
+        Matrix4 projectionBias;
+
+        // Default to no extra auto texture matrix
+        mUseAutoTextureMatrix = false;
+
+        GLfloat eyePlaneS[] = {1.0, 0.0, 0.0, 0.0};
+        GLfloat eyePlaneT[] = {0.0, 1.0, 0.0, 0.0};
+        GLfloat eyePlaneR[] = {0.0, 0.0, 1.0, 0.0};
+        GLfloat eyePlaneQ[] = {0.0, 0.0, 0.0, 1.0};
+
+        glActiveTextureARB_ptr( GL_TEXTURE0 + stage );
+
+        switch( m )
+        {
+        case TEXCALC_NONE:
+            glDisable( GL_TEXTURE_GEN_S );
+            glDisable( GL_TEXTURE_GEN_T );
+            glDisable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+            break;
+
+        case TEXCALC_ENVIRONMENT_MAP:
+            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
+            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
+
+            glEnable( GL_TEXTURE_GEN_S );
+            glEnable( GL_TEXTURE_GEN_T );
+            glDisable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+
+            // Need to use a texture matrix to flip the spheremap
+            mUseAutoTextureMatrix = true;
+            memset(mAutoTextureMatrix, 0, sizeof(GLfloat)*16);
+            mAutoTextureMatrix[0] = mAutoTextureMatrix[10] = mAutoTextureMatrix[15] = 1.0f;
+            mAutoTextureMatrix[5] = -1.0f;
+
+            break;
+
+        case TEXCALC_ENVIRONMENT_MAP_PLANAR:            
+            // XXX This doesn't seem right?!
+#ifdef GL_VERSION_1_3
+            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+
+            glEnable( GL_TEXTURE_GEN_S );
+            glEnable( GL_TEXTURE_GEN_T );
+            glEnable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+#else
+            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
+            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
+
+            glEnable( GL_TEXTURE_GEN_S );
+            glEnable( GL_TEXTURE_GEN_T );
+            glDisable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+#endif
+            break;
+        case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
+            
+            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
+
+            glEnable( GL_TEXTURE_GEN_S );
+            glEnable( GL_TEXTURE_GEN_T );
+            glEnable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+
+            // We need an extra texture matrix here
+            // This sets the texture matrix to be the inverse of the modelview matrix
+            mUseAutoTextureMatrix = true;
+            glGetFloatv( GL_MODELVIEW_MATRIX, M );
+
+            // Transpose 3x3 in order to invert matrix (rotation)
+            // Note that we need to invert the Z _before_ the rotation
+            // No idea why we have to invert the Z at all, but reflection is wrong without it
+            mAutoTextureMatrix[0] = M[0]; mAutoTextureMatrix[1] = M[4]; mAutoTextureMatrix[2] = -M[8];
+            mAutoTextureMatrix[4] = M[1]; mAutoTextureMatrix[5] = M[5]; mAutoTextureMatrix[6] = -M[9];
+            mAutoTextureMatrix[8] = M[2]; mAutoTextureMatrix[9] = M[6]; mAutoTextureMatrix[10] = -M[10];
+            mAutoTextureMatrix[3] = mAutoTextureMatrix[7] = mAutoTextureMatrix[11] = 0.0f;
+            mAutoTextureMatrix[12] = mAutoTextureMatrix[13] = mAutoTextureMatrix[14] = 0.0f;
+            mAutoTextureMatrix[15] = 1.0f;
+
+            break;
+        case TEXCALC_ENVIRONMENT_MAP_NORMAL:
+            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
+            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
+            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
+
+            glEnable( GL_TEXTURE_GEN_S );
+            glEnable( GL_TEXTURE_GEN_T );
+            glEnable( GL_TEXTURE_GEN_R );
+            glDisable( GL_TEXTURE_GEN_Q );
+            break;
+        case TEXCALC_PROJECTIVE_TEXTURE:
+            glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
+            glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
+            glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
+            glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
+            glEnable(GL_TEXTURE_GEN_S);
+            glEnable(GL_TEXTURE_GEN_T);
+            glEnable(GL_TEXTURE_GEN_R);
+            glEnable(GL_TEXTURE_GEN_Q);
+
+            mUseAutoTextureMatrix = true;
+
+            // Set scale and translation matrix for projective textures
+            projectionBias = Matrix4::ZERO;
+            projectionBias[0][0] = 0.5; projectionBias[1][1] = -0.5; 
+            projectionBias[2][2] = 1.0; projectionBias[0][3] = 0.5; 
+            projectionBias[1][3] = 0.5; projectionBias[3][3] = 1.0;
+
+            projectionBias = projectionBias * frustum->getProjectionMatrix();
+            projectionBias = projectionBias * frustum->getViewMatrix();
+            projectionBias = projectionBias * mWorldMatrix;
+
+            makeGLMatrix(mAutoTextureMatrix, projectionBias);
+            break;
+        default:
+            break;
+        }
+        glActiveTextureARB_ptr( GL_TEXTURE0 );
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTextureAddressingMode(size_t stage, TextureUnitState::TextureAddressingMode tam)
+    {
+        GLint type;
+        switch(tam)
+        {
+        case TextureUnitState::TAM_WRAP:
+            type = GL_REPEAT;
+            break;
+        case TextureUnitState::TAM_MIRROR:
+            type = GL_MIRRORED_REPEAT;
+            break;
+        case TextureUnitState::TAM_CLAMP:
+            type = GL_CLAMP_TO_EDGE;
+            break;
+        }
+
+        glActiveTextureARB_ptr( GL_TEXTURE0 + stage );
+        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S, type );
+        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T, type );
+        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R, type );
+        glActiveTextureARB_ptr( GL_TEXTURE0 );
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xform)
+    {
+		if (stage >= mFixedFunctionTextureUnits)
+		{
+			// Can't do this
+			return;
+		}
+
+        GLfloat mat[16];
+        makeGLMatrix(mat, xform);
+
+		if(mTextureTypes[stage] != GL_TEXTURE_3D && 
+		   mTextureTypes[stage] != GL_TEXTURE_CUBE_MAP)
+		{
+			// Convert 3x3 rotation/translation matrix to 4x4
+			mat[12] = mat[8];
+			mat[13] = mat[9];
+		}
+//        mat[14] = mat[10];
+//        mat[15] = mat[11];
+
+//        for (int j=0; j< 4; j++)
+//        {
+//            int x = 0;
+//            for (x = 0; x < 4; x++)
+//            {
+//                printf("[%2d]=%0.2f\t", (x*4) + j, mat[(x*4) + j]);
+//            }
+//            printf("\n");
+//        }
+
+        glActiveTextureARB_ptr(GL_TEXTURE0 + stage);
+        glMatrixMode(GL_TEXTURE);
+
+        if (mUseAutoTextureMatrix)
+        {
+            // Load auto matrix in
+            glLoadMatrixf(mAutoTextureMatrix);
+            // Concat new matrix
+            glMultMatrixf(mat);
+
+        }
+        else
+        {
+            // Just load this matrix
+            glLoadMatrixf(mat);
+        }
+
+        glMatrixMode(GL_MODELVIEW);
+        glActiveTextureARB_ptr(GL_TEXTURE0);
+    }
+    //-----------------------------------------------------------------------------
+    GLint GLRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const
+    {
+        switch(ogreBlend)
+        {
+        case SBF_ONE:
+            return GL_ONE;
+        case SBF_ZERO:
+            return GL_ZERO;
+        case SBF_DEST_COLOUR:
+            return GL_DST_COLOR;
+        case SBF_SOURCE_COLOUR:
+            return GL_SRC_COLOR;
+        case SBF_ONE_MINUS_DEST_COLOUR:
+            return GL_ONE_MINUS_DST_COLOR;
+        case SBF_ONE_MINUS_SOURCE_COLOUR:
+            return GL_ONE_MINUS_SRC_COLOR;
+        case SBF_DEST_ALPHA:
+            return GL_DST_ALPHA;
+        case SBF_SOURCE_ALPHA:
+            return GL_SRC_ALPHA;
+        case SBF_ONE_MINUS_DEST_ALPHA:
+            return GL_ONE_MINUS_DST_ALPHA;
+        case SBF_ONE_MINUS_SOURCE_ALPHA:
+            return GL_ONE_MINUS_SRC_ALPHA;
+        };
+		// to keep compiler happy
+		return GL_ONE;
+    }
+
+    void GLRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
+    {
+        GLint sourceBlend = getBlendMode(sourceFactor);
+        GLint destBlend = getBlendMode(destFactor);
+        if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
+        {
+            glDisable(GL_BLEND);
+        }
+        else
+        {
+        glEnable(GL_BLEND);
+        glBlendFunc(sourceBlend, destBlend);
+    }
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value)
+    {
+        if(func == CMPF_ALWAYS_PASS)
+        {
+            glDisable(GL_ALPHA_TEST);
+        }
+        else
+        {
+        glEnable(GL_ALPHA_TEST);
+        glAlphaFunc(convertCompareFunction(func), value / 255.0f);
+    }
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setViewport(Viewport *vp)
+    {
+        // Check if viewport is different
+        if (vp != mActiveViewport || vp->_isUpdated())
+        {
+            RenderTarget* target;
+            target = vp->getTarget();
+            _setRenderTarget(target);
+            mActiveViewport = vp;
+              
+              GLsizei x, y, w, h;
+ 
+              // Calculate the "lower-left" corner of the viewport
+              w = vp->getActualWidth();
+              h = vp->getActualHeight();
+              x = vp->getActualLeft();
+              y = target->getHeight() - vp->getActualTop() - h;
+  
+              glViewport(x, y, w, h);
+  
+              // Configure the viewport clipping
+              glScissor(x, y, w, h);
+  
+              vp->_clearUpdatedFlag();
+        }
+    }
+
+	void GLRenderSystem::setLights()
+	{
+        for (size_t i = 0; i < MAX_LIGHTS; ++i)
+        {
+            if (mLights[i] != NULL)
+            {
+                Light* lt = mLights[i];
+                setGLLightPositionDirection(lt, GL_LIGHT0 + i);
+            }
+        }
+	}
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_beginFrame(void)
+    {
+        OgreGuard( "GLRenderSystem::_beginFrame" );
+        
+        if (!mActiveViewport)
+            OGRE_EXCEPT(999, "Cannot begin frame - no viewport selected.",
+                "GLRenderSystem::_beginFrame");
+
+        // Activate the viewport clipping
+        glEnable(GL_SCISSOR_TEST);
+        // Clear the viewport if required
+        if (mActiveViewport->getClearEveryFrame())
+        {
+            clearFrameBuffer(FBT_COLOUR | FBT_DEPTH, 
+                mActiveViewport->getBackgroundColour());
+        }        
+
+        OgreUnguard();
+    }
+   
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_endFrame(void)
+    {
+        // Deactivate the viewport clipping.
+        glDisable(GL_SCISSOR_TEST);
+    }
+
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setCullingMode(CullingMode mode)
+    {
+        // NB: Because two-sided stencil API dependence of the front face, we must
+        // use the same 'winding' for the front face everywhere. As the OGRE default
+        // culling mode is clockwise, we also treat anticlockwise winding as front
+        // face for consistently. On the assumption that, we can't change the front
+        // face by glFrontFace anywhere.
+
+        GLenum cullMode;
+
+        switch( mode )
+        {
+        case CULL_NONE:
+            glDisable( GL_CULL_FACE );
+            return;
+        case CULL_CLOCKWISE:
+            if (mActiveRenderTarget && 
+                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
+                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
+            {
+                cullMode = GL_FRONT;
+            }
+            else
+            {
+                cullMode = GL_BACK;
+            }
+            break;
+        case CULL_ANTICLOCKWISE:
+            if (mActiveRenderTarget && 
+                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
+                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
+            {
+                cullMode = GL_BACK;
+            }
+            else
+            {
+                cullMode = GL_FRONT;
+            }
+            break;
+        }
+
+        glEnable( GL_CULL_FACE );
+        glCullFace( cullMode );
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
+    {
+        _setDepthBufferCheckEnabled(depthTest);
+        _setDepthBufferWriteEnabled(depthWrite);
+        _setDepthBufferFunction(depthFunction);
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
+    {
+        if (enabled)
+        {
+            glClearDepth(1.0f);
+            glEnable(GL_DEPTH_TEST);
+        }
+        else
+        {
+            glDisable(GL_DEPTH_TEST);
+        }
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
+    {
+        GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
+        glDepthMask( flag );  
+        // Store for reference in _beginFrame
+        mDepthWrite = enabled;
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setDepthBufferFunction(CompareFunction func)
+    {
+        glDepthFunc(convertCompareFunction(func));
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setDepthBias(ushort bias)
+    {
+        if (bias > 0)
+        {
+            glEnable(GL_POLYGON_OFFSET_FILL);
+            glEnable(GL_POLYGON_OFFSET_POINT);
+            glEnable(GL_POLYGON_OFFSET_LINE);
+            // Bias is in {0, 16}, scale the unit addition appropriately
+            glPolygonOffset(0.0f, -bias);
+        }
+        else
+        {
+            glDisable(GL_POLYGON_OFFSET_FILL);
+            glDisable(GL_POLYGON_OFFSET_POINT);
+            glDisable(GL_POLYGON_OFFSET_LINE);
+        }
+    }
+	//-----------------------------------------------------------------------------
+	void GLRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
+	{
+		glColorMask(red, green, blue, alpha);
+		// record this
+		mColourWrite[0] = red;
+		mColourWrite[1] = blue;
+		mColourWrite[2] = green;
+		mColourWrite[3] = alpha;
+	}
+	//-----------------------------------------------------------------------------
+    String GLRenderSystem::getErrorDescription(long errCode) const
+    {
+        const GLubyte *errString = gluErrorString (errCode);
+        return String((const char*) errString);
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::setLightingEnabled(bool enabled)
+    {
+        if (enabled) 
+        {      
+            glEnable(GL_LIGHTING);
+        } 
+        else 
+        {
+            glDisable(GL_LIGHTING);
+        }
+    }
+    //-----------------------------------------------------------------------------
+    void GLRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
+    {
+
+        GLint fogMode;
+        switch (mode)
+        {
+        case FOG_EXP:
+            fogMode = GL_EXP;
+            break;
+        case FOG_EXP2:
+            fogMode = GL_EXP2;
+            break;
+        case FOG_LINEAR:
+            fogMode = GL_LINEAR;
+            break;
+        default:
+            // Give up on it
+            glDisable(GL_FOG);
+            return;
+        }
+
+        glEnable(GL_FOG);
+        glFogi(GL_FOG_MODE, fogMode);
+        GLfloat fogColor[4] = {colour.r, colour.g, colour.b, colour.a};
+        glFogfv(GL_FOG_COLOR, fogColor);
+        glFogf(GL_FOG_DENSITY, density);
+        glFogf(GL_FOG_START, start);
+        glFogf(GL_FOG_END, end);
+        // XXX Hint here?
+    }
+
+    void GLRenderSystem::convertColourValue(const ColourValue& colour, uint32* pDest)
+    {
+    #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+        *pDest = colour.getAsRGBA();
+    #else
+      // GL accesses by byte, so use ABGR so little-endian format will make it RGBA in byte mode
+        *pDest = colour.getAsABGR();
+    #endif
+    }
+    
+    void GLRenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane, 
+        Real farPlane, Matrix4& dest, bool forGpuProgram)
+    {
+        Radian thetaY ( fovy / 2.0f );
+        Real tanThetaY = Math::Tan(thetaY);
+        //Real thetaX = thetaY * aspect;
+        //Real tanThetaX = Math::Tan(thetaX);
+
+        // Calc matrix elements
+        Real w = (1.0f / tanThetaY) / aspect;
+        Real h = 1.0f / tanThetaY;
+        Real q, qn;
+        if (farPlane == 0)
+        {
+            // Infinite far plane
+            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
+        }
+        else
+        {
+            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
+            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
+        }
+
+        // NB This creates Z in range [-1,1]
+        //
+        // [ w   0   0   0  ]
+        // [ 0   h   0   0  ]
+        // [ 0   0   q   qn ]
+        // [ 0   0   -1  0  ]
+
+        dest = Matrix4::ZERO;
+        dest[0][0] = w;
+        dest[1][1] = h;
+        dest[2][2] = q;
+        dest[2][3] = qn;
+        dest[3][2] = -1;
+
+    }
+    
+    void GLRenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, 
+        Real farPlane, Matrix4& dest, bool forGpuProgram)
+    {
+        Radian thetaY (fovy / 2.0f);
+        Real tanThetaY = Math::Tan(thetaY);
+
+        //Real thetaX = thetaY * aspect;
+        Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
+        Real half_w = tanThetaX * nearPlane;
+        Real half_h = tanThetaY * nearPlane;
+        Real iw = 1.0 / half_w;
+        Real ih = 1.0 / half_h;
+        Real q;
+        if (farPlane == 0)
+        {
+            q = 0;
+        }
+        else
+        {
+            q = 2.0 / (farPlane - nearPlane);
+        }
+        dest = Matrix4::ZERO;
+        dest[0][0] = iw;
+        dest[1][1] = ih;
+        dest[2][2] = -q;
+        dest[2][3] = - (farPlane + nearPlane)/(farPlane - nearPlane);
+        dest[3][3] = 1;
+	}
+
+    void GLRenderSystem::_setRasterisationMode(SceneDetailLevel level)
+    {
+        GLenum glmode;
+        switch(level)
+        {
+        case SDL_POINTS:
+            glmode = GL_POINT;
+            break;
+        case SDL_WIREFRAME:
+            glmode = GL_LINE;
+            break;
+        case SDL_SOLID:
+            glmode = GL_FILL;
+            break;
+        }
+        glPolygonMode(GL_FRONT_AND_BACK, glmode);
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::setStencilCheckEnabled(bool enabled)
+    {
+        if (enabled)
+        {
+            glEnable(GL_STENCIL_TEST);
+        }
+        else
+        {
+            glDisable(GL_STENCIL_TEST);
+        }
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::setStencilBufferParams(CompareFunction func, 
+        uint32 refValue, uint32 mask, StencilOperation stencilFailOp, 
+        StencilOperation depthFailOp, StencilOperation passOp, 
+        bool twoSidedOperation)
+    {
+        bool flip;
+
+        if (twoSidedOperation)
+        {
+            if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
+                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
+                    "GLRenderSystem::setStencilBufferParams");
+            glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+            // NB: We should always treat CCW as front face for consistent with default
+            // culling mode. Therefore, we must take care with two-sided stencil settings.
+            flip = (mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping()) ||
+                   (!mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping());
+
+            // Set alternative versions of ops
+            glActiveStencilFaceEXT_ptr(GL_BACK);
+            glStencilMask(mask);
+            glStencilFunc(convertCompareFunction(func), refValue, mask);
+            glStencilOp(
+                convertStencilOp(stencilFailOp, !flip), 
+                convertStencilOp(depthFailOp, !flip), 
+                convertStencilOp(passOp, !flip));
+            // reset
+            glActiveStencilFaceEXT_ptr(GL_FRONT);
+        }
+        else
+        {
+            glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+            flip = false;
+        }
+
+        glStencilMask(mask);
+        glStencilFunc(convertCompareFunction(func), refValue, mask);
+        glStencilOp(
+            convertStencilOp(stencilFailOp, flip),
+            convertStencilOp(depthFailOp, flip), 
+            convertStencilOp(passOp, flip));
+    }
+    //---------------------------------------------------------------------
+    GLint GLRenderSystem::convertCompareFunction(CompareFunction func) const
+    {
+        switch(func)
+        {
+        case CMPF_ALWAYS_FAIL:
+            return GL_NEVER;
+        case CMPF_ALWAYS_PASS:
+            return GL_ALWAYS;
+        case CMPF_LESS:
+            return GL_LESS;
+        case CMPF_LESS_EQUAL:
+            return GL_LEQUAL;
+        case CMPF_EQUAL:
+            return GL_EQUAL;
+        case CMPF_NOT_EQUAL:
+            return GL_NOTEQUAL;
+        case CMPF_GREATER_EQUAL:
+            return GL_GEQUAL;
+        case CMPF_GREATER:
+            return GL_GREATER;
+        };
+        // to keep compiler happy
+        return GL_ALWAYS;
+    }
+    //---------------------------------------------------------------------
+    GLint GLRenderSystem::convertStencilOp(StencilOperation op, bool invert) const
+    {
+        switch(op)
+        {
+        case SOP_KEEP:
+            return GL_KEEP;
+        case SOP_ZERO:
+            return GL_ZERO;
+        case SOP_REPLACE:
+            return GL_REPLACE;
+        case SOP_INCREMENT:
+            return invert ? GL_DECR : GL_INCR;
+        case SOP_DECREMENT:
+            return invert ? GL_INCR : GL_DECR;
+        case SOP_INCREMENT_WRAP:
+            return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT;
+        case SOP_DECREMENT_WRAP:
+            return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT;
+        case SOP_INVERT:
+            return GL_INVERT;
+        };
+        // to keep compiler happy
+        return SOP_KEEP;
+    }
+	//---------------------------------------------------------------------
+    GLuint GLRenderSystem::getCombinedMinMipFilter(void) const
+    {
+        switch(mMinFilter)
+        {
+        case FO_ANISOTROPIC:
+        case FO_LINEAR:
+            switch(mMipFilter)
+            {
+            case FO_ANISOTROPIC:
+            case FO_LINEAR:
+                // linear min, linear mip
+                return GL_LINEAR_MIPMAP_LINEAR;
+            case FO_POINT:
+                // linear min, point mip
+                return GL_LINEAR_MIPMAP_NEAREST;
+            case FO_NONE:
+                // linear min, no mip
+                return GL_LINEAR;
+            }
+            break;
+        case FO_POINT:
+        case FO_NONE:
+            switch(mMipFilter)
+            {
+            case FO_ANISOTROPIC:
+            case FO_LINEAR:
+                // nearest min, linear mip
+                return GL_NEAREST_MIPMAP_LINEAR;
+            case FO_POINT:
+                // nearest min, point mip
+                return GL_NEAREST_MIPMAP_NEAREST;
+            case FO_NONE:
+                // nearest min, no mip
+                return GL_NEAREST;
+            }
+            break;
+        }
+
+        // should never get here
+        return 0;
+
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::_setTextureUnitFiltering(size_t unit, 
+        FilterType ftype, FilterOptions fo)
+	{
+        OgreGuard( "GLRenderSystem::_setTextureUnitFiltering" );        
+
+		glActiveTextureARB_ptr( GL_TEXTURE0 + unit );
+        switch(ftype)
+        {
+        case FT_MIN:
+            mMinFilter = fo;
+            // Combine with existing mip filter
+			glTexParameteri(
+                mTextureTypes[unit],
+				GL_TEXTURE_MIN_FILTER, 
+				getCombinedMinMipFilter());
+            break;
+        case FT_MAG:
+            switch (fo)
+            {
+            case FO_ANISOTROPIC: // GL treats linear and aniso the same
+            case FO_LINEAR:
+			    glTexParameteri(
+                    mTextureTypes[unit],
+				    GL_TEXTURE_MAG_FILTER, 
+				    GL_LINEAR);
+                break;
+            case FO_POINT:
+            case FO_NONE:
+			    glTexParameteri(
+                    mTextureTypes[unit],
+				    GL_TEXTURE_MAG_FILTER, 
+				    GL_NEAREST);
+                break;
+            }
+            break;
+        case FT_MIP:
+            mMipFilter = fo;
+            // Combine with existing min filter
+			glTexParameteri(
+                mTextureTypes[unit],
+				GL_TEXTURE_MIN_FILTER, 
+				getCombinedMinMipFilter());
+            break;
+		}
+
+        glActiveTextureARB_ptr( GL_TEXTURE0 );
+
+		OgreUnguard();
+	}
+	//---------------------------------------------------------------------
+	GLfloat GLRenderSystem::_getCurrentAnisotropy(size_t unit)
+	{
+		GLfloat curAniso = 0;
+		glGetTexParameterfv(mTextureTypes[unit], 
+            GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso);
+		return curAniso ? curAniso : 1;
+	}
+	//---------------------------------------------------------------------
+	void GLRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
+	{
+       if (!mCapabilities->hasCapability(RSC_ANISOTROPY))
+			return;
+
+		GLfloat largest_supported_anisotropy = 0;
+		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+		if (maxAnisotropy > largest_supported_anisotropy)
+			maxAnisotropy = largest_supported_anisotropy ? largest_supported_anisotropy : 1;
+		if (_getCurrentAnisotropy(unit) != maxAnisotropy)
+			glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
+	}
+	//-----------------------------------------------------------------------------
+    void GLRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
+    {       
+		if (stage >= mFixedFunctionTextureUnits)
+		{
+			// Can't do this
+			return;
+		}
+
+        // Check to see if blending is supported
+        if(!mCapabilities->hasCapability(RSC_BLENDING))
+            return;
+
+        GLenum src1op, src2op, cmd;
+        GLfloat cv1[4], cv2[4];
+
+		if (bm.blendType == LBT_COLOUR)
+        {
+		    cv1[0] = bm.colourArg1.r;
+		    cv1[1] = bm.colourArg1.g;
+		    cv1[2] = bm.colourArg1.b;
+		    cv1[3] = bm.colourArg1.a;
+			mManualBlendColours[stage][0] = bm.colourArg1;
+
+
+		    cv2[0] = bm.colourArg2.r;
+		    cv2[1] = bm.colourArg2.g;
+		    cv2[2] = bm.colourArg2.b;
+		    cv2[3] = bm.colourArg2.a;
+			mManualBlendColours[stage][1] = bm.colourArg2;
+        }
+
+		if (bm.blendType == LBT_ALPHA)
+        {
+		    cv1[0] = mManualBlendColours[stage][0].r;
+		    cv1[1] = mManualBlendColours[stage][0].g;
+		    cv1[2] = mManualBlendColours[stage][0].b;
+		    cv1[3] = bm.alphaArg1;
+
+		    cv2[0] = mManualBlendColours[stage][1].r;
+		    cv2[1] = mManualBlendColours[stage][1].g;
+		    cv2[2] = mManualBlendColours[stage][1].b;
+		    cv2[3] = bm.alphaArg2;
+        }
+
+        switch (bm.source1)
+        {
+        case LBS_CURRENT:
+            src1op = GL_PREVIOUS;
+            break;
+        case LBS_TEXTURE:
+            src1op = GL_TEXTURE;
+            break;
+        case LBS_MANUAL:
+            src1op = GL_CONSTANT;
+			break;
+        case LBS_DIFFUSE:
+            src1op = GL_PRIMARY_COLOR;
+			break;
+        // XXX
+        case LBS_SPECULAR:
+		default:
+            src1op = 0;
+        }
+
+        switch (bm.source2)
+        {
+        case LBS_CURRENT:
+            src2op = GL_PREVIOUS;
+            break;
+        case LBS_TEXTURE:
+            src2op = GL_TEXTURE;
+            break;
+        case LBS_MANUAL:
+			src2op = GL_CONSTANT;
+			break;
+		case LBS_DIFFUSE:
+            src2op = GL_PRIMARY_COLOR;
+			break;
+        // XXX
+        case LBS_SPECULAR:
+		default:
+            src2op = 0;
+        }
+
+        switch (bm.operation)
+        {
+        case LBX_SOURCE1:
+            cmd = GL_REPLACE;
+            break;
+        case LBX_SOURCE2:
+            cmd = GL_REPLACE;
+            break;
+        case LBX_MODULATE:
+            cmd = GL_MODULATE;
+            break;
+        case LBX_MODULATE_X2:
+            cmd = GL_MODULATE;
+            break;
+        case LBX_MODULATE_X4:
+            cmd = GL_MODULATE;
+            break;
+        case LBX_ADD:
+            cmd = GL_ADD;
+            break;
+        case LBX_ADD_SIGNED:
+            cmd = GL_ADD_SIGNED;
+            break;
+        case LBX_SUBTRACT:
+            cmd = GL_SUBTRACT;
+            break;
+        case LBX_BLEND_DIFFUSE_ALPHA:
+            cmd = GL_INTERPOLATE;
+            break;
+        case LBX_BLEND_TEXTURE_ALPHA:
+            cmd = GL_INTERPOLATE;
+            break;
+        case LBX_BLEND_CURRENT_ALPHA:
+            cmd = GL_INTERPOLATE;
+            break;
+        case LBX_BLEND_MANUAL:
+            cmd = GL_INTERPOLATE;
+            break;
+        case LBX_DOTPRODUCT:
+            cmd = mCapabilities->hasCapability(RSC_DOT3) 
+                ? GL_DOT3_RGB : GL_MODULATE;
+            break;
+		default:
+            cmd = 0;
+        }
+
+		glActiveTextureARB_ptr(GL_TEXTURE0 + stage);
+		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+
+	    if (bm.blendType == LBT_COLOUR)
+	    {
+		    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, cmd);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, src1op);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, src2op);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
+	    }
+	    else
+	    {
+		    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, cmd);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, src1op);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, src2op);
+		    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
+	    }
+
+        float blendValue[4] = {0, 0, 0, bm.factor};
+        switch (bm.operation)
+        {
+        case LBX_BLEND_DIFFUSE_ALPHA:
+            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
+            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
+            break;
+        case LBX_BLEND_TEXTURE_ALPHA:
+			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
+			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_TEXTURE);
+            break;
+        case LBX_BLEND_CURRENT_ALPHA:
+			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
+			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PREVIOUS);
+            break;
+        case LBX_BLEND_MANUAL:
+            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendValue);
+            break;
+        default:
+            break;
+        };
+
+        switch (bm.operation)
+        {
+        case LBX_MODULATE_X2:
+			glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
+                GL_RGB_SCALE : GL_ALPHA_SCALE, 2);
+            break;
+        case LBX_MODULATE_X4:
+			glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
+                GL_RGB_SCALE : GL_ALPHA_SCALE, 4);
+            break;
+        default:
+			glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? 
+                GL_RGB_SCALE : GL_ALPHA_SCALE, 1);
+            break;
+		}
+
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
+        if(bm.source1 == LBS_MANUAL)
+            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv1);
+        if (bm.source2 == LBS_MANUAL)
+            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv2);
+
+        glActiveTextureARB_ptr(GL_TEXTURE0);
+	}
+    //---------------------------------------------------------------------
+    void GLRenderSystem::setGLLightPositionDirection(Light* lt, GLenum lightindex)
+    {
+        // Set position / direction
+        Vector4 vec;
+		// Use general 4D vector which is the same as GL's approach
+		vec = lt->getAs4DVector();
+
+#if OGRE_DOUBLE_PRECISION
+		// Must convert to float*
+		float tmp[4] = {vec.x, vec.y, vec.z, vec.w};
+		glLightfv(lightindex, GL_POSITION, tmp);
+#else
+		glLightfv(lightindex, GL_POSITION, vec.val);
+#endif
+		// Set spotlight direction
+        if (lt->getType() == Light::LT_SPOTLIGHT)
+        {
+            vec = lt->getDerivedDirection();
+            vec.w = 0.0; 
+#if OGRE_DOUBLE_PRECISION
+			// Must convert to float*
+			float tmp2[4] = {vec.x, vec.y, vec.z, vec.w};
+			glLightfv(lightindex, GL_SPOT_DIRECTION, tmp2);
+#else
+            glLightfv(lightindex, GL_SPOT_DIRECTION, vec.val);
+#endif
+        }
+    }
+    //---------------------------------------------------------------------
+	void GLRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
+	{
+	}
+    //---------------------------------------------------------------------
+	void GLRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
+	{
+	}
+    //---------------------------------------------------------------------
+    void GLRenderSystem::_render(const RenderOperation& op)
+	{
+        // Guard
+        OgreGuard ("GLRenderSystem::_render");
+        // Call super class
+        RenderSystem::_render(op);
+
+        void* pBufferData = 0;
+        
+        const VertexDeclaration::VertexElementList& decl = 
+            op.vertexData->vertexDeclaration->getElements();
+        VertexDeclaration::VertexElementList::const_iterator elem, elemEnd;
+        elemEnd = decl.end();
+
+        for (elem = decl.begin(); elem != elemEnd; ++elem)
+        {
+            HardwareVertexBufferSharedPtr vertexBuffer = 
+                op.vertexData->vertexBufferBinding->getBuffer(elem->getSource());
+            if(mCapabilities->hasCapability(RSC_VBO))
+            {
+                glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, 
+                    static_cast<const GLHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
+                pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
+            }
+            else
+            {
+                pBufferData = static_cast<const GLDefaultHardwareVertexBuffer*>(vertexBuffer.get())->getDataPtr(elem->getOffset());
+            }
+            if (op.vertexData->vertexStart)
+            {
+                pBufferData = static_cast<char*>(pBufferData) + op.vertexData->vertexStart * vertexBuffer->getVertexSize();
+            }
+
+            unsigned int i = 0;
+
+            switch(elem->getSemantic())
+            {
+            case VES_POSITION:
+                glVertexPointer(VertexElement::getTypeCount(
+                    elem->getType()), 
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableClientState( GL_VERTEX_ARRAY );
+                break;
+            case VES_NORMAL:
+                glNormalPointer(
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableClientState( GL_NORMAL_ARRAY );
+                break;
+            case VES_DIFFUSE:
+                glColorPointer(4, 
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableClientState( GL_COLOR_ARRAY );
+                break;
+            case VES_SPECULAR:
+                glSecondaryColorPointerEXT_ptr(4, 
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
+                break;
+            case VES_TEXTURE_COORDINATES:
+
+                for (i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
+                {
+					// Only set this texture unit's texcoord pointer if it
+					// is supposed to be using this element's index
+					if (mTextureCoordIndex[i] == elem->getIndex())
+					{
+						glClientActiveTextureARB_ptr(GL_TEXTURE0 + i);
+						glTexCoordPointer(
+							VertexElement::getTypeCount(elem->getType()), 
+							GLHardwareBufferManager::getGLType(elem->getType()),
+                            static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                                pBufferData);
+						glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+					}
+                }
+                break;
+            case VES_BLEND_INDICES:
+                assert(mCapabilities->hasCapability(RSC_VERTEX_PROGRAM));
+                glVertexAttribPointerARB_ptr(
+                    7, // matrix indices are vertex attribute 7 (no def?)
+                    VertexElement::getTypeCount(elem->getType()), 
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    GL_FALSE, // normalisation disabled
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableVertexAttribArrayARB_ptr(7);
+                break;
+            case VES_BLEND_WEIGHTS:
+                assert(mCapabilities->hasCapability(RSC_VERTEX_PROGRAM));
+                glVertexAttribPointerARB_ptr(
+                    1, // weights are vertex attribute 1 (no def?)
+                    VertexElement::getTypeCount(elem->getType()), 
+                    GLHardwareBufferManager::getGLType(elem->getType()), 
+                    GL_FALSE, // normalisation disabled
+                    static_cast<GLsizei>(vertexBuffer->getVertexSize()), 
+                    pBufferData);
+                glEnableVertexAttribArrayARB_ptr(1);
+                break;
+            default:
+                break;
+            };
+
+        }
+
+        glClientActiveTextureARB_ptr(GL_TEXTURE0);
+
+        // Find the correct type to render
+        GLint primType;
+        switch (op.operationType)
+        {
+        case RenderOperation::OT_POINT_LIST:
+            primType = GL_POINTS;
+            break;
+        case RenderOperation::OT_LINE_LIST:
+            primType = GL_LINES;
+            break;
+        case RenderOperation::OT_LINE_STRIP:
+            primType = GL_LINE_STRIP;
+            break;
+        case RenderOperation::OT_TRIANGLE_LIST:
+            primType = GL_TRIANGLES;
+            break;
+        case RenderOperation::OT_TRIANGLE_STRIP:
+            primType = GL_TRIANGLE_STRIP;
+            break;
+        case RenderOperation::OT_TRIANGLE_FAN:
+            primType = GL_TRIANGLE_FAN;
+            break;
+        }
+
+        if (op.useIndexes)
+        {
+            if(mCapabilities->hasCapability(RSC_VBO))
+            {
+                glBindBufferARB_ptr(GL_ELEMENT_ARRAY_BUFFER_ARB, 
+                    static_cast<GLHardwareIndexBuffer*>(
+                        op.indexData->indexBuffer.get())->getGLBufferId());
+
+                pBufferData = VBO_BUFFER_OFFSET(
+                    op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
+            }
+            else
+            {
+                pBufferData = static_cast<GLDefaultHardwareIndexBuffer*>(
+                    op.indexData->indexBuffer.get())->getDataPtr(
+                        op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
+            }
+
+            GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+
+            glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData);
+
+        }
+        else
+        {
+            glDrawArrays(primType, 0, op.vertexData->vertexCount);
+        }
+
+        glDisableClientState( GL_VERTEX_ARRAY );
+        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
+        {
+            glClientActiveTextureARB_ptr(GL_TEXTURE0 + i);
+            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+        }
+        glClientActiveTextureARB_ptr(GL_TEXTURE0);
+        glDisableClientState( GL_NORMAL_ARRAY );
+        glDisableClientState( GL_COLOR_ARRAY );
+        glDisableClientState( GL_SECONDARY_COLOR_ARRAY );
+        if (mCapabilities->hasCapability(RSC_VERTEX_PROGRAM))
+        {
+            glDisableVertexAttribArrayARB_ptr(7); // disable indices
+            glDisableVertexAttribArrayARB_ptr(1); // disable weights
+        }
+
+        glSecondaryColor3fEXT_ptr(0.0f, 0.0f, 0.0f);
+
+        // UnGuard
+        OgreUnguard();
+	}
+    //---------------------------------------------------------------------
+    void GLRenderSystem::setNormaliseNormals(bool normalise)
+    {
+        if (normalise)
+            glEnable(GL_NORMALIZE);
+        else
+            glDisable(GL_NORMALIZE);
+
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::bindGpuProgram(GpuProgram* prg)
+    {
+        GLGpuProgram* glprg = static_cast<GLGpuProgram*>(prg);
+        glprg->bindProgram();
+        if (glprg->getType() == GPT_VERTEX_PROGRAM)
+        {
+            mCurrentVertexProgram = glprg;
+        }
+        else
+        {
+            mCurrentFragmentProgram = glprg;
+        }
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::unbindGpuProgram(GpuProgramType gptype)
+    {
+
+        if (gptype == GPT_VERTEX_PROGRAM && mCurrentVertexProgram)
+        {
+            mCurrentVertexProgram->unbindProgram();
+            mCurrentVertexProgram = 0;
+        }
+        else if (gptype == GPT_FRAGMENT_PROGRAM && mCurrentFragmentProgram)
+        {
+            mCurrentFragmentProgram->unbindProgram();
+            mCurrentFragmentProgram = 0;
+        }
+
+
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params)
+    {
+        if (gptype == GPT_VERTEX_PROGRAM)
+        {
+            mCurrentVertexProgram->bindProgramParameters(params);
+        }
+        else
+        {
+            mCurrentFragmentProgram->bindProgramParameters(params);
+        }
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::setClipPlanes(const PlaneList& clipPlanes)
+    {
+        size_t i;
+        size_t numClipPlanes;
+        GLdouble clipPlane[4];
+
+        numClipPlanes = clipPlanes.size();
+        for (i = 0; i < numClipPlanes; ++i)
+        {
+            GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i);
+            const Plane& plane = clipPlanes[i];
+
+            if (i >= GL_MAX_CLIP_PLANES)
+            {
+                OGRE_EXCEPT(0, "Unable to set clip plane", 
+                    "GLRenderSystem::setClipPlanes");
+            }
+
+            clipPlane[0] = plane.normal.x;
+            clipPlane[1] = plane.normal.y;
+            clipPlane[2] = plane.normal.z;
+            clipPlane[3] = -plane.d;
+
+            glClipPlane(clipPlaneId, clipPlane);
+            glEnable(clipPlaneId);
+        }
+
+            // disable remaining clip planes
+        for ( ; i < 6/*GL_MAX_CLIP_PLANES*/; ++i)
+        {
+            glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i));
+        }
+    }
+	//---------------------------------------------------------------------
+    void GLRenderSystem::setScissorTest(bool enabled, size_t left, 
+        size_t top, size_t right, size_t bottom)
+    {
+        //  GL measures from the bottom, not the top
+        size_t targetHeight = mActiveRenderTarget->getHeight();
+        // Calculate the "lower-left" corner of the viewport
+        GLsizei w, h, x, y;
+
+        if (enabled)
+        {
+            glEnable(GL_SCISSOR_TEST);
+            // NB GL uses width / height rather than right / bottom
+            x = left;
+            y = targetHeight - bottom;
+            w = right - left;
+            h = bottom - top;
+            glScissor(x, y, w, h);
+        }
+        else
+        {
+            glDisable(GL_SCISSOR_TEST);
+            // GL requires you to reset the scissor when disabling
+            w = mActiveViewport->getActualWidth();
+            h = mActiveViewport->getActualHeight();
+            x = mActiveViewport->getActualLeft();
+            y = targetHeight - mActiveViewport->getActualTop() - h;
+            glScissor(x, y, w, h);
+        }
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::clearFrameBuffer(unsigned int buffers, 
+        const ColourValue& colour, Real depth, unsigned short stencil)
+    {
+
+        GLbitfield flags = 0;
+        if (buffers & FBT_COLOUR)
+        {
+            flags |= GL_COLOR_BUFFER_BIT;
+        }
+        if (buffers & FBT_DEPTH)
+        {
+            flags |= GL_DEPTH_BUFFER_BIT;
+        }
+        if (buffers & FBT_STENCIL)
+        {
+            flags |= GL_STENCIL_BUFFER_BIT;
+        }
+
+
+        // Enable depth & colour buffer for writing if it isn't
+
+        if (!mDepthWrite)
+        {
+            glDepthMask( GL_TRUE );
+        }
+        bool colourMask = !mColourWrite[0] || !mColourWrite[1] 
+        || !mColourWrite[2] || mColourWrite[3]; 
+        if (colourMask)
+        {
+            glColorMask(true, true, true, true);
+        }
+        // Set values
+        glClearColor(colour.r, colour.g, colour.b, colour.a);
+        glClearDepth(depth);
+        glClearStencil(stencil);
+        // Clear buffers
+        glClear(flags);
+        // Reset depth write state if appropriate
+        // Enable depth buffer for writing if it isn't
+        if (!mDepthWrite)
+        {
+            glDepthMask( GL_FALSE );
+        }
+        if (colourMask)
+        {
+            glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
+        }
+
+    }
+    // ------------------------------------------------------------------
+    void GLRenderSystem::_makeProjectionMatrix(Real left, Real right, 
+        Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest, 
+        bool forGpuProgram)
+    {
+        Real width = right - left;
+        Real height = top - bottom;
+        Real q, qn;
+        if (farPlane == 0)
+        {
+            // Infinite far plane
+            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
+        }
+        else
+        {
+            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
+            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
+        }
+        dest = Matrix4::ZERO;
+        dest[0][0] = 2 * nearPlane / width;
+        dest[0][2] = (right+left) / width;
+        dest[1][1] = 2 * nearPlane / height;
+        dest[1][2] = (top+bottom) / height;
+        dest[2][2] = q;
+        dest[2][3] = qn;
+        dest[3][2] = -1;
+    }
+
+    // ------------------------------------------------------------------
+    void GLRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
+    {
+        if (ushort(mClipPlanes.size()) < index+1)
+            mClipPlanes.resize(index+1);
+        mClipPlanes[index] = Vector4 (A, B, C, D);
+        GLdouble plane[4] = { A, B, C, D };
+        glClipPlane (GL_CLIP_PLANE0 + index, plane);
+    }
+
+    // ------------------------------------------------------------------
+    void GLRenderSystem::setGLClipPlanes() const
+    {
+        size_t size = mClipPlanes.size();
+        for (size_t i=0; i<size; i++)
+        {
+            const Vector4 &p = mClipPlanes[i];
+            GLdouble plane[4] = { p.x, p.y, p.z, p.w };
+            glClipPlane (GL_CLIP_PLANE0 + i, plane);
+        }
+    }
+
+    // ------------------------------------------------------------------
+    void GLRenderSystem::enableClipPlane (ushort index, bool enable)
+    {
+        glEnable (GL_CLIP_PLANE0 + index);
+    }
+    //---------------------------------------------------------------------
+    HardwareOcclusionQuery* GLRenderSystem::createHardwareOcclusionQuery(void)
+    {
+        return new GLHardwareOcclusionQuery(); 
+    }
+    //---------------------------------------------------------------------
+    Real GLRenderSystem::getHorizontalTexelOffset(void)
+    {
+        // No offset in GL
+        return 0.0f;
+    }
+    //---------------------------------------------------------------------
+    Real GLRenderSystem::getVerticalTexelOffset(void)
+    {
+        // No offset in GL
+        return 0.0f;
+    }
+ 	//---------------------------------------------------------------------
+    void GLRenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane, 
+        bool forGpuProgram)
+    {
+        // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
+
+        // Calculate the clip-space corner point opposite the clipping plane
+        // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
+        // transform it into camera space by multiplying it
+        // by the inverse of the projection matrix
+
+        Vector4 q;
+        q.x = (Math::Sign(plane.normal.x) + matrix[0][2]) / matrix[0][0];
+        q.y = (Math::Sign(plane.normal.y) + matrix[1][2]) / matrix[1][1];
+        q.z = -1.0F;
+        q.w = (1.0F + matrix[2][2]) / matrix[2][3];
+
+        // Calculate the scaled plane vector
+        Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
+        Vector4 c = clipPlane4d * (2.0F / (clipPlane4d.dotProduct(q)));
+
+        // Replace the third row of the projection matrix
+        matrix[2][0] = c.x;
+        matrix[2][1] = c.y;
+        matrix[2][2] = c.z + 1.0F;
+        matrix[2][3] = c.w; 
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::_oneTimeContextInitialization()
+    {
+        // Set nicer lighting model -- d3d9 has this by default
+        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);        
+        glEnable(GL_COLOR_SUM);
+        glDisable(GL_DITHER);
+
+        // Check for FSAA
+        // Enable the extension if it was enabled by the GLSupport
+        if (mGLSupport->checkExtension("GL_ARB_multisample"))
+        {
+            int fsaa_active = false;
+            glGetIntegerv(GL_SAMPLE_BUFFERS_ARB,(GLint*)&fsaa_active);
+            if(fsaa_active)
+            {
+                glEnable(GL_MULTISAMPLE_ARB);
+                LogManager::getSingleton().logMessage("Using FSAA from GL_ARB_multisample extension.");
+            }            
+        }
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::_setRenderTarget(RenderTarget *target)
+    {
+        mActiveRenderTarget = target;
+        // Switch context if different from current one
+        ContextMap::iterator i = mContextMap.find(target);
+        if(i != mContextMap.end() && mCurrentContext != i->second) {
+            mCurrentContext->endCurrent();
+            mCurrentContext = i->second;
+            // Check if the context has already done one-time initialisation
+            if(!mCurrentContext->getInitialized()) {
+               _oneTimeContextInitialization();
+               mCurrentContext->setInitialized();
+            }
+            mCurrentContext->setCurrent();
+        }
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::_registerContext(RenderTarget *target, GLContext *context)
+    {
+        mContextMap[target] = context;
+    }
+    //---------------------------------------------------------------------
+    void GLRenderSystem::_unregisterContext(RenderTarget *target)
+    {
+        ContextMap::iterator i = mContextMap.find(target);
+        if(i != mContextMap.end() && mCurrentContext == i->second) {
+            // Change the context to something else so that a valid context
+            // remains active. When this is the main context being unregistered,
+            // we set the main context to 0.
+            if(mCurrentContext != mMainContext) {
+                mCurrentContext->endCurrent();
+                mCurrentContext = mMainContext;
+                mCurrentContext->setCurrent();
+            } else {
+                mMainContext = 0;
+            }
+        }
+        mContextMap.erase(target);
+    }
+    //---------------------------------------------------------------------
+    GLContext *GLRenderSystem::_getMainContext() {
+        return mMainContext;
+    }
+    //---------------------------------------------------------------------
+    Real GLRenderSystem::getMinimumDepthInputValue(void)
+    {
+        // Range [-1.0f, 1.0f]
+        return -1.0f;
+    }
+    //---------------------------------------------------------------------
+    Real GLRenderSystem::getMaximumDepthInputValue(void)
+    {
+        // Range [-1.0f, 1.0f]
+        return 1.0f;
+    }
+
+}
Index: OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp	(revision 193)
@@ -0,0 +1,515 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreWin32Window.h"
+#include "OgreRoot.h"
+#include "OgreLogManager.h"
+#include "OgreRenderSystem.h"
+#include "OgreImageCodec.h"
+#include "OgreStringConverter.h"
+#include "OgreException.h"
+#include "OgreWin32GLSupport.h"
+#include "OgreWin32Context.h"
+
+namespace Ogre {
+
+	Win32Window::Win32Window(Win32GLSupport &glsupport):
+		mGLSupport(glsupport),
+        mContext(0)
+    {
+		mIsFullScreen = false;
+		mHWnd = 0;
+		mIsExternal = false;
+		mSizing = false;
+		mClosed = false;
+		mDisplayFrequency = 0;
+		mActive = false;
+    }
+
+    Win32Window::~Win32Window()
+    {
+		destroy();
+    }
+
+	void Win32Window::create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams)
+    {
+		// destroy current window, if any
+		if (mHWnd)
+			destroy();
+
+		HINSTANCE hInst = GetModuleHandle("RenderSystem_GL.dll");
+
+		mHWnd = 0;
+		mName = name;
+		mIsFullScreen = fullScreen;
+		mClosed = false;
+
+		// load window defaults
+		mLeft = mTop = -1; // centered
+		mWidth = width;
+		mHeight = height;
+		mDisplayFrequency = 0;
+		mIsDepthBuffered = true;
+		mColourDepth = mIsFullScreen? 32 : GetDeviceCaps(GetDC(0), BITSPIXEL);
+
+		HWND parent = 0;
+		String title = name;
+		bool vsync = false;
+		int fsaa = 0;
+		String border = "";
+		bool outerSize = false;
+
+		if(miscParams)
+		{
+			// Get variable-length params
+			NameValuePairList::const_iterator opt;
+			NameValuePairList::const_iterator end = miscParams->end();
+
+			if ((opt = miscParams->find("title")) != end)
+				title = opt->second;
+
+			if ((opt = miscParams->find("left")) != end)
+				mLeft = StringConverter::parseInt(opt->second);
+
+			if ((opt = miscParams->find("top")) != end)
+				mTop = StringConverter::parseInt(opt->second);
+
+			if ((opt = miscParams->find("depthBuffer")) != end)
+				mIsDepthBuffered = StringConverter::parseBool(opt->second);
+
+			if ((opt = miscParams->find("vsync")) != end)
+				vsync = StringConverter::parseBool(opt->second);
+
+			if ((opt = miscParams->find("FSAA")) != end)
+				fsaa = StringConverter::parseUnsignedInt(opt->second);
+
+			if ((opt = miscParams->find("externalWindowHandle")) != end)
+			{
+				mHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
+				if (mHWnd)
+				{
+					mIsExternal = true;
+					mIsFullScreen = false;
+				}
+			}
+			// window border style
+			opt = miscParams->find("border");
+			if(opt != miscParams->end())
+				border = opt->second;
+			// set outer dimensions?
+			opt = miscParams->find("outerDimensions");
+			if(opt != miscParams->end())
+				outerSize = StringConverter::parseBool(opt->second);
+		
+			if (mIsFullScreen)
+        {
+				// only available with fullscreen
+				if ((opt = miscParams->find("displayFrequency")) != end)
+					mDisplayFrequency = StringConverter::parseUnsignedInt(opt->second);
+				if ((opt = miscParams->find("colourDepth")) != end)
+					mColourDepth = StringConverter::parseUnsignedInt(opt->second);
+        }
+		else 
+		{
+				// incompatible with fullscreen
+				if ((opt = miscParams->find("parentWindowHandle")) != end)
+					parent = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			}
+		}
+
+		if (!mIsExternal)
+			{
+			DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+			DWORD dwStyleEx = 0;
+			int outerw, outerh;
+
+			if (mIsFullScreen)
+                {
+				dwStyle |= WS_POPUP;
+				dwStyleEx |= WS_EX_TOPMOST;
+				outerw = mWidth;
+				outerh = mHeight;
+				mLeft = mTop = 0;
+                }
+				else
+                {
+				if (border == "none")
+					dwStyle |= WS_POPUP;
+				else if (border == "fixed")
+					dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
+					WS_SYSMENU | WS_MINIMIZEBOX;
+				else
+					dwStyle |= WS_OVERLAPPEDWINDOW;
+
+				int screenw = GetSystemMetrics(SM_CXSCREEN);
+				int screenh = GetSystemMetrics(SM_CYSCREEN);
+
+				if (!outerSize)
+                {
+					// calculate overall dimensions for requested client area
+					RECT rc = { 0, 0, mWidth, mHeight };
+					AdjustWindowRect(&rc, dwStyle, false);
+
+					// clamp window dimensions to screen size
+					outerw = (rc.right-rc.left < screenw)? rc.right-rc.left : screenw;
+					outerh = (rc.bottom-rc.top < screenh)? rc.bottom-rc.top : screenh;
+            }
+
+				// center window if given negative coordinates
+				if (mLeft < 0)
+					mLeft = (screenw - outerw) / 2;
+				if (mTop < 0)
+					mTop = (screenh - outerh) / 2;
+
+				// keep window contained in visible screen area
+				if (mLeft > screenw - outerw)
+					mLeft = screenw - outerw;
+				if (mTop > screenh - outerh)
+					mTop = screenh - outerh;
+			}
+
+			// register class and create window
+			WNDCLASS wc = { CS_OWNDC, WndProc, 0, 0, hInst,
+				LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
+				(HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "OgreGLWindow" };
+			RegisterClass(&wc);
+
+			// Pass pointer to self as WM_CREATE parameter
+			mHWnd = CreateWindowEx(dwStyleEx, "OgreGLWindow", title.c_str(),
+				dwStyle, mLeft, mTop, outerw, outerh, parent, 0, hInst, this);
+
+			StringUtil::StrStreamType str;
+			str << "Created Win32Window '"
+				<< mName << "' : " << mWidth << "x" << mHeight
+				<< ", " << mColourDepth << "bpp";
+			LogManager::getSingleton().logMessage(LML_NORMAL, str.str());
+
+			if (mIsFullScreen)
+			{
+				DEVMODE dm;
+				dm.dmSize = sizeof(DEVMODE);
+				dm.dmBitsPerPel = mColourDepth;
+				dm.dmPelsWidth = mWidth;
+				dm.dmPelsHeight = mHeight;
+				dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+				if (mDisplayFrequency)
+				{
+					dm.dmDisplayFrequency = mDisplayFrequency;
+					dm.dmFields |= DM_DISPLAYFREQUENCY;
+				}
+				if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+					LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed");
+			}
+		    }
+
+			RECT rc;
+		// top and left represent outer window position
+		GetWindowRect(mHWnd, &rc);
+		mTop = rc.top;
+		mLeft = rc.left;
+		// width and height represent drawable area only
+			GetClientRect(mHWnd, &rc);
+			mWidth = rc.right;
+			mHeight = rc.bottom;
+		
+		mHDC = GetDC(mHWnd);
+
+		if (!mGLSupport.selectPixelFormat(mHDC, mColourDepth, fsaa))
+		{
+			if (fsaa == 0)
+				OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
+
+			LogManager::getSingleton().logMessage(LML_NORMAL, "FSAA level not supported, falling back");
+			if (!mGLSupport.selectPixelFormat(mHDC, mColourDepth, 0))
+				OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
+		}
+
+		mGlrc = wglCreateContext(mHDC);
+		if (!mGlrc)
+			OGRE_EXCEPT(0, "wglCreateContext", "Win32Window::create");
+		if (!wglMakeCurrent(mHDC, mGlrc))
+			OGRE_EXCEPT(0, "wglMakeCurrent", "Win32Window::create");
+		
+		wglSwapIntervalEXT(vsync? 1 : 0);
+
+        // Create RenderSystem context
+        mContext = new Win32Context(mHDC, mGlrc);
+        // Register the context with the rendersystem and associate it with this window
+        GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
+        rs->_registerContext(this, mContext);
+
+		mActive = true;
+    }
+
+    void Win32Window::destroy(void)
+    {
+		if (!mHWnd)
+			return;
+
+        // Unregister and destroy OGRE GLContext
+        if (mContext)
+        {
+            GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
+            rs->_unregisterContext(this);
+            delete mContext;
+			mContext = 0;
+        }
+		if (mGlrc)
+		{
+			wglDeleteContext(mGlrc);
+			mGlrc = 0;
+		}
+		if (!mIsExternal)
+		{
+		if (mIsFullScreen)
+			ChangeDisplaySettings(NULL, 0);
+	        DestroyWindow(mHWnd);
+        }
+        mActive = false;
+		mHDC = 0; // no release thanks to CS_OWNDC wndclass style
+		mHWnd = 0;
+    }
+
+	bool Win32Window::isVisible() const
+    {
+		return (mHWnd && !IsIconic(mHWnd));
+    }
+
+    bool Win32Window::isClosed() const
+    {
+        return mClosed;
+    }
+
+    void Win32Window::reposition(int left, int top)
+    {
+		if (mHWnd && !mIsFullScreen)
+		{
+			SetWindowPos(mHWnd, 0, left, top, 0, 0,
+				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+		}
+    }
+
+    void Win32Window::resize(unsigned int width, unsigned int height)
+    {
+		if (mHWnd && !mIsFullScreen)
+		{
+			RECT rc = { 0, 0, width, height };
+			AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
+			width = rc.right - rc.left;
+			height = rc.bottom - rc.top;
+			SetWindowPos(mHWnd, 0, 0, 0, width, height,
+				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+		}
+	}
+
+	void Win32Window::windowMovedOrResized()
+	{
+		if (!isVisible())
+			return;
+
+		RECT rc;
+		// top and left represent outer window position
+		GetWindowRect(mHWnd, &rc);
+		mTop = rc.top;
+		mLeft = rc.left;
+		// width and height represent drawable area only
+		GetClientRect(mHWnd, &rc);
+
+		if (mWidth == rc.right && mHeight == rc.bottom)
+			return;
+
+		mWidth = rc.right;
+		mHeight = rc.bottom;
+
+		// Notify viewports of resize
+		ViewportList::iterator it, itend;
+        itend = mViewportList.end();
+		for( it = mViewportList.begin(); it != itend; ++it )
+			(*it).second->_updateDimensions();
+	}
+
+    void Win32Window::swapBuffers(bool waitForVSync)
+    {
+		SwapBuffers(mHDC);
+    }
+
+	void Win32Window::writeContentsToFile(const String& filename)
+	{
+		ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+		imgData->width = mWidth;
+		imgData->height = mHeight;
+		imgData->depth = 1;
+		imgData->format = PF_BYTE_RGB;
+
+		// Allocate buffer 
+		uchar* pBuffer = new uchar[mWidth * mHeight * 3];
+
+		// Read pixels
+		// I love GL: it does all the locking & colour conversion for us
+		glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+		// Wrap buffer in a memory stream
+		DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
+
+		// Need to flip the read data over in Y though
+		Image img;
+		img.loadRawData(stream, mWidth, mHeight, imgData->format );
+		img.flipAroundX();
+
+		MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
+
+		// Get codec 
+		size_t pos = filename.find_last_of(".");
+		String extension;
+		if( pos == String::npos )
+			OGRE_EXCEPT(
+			Exception::ERR_INVALIDPARAMS, 
+			"Unable to determine image type for '" + filename + "' - invalid extension.",
+			"Win32Window::writeContentsToFile" );
+
+		while( pos != filename.length() - 1 )
+			extension += filename[++pos];
+
+		// Get the codec
+		Codec * pCodec = Codec::getCodec(extension);
+
+		// Write out
+		Codec::CodecDataPtr ptr(imgData);
+        pCodec->codeToFile(streamFlipped, filename, ptr);
+
+		delete [] pBuffer;
+	}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar *Win32Window::getBufferContents(int &dimx, int &dimy)
+	{
+		dimx = mWidth;
+		dimy = mHeight;
+		
+		// Allocate buffer 
+		uchar* pBuffer = new uchar[mWidth * mHeight * 3];
+
+		// Read pixels
+		// I love GL: it does all the locking & colour conversion for us
+		glReadPixels(0, 0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+		return pBuffer;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+	// Window procedure callback
+	// This is a static member, so applies to all windows but we store the
+	// Win32Window instance in the window data GetWindowLog/SetWindowLog
+	LRESULT Win32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+	{
+
+		if (uMsg == WM_CREATE)
+		{
+			// Store pointer to Win32Window in user data area
+			SetWindowLong(hWnd, GWL_USERDATA,
+				(LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams));
+			return 0;
+		}
+
+		// look up window instance
+		// note: it is possible to get a WM_SIZE before WM_CREATE
+		Win32Window* win = (Win32Window*)GetWindowLong(hWnd, GWL_USERDATA);
+		if (!win)
+			return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+		switch( uMsg )
+		{
+		case WM_ACTIVATE:
+			if (win->mIsFullScreen)
+			{
+				if (LOWORD(wParam) == WA_INACTIVE)
+				{
+				win->mActive = false;
+					ChangeDisplaySettings(NULL, 0);
+					ShowWindow(hWnd, SW_SHOWMINNOACTIVE);
+				}
+			else
+				{
+				win->mActive = true;
+					ShowWindow(hWnd, SW_SHOWNORMAL);
+
+					DEVMODE dm;
+					dm.dmSize = sizeof(DEVMODE);
+					dm.dmBitsPerPel = win->mColourDepth;
+					dm.dmPelsWidth = win->mWidth;
+					dm.dmPelsHeight = win->mHeight;
+					dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+					if (win->mDisplayFrequency)
+					{
+						dm.dmDisplayFrequency = win->mDisplayFrequency;
+						dm.dmFields |= DM_DISPLAYFREQUENCY;
+					}
+					ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
+				}
+			}
+			break;
+
+		case WM_ENTERSIZEMOVE:
+			win->mSizing = true;
+			break;
+
+		case WM_EXITSIZEMOVE:
+			win->windowMovedOrResized();
+			win->mSizing = false;
+			break;
+
+		case WM_MOVE:
+		case WM_SIZE:
+			if (!win->mSizing)
+					win->windowMovedOrResized();
+			break;
+
+		case WM_GETMINMAXINFO:
+			// Prevent the window from going smaller than some minimu size
+			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+			break;
+
+		case WM_CLOSE:
+			win->destroy(); // will call DestroyWindow
+			win->mClosed = true;
+			return 0;
+		}
+
+		return DefWindowProc( hWnd, uMsg, wParam, lParam );
+	}
+	
+	void Win32Window::getCustomAttribute( const String& name, void* pData )
+	{
+		if( name == "HWND" )
+		{
+			HWND *pHwnd = (HWND*)pData;
+			*pHwnd = getWindowHandle();
+			return;
+		}
+	}
+
+}
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7Texture.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7Texture.h	(revision 154)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7Texture.h	(revision 154)
@@ -0,0 +1,230 @@
+/*
+-----------------------------------------------------------------------------
+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 _D3DTexture_H__
+#define _D3DTexture_H__
+
+#include "OgreD3D7Prerequisites.h"
+#include "OgreTexture.h"
+#include "OgreRenderTarget.h"
+#include "OgreRenderTexture.h"
+#include "OgreRenderTargetListener.h"
+#include "OgreD3D7HardwarePixelBuffer.h"
+
+namespace Ogre {
+
+    /** Direct3D7-specific texture resource implementation. 
+    */
+    class D3DTexture : public Texture
+    {
+    public:
+        // Constructor, called from D3DTextureManager
+        D3DTexture(ResourceManager* creator, const String& name, ResourceHandle handle,
+            const String& group, bool isManual, ManualResourceLoader* loader, 
+            IDirect3DDevice7 * lpDirect3dDevice);
+        virtual ~D3DTexture();
+
+        virtual void loadImage( const Image &img );
+		virtual void loadImage3D( const Image imgs[]);
+        virtual void copyToTexture(TexturePtr& target );
+
+        /// D3D-specific member that returns the underlying surface.
+        LPDIRECTDRAWSURFACE7 getDDSurface(void);
+
+        /// @copydoc Texture::createInternalResources
+        void createInternalResources(void);
+
+		/// @copydoc Texture::getBuffer
+		HardwarePixelBufferSharedPtr getBuffer(size_t face, size_t mipmap);
+
+		/// Static pixelformat functions
+		static D3DX_SURFACEFORMAT OgreFormat_to_D3DXFormat( PixelFormat format );
+		static PixelFormat closestD3DXFormat( PixelFormat format );
+		static bool OgreFormat_to_DDPixelFormat( PixelFormat format, DDPIXELFORMAT & out );
+    protected:
+        IDirect3DDevice7 * mD3DDevice;       ///< A pointer to the Direct3D device.
+        IDirectDrawSurface7 * mSurface;      ///< Surface of the (first) device-specific texture.
+		/// cube texture individual face names
+		String mCubeFaceNames[6];
+		/// Vector of pointers to subsurfaces
+		typedef std::vector<HardwarePixelBufferSharedPtr> SurfaceList;
+		SurfaceList						mSurfaceList;
+	
+
+        /// @copydoc Resource::loadImpl
+        void loadImpl(void);
+        /// @copydoc Resource::unloadImpl
+        void unloadImpl(void);
+		
+		void createSurface2D(void);
+		void createSurface3D(void);
+
+		/// internal method, return a D3D pixel format for texture creation
+		void _chooseD3DFormat(DDPIXELFORMAT &ddpf);
+
+		/// internal method, construct full cube texture face names from a given string
+		void _constructCubeFaceNames(const String name);
+
+		/// internal method, the cube map face name for the spec. face index
+		String _getCubeFaceName(unsigned char face) const
+		{ assert(face < 6); return mCubeFaceNames[face]; }
+
+		// Create the list of surfaces
+		void _createSurfaceList();
+    };
+
+    /** Specialisation of SharedPtr to allow SharedPtr to be assigned to D3DTexturePtr 
+    @note Has to be a subclass since we need operator=.
+    We could templatise this instead of repeating per Resource subclass, 
+    except to do so requires a form VC6 does not support i.e.
+    ResourceSubclassPtr<T> : public SharedPtr<T>
+    */
+    class D3DTexturePtr : public SharedPtr<D3DTexture> 
+    {
+    public:
+        D3DTexturePtr() : SharedPtr<D3DTexture>() {}
+        explicit D3DTexturePtr(D3DTexture* rep) : SharedPtr<D3DTexture>(rep) {}
+        D3DTexturePtr(const D3DTexturePtr& r) : SharedPtr<D3DTexture>(r) {} 
+        D3DTexturePtr(const ResourcePtr& r) : SharedPtr<D3DTexture>()
+        {
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<D3DTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+        }
+
+        /// Operator used to convert a ResourcePtr to a D3DTexturePtr
+        D3DTexturePtr& operator=(const ResourcePtr& r)
+        {
+            if (pRep == static_cast<D3DTexture*>(r.getPointer()))
+                return *this;
+            release();
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<D3DTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+        /// Operator used to convert a TexturePtr to a D3DTexturePtr
+        D3DTexturePtr& operator=(const TexturePtr& r)
+        {
+            if (pRep == static_cast<D3DTexture*>(r.getPointer()))
+                return *this;
+            release();
+            pRep = static_cast<D3DTexture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+    };
+
+
+    /// D3D7 implementation of RenderTexture
+    class D3D7RenderTexture : public RenderTexture
+    {
+    public:
+        D3D7RenderTexture( const String & name, 
+			unsigned int width, unsigned int height,
+			TextureType texType, PixelFormat internalFormat, 
+			const NameValuePairList *misc )
+			: RenderTexture( name, width, height, texType, internalFormat )
+        {
+            mPrivateTex = TextureManager::getSingleton().createManual(mName + 
+                "_PRIVATE##", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
+                texType, mWidth, mHeight, 0, internalFormat, TU_RENDERTARGET);
+            mPrivateTex->createInternalResources();
+        }
+
+		virtual ~D3D7RenderTexture()
+		{
+			mPrivateTex->unload();
+			TextureManager::getSingleton().remove(mPrivateTex->getName());
+		}
+
+		bool requiresTextureFlipping() const { return false; }
+
+        virtual void getCustomAttribute( const String& name, void* pData )
+        {
+            if( name == "DDBACKBUFFER" )
+            {
+                LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
+
+                *pSurf = mPrivateTex->getDDSurface();
+                return;
+            }
+            else if( name == "DDFRONTBUFFER" )
+            {
+                LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
+
+                *pSurf = mPrivateTex->getDDSurface();
+                return;
+            }
+            else if( name == "HWND" )
+            {
+                HWND *pHwnd = (HWND*)pData;
+
+                *pHwnd = NULL;
+                return;
+            }
+            else if( name == "isTexture" )
+            {
+                bool *b = reinterpret_cast< bool * >( pData );
+                *b = true;
+
+                return;
+            }
+        }
+        virtual void writeContentsToFile( const String & filename ) {}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy) { dimx = dimy = 0; return NULL; };
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+        /// The texture to which rendering takes place.
+        D3DTexturePtr mPrivateTex;
+
+    protected:
+        virtual void _copyToTexture()
+        {
+            // Copy the newly-rendered data to the public texture surface.
+            mPrivateTex->copyToTexture( mTexture );
+        }
+    };
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7RenderWindow.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7RenderWindow.h	(revision 153)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/include/OgreD3D7RenderWindow.h	(revision 153)
@@ -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.
+-----------------------------------------------------------------------------
+*/
+#ifndef __D3D7RenderWindow_H__
+#define __D3D7RenderWindow_H__
+
+// Precompiler options
+#include "OgreD3D7Prerequisites.h"
+
+#include "OgreRenderWindow.h"
+#include "OgreDDDriver.h"
+#include "OgreD3D7DeviceList.h"
+#include "OgreD3D7Device.h"
+
+namespace Ogre {
+    /** Defines the rendering window on Win32 systems
+        @remarks
+            This class represents the rendering window on the
+            Windows family of operating systems.
+     */
+    class D3D7RenderWindow : public RenderWindow
+    {
+    public:
+        D3D7RenderWindow(HINSTANCE instance, DDDriver *driver);
+        ~D3D7RenderWindow();
+
+		void create(const String& name, unsigned int width, unsigned int height,
+			bool fullScreen, const NameValuePairList *miscParams);
+
+        /** Overridden - see RenderWindow 
+        */
+        void destroy(void);
+
+        /** Overridden - see RenderWindow
+        */
+        bool isActive(void) const;
+
+        /** Overridden - see RenderWindow
+        */
+        bool isClosed(void) const;
+
+        /** Overridden - see RenderWindow
+        */
+        void reposition(int left, int top);
+
+        /** Overridden - see RenderWindow
+        */
+        void resize(unsigned int width, unsigned int height);
+
+        /** Overridden - see RenderWindow
+        */
+        void swapBuffers(bool waitForVSync);
+
+        /** Retrieves a handle to the window (Win32 specific)
+        */
+        HWND getWindowHandle(void) const;
+
+        /** Retrieves a handle to the window's parent, or 0 if there is no parent.
+        */
+        HWND getParentWindowHandle(void) const;
+
+        /** Returns true if this window is using DirectDraw.
+        */
+        bool isUsingDirectDraw(void) const;
+        /** Retrieves a pointer to the DirectDraw wrapper object used to 
+            manage the window's surface. (Win32 specific)
+            @note
+                Only applicable for windows using DirectDraw.
+        */
+        DDDriver* getDirectDrawDriver(void);
+
+        /** Returns a pointer to a DirectDraw surface containing the
+            front buffer.
+            @note
+                Only applicable for windows using DirectDraw.
+        */
+        LPDIRECTDRAWSURFACE7 getDDFrontBuffer(void);
+
+        /** Returns a pointer to a DirectDraw surface containing the back 
+            buffer. Only applicable if using DirectDraw.
+        */
+        LPDIRECTDRAWSURFACE7 getDDBackBuffer(void);
+
+        /** Returns a pointer to the Direct3D device that works with this
+            window
+            @note
+                Only applicable for windows using DirectDraw.
+        */
+        LPDIRECT3DDEVICE7 getD3DDevice(void);
+
+        bool requiresTextureFlipping() const { return false; }
+
+        /** Overridden - see RenderTarget.
+        */
+        void getCustomAttribute(const String& name, void* pData);
+
+        /** Overridden - see RenderTarget.
+        */
+        void writeContentsToFile(const String& filename);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+		HINSTANCE mInstance;			// Process instance
+		DDDriver *mDriver;			// D3D9 driver
+        // Win32-specific data members
+        bool mIsUsingDirectDraw;
+        HWND mHWnd;                    // Win32 Window handle
+        HWND mParentHWnd;
+        bool mActive;                // Is active i.e. visible
+        bool mReady;                // Is ready i.e. available for update
+        bool mClosed;
+
+        RECT rcBlitDest;            // Target for blit operation
+                                    // == window client area
+
+
+        static LRESULT CALLBACK WndProc( 
+            HWND hWnd, 
+            UINT uMsg, 
+            WPARAM wParam, 
+            LPARAM lParam);
+
+        // ---------------------------------------------------------
+        // DirectX-specific
+        // ---------------------------------------------------------
+
+        // Pointer to DDDriver encapsulating DirectDraw driver (if DirectX in use)
+        DDDriver* mlpDDDriver;
+
+        // Pointers to DX surfaces
+        LPDIRECTDRAWSURFACE7 mlpDDSFront; // Pointer to primary (front) buffer surface
+        LPDIRECTDRAWSURFACE7 mlpDDSBack; // Pointer to back buffer
+
+        // Pointer to the 3D Device specific for this window
+        LPDIRECT3DDEVICE7 mlpD3DDevice;
+
+        // DirectDraw Methods
+        void createDDSurfaces(void);
+        void releaseDDSurfaces(void);
+        void restoreDDSurfaces(void);
+        void createDepthBuffer(void);
+
+        // Method for dealing with resize / move & 3d library
+        void windowMovedOrResized(void);
+        
+        // ---------------------------------------------------------
+        // OpenGL-specific details
+        // ---------------------------------------------------------
+
+        // TODO
+    };
+}
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/src/OgreD3D7RenderWindow.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/src/OgreD3D7RenderWindow.cpp	(revision 153)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D7/src/OgreD3D7RenderWindow.cpp	(revision 153)
@@ -0,0 +1,908 @@
+/*-------------------------------------------------------------------------
+This source file is a part of OGRE
+(Object-oriented Graphics Rendering Engine)
+
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This library is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License (LGPL) as 
+published by the Free Software Foundation; either version 2.1 of the 
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License 
+along with this library; if not, write to the Free Software Foundation, 
+Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
+http://www.gnu.org/copyleft/lesser.txt
+-------------------------------------------------------------------------*/
+#include "OgreD3D7RenderWindow.h"
+
+#include "OgreLogManager.h"
+#include "OgreViewport.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreRenderSystem.h"
+#include "OgreD3D7TextureManager.h"
+#include "OgreBitwise.h"
+#include "OgreImageCodec.h"
+#include "OgreStringConverter.h"
+
+namespace Ogre {
+
+
+    // Window procedure callback
+    // This is a static member, so applies to all windows but we store the 
+    // D3D7RenderWindow instance in the window data GetWindowLong/SetWindowLong.
+    LRESULT D3D7RenderWindow::WndProc( 
+        HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+    {
+        LPCREATESTRUCT lpcs;
+        D3D7RenderWindow* win;
+
+        // look up window instance
+        if (uMsg != WM_CREATE)
+        {
+            // Get window pointer
+            win = (D3D7RenderWindow*)GetWindowLong(hWnd, 0);
+        }
+
+        switch( uMsg )
+        {
+            case WM_ACTIVATE:
+                if( LOWORD( wParam ) == WA_INACTIVE )
+                    win->mActive = false;
+                else
+                    win->mActive = true;
+                break;
+
+            case WM_CREATE:
+                // Log the new window
+                // Get CREATESTRUCT
+                lpcs = (LPCREATESTRUCT)lParam;
+                win = (D3D7RenderWindow*)(lpcs->lpCreateParams);
+                // Store pointer in window user data area
+                SetWindowLong(hWnd, 0, (long)win);
+                win->mActive = true;
+
+                return 0;
+
+            case WM_KEYDOWN:
+                // TEMPORARY CODE
+                // TODO - queue up keydown / keyup events with
+                //  window name and timestamp to be processed
+                //  by main loop
+
+                // ESCAPE closes window
+                //if (wParam == VK_ESCAPE)
+                //{
+                //    win->mClosed = true;
+                //    return 0L;
+                //}
+                break;
+
+            case WM_PAINT:
+                // If we get WM_PAINT messages, it usually means our window was
+                // covered up, so we need to refresh it by re-showing the contents
+                // of the current frame.
+                if (win->mActive && win->mReady)
+                    win->update();
+                break;
+
+            case WM_MOVE:
+                // Move messages need to be tracked to update the screen rects
+                // used for blitting the backbuffer to the primary.
+                if(win->mActive && win->mReady)
+                    win->windowMovedOrResized();
+                break;
+
+            case WM_ENTERSIZEMOVE:
+                // Prevent rendering while moving / sizing
+                win->mReady = false;
+                break;
+
+            case WM_EXITSIZEMOVE:
+                win->windowMovedOrResized();
+                win->mReady = true;
+                break;
+
+            case WM_SIZE:
+                // Check to see if we are losing or gaining our window. Set the
+                // active flag to match.
+                if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
+                    win->mActive = false;
+                else
+                {
+                    win->mActive = true;
+                    if (win->mReady)
+                        win->windowMovedOrResized();
+                }
+
+                break;
+
+            case WM_GETMINMAXINFO:
+                // Prevent the window from going smaller than some minimum size
+                ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+                ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+                break;
+
+            case WM_CLOSE:
+                DestroyWindow( win->mHWnd );
+                win->mClosed = true;
+                return 0;
+
+            /*
+            case WM_DESTROY:
+                g_DIMSystem->CleanupRenderer();
+                PostQuitMessage(0);
+                return 0L;
+            */
+        }
+
+
+
+        return DefWindowProc( hWnd, uMsg, wParam, lParam );
+    }
+
+    // -------------------------------------------
+    // D3D7RenderWindow Implementation
+    // -------------------------------------------
+	D3D7RenderWindow::D3D7RenderWindow(HINSTANCE instance, DDDriver *driver):
+		mInstance(instance),
+		mDriver(driver)
+    {
+        mIsUsingDirectDraw = false;
+        mIsFullScreen = false;
+        mlpDDDriver = 0;
+        mHWnd = 0;
+        mActive = false;
+        mReady = false;
+        mClosed = false;
+    }
+
+    D3D7RenderWindow::~D3D7RenderWindow()
+    {
+    }
+
+
+
+	void D3D7RenderWindow::create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams)
+    {
+
+        HWND parentHWnd = 0;
+        HINSTANCE hInst = mInstance;
+        DDDriver* drv = mDriver;
+        long tempPtr;
+		bool vsync = false;
+		unsigned int displayFrequency = 0;
+		String title = name;
+		unsigned int colourDepth = 32;
+		unsigned int left = 0; // Defaults to screen center
+		unsigned int top = 0; // Defaults to screen center
+		bool depthBuffer = true;
+		
+		if(miscParams)
+		{
+			// Get variable-length params
+			NameValuePairList::const_iterator opt;
+			// left (x)
+			opt = miscParams->find("left");
+			if(opt != miscParams->end())
+				left = StringConverter::parseUnsignedInt(opt->second);
+			// top (y)
+			opt = miscParams->find("top");
+			if(opt != miscParams->end())
+				top = StringConverter::parseUnsignedInt(opt->second);
+			// Window title
+			opt = miscParams->find("title");
+			if(opt != miscParams->end())
+				title = opt->second;
+			// parentWindowHandle -> parentHWnd
+			opt = miscParams->find("parentWindowHandle");
+			if(opt != miscParams->end()) 
+				parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			// vsync	[parseBool]
+			opt = miscParams->find("vsync");
+			if(opt != miscParams->end())
+				vsync = StringConverter::parseBool(opt->second);
+			// displayFrequency
+			opt = miscParams->find("displayFrequency");
+			if(opt != miscParams->end())
+				displayFrequency = StringConverter::parseUnsignedInt(opt->second);
+			// colourDepth
+			opt = miscParams->find("colourDepth");
+			if(opt != miscParams->end())
+				colourDepth = StringConverter::parseUnsignedInt(opt->second);
+			// depthBuffer [parseBool]
+			opt = miscParams->find("depthBuffer");
+			if(opt != miscParams->end())
+				depthBuffer = StringConverter::parseBool(opt->second);
+		}
+
+
+        // Destroy current window if any
+        if (mHWnd)
+        {
+            destroy();
+        }
+
+        // TODO: deal with child windows
+        mParentHWnd = parentHWnd;
+
+		DWORD dwStyle = (fullScreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+		RECT rc;
+
+		mWidth = width;
+		mHeight = height;
+
+		if (!fullScreen)
+		{
+			// Calculate window dimensions required to get the requested client area
+			SetRect(&rc, 0, 0, mWidth, mHeight);
+			AdjustWindowRect(&rc, dwStyle, false);
+			mWidth = rc.right - rc.left;
+			mHeight = rc.bottom - rc.top;
+
+			// Clamp width and height to the desktop dimensions
+			if (mWidth > (unsigned)GetSystemMetrics(SM_CXSCREEN))
+				mWidth = (unsigned)GetSystemMetrics(SM_CXSCREEN);
+			if (mHeight > (unsigned)GetSystemMetrics(SM_CYSCREEN))
+				mHeight = (unsigned)GetSystemMetrics(SM_CYSCREEN);
+
+			if (!left)
+				mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
+			else
+				mLeft = left;
+			if (!top)
+				mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
+			else
+				mTop = top;
+		}
+		else
+			mTop = mLeft = 0;
+
+		// Register the window class
+        // NB Allow 4 bytes of window data for D3D7RenderWindow pointer
+        WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
+                              LoadIcon( NULL, IDI_APPLICATION ),
+                              LoadCursor(NULL, IDC_ARROW),
+                              (HBRUSH)GetStockObject(BLACK_BRUSH), NULL,
+                              TEXT(title.c_str()) };
+        RegisterClass( &wndClass );
+
+        // Create our main window
+        // Pass pointer to self
+        HWND hWnd = CreateWindow( TEXT(title.c_str()),
+                                  TEXT(title.c_str()),
+                                  dwStyle, mLeft, mTop,
+                                  mWidth, mHeight, 0L, 0L, hInst, this );
+
+		GetClientRect(hWnd,&rc);
+		mWidth = rc.right;
+		mHeight = rc.bottom;
+
+		ShowWindow( hWnd, SW_SHOWNORMAL );
+        UpdateWindow( hWnd );
+
+        mHWnd = hWnd;
+
+        // Store info
+        mName = name;
+        mWidth = width;
+        mHeight = height;
+        mIsDepthBuffered = depthBuffer;
+        mIsFullScreen = fullScreen;
+
+        if (fullScreen)
+        {
+            mColourDepth = colourDepth;
+            mLeft = 0;
+            mTop = 0;
+        }
+        else
+        {
+            // Get colour depth from display
+            HDC hdc = GetDC( mHWnd );
+            mColourDepth = GetDeviceCaps( hdc, BITSPIXEL );
+            ReleaseDC( mHWnd, hdc );
+            mTop = top;
+            mLeft = left;
+
+            // Record the dimensions of the blit location
+            GetClientRect( mHWnd, &rcBlitDest );
+            ClientToScreen( mHWnd, (POINT*)&rcBlitDest.left );
+            ClientToScreen( mHWnd, (POINT*)&rcBlitDest.right );
+        }
+
+        StringUtil::StrStreamType str;
+        str << "D3D7 : Created D3D7 Rendering Window '"
+            << mName << "' : " << mWidth << "x" << mHeight 
+            << ", " << mColourDepth << "bpp";
+        LogManager::getSingleton().logMessage(
+            LML_NORMAL, str.str());
+
+        // Set up DirectDraw if appropriate
+        // NB devices & surfaces set up for root window only
+        if (drv && mParentHWnd == NULL)
+        {
+            // DD Driver object passed
+            mlpDDDriver = drv;
+            mIsUsingDirectDraw = true;
+
+            createDDSurfaces();
+            // Get best device based on render bit depth
+            D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
+
+            // create D3D device for this window
+            mlpD3DDevice = dev->createDevice(mlpDDSBack);
+            createDepthBuffer();
+        }
+        else
+            mIsUsingDirectDraw = false;
+
+        mReady = true;
+    }
+
+    void D3D7RenderWindow::destroy(void)
+    {
+        if (mIsUsingDirectDraw)
+            releaseDDSurfaces();
+
+        DestroyWindow(mHWnd);
+
+    }
+
+    bool D3D7RenderWindow::isActive(void) const
+    {
+        return mActive;
+    }
+
+    bool D3D7RenderWindow::isClosed(void) const
+    {
+        return mClosed;
+    }
+
+    void D3D7RenderWindow::reposition(int left, int top)
+    {
+
+    }
+
+    void D3D7RenderWindow::resize(unsigned int width, unsigned int height)
+    {
+        mWidth = width;
+        mHeight = height;
+
+        // Notify viewports of resize
+        ViewportList::iterator it = mViewportList.begin();
+        while (it != mViewportList.end())
+            (*it++).second->_updateDimensions();
+
+        // TODO - resize window
+
+    }
+
+    void D3D7RenderWindow::swapBuffers(bool waitForVSync)
+    {
+        HRESULT hr;
+        DWORD flags;
+        if (mIsUsingDirectDraw)
+        {
+            if (mIsFullScreen)
+            {
+                // Use flipping chain
+                if (waitForVSync)
+                {
+                    flags = DDFLIP_WAIT;
+                }
+                else
+                {
+                    flags = DDFLIP_WAIT | DDFLIP_NOVSYNC;
+                }
+
+                hr = mlpDDSFront->Flip(NULL,flags);
+            }
+            else
+            {
+                // Ordinary Blit
+                RECT srcRect;
+                srcRect.left = 0;
+                srcRect.top = 0;
+                srcRect.right = rcBlitDest.right - rcBlitDest.left;
+                srcRect.bottom = rcBlitDest.bottom - rcBlitDest.top;
+                hr = mlpDDSFront->Blt(&rcBlitDest,mlpDDSBack,&srcRect,DDBLT_WAIT,NULL);
+            }
+
+            if (hr == DDERR_SURFACELOST)
+            {
+                // Restore surfaces
+                restoreDDSurfaces();
+            }
+            else if (FAILED(hr))
+            {
+                 OGRE_EXCEPT( 
+                     hr,
+                     "Error flipping surfaces", 
+                     "D3D7RenderWindow::swapBuffers" );
+            }
+        }
+
+    }
+
+    HWND D3D7RenderWindow::getWindowHandle(void) const
+    {
+        return mHWnd;
+    }
+
+    HWND D3D7RenderWindow::getParentWindowHandle(void) const
+    {
+        return mParentHWnd;
+    }
+
+    bool D3D7RenderWindow::isUsingDirectDraw(void) const
+    {
+        return mIsUsingDirectDraw;
+    }
+
+    // -------------------------------------------------------
+    //   DirectDraw specific methods
+    // -------------------------------------------------------
+    DDDriver* D3D7RenderWindow::getDirectDrawDriver(void)
+    {
+        return mlpDDDriver;
+    }
+
+    LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDFrontBuffer(void)
+    {
+        return mlpDDSFront;
+
+    }
+
+    LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDBackBuffer(void)
+    {
+        return mlpDDSBack;
+    }
+    LPDIRECT3DDEVICE7 D3D7RenderWindow::getD3DDevice(void)
+    {
+        return mlpD3DDevice;
+    }
+
+    void D3D7RenderWindow::createDDSurfaces(void)
+    {
+        // Use DirectDraw wrapper object to create surfaces
+        if( !mlpDDDriver )
+        {
+            OGRE_EXCEPT(
+            Exception::ERR_INVALIDPARAMS, 
+            "Cannot create surfaces because of no valid DirectDraw object",
+            "D3D7RenderWindow::createDDSurfaces" );
+        }
+
+        if( mIsFullScreen )
+        {
+            mlpDDDriver->createWindowSurfaces(
+                mHWnd, 
+                mWidth, mHeight, mColourDepth,
+                true, &mlpDDSFront, &mlpDDSBack);
+        }
+        else
+        {
+            // Windowed mode - need to use client rect for surface dimensions
+            // I.e. we need to ignore menu bars, borders, title bar etc
+            RECT rcClient;
+            unsigned int cWidth, cHeight;
+
+            GetClientRect( mHWnd, &rcClient );
+            ClientToScreen( mHWnd, (POINT*)&rcClient.left );
+            ClientToScreen( mHWnd, (POINT*)&rcClient.right );
+
+            cWidth  = rcClient.right - rcClient.left;
+            cHeight = rcClient.bottom - rcClient.top;
+
+            // Create surfaces (AND clipper)
+            mlpDDDriver->createWindowSurfaces(
+                mHWnd, 
+                cWidth, cHeight, 0,
+                false, &mlpDDSFront, &mlpDDSBack);
+
+            // Update own dimensions since target width / height is this
+            mWidth = cWidth;
+            mHeight = cHeight;
+        }
+    }
+
+    void D3D7RenderWindow::createDepthBuffer(void)
+    {
+        // Get best device based on render bit depth
+        D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
+        if (mIsDepthBuffered && dev->NeedsZBuffer())
+        {
+            // Create Z buffer
+            dev->createDepthBuffer(mlpDDSBack);
+            // Don't set z buffer params here, leave to material
+        }
+    }
+
+    void D3D7RenderWindow::releaseDDSurfaces(void)
+    {
+        // Release Z-buffer
+        HRESULT hr;
+        DDSCAPS2 ddscaps;
+
+        ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
+        ddscaps.dwCaps = DDSCAPS_ZBUFFER;
+
+        LPDIRECTDRAWSURFACE7 zBufSurface;
+
+        hr = mlpDDSBack->GetAttachedSurface( &ddscaps, &zBufSurface );
+
+        // Release twice as this method has increased
+        zBufSurface->Release();
+        zBufSurface->Release();
+
+        // Release std buffers
+        mlpDDSBack->Release();
+        mlpDDSFront->Release();
+
+        mlpDDSBack = mlpDDSFront = 0;
+    }
+
+    void D3D7RenderWindow::restoreDDSurfaces(void)
+    {
+        HRESULT hr;
+
+        if( mlpDDSFront->IsLost() )
+        {
+            hr = mlpDDSFront->Restore();
+
+            if( FAILED( hr ) )
+                OGRE_EXCEPT( 
+                    Exception::ERR_INTERNAL_ERROR, 
+                    "Error restoring lost primary surface.", 
+                    "D3D7RenderWindow - restoreDDSurfaces" );
+        }
+
+        if( mlpDDSBack->IsLost() )
+        {
+            hr = mlpDDSBack->Restore();
+
+            if( FAILED( hr ) )
+                OGRE_EXCEPT( 
+                    Exception::ERR_INTERNAL_ERROR, 
+                    "Error restoring lost back buffer surface.", 
+                    "D3D7RenderWindow - restoreDDSurfaces" );
+        }
+    }
+
+    void D3D7RenderWindow::windowMovedOrResized(void)
+    {
+        // If windowed mode, check window size & position
+        RECT rcCheck;
+
+        if( mIsFullScreen )
+            return; // Nothing to check
+
+        GetClientRect( mHWnd, &rcCheck );
+        ClientToScreen( mHWnd, (POINT*)&rcCheck.left );
+        ClientToScreen( mHWnd, (POINT*)&rcCheck.right );
+
+        // Has the window resized? If so, we need to recreate surfaces
+        if( ( rcCheck.right - rcCheck.left != 
+                rcBlitDest.right - rcBlitDest.left ) ||
+            ( rcCheck.bottom - rcCheck.top !=
+                rcBlitDest.bottom - rcBlitDest.top ) )
+        {
+            // The window has changed size - DD surfaces must be recreated
+            releaseDDSurfaces();
+            createDDSurfaces();
+            createDepthBuffer();
+
+            // Update Viewport Sizes
+            
+            for( 
+                ViewportList::iterator it = mViewportList.begin();
+                it != mViewportList.end(); 
+                ++it )
+            {
+                it->second->_updateDimensions();
+            }
+
+            rcBlitDest = rcCheck;
+        }
+        else if( 
+            rcCheck.left != rcBlitDest.left ||
+            rcCheck.top  != rcBlitDest.top )
+        {
+            // Window has only moved
+            // Just alter the blit location
+            rcBlitDest = rcCheck;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    void D3D7RenderWindow::getCustomAttribute( const String& name, void* pData )
+    {
+        // Valid attributes and their equivalent native functions:
+        // D3DDEVICE            : getD3DDeviceDriver
+        // DDBACKBUFFER         : getDDBackBuffer
+        // DDFRONTBUFFER        : getDDFrontBuffer
+        // HWND                 : getWindowHandle
+
+        if( name == "D3DDEVICE" )
+        {
+            LPDIRECT3DDEVICE7 *pDev = (LPDIRECT3DDEVICE7*)pData;
+
+            *pDev = getD3DDevice();
+            return;
+        }
+        else if( name == "DDBACKBUFFER" )
+        {
+            LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
+
+            *pSurf = getDDBackBuffer();
+            return;
+        }
+        else if( name == "DDFRONTBUFFER" )
+        {
+            LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
+
+            *pSurf = getDDFrontBuffer();
+            return;
+        }
+        else if( name == "HWND" )
+        {
+            HWND *pHwnd = (HWND*)pData;
+
+            *pHwnd = getWindowHandle();
+            return;
+        }
+        else if( name == "isTexture" )
+        {
+            bool *b = reinterpret_cast< bool * >( pData );
+            *b = false;
+
+            return;
+        }
+    }
+
+
+    void D3D7RenderWindow::writeContentsToFile(const String& filename)
+    {
+         HRESULT hr;
+         LPDIRECTDRAWSURFACE7 pTempSurf;
+         DDSURFACEDESC2 desc;
+         RECT srcRect;
+ 
+         // Cannot lock surface direct, so create temp surface and blit
+         memset(&desc, 0, sizeof (DDSURFACEDESC2));
+		 desc.dwSize = sizeof(DDSURFACEDESC2);
+         if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc)))
+         {
+	         OGRE_EXCEPT(hr, "Error getting description of back buffer!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+         }
+
+         desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+         desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+		 if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL)))
+		 {
+             OGRE_EXCEPT(hr, "Error creating temporary surface!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+		 }
+
+         if (mIsFullScreen)
+		 {
+         	pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL);
+		 }
+         else
+         {
+         	GetWindowRect(mHWnd, &srcRect);
+            srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME);
+            srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
+            srcRect.right = srcRect.left + desc.dwWidth;
+            srcRect.bottom = srcRect.top + desc.dwHeight;
+
+            pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL);
+         }
+
+		 if (FAILED(hr = pTempSurf->Lock(NULL, &desc,  
+             DDLOCK_WAIT | DDLOCK_READONLY, NULL)))
+         {
+             OGRE_EXCEPT(hr, "Cannot lock surface!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+         }
+ 
+ 
+         ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+         imgData->width = desc.dwWidth;
+         imgData->height = desc.dwHeight;
+         imgData->format = PF_BYTE_RGB;
+ 
+         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
+         uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3];
+ 
+         uint x, y;
+         uchar *pData, *pDest;
+ 
+         pData = (uchar*)desc.lpSurface;
+         pDest = pBuffer;
+         for (y = 0; y < desc.dwHeight; ++y)
+         {
+             uchar *pRow = pData;
+ 
+             for (x = 0; x < desc.dwWidth; ++x)
+             {
+				 if (desc.ddpfPixelFormat.dwRGBBitCount == 16)
+				 {
+                     WORD val;
+ 
+                     val = *((WORD*)pRow);
+					 pRow += 2;
+
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
+				 }
+				 else
+				 {
+					 // Actual format is BRGA for some reason
+                     *pDest++ = pRow[2]; // R
+                     *pDest++ = pRow[1]; // G
+                     *pDest++ = pRow[0]; // B
+
+                     pRow += 3; // skip alpha / dummy
+
+					 if (desc.ddpfPixelFormat.dwRGBBitCount == 32)
+					 {
+						 ++pRow; // Skip alpha
+					 }
+                 }
+ 
+                 
+             }
+             // increase by one line
+             pData += desc.lPitch;
+ 
+         }
+ 
+ 
+         // Wrap buffer in a chunk
+         MemoryDataStreamPtr stream(new MemoryDataStream(pBuffer, desc.dwWidth * desc.dwHeight * 3, false));
+ 
+         // Get codec 
+         size_t pos = filename.find_last_of(".");
+         String extension;
+ 	    if( pos == String::npos )
+             OGRE_EXCEPT(
+ 		    Exception::ERR_INVALIDPARAMS, 
+ 		    "Unable to determine image type for '" + filename + "' - invalid extension.",
+             "D3D8RenderWindow::writeContentsToFile" );
+ 
+         while( pos != filename.length() - 1 )
+             extension += filename[++pos];
+ 
+         // Get the codec
+         Codec * pCodec = Codec::getCodec(extension);
+ 
+         // Write out
+         pCodec->codeToFile(stream, filename, Codec::CodecDataPtr(imgData));
+ 
+         delete [] pBuffer;
+		 pTempSurf->Release();
+ 
+     }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar* D3D7RenderWindow::getBufferContents(int &dimx, int &dimy)
+    {
+         HRESULT hr;
+         LPDIRECTDRAWSURFACE7 pTempSurf;
+         DDSURFACEDESC2 desc;
+         RECT srcRect;
+ 
+         // Cannot lock surface direct, so create temp surface and blit
+         memset(&desc, 0, sizeof (DDSURFACEDESC2));
+		 desc.dwSize = sizeof(DDSURFACEDESC2);
+         if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc)))
+         {
+	         OGRE_EXCEPT(hr, "Error getting description of back buffer!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+         }
+
+         desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+         desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+		 if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL)))
+		 {
+             OGRE_EXCEPT(hr, "Error creating temporary surface!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+		 }
+
+         if (mIsFullScreen)
+		 {
+         	pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL);
+		 }
+         else
+         {
+         	GetWindowRect(mHWnd, &srcRect);
+            srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME);
+            srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
+            srcRect.right = srcRect.left + desc.dwWidth;
+            srcRect.bottom = srcRect.top + desc.dwHeight;
+
+            pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL);
+         }
+
+		 if (FAILED(hr = pTempSurf->Lock(NULL, &desc,  
+             DDLOCK_WAIT | DDLOCK_READONLY, NULL)))
+         {
+             OGRE_EXCEPT(hr, "Cannot lock surface!", 
+                 "D3D7RenderWindow::writeContentsToFile");
+         }
+ 
+         dimx = desc.dwWidth;
+         dimy = desc.dwHeight;
+         
+ 
+         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
+         uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3];
+ 
+         uint x, y;
+         uchar *pData, *pDest;
+ 
+         pData = (uchar*)desc.lpSurface;
+         pDest = pBuffer;
+         for (y = 0; y < desc.dwHeight; ++y)
+         {
+             uchar *pRow = pData;
+ 
+             for (x = 0; x < desc.dwWidth; ++x)
+             {
+				 if (desc.ddpfPixelFormat.dwRGBBitCount == 16)
+				 {
+                     WORD val;
+ 
+                     val = *((WORD*)pRow);
+					 pRow += 2;
+
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
+					 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
+				 }
+				 else
+				 {
+					 // Actual format is BRGA for some reason
+                     *pDest++ = pRow[2]; // R
+                     *pDest++ = pRow[1]; // G
+                     *pDest++ = pRow[0]; // B
+
+                     pRow += 3; // skip alpha / dummy
+
+					 if (desc.ddpfPixelFormat.dwRGBBitCount == 32)
+					 {
+						 ++pRow; // Skip alpha
+					 }
+                 }
+ 
+                 
+             }
+             // increase by one line
+             pData += desc.lPitch;
+ 
+         }
+ 
+		 pTempSurf->Release();
+
+		 return pBuffer;
+
+     }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
+
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9Texture.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9Texture.h	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9Texture.h	(revision 193)
@@ -0,0 +1,329 @@
+/*
+-----------------------------------------------------------------------------
+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 __D3D8TEXTURE_H__
+#define __D3D8TEXTURE_H__
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreTexture.h"
+#include "OgreRenderTexture.h"
+#include "OgreImage.h"
+#include "OgreException.h"
+#include "OgreD3D9HardwarePixelBuffer.h"
+
+#include "OgreNoMemoryMacros.h"
+#include <d3d9.h>
+#include <d3dx9.h>
+#include <dxerr9.h>
+#include "OgreMemoryMacros.h"
+
+namespace Ogre {
+	class D3D9Texture : public Texture
+	{
+	protected:
+		/// D3DDevice pointer
+		IDirect3DDevice9		*mpDev;		
+		/// D3D9 pointer
+		IDirect3D9				*mpD3D;
+		/// 1D/2D normal texture pointer
+		IDirect3DTexture9		*mpNormTex;	
+		/// cubic texture pointer
+		IDirect3DCubeTexture9	*mpCubeTex;	
+        /// Volume texture
+        IDirect3DVolumeTexture9 *mpVolumeTex;
+        /// z-buffer for the render surface pointer
+		IDirect3DSurface9		*mpZBuff;	
+		/// actual texture pointer
+		IDirect3DBaseTexture9	*mpTex;		
+
+		/// cube texture individual face names
+		String							mCubeFaceNames[6];
+		/// device creation parameters
+		D3DDEVICE_CREATION_PARAMETERS	mDevCreParams;
+		/// back buffer pixel format
+		D3DFORMAT						mBBPixelFormat;
+		/// The memory pool being used
+		D3DPOOL							mD3DPool;
+		/// device capabilities pointer
+		D3DCAPS9						mDevCaps;
+        // Auto-generated mipmaps?
+        bool                            mAutoGenMipmaps;
+		// Dynamic textures?
+		bool                            mDynamicTextures;
+		/// Vector of pointers to subsurfaces
+		typedef std::vector<HardwarePixelBufferSharedPtr> SurfaceList;
+		SurfaceList						mSurfaceList;
+	
+        /// Initialise the device and get formats
+        void _initDevice(void);
+		/// internal method, load a cube texture
+		void _loadCubeTex();
+		/// internal method, load a normal texture
+		void _loadNormTex();
+		/// internal method, load a volume texture
+		void _loadVolumeTex();
+
+		/// internal method, create a blank normal 1D/2D texture
+		void _createNormTex();
+		/// internal method, create a blank cube texture
+		void _createCubeTex();
+		/// internal method, create a blank cube texture
+		void _createVolumeTex();
+
+		/// internal method, return a D3D pixel format for texture creation
+		D3DFORMAT _chooseD3DFormat();
+
+		/// internal method, free D3D9 resources
+		void _freeResources();
+		/// internal method, set Texture class source image protected attributes
+		void _setSrcAttributes(unsigned long width, unsigned long height, unsigned long depth, PixelFormat format);
+		/// internal method, set Texture class final texture protected attributes
+		void _setFinalAttributes(unsigned long width, unsigned long height, unsigned long depth, PixelFormat format);
+		/// internal method, return the best by hardware supported filter method
+		D3DTEXTUREFILTERTYPE _getBestFilterMethod();
+		/// internal method, return true if the device/texture combination can use dynamic textures
+		bool _canUseDynamicTextures(DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat);
+		/// internal method, return true if the device/texture combination can auto gen. mip maps
+		bool _canAutoGenMipmaps(DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat);
+		/// internal method, create a depth stencil for the render target texture
+		void _createDepthStencil();
+
+		/// internal method, the cube map face name for the spec. face index
+		String _getCubeFaceName(unsigned char face) const
+		{ assert(face < 6); return mCubeFaceNames[face]; }
+		
+		/// internal method, create D3D9HardwarePixelBuffers for every face and
+		/// mipmap level. This method must be called after the D3D texture object was created
+		void _createSurfaceList(bool updateOldList=false);
+
+        /// overriden from Resource
+        void loadImpl();
+        /// overriden from Resource
+        void unloadImpl();
+	public:
+		/// constructor 
+        D3D9Texture(ResourceManager* creator, const String& name, ResourceHandle handle,
+            const String& group, bool isManual, ManualResourceLoader* loader, 
+            IDirect3DDevice9 *pD3DDevice);
+		/// destructor
+		~D3D9Texture();
+
+		/// overriden from Texture
+		void copyToTexture( TexturePtr& target );
+		/// overriden from Texture
+		void loadImage( const Image &img );
+
+        /// @copydoc Texture::createInternalResources
+        void createInternalResources(void);
+
+		/// @copydoc Texture::getBuffer
+		HardwarePixelBufferSharedPtr getBuffer(size_t face, size_t mipmap);
+		
+		/// retrieves a pointer to the actual texture
+		IDirect3DBaseTexture9 *getTexture() 
+		{ assert(mpTex); return mpTex; }
+		/// retrieves a pointer to the normal 1D/2D texture
+		IDirect3DTexture9 *getNormTexture()
+		{ assert(mpNormTex); return mpNormTex; }
+		/// retrieves a pointer to the cube texture
+		IDirect3DCubeTexture9 *getCubeTexture()
+		{ assert(mpCubeTex); return mpCubeTex; }
+		/// retrieves a pointer to the Depth stencil
+		IDirect3DSurface9 *getDepthStencil() 
+		{ assert(mpZBuff); return mpZBuff; }
+		
+		/// utility method, convert D3D9 pixel format to Ogre pixel format
+		static PixelFormat _getPF(D3DFORMAT d3dPF);
+		/// utility method, convert Ogre pixel format to D3D9 pixel format
+		static D3DFORMAT _getPF(PixelFormat ogrePF);
+		/// utility method, find closest Ogre pixel format that D3D9 can support
+		static PixelFormat _getClosestSupportedPF(PixelFormat ogrePF);
+
+		/// For dealing with lost devices - release the resource if in the default pool (and return true)
+		bool releaseIfDefaultPool(void);
+		/// For dealing with lost devices - recreate the resource if in the default pool (and return true)
+		bool recreateIfDefaultPool(LPDIRECT3DDEVICE9 pDev);
+
+    };
+
+    /** Specialisation of SharedPtr to allow SharedPtr to be assigned to D3D9TexturePtr 
+    @note Has to be a subclass since we need operator=.
+    We could templatise this instead of repeating per Resource subclass, 
+    except to do so requires a form VC6 does not support i.e.
+    ResourceSubclassPtr<T> : public SharedPtr<T>
+    */
+    class D3D9TexturePtr : public SharedPtr<D3D9Texture> 
+    {
+    public:
+        D3D9TexturePtr() : SharedPtr<D3D9Texture>() {}
+        explicit D3D9TexturePtr(D3D9Texture* rep) : SharedPtr<D3D9Texture>(rep) {}
+        D3D9TexturePtr(const D3D9TexturePtr& r) : SharedPtr<D3D9Texture>(r) {} 
+        D3D9TexturePtr(const ResourcePtr& r) : SharedPtr<D3D9Texture>()
+        {
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<D3D9Texture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+        }
+
+        /// Operator used to convert a ResourcePtr to a D3D9TexturePtr
+        D3D9TexturePtr& operator=(const ResourcePtr& r)
+        {
+            if (pRep == static_cast<D3D9Texture*>(r.getPointer()))
+                return *this;
+            release();
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<D3D9Texture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+        /// Operator used to convert a TexturePtr to a D3D9TexturePtr
+        D3D9TexturePtr& operator=(const TexturePtr& r)
+        {
+            if (pRep == static_cast<D3D9Texture*>(r.getPointer()))
+                return *this;
+            release();
+			// lock & copy other mutex pointer
+			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+            pRep = static_cast<D3D9Texture*>(r.getPointer());
+            pUseCount = r.useCountPointer();
+            if (pUseCount)
+            {
+                ++(*pUseCount);
+            }
+            return *this;
+        }
+    };
+
+
+    /// RenderTexture implementation for D3D9
+    class D3D9RenderTexture : public RenderTexture
+    {
+    public:
+        D3D9RenderTexture( const String & name, 
+			unsigned int width, unsigned int height,
+			TextureType texType, PixelFormat internalFormat, 
+			const NameValuePairList *miscParams ) 
+			: RenderTexture( name, width, height, texType, internalFormat )
+        {
+            mPrivateTex = TextureManager::getSingleton().createManual
+                (mName + "_PRIVATE##", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
+                texType, mWidth, mHeight, 0, internalFormat, TU_RENDERTARGET );
+			mPrivateTex->load();
+        }
+		
+        ~D3D9RenderTexture()
+        {
+			mPrivateTex->unload();
+			TextureManager::getSingleton().remove(mPrivateTex->getName());
+			
+        }
+
+		virtual void getCustomAttribute( const String& name, void *pData )
+        {
+			if( name == "DDBACKBUFFER" )
+            {
+                IDirect3DSurface9 ** pSurf = (IDirect3DSurface9 **)pData;
+				if (mPrivateTex->getTextureType() == TEX_TYPE_2D)
+					mPrivateTex->getNormTexture()->GetSurfaceLevel( 0, &(*pSurf) );
+				else if (mPrivateTex->getTextureType() == TEX_TYPE_CUBE_MAP)
+					mPrivateTex->getCubeTexture()->GetCubeMapSurface( (D3DCUBEMAP_FACES)0, 0, &(*pSurf) );
+				else
+				{
+					OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, 
+							"getCustomAttribute is implemented only for 2D and cube textures !!!", 
+							"D3D9RenderTexture::getCustomAttribute" );
+				}
+				// decrement reference count
+                (*pSurf)->Release();
+                return;
+            }
+            else if( name == "D3DZBUFFER" )
+            {
+                IDirect3DSurface9 ** pSurf = (IDirect3DSurface9 **)pData;
+                *pSurf = mPrivateTex->getDepthStencil();
+                return;
+            }
+            else if( name == "DDFRONTBUFFER" )
+            {
+                IDirect3DSurface9 ** pSurf = (IDirect3DSurface9 **)pData;
+				if (mPrivateTex->getTextureType() == TEX_TYPE_2D)
+					mPrivateTex->getNormTexture()->GetSurfaceLevel( 0, &(*pSurf) );
+				else if (mPrivateTex->getTextureType() == TEX_TYPE_CUBE_MAP)
+					mPrivateTex->getCubeTexture()->GetCubeMapSurface( (D3DCUBEMAP_FACES)0, 0, &(*pSurf) );
+				else
+				{
+					OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, 
+							"getCustomAttribute is implemented only for 2D and cube textures !!!", 
+							"D3D9RenderTexture::getCustomAttribute" );
+				}
+                (*pSurf)->Release();
+                return;
+            }
+            else if( name == "HWND" )
+            {
+                HWND *pHwnd = (HWND*)pData;
+                *pHwnd = NULL;
+                return;
+            }
+            else if( name == "isTexture" )
+            {
+                bool *b = reinterpret_cast< bool * >( pData );
+                *b = true;
+                return;
+            }
+        }
+
+		bool requiresTextureFlipping() const { return false; }
+        virtual void writeContentsToFile( const String & filename ) {}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy) { dimx = dimy = 0; return NULL; };
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+        /// The texture to which rendering takes place.
+        D3D9TexturePtr mPrivateTex;
+		
+        virtual void _copyToTexture()
+        {
+            // Copy the newly-rendered data to the public texture surface.
+            mPrivateTex->copyToTexture( mTexture );
+        }
+    };
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h	(revision 115)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h	(revision 115)
@@ -0,0 +1,113 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _D3D9HARWAREOCCLUSIONQUERY_H__
+#define _D3D9HARWAREOCCLUSIONQUERY_H__
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+
+namespace Ogre {
+
+// If you use multiple rendering passes you can test only the first pass and all other passes don't have to be rendered 
+	// if the first pass resultet has too few pixels visible.
+
+// Be sure to render all occlluder first and whats out so the RenderQue don't switch places on 
+// the occluding objects and the tested objects because it thinks it's more effective..
+
+/**
+  * This is a class that is the DirectX9 implementation of 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg, email lee@abcmedia.se
+	*
+	* Updated on 12/7/2004 by Chris McGuirk
+  */
+class D3D9HardwareOcclusionQuery : public HardwareOcclusionQuery
+{
+//----------------------------------------------------------------------
+// Public methods
+//--
+public:
+
+	/**
+	  * Default object constructor
+	  * 
+	  */
+	D3D9HardwareOcclusionQuery( IDirect3DDevice9* pD3DDevice );
+
+	/**
+	  * Object destructor
+	  */
+	~D3D9HardwareOcclusionQuery();
+
+	//------------------------------------------------------------------
+	// Occlusion query functions (see base class documentation for this)
+	//--
+
+	void beginOcclusionQuery();	
+	void endOcclusionQuery();
+		bool pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag = HWOCCLUSIONQUERY_FLUSH);
+		unsigned int getLastQuerysPixelcount() { return mPixelCount; }
+
+		// These functions are optional, it's a simple filter that simply skips some hardware occlusion tests on visible objects only
+		// It's easy to use if you don't have to keep track of which objects are visible (can be skipped) and what objects arn't visible..
+		// (None visible objects and object you introduce for the first time have always to be tested although the cheapest possible 
+		// LOD (Level Of Detail) mesh and material-wise). 
+
+	/**
+	  *   
+		* Remarks This function allows you to set how often the hardware occlusion query is sent to the driver
+	  * if you set it to 0 every hw occlusion test is acctually made. If you set it to 1 only the half of your queries are sent 
+		* 2 will result in 25% of all queries to acctualy be sent. 
+		* This functionality is here because this class can keep track on visible and none visible objects for you.
+	  * Once you you set the SkipRate for any hardware occlusion instance it effects all others.
+	  */
+
+		void setSkipRate( int skip ) { mSkipInterval = skip; }			// Using 2 only 50 % of the tests are actully made and 3 results in only 33% of the tests. So on.
+		int	 getSkipRate() { return mSkipInterval; } 
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool pullOcclusionQuery( unsigned int* NumOfFragments, const bool waitForResult, const HW_OCCLUSIONQUERY flag = HWOCCLUSIONQUERY_FLUSH ); 
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+//----------------------------------------------------------------------
+// Protected members
+//--
+protected:
+
+		unsigned int		mPixelCount;		
+		IDirect3DQuery9*	mpQuery;
+		IDirect3DDevice9*   mpDevice;
+		int					mSkipCounter;
+		int					mSkipInterval;
+		bool				mHasOcclusionSupport;
+};
+
+
+}
+
+
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9RenderWindow.h
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9RenderWindow.h	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/include/OgreD3D9RenderWindow.h	(revision 193)
@@ -0,0 +1,119 @@
+/*
+-----------------------------------------------------------------------------
+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 __D3D9RENDERWINDOW_H__
+#define __D3D9RENDERWINDOW_H__
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreRenderWindow.h"
+#include "OgreD3D9Driver.h"
+
+namespace Ogre 
+{
+	class D3D9RenderWindow : public RenderWindow
+	{
+	public:
+		/** Constructor.
+		@param instance The application instance
+		@param driver The root driver
+		@param deviceIfSwapChain The existing D3D device to create an additional swap chain from, if this is not
+			the first window.
+		*/
+		D3D9RenderWindow(HINSTANCE instance, D3D9Driver *driver, LPDIRECT3DDEVICE9 deviceIfSwapChain = 0);
+		~D3D9RenderWindow();
+		void create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams);
+		void destroy(void);
+		bool isVisible() const;
+		bool isClosed() const { return mClosed; }
+		void reposition(int left, int top);
+		void resize( unsigned int width, unsigned int height );
+		void swapBuffers( bool waitForVSync = true );
+		HWND getWindowHandle() const { return mHWnd; }
+
+		D3D9Driver* getDirectD3DDriver() { return mDriver; }
+		// changed to access driver member
+		LPDIRECT3DDEVICE9 getD3DDevice() { return mDriver->getD3DDevice(); }
+
+		void getCustomAttribute( const String& name, void* pData );
+		/** Overridden - see RenderTarget.
+		*/
+		void writeContentsToFile(const String& filename);
+		bool requiresTextureFlipping() const { return false; }
+
+		// Method for dealing with resize / move & 3d library
+		void windowMovedOrResized();
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		uchar *getBufferContents(int &dimx, int &dimy);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+		/// Get the presentation parameters used with this window
+		D3DPRESENT_PARAMETERS* getPresentationParameters(void) 
+		{ return &md3dpp; }
+
+		/// @copydoc RenderTarget::update
+		void update();
+
+		/** Create (or recreate) the D3D device or SwapChain for this window.
+		*/
+		void createD3DResources();
+	
+		/** Destroy the D3D device or SwapChain for this window.
+		*/
+		void destroyD3DResources();
+	
+	protected:
+		HINSTANCE mInstance;			// Process instance
+		D3D9Driver *mDriver;			// D3D9 driver
+		HWND	mHWnd;					// Win32 Window handle
+		bool	mIsExternal;			// window not created by Ogre
+		bool	mSizing;
+		bool	mClosed;
+		bool	mIsSwapChain;			// Is this a secondary window?
+
+		static LRESULT CALLBACK WndProc(
+			HWND hWnd,
+			UINT uMsg,
+			WPARAM wParam,
+			LPARAM lParam );
+
+		// -------------------------------------------------------
+		// DirectX-specific
+		// -------------------------------------------------------
+
+		// Pointer to swap chain, only valid if mIsSwapChain
+		LPDIRECT3DSWAPCHAIN9 mpSwapChain;
+		D3DPRESENT_PARAMETERS md3dpp;
+		LPDIRECT3DSURFACE9 mpRenderSurface;
+		LPDIRECT3DSURFACE9 mpRenderZBuffer;
+		D3DMULTISAMPLE_TYPE mFSAAType;
+		DWORD mFSAAQuality;
+		bool mVSync;
+
+		// just check if the multisampling requested is supported by the device
+		bool _checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen);
+
+	};
+}
+#endif
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp	(revision 193)
@@ -0,0 +1,171 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+Copyright (c) 2000-2005 The OGRE Team
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+-----------------------------------------------------------------------------
+*/
+#include "OgreD3D9HardwareOcclusionQuery.h"
+#include "OgreRenderSystemCapabilities.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+/**
+  * This is a class that is the DirectX9 implementation of 
+  * hardware occlusion testing.
+  *
+  * @author Lee Sandberg
+	*
+	* Updated on 12/7/2004 by Chris McGuirk
+  */
+
+/**
+  * Default object constructor
+  */
+D3D9HardwareOcclusionQuery::D3D9HardwareOcclusionQuery( IDirect3DDevice9* pD3DDevice ) 
+{ 
+		mpDevice = pD3DDevice;
+		mPixelCount = 0; 
+		mSkipCounter = 0;
+		mSkipInterval = 0;
+		mHasOcclusionSupport = false;
+
+		// create the occlusion query
+		HRESULT hr = mpDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mpQuery);
+
+	if ( hr != D3D_OK ) 
+	{
+			mHasOcclusionSupport = false;
+	}
+	else 
+	{
+			mHasOcclusionSupport = true;
+	}
+}
+
+/**
+  * Object destructor
+  */
+D3D9HardwareOcclusionQuery::~D3D9HardwareOcclusionQuery() 
+{ 
+		SAFE_RELEASE(mpQuery); 
+}
+
+//------------------------------------------------------------------
+// Occlusion query functions (see base class documentation for this)
+//--
+void D3D9HardwareOcclusionQuery::beginOcclusionQuery() 
+{ 
+		// Make it fail silently if hardware occlusion isn't supported
+		if(mHasOcclusionSupport)
+	{
+#ifndef GTP_VISIBILITY_MODIFIED_OGRE
+			// Counter starts at 0 again at mSkipInterval 
+			if(mSkipCounter == mSkipInterval) 
+#else
+			if (mSkipCounter >= mSkipInterval)  // otherwise no query ever issued if mSkipInterval = 0 !
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		{
+				mSkipCounter = 0; 
+}
+			if (mSkipCounter == 0)
+		{
+				mpQuery->Issue(D3DISSUE_BEGIN); 
+		}
+	}
+	
+}
+
+	void D3D9HardwareOcclusionQuery::endOcclusionQuery() 
+	{
+		// Make it fail silently if hardware occlusion isn't supported
+		if(mHasOcclusionSupport)
+			{
+			if(mSkipCounter == 0)
+			{ 
+				mpQuery->Issue(D3DISSUE_END); 
+	}
+
+			// The skip counter is increased
+			mSkipCounter++; 
+	}
+}
+
+//------------------------------------------------------------------
+	// This version of pullOcclusionQuery causes the DX9 API/Driver to not flush all commands to the 3D card
+// to allow a fast result from the query, but the batching of API calls to the card will be normal. 
+	// But the query wont be processed until the card recives the query in the next batch.
+// Note: OpenGL dosn't use this flag at all so the application running OpenGL won't display any different behaviour.
+//--
+bool D3D9HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments, const HW_OCCLUSIONQUERY flag  ) 
+{
+	HRESULT hr;
+
+		// Make it fail silently if hardware occlusion isn't supported
+		if(mHasOcclusionSupport)
+	{
+			DWORD d3dFlags = (flag == HWOCCLUSIONQUERY_FLUSH) ? D3DGETDATA_FLUSH : 0;
+	
+			// run until success (http://www.gamedev.net/reference/programming/features/occlusionculling/page2.asp)
+			while(hr = mpQuery->GetData( NumOfFragments, sizeof( NumOfFragments ), d3dFlags) == S_FALSE);
+
+			mPixelCount = *NumOfFragments;
+			}
+			else 
+			{ 
+			// fail silently if not supported, assume visible i suppose
+			mPixelCount = 100000;
+			}
+
+		return true;
+	}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//------------------------------------------------------------------
+	bool D3D9HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments, const bool waitForResult, 
+													     const HW_OCCLUSIONQUERY flag ) 
+	{
+		HRESULT hr = S_OK;
+		DWORD queryFlag = (flag == HWOCCLUSIONQUERY_FLUSH) ? D3DGETDATA_FLUSH : 0;
+
+		if (mHasOcclusionSupport)	// In case hardware occlusion isn't supported
+		{	
+			do
+			{
+				hr = mpQuery->GetData(NumOfFragments, sizeof(NumOfFragments), queryFlag);
+	    	}
+			while(waitForResult && (hr == S_FALSE));
+		
+			mPixelCount = *NumOfFragments;
+		}
+		else
+		{
+			mPixelCount = 100000; // every object is visible
+		}
+	
+		return hr == S_OK;
+	}
+
+
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+
+}
Index: OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9RenderWindow.cpp
===================================================================
--- OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9RenderWindow.cpp	(revision 193)
+++ OGRE/trunk/ogre_changes/RenderSystems/Direct3D9/src/OgreD3D9RenderWindow.cpp	(revision 193)
@@ -0,0 +1,1085 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreD3D9RenderWindow.h"
+#include "OgreLogManager.h"
+#include "OgreViewport.h"
+#include "OgreException.h"
+#include "OgreD3D9RenderSystem.h"
+#include "OgreRenderSystem.h"
+#include "OgreBitwise.h"
+#include "OgreImageCodec.h"
+#include "OgreStringConverter.h"
+
+#include "OgreNoMemoryMacros.h"
+#include <d3d9.h>
+#include "OgreMemoryMacros.h"
+#include "OgreRoot.h"
+
+namespace Ogre
+{
+	// Window procedure callback
+	// This is a static member, so applies to all windows but we store the
+	// D3D9RenderWindow instance in the window data GetWindowLog/SetWindowLog
+	LRESULT D3D9RenderWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+	{
+		if (uMsg == WM_CREATE)
+		{
+			// copy D3D9RenderWindow* from createwindow param to userdata slot
+			SetWindowLong(hWnd, GWL_USERDATA,
+				(LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams));
+			return 0;
+		}
+
+		D3D9RenderWindow* win =
+			(D3D9RenderWindow*)GetWindowLong(hWnd, GWL_USERDATA);
+
+		if (!win)
+			return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+		switch( uMsg )
+		{
+		case WM_ACTIVATE:
+			win->mActive = (LOWORD(wParam) != WA_INACTIVE);
+			break;
+
+		case WM_ENTERSIZEMOVE:
+			win->mSizing = true;
+			break;
+
+		case WM_EXITSIZEMOVE:
+			win->windowMovedOrResized();
+			win->mSizing = false;
+			break;
+
+		case WM_MOVE:
+		case WM_SIZE:
+			if (!win->mSizing)
+				win->windowMovedOrResized();
+			break;
+
+		case WM_GETMINMAXINFO:
+			// Prevent the window from going smaller than some minimu size
+			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+			break;
+
+		case WM_CLOSE:
+			win->destroy(); // cleanup and call DestroyWindow
+			win->mClosed = true;
+			return 0;
+		}
+
+		return DefWindowProc( hWnd, uMsg, wParam, lParam );
+	}
+
+	D3D9RenderWindow::D3D9RenderWindow(HINSTANCE instance, D3D9Driver *driver, LPDIRECT3DDEVICE9 deviceIfSwapChain):
+		mInstance(instance),
+		mDriver(driver)
+	{
+		mIsFullScreen = false;
+		mIsSwapChain = (deviceIfSwapChain != NULL);
+		mIsExternal = false;
+		mHWnd = 0;
+		mActive = false;
+		mSizing = false;
+		mClosed = false;
+	}
+
+	D3D9RenderWindow::~D3D9RenderWindow()
+	{
+		// access and update device through driver, realse only primary
+		if (!mIsSwapChain) 
+		{
+			LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+			SAFE_RELEASE( mpD3DDevice );
+			mDriver->setD3DDevice( NULL );
+		}
+	}
+
+	bool D3D9RenderWindow::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
+	{
+		LPDIRECT3D9 pD3D = mDriver->getD3D();
+
+		if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType(
+				adapterNum, 
+				deviceType, format, 
+				fullScreen, type, outQuality)))
+			return true;
+		else
+			return false;
+	}
+
+	void D3D9RenderWindow::create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams)
+	{
+		HINSTANCE hInst = mInstance;
+		D3D9Driver* driver = mDriver;
+		
+		HWND parentHWnd = 0;
+		HWND externalHandle = 0;
+		mFSAAType = D3DMULTISAMPLE_NONE;
+		mFSAAQuality = 0;
+		mVSync = false;
+		unsigned int displayFrequency = 0;
+		String title = name;
+		unsigned int colourDepth = 32;
+		int left = -1; // Defaults to screen center
+		int top = -1; // Defaults to screen center
+		bool depthBuffer = true;
+		String border = "";
+		bool outerSize = false;
+		
+		if(miscParams)
+		{
+			// Get variable-length params
+			NameValuePairList::const_iterator opt;
+			// left (x)
+			opt = miscParams->find("left");
+			if(opt != miscParams->end())
+				left = StringConverter::parseInt(opt->second);
+			// top (y)
+			opt = miscParams->find("top");
+			if(opt != miscParams->end())
+				top = StringConverter::parseInt(opt->second);
+			// Window title
+			opt = miscParams->find("title");
+			if(opt != miscParams->end())
+				title = opt->second;
+			// parentWindowHandle		-> parentHWnd
+			opt = miscParams->find("parentWindowHandle");
+			if(opt != miscParams->end())
+				parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			// externalWindowHandle		-> externalHandle
+			opt = miscParams->find("externalWindowHandle");
+			if(opt != miscParams->end())
+				externalHandle = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			// vsync	[parseBool]
+			opt = miscParams->find("vsync");
+			if(opt != miscParams->end())
+				mVSync = StringConverter::parseBool(opt->second);
+			// displayFrequency
+			opt = miscParams->find("displayFrequency");
+			if(opt != miscParams->end())
+				displayFrequency = StringConverter::parseUnsignedInt(opt->second);
+			// colourDepth
+			opt = miscParams->find("colourDepth");
+			if(opt != miscParams->end())
+				colourDepth = StringConverter::parseUnsignedInt(opt->second);
+			// depthBuffer [parseBool]
+			opt = miscParams->find("depthBuffer");
+			if(opt != miscParams->end())
+				depthBuffer = StringConverter::parseBool(opt->second);
+			// FSAA type
+			opt = miscParams->find("FSAA");
+			if(opt != miscParams->end())
+				mFSAAType = (D3DMULTISAMPLE_TYPE)StringConverter::parseUnsignedInt(opt->second);
+			// FSAA quality
+			opt = miscParams->find("FSAAQuality");
+			if(opt != miscParams->end())
+				mFSAAQuality = StringConverter::parseUnsignedInt(opt->second);
+			// window border style
+			opt = miscParams->find("border");
+			if(opt != miscParams->end())
+				border = opt->second;
+			// set outer dimensions?
+			opt = miscParams->find("outerDimensions");
+			if(opt != miscParams->end())
+				outerSize = StringConverter::parseBool(opt->second);
+		}
+		
+		// Destroy current window if any
+		if( mHWnd )
+			destroy();
+
+
+		if (!externalHandle)
+		{
+			DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+			RECT rc;
+
+			mWidth = width;
+			mHeight = height;
+			mTop = top;
+			mLeft = left;
+
+			if (!fullScreen)
+			{
+				if (parentHWnd)
+				{
+					dwStyle |= WS_CHILD;
+				}
+				else
+				{
+					if (border == "none")
+						dwStyle |= WS_POPUP;
+					else if (border == "fixed")
+						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
+						WS_SYSMENU | WS_MINIMIZEBOX;
+					else
+						dwStyle |= WS_OVERLAPPEDWINDOW;
+				}
+
+				if (!outerSize)
+				{
+					// Calculate window dimensions required
+					// to get the requested client area
+				SetRect(&rc, 0, 0, mWidth, mHeight);
+				AdjustWindowRect(&rc, dwStyle, false);
+				mWidth = rc.right - rc.left;
+				mHeight = rc.bottom - rc.top;
+
+				// Clamp width and height to the desktop dimensions
+					int screenw = GetSystemMetrics(SM_CXSCREEN);
+					int screenh = GetSystemMetrics(SM_CYSCREEN);
+					if ((int)mWidth > screenw)
+						mWidth = screenw;
+					if ((int)mHeight > screenh)
+						mHeight = screenh;
+					if (mLeft < 0)
+						mLeft = (screenw - mWidth) / 2;
+					if (mTop < 0)
+						mTop = (screenh - mHeight) / 2;
+				}
+			}
+			else
+			{
+				dwStyle |= WS_POPUP;
+				mTop = mLeft = 0;
+			}
+
+			// Register the window class
+			// NB allow 4 bytes of window data for D3D9RenderWindow pointer
+			WNDCLASS wc = { 0, WndProc, 0, 0, hInst,
+				LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
+				(HBRUSH)GetStockObject(BLACK_BRUSH), 0, "OgreD3D9Wnd" };
+			RegisterClass(&wc);
+
+			// Create our main window
+			// Pass pointer to self
+			mIsExternal = false;
+			mHWnd = CreateWindow("OgreD3D9Wnd", title.c_str(), dwStyle,
+				mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);
+		}
+		else
+		{
+			mHWnd = externalHandle;
+			mIsExternal = true;
+		}
+
+			RECT rc;
+		// top and left represent outer window coordinates
+		GetWindowRect(mHWnd, &rc);
+		mTop = rc.top;
+		mLeft = rc.left;
+		// width and height represent interior drawable area
+			GetClientRect(mHWnd,&rc);
+			mWidth = rc.right;
+			mHeight = rc.bottom;
+
+			mName = name;
+			mIsDepthBuffered = depthBuffer;
+			mIsFullScreen = fullScreen;
+		mColourDepth = colourDepth;
+
+        StringUtil::StrStreamType str;
+        str << "D3D9 : Created D3D9 Rendering Window '"
+            << mName << "' : " << mWidth << "x" << mHeight 
+       		<< ", " << mColourDepth << "bpp";
+		LogManager::getSingleton().logMessage(
+			LML_NORMAL, str.str());
+
+		createD3DResources();
+
+		mActive = true;
+	}
+
+	void D3D9RenderWindow::createD3DResources(void)
+	{
+		// access device via driver
+		LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+
+		if (mIsSwapChain && !mpD3DDevice)
+		{
+			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
+				"Secondary window has not been given the device from the primary!",
+				"D3D9RenderWindow::createD3DResources");
+		}
+
+		// Set up the presentation parameters
+		HRESULT hr;
+		LPDIRECT3D9 pD3D = mDriver->getD3D();
+		D3DDEVTYPE devType = D3DDEVTYPE_HAL;
+
+		ZeroMemory( &md3dpp, sizeof(D3DPRESENT_PARAMETERS) );
+		md3dpp.Windowed					= !mIsFullScreen;
+		md3dpp.SwapEffect				= D3DSWAPEFFECT_DISCARD;
+		md3dpp.BackBufferCount			= 1;
+		md3dpp.EnableAutoDepthStencil	= mIsDepthBuffered;
+		md3dpp.hDeviceWindow			= mHWnd;
+		md3dpp.BackBufferWidth			= mWidth;
+		md3dpp.BackBufferHeight			= mHeight;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//md3dpp.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
+#endif
+		if (mVSync)
+			md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+		else
+			md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+
+		md3dpp.BackBufferFormat		= D3DFMT_R5G6B5;
+		if( mColourDepth > 16 )
+			md3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
+
+		if (mColourDepth > 16 )
+		{
+			// Try to create a 32-bit depth, 8-bit stencil
+			if( FAILED( pD3D->CheckDeviceFormat(mDriver->getAdapterNumber(),
+				devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL, 
+				D3DRTYPE_SURFACE, D3DFMT_D24S8 )))
+			{
+				// Bugger, no 8-bit hardware stencil, just try 32-bit zbuffer 
+				if( FAILED( pD3D->CheckDeviceFormat(mDriver->getAdapterNumber(),
+					devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL, 
+					D3DRTYPE_SURFACE, D3DFMT_D32 )))
+				{
+					// Jeez, what a naff card. Fall back on 16-bit depth buffering
+					md3dpp.AutoDepthStencilFormat = D3DFMT_D16;
+				}
+				else
+					md3dpp.AutoDepthStencilFormat = D3DFMT_D32;
+			}
+			else
+			{
+				// Woohoo!
+				if( SUCCEEDED( pD3D->CheckDepthStencilMatch( mDriver->getAdapterNumber(), devType,
+					md3dpp.BackBufferFormat, md3dpp.BackBufferFormat, D3DFMT_D24S8 ) ) )
+				{
+					md3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 
+				} 
+				else 
+					md3dpp.AutoDepthStencilFormat = D3DFMT_D24X8; 
+			}
+		}
+		else
+			// 16-bit depth, software stencil
+			md3dpp.AutoDepthStencilFormat	= D3DFMT_D16;
+
+		md3dpp.MultiSampleType = mFSAAType;
+		md3dpp.MultiSampleQuality = (mFSAAQuality == 0) ? 0 : mFSAAQuality;
+
+		if (mIsSwapChain)
+		{
+			// Create swap chain			
+			hr = mpD3DDevice->CreateAdditionalSwapChain(
+				&md3dpp, &mpSwapChain);
+			if (FAILED(hr))
+			{
+				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
+					"Unable to create an additional swap chain",
+					"D3D9RenderWindow::createD3DResources");
+
+			}
+			// Store references to buffers for convenience
+			mpSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &mpRenderSurface );
+			// Additional swap chains need their own depth buffer
+			// to support resizing them
+			if (mIsDepthBuffered) 
+			{
+				hr = mpD3DDevice->CreateDepthStencilSurface(
+					mWidth, mHeight,
+					md3dpp.AutoDepthStencilFormat,
+					md3dpp.MultiSampleType,
+					md3dpp.MultiSampleQuality, 
+					(md3dpp.Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL),
+					&mpRenderZBuffer, NULL
+					);
+
+				if (FAILED(hr)) 
+				{
+					OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
+						"Unable to create a depth buffer for the swap chain",
+						"D3D9RenderWindow::createD3DResources");
+
+				}
+			} 
+			else 
+			{
+				mpRenderZBuffer = 0;
+			}
+			// release immediately so we don't hog them
+			mpRenderSurface->Release();
+			// We'll need the depth buffer for rendering the swap chain
+			//mpRenderZBuffer->Release();
+		}
+		else
+		{
+			if (!mpD3DDevice)
+			{
+				// We haven't created the device yet, this must be the first time
+
+				// Do we want to preserve the FPU mode? Might be useful for scientific apps
+				DWORD extraFlags = 0;
+				ConfigOptionMap& options = Root::getSingleton().getRenderSystem()->getConfigOptions();
+				ConfigOptionMap::iterator opti = options.find("Floating-point mode");
+				if (opti != options.end() && opti->second.currentValue == "Consistent")
+					extraFlags |= D3DCREATE_FPU_PRESERVE;
+
+				hr = pD3D->CreateDevice( mDriver->getAdapterNumber(), devType, mHWnd,
+					D3DCREATE_HARDWARE_VERTEXPROCESSING | extraFlags, &md3dpp, &mpD3DDevice );
+				if( FAILED( hr ) )
+				{
+					hr = pD3D->CreateDevice( mDriver->getAdapterNumber(), devType, mHWnd,
+						D3DCREATE_MIXED_VERTEXPROCESSING | extraFlags, &md3dpp, &mpD3DDevice );
+					if( FAILED( hr ) )
+					{
+						hr = pD3D->CreateDevice( mDriver->getAdapterNumber(), devType, mHWnd,
+							D3DCREATE_SOFTWARE_VERTEXPROCESSING | extraFlags, &md3dpp, &mpD3DDevice );
+					}
+				}
+				// TODO: make this a bit better e.g. go from pure vertex processing to software
+				if( FAILED( hr ) )
+				{
+					destroy();
+					OGRE_EXCEPT( hr, "Failed to create Direct3D9 Device: " + 
+						Root::getSingleton().getErrorDescription(hr), 
+						"D3D9RenderWindow::createD3DResources" );
+				}
+			}
+			// update device in driver
+			mDriver->setD3DDevice( mpD3DDevice );
+			// Store references to buffers for convenience
+			mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
+			mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
+			// release immediately so we don't hog them
+			mpRenderSurface->Release();
+			mpRenderZBuffer->Release();
+		}
+
+	}
+
+	void D3D9RenderWindow::destroyD3DResources()
+	{
+		mpRenderSurface = 0;
+		if (mIsSwapChain)
+		{
+			SAFE_RELEASE(mpRenderZBuffer);
+			SAFE_RELEASE(mpSwapChain);
+		}
+		else
+		{
+			// ignore depth buffer, access device through driver
+			mpRenderZBuffer = 0;
+			LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+			SAFE_RELEASE(mpD3DDevice);
+			mDriver->setD3DDevice(NULL);
+		}
+	}
+
+	void D3D9RenderWindow::destroy()
+	{
+		if (mHWnd && !mIsExternal)
+			DestroyWindow( mHWnd );
+		mHWnd = 0;
+		mActive = false;
+	}
+
+	bool D3D9RenderWindow::isVisible() const
+	{
+		return (mHWnd && !IsIconic(mHWnd));
+	}
+
+	void D3D9RenderWindow::reposition(int top, int left)
+	{
+		if (mHWnd && !mIsFullScreen)
+		{
+			SetWindowPos(mHWnd, 0, top, left, 0, 0,
+				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+		}
+	}
+
+	void D3D9RenderWindow::resize( unsigned int width, unsigned int height )
+	{
+		if (mHWnd && !mIsFullScreen)
+		{
+			RECT rc = { 0, 0, width, height };
+			AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
+			width = rc.right - rc.left;
+			height = rc.bottom - rc.top;
+			SetWindowPos(mHWnd, 0, 0, 0, width, height,
+				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+		}
+	}
+
+	void D3D9RenderWindow::windowMovedOrResized()
+	{
+		if (!mHWnd || IsIconic(mHWnd))
+			return;
+
+		RECT rc;
+		// top and left represent outer window position
+		GetWindowRect(mHWnd, &rc);
+		mTop = rc.top;
+		mLeft = rc.left;
+		// width and height represent drawable area only
+		GetClientRect(mHWnd, &rc);
+		unsigned int width = rc.right;
+		unsigned int height = rc.bottom;
+		if (mWidth == width && mHeight == height)
+			return;
+		
+		if (mIsSwapChain) 
+		{
+
+			D3DPRESENT_PARAMETERS pp = md3dpp;
+
+			pp.BackBufferWidth = width;
+			pp.BackBufferHeight = height;
+
+			SAFE_RELEASE( mpRenderZBuffer );
+			SAFE_RELEASE( mpSwapChain );
+
+			HRESULT hr = mDriver->getD3DDevice()->CreateAdditionalSwapChain(
+				&pp,
+				&mpSwapChain);
+
+			if (FAILED(hr)) 
+			{
+				StringUtil::StrStreamType str;
+				str << "D3D9RenderWindow: failed to reset device to new dimensions << "
+					<< width << " x " << height << ". Trying to recover.";
+				LogManager::getSingleton().logMessage(LML_CRITICAL, str.str());
+
+				// try to recover
+				hr = mDriver->getD3DDevice()->CreateAdditionalSwapChain(
+					&md3dpp,
+					&mpSwapChain);
+
+				if (FAILED(hr))
+					OGRE_EXCEPT( hr, "Reset window to last size failed", "D3D9RenderWindow::resize" );
+
+			}		
+			else 
+			{
+				md3dpp = pp;
+
+				mWidth = width;
+				mHeight = height;
+
+				hr = mpSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mpRenderSurface);
+				hr = mDriver->getD3DDevice()->CreateDepthStencilSurface(
+						mWidth, mHeight,
+						md3dpp.AutoDepthStencilFormat,
+						md3dpp.MultiSampleType,
+						md3dpp.MultiSampleQuality, 
+						(md3dpp.Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL),
+						&mpRenderZBuffer, NULL
+						);
+
+				if (FAILED(hr)) 
+				{
+					OGRE_EXCEPT( hr, "Failed to create depth stencil surface for Swap Chain", "D3D9RenderWindow::resize" );
+				}
+
+				mpRenderSurface->Release();
+			}
+		}
+		// primary windows must reset the device
+		else 
+		{
+			md3dpp.BackBufferWidth = mWidth = width;
+			md3dpp.BackBufferHeight = mHeight = height;
+			static_cast<D3D9RenderSystem*>(
+				Root::getSingleton().getRenderSystem())->_notifyDeviceLost();
+		}
+
+		// Notify viewports of resize
+		ViewportList::iterator it = mViewportList.begin();
+		while( it != mViewportList.end() )
+			(*it++).second->_updateDimensions();
+	}
+
+	void D3D9RenderWindow::swapBuffers( bool waitForVSync )
+	{
+		// access device through driver
+		LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+		if( mpD3DDevice )
+		{
+			HRESULT hr;
+			if (mIsSwapChain)
+			{
+				hr = mpSwapChain->Present(NULL, NULL, NULL, NULL, 0);
+			}
+			else
+			{
+				hr = mpD3DDevice->Present( NULL, NULL, 0, NULL );
+			}
+			if( D3DERR_DEVICELOST == hr )
+			{
+				static_cast<D3D9RenderSystem*>(
+					Root::getSingleton().getRenderSystem())->_notifyDeviceLost();
+			}
+			else if( FAILED(hr) )
+				OGRE_EXCEPT( hr, "Error Presenting surfaces", "D3D9RenderWindow::swapBuffers" );
+		}
+	}
+
+	void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData )
+	{
+		// Valid attributes and their equvalent native functions:
+		// D3DDEVICE			: getD3DDevice
+		// HWND					: getWindowHandle
+
+		if( name == "D3DDEVICE" )
+		{
+			LPDIRECT3DDEVICE9 *pDev = (LPDIRECT3DDEVICE9*)pData;
+			*pDev = getD3DDevice();
+			return;
+		}
+		else if( name == "HWND" )
+		{
+			HWND *pHwnd = (HWND*)pData;
+			*pHwnd = getWindowHandle();
+			return;
+		}
+		else if( name == "isTexture" )
+		{
+			bool *b = reinterpret_cast< bool * >( pData );
+			*b = false;
+
+			return;
+		}
+		else if( name == "D3DZBUFFER" )
+		{
+			LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
+			*pSurf = mpRenderZBuffer;
+			return;
+		}
+		else if( name == "DDBACKBUFFER" )
+		{
+			LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
+			*pSurf = mpRenderSurface;
+			return;
+		}
+		else if( name == "DDFRONTBUFFER" )
+		{
+			LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
+			*pSurf = mpRenderSurface;
+			return;
+		}
+	}
+
+	void D3D9RenderWindow::writeContentsToFile(const String& filename)
+	{
+		HRESULT hr;
+		LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
+		D3DSURFACE_DESC desc;
+		D3DDISPLAYMODE dm;
+
+		// access device through driver
+		LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+
+		// get display dimensions
+		// this will be the dimensions of the front buffer
+		if (FAILED(hr = mpD3DDevice->GetDisplayMode(0, &dm)))
+			OGRE_EXCEPT(hr, "Can't get display mode!", "D3D9RenderWindow::writeContentsToFile");
+
+		desc.Width = dm.Width;
+		desc.Height = dm.Height;
+		desc.Format = D3DFMT_A8R8G8B8;
+		if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
+						desc.Width, 
+						desc.Height, 
+						desc.Format, 
+						D3DPOOL_SYSTEMMEM, 
+						&pTempSurf, 
+						NULL)))
+		{
+			OGRE_EXCEPT(hr, "Cannot create offscreen buffer 1!", "D3D9RenderWindow::writeContentsToFile");
+		}
+
+		if (FAILED(hr = mpD3DDevice->GetFrontBufferData(0, pTempSurf)))
+		{
+			SAFE_RELEASE(pTempSurf);
+			OGRE_EXCEPT(hr, "Can't get front buffer!", "D3D9RenderWindow::writeContentsToFile");
+		}
+
+		if (!mIsFullScreen)
+		{
+			POINT pt={0, 0};
+			RECT srcRect;
+			GetWindowRect(mHWnd, &srcRect);
+
+			desc.Width = srcRect.right - srcRect.left;
+			desc.Height = srcRect.bottom - srcRect.top;
+			desc.Format = D3DFMT_A8R8G8B8;         // this is what we get from the screen, so stick with it
+
+			// NB we can't lock the back buffer direct because it's no created that way
+			// and to do so hits performance, so copy to another surface
+			// Must be the same format as the source surface
+			if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
+							desc.Width, 
+							desc.Height, 
+							desc.Format, 
+							D3DPOOL_DEFAULT, 
+							&pSurf,
+							NULL)))
+			{
+				SAFE_RELEASE(pSurf);
+				OGRE_EXCEPT(hr, "Cannot create offscreen buffer 2!", "D3D9RenderWindow::writeContentsToFile");
+			}
+
+			// Copy
+			if (FAILED(hr = mpD3DDevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt)))
+			{
+				SAFE_RELEASE(pTempSurf);
+				SAFE_RELEASE(pSurf);
+				OGRE_EXCEPT(hr, "Cannot update surface!", "D3D9RenderWindow::writeContentsToFile");
+			}
+
+			SAFE_RELEASE(pTempSurf);
+			pTempSurf = pSurf;
+			pSurf = NULL;
+		}
+
+		D3DLOCKED_RECT lockedRect;
+		if (FAILED(hr = pTempSurf->LockRect(&lockedRect, NULL, 
+			D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
+		{
+			OGRE_EXCEPT(hr, "can't lock rect!", "D3D9RenderWindow::writeContentsToFile");
+		} 
+
+        ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+        imgData->width = desc.Width;
+        imgData->height = desc.Height;
+        imgData->format = PF_BYTE_RGB;
+
+		// Allocate contiguous buffer (surfaces aren't necessarily contiguous)
+		uchar* pBuffer = new uchar[desc.Width * desc.Height * 3];
+
+		uint x, y;
+		uchar *pData, *pDest;
+
+		pData = (uchar*)lockedRect.pBits;
+		pDest = pBuffer;
+		for (y = 0; y < desc.Height; ++y)
+		{
+			uchar *pRow = pData;
+
+			for (x = 0; x < desc.Width; ++x)
+			{
+				switch(desc.Format)
+				{
+				case D3DFMT_R5G6B5:
+					WORD val;
+
+					val = *((WORD*)pRow);
+					pRow += 2;
+
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
+					break;
+				case D3DFMT_A8R8G8B8:
+				case D3DFMT_X8R8G8B8:
+					// Actual format is BRGA for some reason
+					*pDest++ = pRow[2]; // R
+					*pDest++ = pRow[1]; // G
+					*pDest++ = pRow[0]; // B
+					pRow += 4; // skip alpha / dummy
+					break;
+				case D3DFMT_R8G8B8:
+					// Actual format is BRGA for some reason
+					*pDest++ = pRow[2]; // R
+					*pDest++ = pRow[1]; // G
+					*pDest++ = pRow[0]; // B
+					pRow += 3; 
+					break;
+				}
+
+
+			}
+			// increase by one line
+			pData += lockedRect.Pitch;
+		}
+
+		// Wrap buffer in a chunk
+		MemoryDataStreamPtr stream(new MemoryDataStream(pBuffer, desc.Width * desc.Height * 3, false));
+
+		// Get codec 
+		size_t pos = filename.find_last_of(".");
+		String extension;
+		if( pos == String::npos )
+			OGRE_EXCEPT(
+			Exception::ERR_INVALIDPARAMS, 
+			"Unable to determine image type for '" + filename + "' - invalid extension.",
+			"D3D9RenderWindow::writeContentsToFile" );
+
+		while( pos != filename.length() - 1 )
+			extension += filename[++pos];
+
+		// Get the codec
+		Codec * pCodec = Codec::getCodec(extension);
+
+		// Write out
+		{
+			Codec::CodecDataPtr ptr(imgData);
+        	pCodec->codeToFile(stream, filename, ptr);
+		}
+
+		delete [] pBuffer;
+
+		SAFE_RELEASE(pTempSurf);
+		SAFE_RELEASE(pSurf);
+	}
+	//-----------------------------------------------------------------------------
+	void D3D9RenderWindow::update(void)
+	{
+		D3D9RenderSystem* rs = static_cast<D3D9RenderSystem*>(
+			Root::getSingleton().getRenderSystem());
+
+		// access device through driver
+		LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+
+		if (rs->isDeviceLost())
+		{
+			// Test the cooperative mode first
+			HRESULT hr = mpD3DDevice->TestCooperativeLevel();
+			if (hr == D3DERR_DEVICELOST)
+			{
+				// device lost, and we can't reset
+				// can't do anything about it here, wait until we get 
+				// D3DERR_DEVICENOTRESET; rendering calls will silently fail until 
+				// then (except Present, but we ignore device lost there too)
+				mpRenderSurface = 0;
+				// need to release if swap chain
+				if (!mIsSwapChain)
+					mpRenderZBuffer = 0;
+				else
+					SAFE_RELEASE (mpRenderZBuffer);
+				Sleep(50);
+				return;
+			}
+			else
+			{
+				// device lost, and we can reset
+				rs->restoreLostDevice();
+
+				// Still lost?
+				if (rs->isDeviceLost())
+				{
+					// Wait a while
+					Sleep(50);
+					return;
+				}
+			
+				// fixed: this only works for not swap chained
+				if (!mIsSwapChain) 
+				{
+					// re-qeuery buffers
+					mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
+					mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
+					// release immediately so we don't hog them
+					mpRenderSurface->Release();
+					mpRenderZBuffer->Release();
+				}
+				else 
+				{
+					mpSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &mpRenderSurface );
+					if (mIsDepthBuffered) {
+						hr = mpD3DDevice->CreateDepthStencilSurface(
+							mWidth, mHeight,
+							md3dpp.AutoDepthStencilFormat,
+							md3dpp.MultiSampleType,
+							md3dpp.MultiSampleQuality, 
+							(md3dpp.Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL),
+							&mpRenderZBuffer, NULL
+							);
+
+						if (FAILED(hr)) {
+							OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
+								"Unable to re-create depth buffer for the swap chain",
+								"D3D9RenderWindow::update");
+
+						}
+					} 
+					else
+					{
+						mpRenderZBuffer = 0;
+					}
+
+					// release immediately so we don't hog them
+					mpRenderSurface->Release();
+				}
+			}
+
+		}
+		RenderWindow::update();
+	}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar *D3D9RenderWindow::getBufferContents(int &dimx, int &dimy)
+	{
+		HRESULT hr;
+		LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
+		//IDirect3DSurface9 *pTempSurf=NULL;
+		D3DSURFACE_DESC desc;
+		D3DDISPLAYMODE dm;
+
+		// access device through driver
+		LPDIRECT3DDEVICE9 mpD3DDevice = mDriver->getD3DDevice();
+
+		// get display dimensions
+		// this will be the dimensions of the front buffer
+		if (FAILED(hr = mpD3DDevice->GetDisplayMode(0, &dm)))
+			OGRE_EXCEPT(hr, "Can't get display mode!", "D3D9RenderWindow::getBufferContents");
+
+		desc.Width = dm.Width;
+		desc.Height = dm.Height;
+		desc.Format = D3DFMT_A8R8G8B8;
+		if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
+						desc.Width, 
+						desc.Height, 
+						desc.Format, 
+						D3DPOOL_SYSTEMMEM, 
+						&pTempSurf, 
+						NULL)))
+		{
+			OGRE_EXCEPT(hr, "Cannot create offscreen buffer 1!", "D3D9RenderWindow::getBufferContents");
+		}
+
+		if (FAILED(hr = mpD3DDevice->GetFrontBufferData(0, pTempSurf)))
+		//if (FAILED(hr = mpD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pTempSurf)))
+		{
+			SAFE_RELEASE(pTempSurf);
+			OGRE_EXCEPT(hr, "Can't get back buffer!", "D3D9RenderWindow::getBufferContents");
+		}
+
+		if (!mIsFullScreen)
+		{
+			POINT pt={0, 0};
+			RECT srcRect;
+			GetWindowRect(mHWnd, &srcRect);
+
+			desc.Width = srcRect.right - srcRect.left;
+			desc.Height = srcRect.bottom - srcRect.top;
+			desc.Format = D3DFMT_A8R8G8B8;         // this is what we get from the screen, so stick with it
+
+			// NB we can't lock the back buffer direct because it's not created that way
+			// and to do so hits performance, so copy to another surface
+			// Must be the same format as the source surface
+			if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
+							desc.Width, 
+							desc.Height, 
+							desc.Format, 
+							D3DPOOL_DEFAULT, 
+							&pSurf,
+							NULL)))
+			{
+				SAFE_RELEASE(pSurf);
+				OGRE_EXCEPT(hr, "Cannot create offscreen buffer 2!", "D3D9RenderWindow::getBufferContents");
+			}
+
+			// Copy
+			if (FAILED(hr = mpD3DDevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt)))
+			{
+				SAFE_RELEASE(pTempSurf);
+				SAFE_RELEASE(pSurf);
+				OGRE_EXCEPT(hr, "Cannot update surface!", "D3D9RenderWindow::getBufferContents");
+			}
+
+			SAFE_RELEASE(pTempSurf);
+			pTempSurf = pSurf;
+			pSurf = NULL;
+		}
+
+		D3DLOCKED_RECT lockedRect;
+		if (FAILED(hr = pTempSurf->LockRect(&lockedRect, NULL, 
+			D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
+		{
+			OGRE_EXCEPT(hr, "can't lock rect!", "D3D9RenderWindow::getBufferContents");
+		} 
+
+       
+        dimx = desc.Width;
+        dimy = desc.Height;
+      
+		// Allocate contiguous buffer (surfaces aren't necessarily contiguous)
+		uchar* pBuffer = new uchar[desc.Width * desc.Height * 3];
+
+		uint x, y;
+		uchar *pData, *pDest;
+
+		pData = (uchar*)lockedRect.pBits;
+		pDest = pBuffer;
+		for (y = 0; y < desc.Height; ++y)
+		{
+			uchar *pRow = pData;
+
+			for (x = 0; x < desc.Width; ++x)
+			{
+				switch(desc.Format)
+				{
+				case D3DFMT_R5G6B5:
+					WORD val;
+
+					val = *((WORD*)pRow);
+					pRow += 2;
+
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
+					*pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
+					break;
+				case D3DFMT_A8R8G8B8:
+				case D3DFMT_X8R8G8B8:
+					// Actual format is BRGA for some reason
+					*pDest++ = pRow[2]; // R
+					*pDest++ = pRow[1]; // G
+					*pDest++ = pRow[0]; // B
+					pRow += 4; // skip alpha / dummy
+					break;
+				case D3DFMT_R8G8B8:
+					// Actual format is BRGA for some reason
+					*pDest++ = pRow[2]; // R
+					*pDest++ = pRow[1]; // G
+					*pDest++ = pRow[0]; // B
+					pRow += 3; 
+					break;
+				}
+
+
+			}
+			// increase by one line
+			pData += lockedRect.Pitch;
+		}
+
+//pTempSurf->UnlockRect();
+		SAFE_RELEASE(pTempSurf);
+		SAFE_RELEASE(pSurf);
+
+		return pBuffer;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
