Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreHardwareOcclusionQuery.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreHardwareOcclusionQuery.h	(revision 921)
@@ -0,0 +1,131 @@
+/*
+-----------------------------------------------------------------------------
+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 {
+
+/**
+  * This is a abstract class that that provides the interface for the query class for 
+  * hardware occlusion.
+  *
+  * @author Lee Sandberg
+  * Updated on 13/8/2005 by Tuan Kuranes email: tuan.kuranes@free.fr
+  */
+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 );
+	  *			
+	  */
+	virtual void beginOcclusionQuery() = 0;
+
+	/**
+	  * Ends the hardware occlusion test
+	  */
+	virtual void endOcclusionQuery() = 0;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE_DUMPED
+	/**
+		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) = 0; 
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+	/**
+      * 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.
+      */
+	virtual bool pullOcclusionQuery(unsigned int* NumOfFragments) = 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.
+	  */
+	unsigned int getLastQuerysPixelcount() const { return mPixelCount; }
+
+	/**
+	  * Lets you know when query is done, or still be processed by the Hardware
+	  * @return true if query isn't finished.
+	  */
+	 virtual bool isStillOutstanding(void) = 0; 
+
+
+    //----------------------------------------------------------------------
+    // protected members
+    //--
+    protected :
+        // numbers of visible pixels determined by last query
+        unsigned int mPixelCount;
+        // is query hasn't yet returned a result.
+		bool		 mIsQueryResultStillOutstanding;
+};
+
+}
+#endif
+
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderable.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderable.h	(revision 768)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderable.h	(revision 921)
@@ -53,10 +53,10 @@
     {
     public:
-		Renderable() : mPolygonModeOverrideable(true) 
-		{
-#ifdef GAMETOOLS_ILLUMINATION_MODULE
-			this->mRenderTechniqueGroup = 0;			
-#endif
-		}
+		Renderable() : mPolygonModeOverrideable(true)
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		, mId(-1)
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		{}
+
         /** Virtual destructor needed as class has virtual methods. */
         virtual ~Renderable() { }
@@ -247,6 +247,12 @@
 		}
 
-
-
+#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;
@@ -254,25 +260,7 @@
         CustomParameterMap mCustomParameters;
 		bool mPolygonModeOverrideable;
-
-#ifdef GAMETOOLS_ILLUMINATION_MODULE
-	public:
-
-		virtual void setRenderTechniqueGroup(UserDefinedObject* renderTechniqueGroup)
-		{
-			this->mRenderTechniqueGroup = renderTechniqueGroup;
-		}
-
-		virtual UserDefinedObject* getRenderTechniqueGroup(void) const
-		{
-			return this->mRenderTechniqueGroup;
-		}		
-
-		virtual void setMaterialName(const String &name){}
-
-		protected:
-
-			UserDefinedObject* mRenderTechniqueGroup;
-#endif
-
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		int mId;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
     };
 
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneNode.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneNode.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneNode.h	(revision 921)
@@ -0,0 +1,460 @@
+/*
+-----------------------------------------------------------------------------
+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;
+
+        /** 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);
+
+		/** Tells the SceneNode to update the world bound info it stores.
+		*/
+		virtual void _updateBounds(void);
+
+        /** 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/Ogre1.2/OgreMain/include/OgreFrustum.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreFrustum.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreFrustum.h	(revision 921)
@@ -0,0 +1,603 @@
+/*
+-----------------------------------------------------------------------------
+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;
+        /// Off-axis frustum center offset - default (0.0, 0.0)
+        Vector2 mFrustumOffset;
+        /// Focal length of frustum (for stereo rendering, defaults to 1.0)
+        Real mFocalLength;
+
+        /// 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 for the specific render system
+        mutable Matrix4 mProjMatrixRS;
+        /// Pre-calced standard projection matrix but with render system depth range
+        mutable Matrix4 mProjMatrixRSDepth;
+        /// Pre-calced standard projection matrix
+        mutable Matrix4 mProjMatrix;
+        /// 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;
+        /// Something re the frustum planes has changed
+        mutable bool mRecalcFrustumPlanes;
+        /// Something re the world space corners has changed
+        mutable bool mRecalcWorldSpaceCorners;
+        /// Something re the vertex data has changed
+        mutable bool mRecalcVertexData;
+		/// Are we using a custom view matrix?
+		bool mCustomViewMatrix;
+		/// Are we using a custom projection matrix?
+		bool mCustomProjMatrix;
+
+		
+        // Internal functions for calcs
+        virtual void calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const;
+		/// Update frustum if out of date
+        virtual void updateFrustum(void) const;
+		/// Update view if out of date
+        virtual void updateView(void) const;
+		/// Implementation of updateFrustum (called if out of date)
+		virtual void updateFrustumImpl(void) const;
+		/// Implementation of updateView (called if out of date)
+		virtual void updateViewImpl(void) const;
+        virtual void updateFrustumPlanes(void) const;
+		/// Implementation of updateFrustumPlanes (called if out of date)
+		virtual void updateFrustumPlanesImpl(void) const;
+        virtual void updateWorldSpaceCorners(void) const;
+		/// Implementation of updateWorldSpaceCorners (called if out of date)
+		virtual void updateWorldSpaceCornersImpl(void) const;
+        virtual void updateVertexData(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;
+
+        /** Sets frustum offsets, used in stereo rendering.
+            @remarks
+                You can set both horizontal and vertical plane offsets of "eye"; in
+                stereo rendering frustum is moved in horizontal plane. To be able to
+                render from two "eyes" you'll need two cameras rendering on two
+                RenderTargets.
+            @par
+                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
+            @param
+                offset The horizontal and vertical plane offsets.
+        */
+        virtual void setFrustumOffset(const Vector2& offset);
+
+        /** Sets frustum offsets, used in stereo rendering.
+            @remarks
+                You can set both horizontal and vertical plane offsets of "eye"; in
+                stereo rendering frustum is moved in horizontal plane. To be able to
+                render from two "eyes" you'll need two cameras rendering on two
+                RenderTargets.
+            @par
+                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
+            @param
+                horizontal The horizontal plane offset.
+            @param
+                vertical The vertical plane offset.
+        */
+        virtual void setFrustumOffset(Real horizontal = 0.0, Real vertical = 0.0);
+
+        /** Retreives the frustum offsets.
+        */
+        virtual const Vector2& getFrustumOffset() const;
+
+        /** Sets frustum focal length (used in stereo rendering).
+            @param
+                focalLength The distance to the focal plane from the frustum in world coordinates.
+        */
+        virtual void setFocalLength(Real focalLength = 1.0);
+
+        /** Returns focal length of frustum.
+        */
+        virtual Real getFocalLength() const;
+
+        /** Gets the projection matrix for this frustum adjusted for the current
+			rendersystem specifics (may be right or left-handed, depth range
+			may vary).
+        @remarks
+            This method retrieves the rendering-API dependent version of the projection
+            matrix. If you want a 'typical' projection matrix then use 
+            getProjectionMatrix.
+
+        */
+        virtual const Matrix4& getProjectionMatrixRS(void) const;
+        /** Gets the depth-adjusted projection matrix for the current rendersystem,
+			but one which still conforms to right-hand 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& getProjectionMatrixWithRSDepth(void) const;
+        /** Gets the normal projection matrix for this frustum, ie the 
+        projection matrix which conforms to standard right-handed rules and
+        uses depth range [-1,+1].
+        @remarks
+            This differs from the rendering-API dependent getRenderSystemProjectionMatrix
+            in that it always returns a right-handed projection matrix with depth
+            range [-1,+1], result no matter what rendering API is being used - this
+            is required for some uniform algebra for example.
+        */
+        virtual const Matrix4& getProjectionMatrix(void) const;
+
+        /** Gets the view matrix for this frustum. Mainly for use by OGRE internally.
+        */
+        virtual const Matrix4& getViewMatrix(void) const;
+
+		/** Set whether to use a custom view matrix on this frustum.
+		@remarks
+			This is an advanced method which allows you to manually set
+			the view matrix on this frustum, rather than having it calculate
+			itself based on it's position and orientation. 
+		@note
+			After enabling a custom view matrix, the frustum will no longer
+			update on its own based on position / orientation changes. You 
+			are completely responsible for keeping the view matrix up to date.
+			The custom matrix will be returned from getViewMatrix.
+		@param enable If true, the custom view matrix passed as the second 
+			parameter will be used in preference to an auto calculated one. If
+			false, the frustum will revert to auto calculating the view matrix.
+		@param viewMatrix The custom view matrix to use
+		@see Frustum::setCustomProjectionMatrix
+		*/
+		virtual void setCustomViewMatrix(bool enable, 
+			const Matrix4& viewMatrix = Matrix4::IDENTITY);
+		/// Returns whether a custom view matrix is in use
+		virtual bool isCustomViewMatrixEnabled(void) const 
+		{ return mCustomViewMatrix; }
+		
+		/** Set whether to use a custom projection matrix on this frustum.
+		@remarks
+			This is an advanced method which allows you to manually set
+			the projection matrix on this frustum, rather than having it 
+			calculate itself based on it's position and orientation. 
+		@note
+			After enabling a custom projection matrix, the frustum will no 
+			longer update on its own based on field of view and near / far
+			distance changes. You are completely responsible for keeping the 
+			projection matrix up to date if those values change. The custom 
+			matrix will be returned from getProjectionMatrix and derivative
+			functions.
+		@param enable If true, the custom projection matrix passed as the 
+			second parameter will be used in preference to an auto calculated 
+			one. If	false, the frustum will revert to auto calculating the 
+			projection matrix.
+		@param projectionMatrix The custom view matrix to use
+		@see Frustum::setCustomViewMatrix
+		*/
+		virtual void setCustomProjectionMatrix(bool enable, 
+			const Matrix4& projectionMatrix = Matrix4::IDENTITY);
+		/// Returns whether a custom projection matrix is in use
+		virtual bool isCustomProjectionMatrixEnabled(void) const
+		{ return mCustomProjMatrix; }
+
+		/** Retrieves the clipping planes of the frustum.
+        @remarks
+            The clipping planes are ordered as declared in enumerate constants FrustumPlane.
+        */
+        virtual const Plane* getFrustumPlanes(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 */
+        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);
+		/** Is a custom near clip plane in use? */
+		virtual bool isCustomNearClipPlaneEnabled(void) const 
+		{ return mObliqueDepthProjection; }
+		
+
+        /// 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/Ogre1.2/OgreMain/include/OgreRenderQueueSortingGrouping.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderQueueSortingGrouping.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderQueueSortingGrouping.h	(revision 921)
@@ -0,0 +1,694 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreRadixSort.h"
+
+namespace Ogre {
+
+	/** Struct associating a single Pass with a single Renderable. 
+		This is used to for objects sorted by depth and thus not
+		grouped by pass.
+	*/
+	struct RenderablePass
+	{
+		/// Pointer to the Renderable details
+		Renderable* renderable;
+		/// Pointer to the Pass
+		Pass* pass;
+
+		RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
+	};
+
+
+	/** Visitor interface for items in a QueuedRenderableCollection.
+	@remarks
+		Those wishing to iterate over the items in a 
+		QueuedRenderableCollection should implement this visitor pattern,
+		since internal organisation of the collection depends on the 
+		sorting method in use.
+	*/
+	class _OgreExport QueuedRenderableVisitor
+	{
+	public:
+		QueuedRenderableVisitor() {}
+		virtual ~QueuedRenderableVisitor() {}
+		
+		/** Called when visiting a RenderablePass, ie items in a
+			sorted collection where items are not grouped by pass.
+		@remarks
+			If this is called, neither of the other 2 visit methods
+			will be called.
+		*/
+		virtual void visit(const RenderablePass* rp) = 0;
+
+		/* When visiting a collection grouped by pass, this is
+			called when the grouping pass changes.
+		@remarks
+			If this method is called, the RenderablePass visit 
+			method will not be called for this collection. The 
+			Renderable visit method will be called for each item
+			underneath the pass grouping level.
+		@returns True to continue, false to skip the Renderables underneath
+		*/
+		virtual bool visit(const Pass* p) = 0;
+		/** Visit method called once per Renderable on a grouped 
+			collection.
+		@remarks
+			If this method is called, the RenderablePass visit 
+			method will not be called for this collection. 
+		*/
+		virtual void visit(const Renderable* r) = 0;
+		
+		
+	};
+
+	/** Lowest level collection of renderables.
+	@remarks
+		To iterate over items in this collection, you must call
+		the accept method and supply a QueuedRenderableVisitor.
+		The order of the iteration, and whether that iteration is
+		over a RenderablePass list or a 2-level grouped list which 
+		causes a visit call at the Pass level, and a call for each
+		Renderable underneath.
+	*/
+	class _OgreExport QueuedRenderableCollection
+	{
+	public:
+		/** Organisation modes required for this collection.
+		@remarks
+			This affects the internal placement of the items added to this collection;
+			if only one type of sorting / grouping is to be required, then renderables
+			can be stored only once, whilst if multiple types are going to be needed
+			then internally there will be multiple organisations. Changing the organisation
+			needs to be done when the collection is empty.
+		*/		
+		enum OrganisationMode
+		{
+			/// Group by pass
+			OM_PASS_GROUP = 1,
+			/// Sort descending camera distance
+			OM_SORT_DESCENDING = 2,
+			/** Sort ascending camera distance 
+				Note value overlaps with descending since both use same sort
+			*/
+			OM_SORT_ASCENDING = 6
+		};
+
+	protected:
+        /// Comparator to order pass groups
+        struct PassGroupLess
+        {
+            bool _OgreExport operator()(const Pass* a, const Pass* b) const
+            {
+                // Sort by passHash, which is pass, then texture unit changes
+                uint32 hasha = a->getHash();
+                uint32 hashb = b->getHash();
+                if (hasha == hashb)
+                {
+                    // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash
+                    return a < b;
+                }
+                else
+                {
+                    return hasha < hashb;
+                }
+            }
+        };
+        /// Comparator to order objects by descending camera distance
+		struct DepthSortDescendingLess
+        {
+            const Camera* camera;
+
+            DepthSortDescendingLess(const Camera* cam)
+                : camera(cam)
+            {
+            }
+
+            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);
+				    }
+                }
+
+            }
+        };
+
+        /** 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> RenderablePassList;
+        typedef std::vector<Renderable*> RenderableList;
+        /** Map of pass to renderable lists, this is a grouping by pass. */
+        typedef std::map<Pass*, RenderableList*, PassGroupLess> PassGroupRenderableMap;
+
+		/// Functor for accessing sort value 1 for radix sort (Pass)
+		struct RadixSortFunctorPass
+		{
+			uint32 operator()(const RenderablePass& p) const
+            {
+                return p.pass->getHash();
+            }
+		};
+
+        /// Radix sorter for accessing sort value 1 (Pass)
+		static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1;
+
+		/// Functor for descending sort value 2 for radix sort (distance)
+		struct RadixSortFunctorDistance
+		{
+			const Camera* camera;
+
+            RadixSortFunctorDistance(const Camera* cam)
+                : camera(cam)
+            {
+            }
+
+			float operator()(const RenderablePass& p) const
+            {
+                // Sort DESCENDING by depth (ie far objects first), use negative distance
+                // here because radix sorter always dealing with accessing sort
+                return static_cast<float>(- p.renderable->getSquaredViewDepth(camera));
+            }
+		};
+
+        /// Radix sorter for sort value 2 (distance)
+		static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2;
+
+		/// Bitmask of the organisation modes requested
+		uint8 mOrganisationMode;
+
+		/// Grouped 
+		PassGroupRenderableMap mGrouped;
+		/// Sorted descending (can iterate backwards to get ascending)
+		RenderablePassList mSortedDescending;
+
+		/// Internal visitor implementation
+		void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const;
+		/// Internal visitor implementation
+		void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const;
+		/// Internal visitor implementation
+		void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const;
+
+	public:
+		QueuedRenderableCollection();
+		~QueuedRenderableCollection();
+
+		/// Empty the collection
+		void clear(void);
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		void clear(bool destroy);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+		/** Remove the group entry (if any) for a given Pass.
+		@remarks
+			To be used when a pass is destroyed, such that any
+			grouping level for it becomes useless.
+		*/	
+		void removePassGroup(Pass* p);
+		
+		/** Reset the organisation modes required for this collection. 
+		@remarks
+			You can only do this when the collection is empty.
+		@see OrganisationMode
+		*/
+		void resetOrganisationModes(void) 
+		{ 
+			mOrganisationMode = 0; 
+		}
+		
+		/** Add a required sorting / grouping mode to this collection when next used.
+		@remarks
+			You can only do this when the collection is empty.
+		@see OrganisationMode
+		*/
+		void addOrganisationMode(OrganisationMode om) 
+		{ 
+			mOrganisationMode |= om; 
+		}
+
+        /// Add a renderable to the collection using a given pass
+        void addRenderable(Pass* pass, Renderable* rend);
+		
+		/** Perform any sorting that is required on this collection.
+		@param cam The camera
+		*/
+		void sort(const Camera* cam);
+
+		/** Accept a visitor over the collection contents.
+		@param visitor Visitor class which should be called back
+		@param om The organisation mode which you want to iterate over.
+			Note that this must have been included in an addOrganisationMode
+			call before any renderables were added.
+		*/
+		void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const;
+		
+	};
+
+	/** Collection of renderables 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 can order solid renderables by a number of criteria; 
+		it can optimise them into groups based on pass to reduce render 
+		state changes, or can sort them by ascending or descending view 
+		depth. Transparent objects are always ordered by descending depth.
+	@par
+		To iterate over items in the collections held by this object 
+	   	you should retrieve the collection in use (e.g. solids, solids with
+		no shadows, transparents) and use the accept() method, providing 
+		a class implementing QueuedRenderableVisitor.
+	
+    */
+    class _OgreExport RenderPriorityGroup
+    {
+	protected:
+
+		/// Parent queue group
+        RenderQueueGroup* mParent;
+        bool mSplitPassesByLightingType;
+        bool mSplitNoShadowPasses;
+		bool mShadowCastersNotReceivers;
+        /// Solid pass list, used when no shadows, modulative shadows, or ambient passes for additive
+		QueuedRenderableCollection mSolidsBasic;
+        /// Solid per-light pass list, used with additive shadows
+        QueuedRenderableCollection mSolidsDiffuseSpecular;
+        /// Solid decal (texture) pass list, used with additive shadows
+        QueuedRenderableCollection mSolidsDecal;
+        /// Solid pass list, used when shadows are enabled but shadow receive is turned off for these passes
+        QueuedRenderableCollection mSolidsNoShadowReceive;
+		/// Transparent list
+		QueuedRenderableCollection mTransparents;
+
+        /// remove a pass entry from all collections
+        void removePassEntry(Pass* p);
+
+        /// 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, 
+			bool shadowCastersNotReceivers); 
+           
+        ~RenderPriorityGroup() { }
+
+        /** Get the collection of basic solids currently queued, this includes
+			all solids when there are no shadows, or all solids which have shadow
+			receiving enabled when using modulative shadows, or all ambient passes
+			of solids which have shadow receive enabled for additive shadows. */
+        const QueuedRenderableCollection& getSolidsBasic(void) const
+        { return mSolidsBasic; }
+        /** Get the collection of solids currently queued per light (only applicable in 
+		 	additive shadow modes). */
+        const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const
+        { return mSolidsDiffuseSpecular; }
+        /** Get the collection of solids currently queued for decal passes (only 
+			applicable in additive shadow modes). */
+        const QueuedRenderableCollection& getSolidsDecal(void) const
+        { return mSolidsDecal; }
+        /** Get the collection of solids for which shadow receipt is disabled (only
+			applicable when shadows are enabled). */
+        const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const
+        { return mSolidsNoShadowReceive; }
+        /** Get the collection of transparent objects currently queued */
+        const QueuedRenderableCollection& getTransparents(void) const
+        { return mTransparents; }
+
+
+		/** Reset the organisation modes required for the solids in this group. 
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void resetOrganisationModes(void);
+		
+		/** Add a required sorting / grouping mode for the solids in this group.
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 
+
+		/** Set the sorting / grouping mode for the solids in this group to the default.
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void defaultOrganisationMode(void); 
+
+		/** Add a renderable to this group. */
+        void addRenderable(Renderable* pRend, Technique* pTech);
+
+		/** 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, bool destroy);
+
+		/*** msz: no more destroy function, hope we don't need it***/
+
+#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;
+        }
+
+		/** Sets whether or not objects which cast shadows should be treated as
+			never receiving shadows. 
+		*/
+		void setShadowCastersCannotBeReceivers(bool ind)
+		{
+			mShadowCastersNotReceivers = ind;
+		}
+
+
+
+    };
+
+
+    /** 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).
+    */
+    class _OgreExport RenderQueueGroup
+    {
+    public:
+        typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
+        typedef MapIterator<PriorityMap> PriorityMapIterator;
+    protected:
+        RenderQueue* mParent;
+        bool mSplitPassesByLightingType;
+        bool mSplitNoShadowPasses;
+		bool mShadowCastersNotReceivers;
+        /// Map of RenderPriorityGroup objects
+        PriorityMap mPriorityGroups;
+		/// Whether shadows are enabled for this queue
+		bool mShadowsEnabled;
+
+
+    public:
+		RenderQueueGroup(RenderQueue* parent,
+            bool splitPassesByLightingType,
+            bool splitNoShadowPasses,
+            bool shadowCastersNotReceivers) 
+            : mParent(parent)
+            , mSplitPassesByLightingType(splitPassesByLightingType)
+            , mSplitNoShadowPasses(splitNoShadowPasses)
+            , mShadowCastersNotReceivers(shadowCastersNotReceivers)
+            , 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, Technique* pTech, 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, 
+					mShadowCastersNotReceivers);
+                mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
+            }
+            else
+            {
+                pPriorityGrp = i->second;
+            }
+
+            // Add
+            pPriorityGrp->addRenderable(pRend, pTech);
+
+        }
+
+        /** Clears this group of renderables. 
+        @param destroy
+            If false, 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. If
+			true, completely destroys.
+        */
+        void clear(bool destroy = false)
+        {
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+				if (destroy)
+					delete i->second;
+				else
+					i->second->clear();
+            }
+
+			if (destroy)
+				mPriorityGroups.clear();
+
+        }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE	
+		void clear(const int passes, bool destroy = false)
+        {
+            PriorityMap::iterator i, iend;
+            iend = mPriorityGroups.end();
+            for (i = mPriorityGroups.begin(); i != iend; ++i)
+            {
+				i->second->clear(passes, destroy);
+            }
+
+			/** msz: destroy all when no passes left **/
+			if (!passes && destroy)
+			{
+				mPriorityGroups.clear();
+			}
+        }
+
+#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);
+            }
+        }
+		/** Sets whether or not objects which cast shadows should be treated as
+		never receiving shadows. 
+		*/
+		void setShadowCastersCannotBeReceivers(bool ind)
+		{
+			mShadowCastersNotReceivers = ind;
+			PriorityMap::iterator i, iend;
+			iend = mPriorityGroups.end();
+			for (i = mPriorityGroups.begin(); i != iend; ++i)
+			{
+				i->second->setShadowCastersCannotBeReceivers(ind);
+			}
+		}
+		/** Reset the organisation modes required for the solids in this group. 
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void resetOrganisationModes(void)
+		{
+			PriorityMap::iterator i, iend;
+			iend = mPriorityGroups.end();
+			for (i = mPriorityGroups.begin(); i != iend; ++i)
+			{
+				i->second->resetOrganisationModes();
+			}
+		}
+		
+		/** Add a required sorting / grouping mode for the solids in this group.
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
+		{
+			PriorityMap::iterator i, iend;
+			iend = mPriorityGroups.end();
+			for (i = mPriorityGroups.begin(); i != iend; ++i)
+			{
+				i->second->addOrganisationMode(om);
+			}
+		}
+
+		/** Setthe  sorting / grouping mode for the solids in this group to the default.
+		@remarks
+			You can only do this when the group is empty, ie after clearing the 
+			queue.
+		@see QueuedRenderableCollection::OrganisationMode
+		*/
+		void defaultOrganisationMode(void)
+		{
+			PriorityMap::iterator i, iend;
+			iend = mPriorityGroups.end();
+			for (i = mPriorityGroups.begin(); i != iend; ++i)
+			{
+				i->second->defaultOrganisationMode();
+			}
+		}
+
+    };
+
+
+
+}
+
+#endif
+
+
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderTarget.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderTarget.h	(revision 768)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreRenderTarget.h	(revision 921)
@@ -267,4 +267,9 @@
         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.*/
@@ -308,7 +313,4 @@
         */
         virtual Impl *_getImpl();
-
-
-		
     protected:
         /// The name of this target.
@@ -356,12 +358,4 @@
 		/// internal method for firing events
 		virtual void fireViewportRemoved(Viewport* vp);
-
-		#ifdef GAMETOOLS_ILLUMINATION_MODULE 
-		public:
-			unsigned long getLastFrameNumber(){return lastFrame;}
-		protected:
-			unsigned long lastFrame;
-		#endif
-
     };
 
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreCamera.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreCamera.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreCamera.h	(revision 921)
@@ -0,0 +1,545 @@
+/*
+-----------------------------------------------------------------------------
+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 __Camera_H__
+#define __Camera_H__
+
+// Default options
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+#include "OgreMovableObject.h"
+
+// Matrices & Vectors
+#include "OgreMatrix4.h"
+#include "OgreVector3.h"
+#include "OgrePlane.h"
+#include "OgreQuaternion.h"
+#include "OgreCommon.h"
+#include "OgreFrustum.h"
+#include "OgreRay.h"
+
+
+namespace Ogre {
+
+
+
+    /** A viewpoint from which the scene will be rendered.
+        @remarks
+            OGRE renders scenes from a camera viewpoint into a buffer of
+            some sort, normally a window or a texture (a subclass of
+            RenderTarget). OGRE cameras support both perspective projection (the default,
+            meaning objects get smaller the further away they are) and
+            orthographic projection (blueprint-style, no decrease in size
+            with distance). Each camera carries with it a style of rendering,
+            e.g. full textured, flat shaded, wireframe), field of view,
+            rendering distances etc, allowing you to use OGRE to create
+            complex multi-window views if required. In addition, more than
+            one camera can point at a single render target if required,
+            each rendering to a subset of the target, allowing split screen
+            and picture-in-picture views.
+        @par
+            Cameras maintain their own aspect ratios, field of view, and frustrum,
+            and project co-ordinates into a space measured from -1 to 1 in x and y,
+            and 0 to 1 in z. At render time, the camera will be rendering to a
+            Viewport which will translate these parametric co-ordinates into real screen
+            co-ordinates. Obviously it is advisable that the viewport has the same
+            aspect ratio as the camera to avoid distortion (unless you want it!).
+        @par
+            Note that a Camera can be attached to a SceneNode, using the method
+            SceneNode::attachObject. If this is done the Camera will combine it's own
+            position/orientation settings with it's parent SceneNode. 
+            This is useful for implementing more complex Camera / object
+            relationships i.e. having a camera attached to a world object.
+    */
+    class _OgreExport Camera : public Frustum
+    {
+    protected:
+        /// Camera name
+        String mName;
+        /// Scene manager responsible for the scene
+        SceneManager *mSceneMgr;
+
+        /// Camera orientation, quaternion style
+        Quaternion mOrientation;
+
+        /// Camera position - default (0,0,0)
+        Vector3 mPosition;
+
+        /// Derived orientation/position of the camera, including reflection
+        mutable Quaternion mDerivedOrientation;
+        mutable Vector3 mDerivedPosition;
+
+        /// Real world orientation/position of the camera
+        mutable Quaternion mRealOrientation;
+        mutable Vector3 mRealPosition;
+
+        /// Whether to yaw around a fixed axis.
+        bool mYawFixed;
+        /// Fixed axis to yaw around
+        Vector3 mYawFixedAxis;
+
+        /// Rendering type
+        PolygonMode mSceneDetail;
+
+        /// Stored number of visible faces in the last render
+        unsigned int mVisFacesLastRender;
+
+        /// Shared class-level name for Movable type
+        static String msMovableType;
+
+        /// SceneNode which this Camera will automatically track
+        SceneNode* mAutoTrackTarget;
+        /// Tracking offset for fine tuning
+        Vector3 mAutoTrackOffset;
+
+		// Scene LOD factor used to adjust overall LOD
+		Real mSceneLodFactor;
+		/// Inverted scene LOD factor, can be used by Renderables to adjust their LOD
+		Real mSceneLodFactorInv;
+
+
+        /** Viewing window. 
+        @remarks
+        Generalize camera class for the case, when viewing frustum doesn't cover all viewport.
+        */
+        Real mWLeft, mWTop, mWRight, mWBottom;
+        /// Is viewing window used.
+        bool mWindowSet;
+        /// Windowed viewport clip planes 
+        mutable std::vector<Plane> mWindowClipPlanes;
+        // Was viewing window changed.
+        mutable bool mRecalcWindow;
+        /// The last viewport to be added using this camera
+        Viewport* mLastViewport;
+        /** Whether aspect ratio will automaticaally be recalculated 
+            when a vieport changes its size
+        */
+        bool mAutoAspectRatio;
+		/// Custom culling frustum
+		Frustum *mCullFrustum;
+		/// Whether or not the rendering distance of objects should take effect for this camera
+		bool mUseRenderingDistance;
+
+
+        // Internal functions for calcs
+        bool isViewOutOfDate(void) const;
+        /// Signal to update frustum information.
+        void invalidateFrustum(void) const;
+        /// Signal to update view information.
+        void invalidateView(void) const;
+
+
+        /** Do actual window setting, using parameters set in SetWindow call
+        @remarks
+            The method will called on demand.
+        */
+        virtual void setWindowImpl(void) const;
+        /** Get the derived position of this frustum. */
+        const Vector3& getPositionForViewUpdate(void) const;
+        /** Get the derived orientation of this frustum. */
+        const Quaternion& getOrientationForViewUpdate(void) const;
+
+
+    public:
+        /** Standard constructor.
+        */
+        Camera( const String& name, SceneManager* sm);
+
+        /** Standard destructor.
+        */
+        virtual ~Camera();
+
+
+        /** Returns a pointer to the SceneManager this camera is rendering through.
+        */
+        SceneManager* getSceneManager(void) const;
+
+        /** Gets the camera's name.
+        */
+        virtual const String& getName(void) const;
+
+
+        /** Sets the level of rendering detail required from this camera.
+            @remarks
+                Each camera is set to render at full detail by default, that is
+                with full texturing, lighting etc. This method lets you change
+                that behaviour, allowing you to make the camera just render a
+                wireframe view, for example.
+        */
+        void setPolygonMode(PolygonMode sd);
+
+        /** Retrieves the level of detail that the camera will render.
+        */
+        PolygonMode getPolygonMode(void) const;
+
+        /** Sets the camera's position.
+        */
+        void setPosition(Real x, Real y, Real z);
+
+        /** Sets the camera's position.
+        */
+        void setPosition(const Vector3& vec);
+
+        /** Retrieves the camera's position.
+        */
+        const Vector3& getPosition(void) const;
+
+        /** Moves the camera's position by the vector offset provided along world axes.
+        */
+        void move(const Vector3& vec);
+
+        /** Moves the camera's position by the vector offset provided along it's own axes (relative to orientation).
+        */
+        void moveRelative(const Vector3& vec);
+
+        /** Sets the camera's direction vector.
+            @remarks
+                Note that the 'up' vector for the camera will automatically be recalculated based on the
+                current 'up' vector (i.e. the roll will remain the same).
+        */
+        void setDirection(Real x, Real y, Real z);
+
+        /** Sets the camera's direction vector.
+        */
+        void setDirection(const Vector3& vec);
+
+        /* Gets the camera's direction.
+        */
+        Vector3 getDirection(void) const;
+
+        /** Gets the camera's up vector.
+        */
+        Vector3 getUp(void) const;
+
+        /** Gets the camera's right vector.
+        */
+        Vector3 getRight(void) const;
+
+        /** Points the camera at a location in worldspace.
+            @remarks
+                This is a helper method to automatically generate the
+                direction vector for the camera, based on it's current position
+                and the supplied look-at point.
+            @param
+                targetPoint A vector specifying the look at point.
+        */
+        void lookAt( const Vector3& targetPoint );
+        /** Points the camera at a location in worldspace.
+            @remarks
+                This is a helper method to automatically generate the
+                direction vector for the camera, based on it's current position
+                and the supplied look-at point.
+            @param
+                x
+            @param
+                y
+            @param
+                z Co-ordinates of the point to look at.
+        */
+        void lookAt(Real x, Real y, Real z);
+
+        /** Rolls the camera anticlockwise, around its local z axis.
+        */
+        void roll(const Radian& angle);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        void roll(Real degrees) { roll ( Angle(degrees) ); }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Rotates the camera anticlockwise around it's local y axis.
+        */
+        void yaw(const Radian& angle);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        void yaw(Real degrees) { yaw ( Angle(degrees) ); }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Pitches the camera up/down anticlockwise around it's local z axis.
+        */
+        void pitch(const Radian& angle);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        void pitch(Real degrees) { pitch ( Angle(degrees) ); }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Rotate the camera around an arbitrary axis.
+        */
+        void rotate(const Vector3& axis, const Radian& angle);
+#ifndef OGRE_FORCE_ANGLE_TYPES
+        void rotate(const Vector3& axis, Real degrees) { rotate ( axis, Angle(degrees) ); }
+#endif//OGRE_FORCE_ANGLE_TYPES
+
+        /** Rotate the camera around an aritrary axis using a Quarternion.
+        */
+        void rotate(const Quaternion& q);
+
+        /** Tells the camera 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 camera
+				- by default, the camera yaws around a fixed Y axis. This is 
+				often what you want - for example if you're making a first-person 
+				shooter, you really don't want the yaw axis to reflect the local 
+				camera Y, because this would mean a different yaw axis if the 
+				player is looking upwards rather than when they are looking
+                straight ahead. You can change this behaviour by calling this 
+				method, which you will want to do if you are making a completely
+				free camera like the kind used in a flight simulator. 
+            @param
+                useFixed If true, the axis passed in the second parameter will 
+				always be the yaw axis no matter what the camera orientation. 
+				If false, the camera yaws around the local Y.
+            @param
+                fixedAxis The axis to use if the first parameter is true.
+        */
+        void setFixedYawAxis( bool useFixed, const Vector3& fixedAxis = Vector3::UNIT_Y );
+
+
+        /** Returns the camera's current orientation.
+        */
+        const Quaternion& getOrientation(void) const;
+
+        /** Sets the camera's orientation.
+        */
+        void setOrientation(const Quaternion& q);
+
+        /** Tells the Camera to contact the SceneManager to render from it's viewpoint.
+        @param vp The viewport to render to
+        @param includeOverlays Whether or not any overlay objects should be included
+        */
+        void _renderScene(Viewport *vp, bool includeOverlays);
+
+        /** Function for outputting to a stream.
+        */
+        friend std::ostream& operator<<(std::ostream& o, Camera& c);
+
+        /** Internal method to notify camera of the visible faces in the last render.
+        */
+        void _notifyRenderedFaces(unsigned int numfaces);
+
+        /** Internal method to retrieve the number of visible faces in the last render.
+        */
+        unsigned int _getNumRenderedFaces(void) const;
+
+        /** Gets the derived orientation of the camera, including any
+            rotation inherited from a node attachment and reflection matrix. */
+        const Quaternion& getDerivedOrientation(void) const;
+        /** Gets the derived position of the camera, including any
+            translation inherited from a node attachment and reflection matrix. */
+        const Vector3& getDerivedPosition(void) const;
+        /** Gets the derived direction vector of the camera, including any
+            rotation inherited from a node attachment and reflection matrix. */
+        Vector3 getDerivedDirection(void) const;
+        /** Gets the derived up vector of the camera, including any
+            rotation inherited from a node attachment and reflection matrix. */
+        Vector3 getDerivedUp(void) const;
+        /** Gets the derived right vector of the camera, including any
+            rotation inherited from a node attachment and reflection matrix. */
+        Vector3 getDerivedRight(void) const;
+
+        /** Gets the real world orientation of the camera, including any
+            rotation inherited from a node attachment */
+        const Quaternion& getRealOrientation(void) const;
+        /** Gets the real world position of the camera, including any
+            translation inherited from a node attachment. */
+        const Vector3& getRealPosition(void) const;
+        /** Gets the real world direction vector of the camera, including any
+            rotation inherited from a node attachment. */
+        Vector3 getRealDirection(void) const;
+        /** Gets the real world up vector of the camera, including any
+            rotation inherited from a node attachment. */
+        Vector3 getRealUp(void) const;
+        /** Gets the real world right vector of the camera, including any
+            rotation inherited from a node attachment. */
+        Vector3 getRealRight(void) const;
+
+        /** Overridden from MovableObject */
+        const String& getMovableType(void) const;
+
+        /** Enables / disables automatic tracking of a SceneNode.
+        @remarks
+            If you enable auto-tracking, this Camera will automatically rotate to
+            look at the target SceneNode every frame, no matter how 
+            it or SceneNode move. This is handy if you want a Camera to be focused on a
+            single object or group of objects. Note that by default the Camera looks at the 
+            origin of the SceneNode, if you want to tweak this, e.g. if the object which is
+            attached to this target node is quite big and you want to point the camera at
+            a specific point on it, provide a vector in the 'offset' parameter and the 
+            camera's target point will be adjusted.
+        @param enabled If true, the Camera will track the SceneNode supplied as the next 
+            parameter (cannot be null). If false the camera will cease tracking and will
+            remain in it's current orientation.
+        @param target Pointer to the SceneNode which this Camera will 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 offset If supplied, the camera targets this 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& offset = Vector3::ZERO);
+
+
+		/** Sets the level-of-detail factor for this Camera.
+		@remarks
+			This method can be used to influence the overall level of detail of the scenes 
+			rendered using this camera. Various elements of the scene have level-of-detail
+			reductions to improve rendering speed at distance; this method allows you 
+			to hint to those elements that you would like to adjust the level of detail that
+			they would normally use (up or down). 
+		@par
+			The most common use for this method is to reduce the overall level of detail used
+			for a secondary camera used for sub viewports like rear-view mirrors etc.
+			Note that scene elements are at liberty to ignore this setting if they choose,
+			this is merely a hint.
+		@param factor The factor to apply to the usual level of detail calculation. Higher
+			values increase the detail, so 2.0 doubles the normal detail and 0.5 halves it.
+		*/
+		void setLodBias(Real factor = 1.0);
+
+		/** Returns the level-of-detail bias factor currently applied to this camera. 
+		@remarks
+			See Camera::setLodBias for more details.
+		*/
+		Real getLodBias(void) const;
+
+
+
+        /** Gets a world space ray as cast from the camera through a viewport position.
+        @param screenx, screeny The x and y position at which the ray should intersect the viewport, 
+            in normalised screen coordinates [0,1]
+        */
+        Ray getCameraToViewportRay(Real screenx, Real screeny) const;
+
+		/** Internal method for OGRE to use for LOD calculations. */
+		Real _getLodBiasInverse(void) const;
+
+
+        /** Internal method used by OGRE to update auto-tracking cameras. */
+        void _autoTrack(void);
+
+
+        /** Sets the viewing window inside of viewport.
+        @remarks
+        This method can be used to set a subset of the viewport as the rendering
+        target. 
+        @param Left Relative to Viewport - 0 corresponds to left edge, 1 - to right edge (default - 0).
+        @param Top Relative to Viewport - 0 corresponds to top edge, 1 - to bottom edge (default - 0).
+        @param Right Relative to Viewport - 0 corresponds to left edge, 1 - to right edge (default - 1).
+        @param Bottom Relative to Viewport - 0 corresponds to top edge, 1 - to bottom edge (default - 1).
+        */
+        virtual void setWindow (Real Left, Real Top, Real Right, Real Bottom);
+        /// Cancel view window.
+        virtual void resetWindow (void);
+        /// Returns if a viewport window is being used
+        virtual bool isWindowSet(void) const { return mWindowSet; }
+        /// Gets the window clip planes, only applicable if isWindowSet == true
+        const std::vector<Plane>& getWindowPlanes(void) const;
+
+        /** Overridden from MovableObject */
+        Real getBoundingRadius(void) const;
+		/** Get the auto tracking target for this camera, if any. */
+        SceneNode* getAutoTrackTarget(void) const { return mAutoTrackTarget; }
+		/** Get the auto tracking offset for this camera, if it is auto tracking. */
+		const Vector3& getAutoTrackOffset(void) const { return mAutoTrackOffset; }
+		
+        /** Get the last viewport which was attached to this camera. 
+        @note This is not guaranteed to be the only viewport which is
+        using this camera, just the last once which was created referring
+        to it.
+        */
+        Viewport* getViewport(void) const {return mLastViewport;}
+        /** Notifies this camera that a viewport is using it.*/
+        void _notifyViewport(Viewport* viewport) {mLastViewport = viewport;}
+
+        /** If set to true a vieport that owns this frustum will be able to 
+            recalculate the aspect ratio whenever the frustum is resized.
+        @remarks
+            You should set this to true only if the frustum / camera is used by 
+            one viewport at the same time. Otherwise the aspect ratio for other 
+            viewports may be wrong.
+        */    
+        void setAutoAspectRatio(bool autoratio);
+
+        /** Retreives if AutoAspectRatio is currently set or not
+        */
+        bool getAutoAspectRatio(void) const;
+
+		/** Tells the camera to use a separate Frustum instance to perform culling.
+		@remarks
+			By calling this method, you can tell the camera to perform culling
+			against a different frustum to it's own. This is mostly useful for
+			debug cameras that allow you to show the culling behaviour of another
+			camera, or a manual frustum instance. 
+		@param frustum Pointer to a frustum to use; this can either be a manual
+			Frustum instance (which you can attach to scene nodes like any other
+			MovableObject), or another camera. If you pass 0 to this method it
+			reverts the camera to normal behaviour.
+		*/
+		void setCullingFrustum(Frustum* frustum) { mCullFrustum = frustum; }
+		/** Returns the custom culling frustum in use. */
+		Frustum* getCullingFrustum(void) { return mCullFrustum; }
+
+		/// @copydoc Frustum::isVisible
+		bool isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
+		/// @copydoc Frustum::isVisible
+		bool isVisible(const Sphere& bound, FrustumPlane* culledBy = 0) const;
+		/// @copydoc Frustum::isVisible
+		bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy = 0) const;
+#endif
+		/// @copydoc Frustum::getWorldSpaceCorners
+		const Vector3* getWorldSpaceCorners(void) const;
+		/// @copydoc Frustum::getFrustumPlane
+		const Plane& getFrustumPlane( unsigned short plane ) const;
+		/// @copydoc Frustum::projectSphere
+		bool projectSphere(const Sphere& sphere, 
+			Real* left, Real* top, Real* right, Real* bottom) const;
+		/// @copydoc Frustum::getNearClipDistance
+		Real getNearClipDistance(void) const;
+		/// @copydoc Frustum::getFarClipDistance
+		Real getFarClipDistance(void) const;
+		/// @copydoc Frustum::getViewMatrix
+		const Matrix4& getViewMatrix(void) const;
+		/** Specialised version of getViewMatrix allowing caller to differentiate
+			whether the custom culling frustum should be allowed or not. 
+		@remarks
+			The default behaviour of the standard getViewMatrix is to delegate to 
+			the alternate culling frustum, if it is set. This is expected when 
+			performing CPU calculations, but the final rendering must be performed
+			using the real view matrix in order to display the correct debug view.
+		*/
+		const Matrix4& getViewMatrix(bool ownFrustumOnly) const;
+		/** Set whether this camera should use the 'rendering distance' on
+			objects to exclude distant objects from the final image. The
+			default behaviour is to use it.
+		@param use True to use the rendering distance, false not to.
+		*/
+		virtual void setUseRenderingDistance(bool use) { mUseRenderingDistance = use; }
+		/** Get whether this camera should use the 'rendering distance' on
+			objects to exclude distant objects from the final image.
+		*/
+		virtual bool getUseRenderingDistance(void) const { return mUseRenderingDistance; }
+     };
+
+} // namespace Ogre
+#endif
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneManager.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneManager.h	(revision 768)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/include/OgreSceneManager.h	(revision 921)
@@ -196,5 +196,5 @@
 		};
 
-		typedef struct SkyDomeGenParameters
+		struct SkyDomeGenParameters
 		{
 			Real skyDomeCurvature;
@@ -205,5 +205,5 @@
 			int skyDomeYSegments_keep;
 		};
-		
+
 		struct SkyPlaneGenParameters
 		{
@@ -214,9 +214,59 @@
 			int skyPlaneYSegments; 
 		};
-		
+
 		struct SkyBoxGenParameters
 		{
 			Real skyBoxDistance;
 		};
+
+#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 const 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:
 		/// Instance name
@@ -273,20 +323,21 @@
         SceneNode* mSkyBoxNode;
 
+        // Sky plane
         bool mSkyPlaneEnabled;
         bool mSkyPlaneDrawFirst;
         Plane mSkyPlane;
-	SceneManager::SkyPlaneGenParameters	mSkyPlaneGenParameters;
-	   // Sky box
+        SkyPlaneGenParameters mSkyPlaneGenParameters;
+        // Sky box
         bool mSkyBoxEnabled;
         bool mSkyBoxDrawFirst;
         Quaternion mSkyBoxOrientation;
-		SceneManager::SkyBoxGenParameters	mSkyBoxGenParameters;
-	    // Sky dome
+        SkyBoxGenParameters mSkyBoxGenParameters;
+        // Sky dome
         bool mSkyDomeEnabled;
         bool mSkyDomeDrawFirst;
         Quaternion mSkyDomeOrientation;
-		SceneManager::SkyDomeGenParameters mSkyDomeGenParameters;
-	
-		// Fog
+        SkyDomeGenParameters mSkyDomeGenParameters;
+
+        // Fog
         FogMode mFogMode;
         ColourValue mFogColour;
@@ -1297,7 +1348,8 @@
 
 		/** Get the sky plane node, if enabled. */
-		virtual SceneNode* getSkyPlaneNode(void) { return mSkyPlaneNode; }		
+		virtual SceneNode* getSkyPlaneNode(void) const { return mSkyPlaneNode; }
+
 		/** Get the parameters used to construct the SkyPlane, if any **/
-		virtual SceneManager::SkyPlaneGenParameters getSkyPlaneGenParameters(void) const { return mSkyPlaneGenParameters; }
+		virtual const SkyPlaneGenParameters& getSkyPlaneGenParameters(void) const { return mSkyPlaneGenParameters; }
 
         /** Enables / disables a 'sky box' i.e. a 6-sided box at constant
@@ -1352,8 +1404,8 @@
 		/** Get the skybox node, if enabled. */
 		virtual SceneNode* getSkyBoxNode(void) const { return mSkyBoxNode; }
-		
-		/** Get the parameters used to generate the current SKyBox, if any */
-		virtual SceneManager::SkyBoxGenParameters	getSkyBoxGenParameters(void) const { return mSkyBoxGenParameters; }
-        
+
+		/** Get the parameters used to generate the current SkyBox, if any */
+		virtual const SkyBoxGenParameters& getSkyBoxGenParameters(void) const { return mSkyBoxGenParameters; }
+
 		/** Enables / disables a 'sky dome' i.e. an illusion of a curved sky.
             @remarks
@@ -1422,8 +1474,9 @@
 
 		/** Get the sky dome node, if enabled. */
-		virtual SceneNode* getSkyDomeNode(void) { return mSkyDomeNode; }	
-		
+		virtual SceneNode* getSkyDomeNode(void) const { return mSkyDomeNode; }
+
 		/** Get the parameters used to generate the current SkyDome, if any */
-		virtual SceneManager::SkyDomeGenParameters	getSkyDomeGenParameters(void) const { return mSkyDomeGenParameters; }
+		virtual const SkyDomeGenParameters& getSkyDomeGenParameters(void) const { return mSkyDomeGenParameters; }
+
 		/** Sets the fogging mode applied to the scene.
             @remarks
@@ -2326,10 +2379,4 @@
 		*/
 		RenderSystem *getDestinationRenderSystem();
-
-#ifdef GAMETOOLS_ILLUMINATION_MODULE 
-		public:
-			void prepareRenderQueue_Wrap(){this->prepareRenderQueue();}
-#endif
-
     };
 
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneNode.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneNode.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneNode.cpp	(revision 921)
@@ -0,0 +1,680 @@
+/*
+-----------------------------------------------------------------------------
+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)
+    {
+        if (obj->isAttached())
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+                "Object already attached to a SceneNode or a Bone",
+                "SceneNode::attachObject");
+        }
+
+        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, onlyShadowCasters);
+            }
+        }
+
+        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;)
+        {
+            SceneNode* sn = static_cast<SceneNode*>(i->second);
+			// increment iterator before destroying (iterator invalidated by 
+			// SceneManager::destroySceneNode because it causes removal from parent)
+			++i;
+            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;
+
+        // The direction we want the local direction point to
+        Vector3 targetDir = vec.normalisedCopy();
+
+        // Transform target direction to world space
+        switch (relativeTo)
+        {
+        case TS_PARENT:
+            if (mInheritOrientation)
+            {
+                if (mParent)
+                {
+                    targetDir = mParent->_getDerivedOrientation() * targetDir;
+                }
+            }
+            break;
+        case TS_LOCAL:
+            targetDir = _getDerivedOrientation() * targetDir;
+            break;
+        }
+
+        // Calculate target orientation relative to world space
+        Quaternion targetOrientation;
+        if( mYawFixed )
+        {
+            // Calculate the quaternion for rotate local Z to target direction
+            Vector3 xVec = mYawFixedAxis.crossProduct(targetDir);
+            xVec.normalise();
+            Vector3 yVec = targetDir.crossProduct(xVec);
+            yVec.normalise();
+            Quaternion unitZToTarget = Quaternion(xVec, yVec, targetDir);
+
+            if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
+            {
+                // Specail case for avoid calculate 180 degree turn
+                targetOrientation =
+                    Quaternion(-unitZToTarget.y, -unitZToTarget.z, unitZToTarget.w, unitZToTarget.x);
+            }
+            else
+            {
+                // Calculate the quaternion for rotate local direction to target direction
+                Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
+                targetOrientation = unitZToTarget * localToUnitZ;
+            }
+        }
+        else
+        {
+            const Quaternion& currentOrient = _getDerivedOrientation();
+
+            // Get current local direction relative to world space
+            Vector3 currentDir = currentOrient * localDirectionVector;
+
+            if ((currentDir+targetDir).squaredLength() < 0.00005f)
+            {
+                // Oops, a 180 degree turn (infinite possible rotation axes)
+                // Default to yaw i.e. use current UP
+                targetOrientation =
+                    Quaternion(-currentOrient.y, -currentOrient.z, currentOrient.w, currentOrient.x);
+            }
+            else
+            {
+                // Derive shortest arc to new direction
+                Quaternion rotQuat = currentDir.getRotationTo(targetDir);
+                targetOrientation = rotQuat * currentOrient;
+            }
+        }
+
+        // Set target orientation, transformed to parent space
+        if (mParent && mInheritOrientation)
+            setOrientation(mParent->_getDerivedOrientation().UnitInverse() * targetOrientation);
+        else
+            setOrientation(targetOrientation);
+    }
+    //-----------------------------------------------------------------------
+    void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo, 
+        const Vector3& localDirectionVector)
+    {
+        // Calculate ourself origin relative to the given transform space
+        Vector3 origin;
+        switch (relativeTo)
+        {
+        default:    // Just in case
+        case TS_WORLD:
+            origin = _getDerivedPosition();
+            break;
+        case TS_PARENT:
+            origin = mPosition;
+            break;
+        case TS_LOCAL:
+            origin = Vector3::ZERO;
+            break;
+        }
+
+        setDirection(targetPoint - origin, 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/Ogre1.2/OgreMain/src/OgreFrustum.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreFrustum.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreFrustum.cpp	(revision 921)
@@ -0,0 +1,1178 @@
+/*
+-----------------------------------------------------------------------------
+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), 
+        mFrustumOffset(Vector2::ZERO),
+        mFocalLength(1.0f),
+        mLastParentOrientation(Quaternion::IDENTITY),
+        mLastParentPosition(Vector3::ZERO),
+        mRecalcFrustum(true), 
+        mRecalcView(true), 
+        mRecalcFrustumPlanes(true),
+        mRecalcWorldSpaceCorners(true),
+        mRecalcVertexData(true),
+		mCustomViewMatrix(false),
+		mCustomProjMatrix(false),
+        mReflect(false), 
+        mLinkedReflectPlane(0),
+        mObliqueDepthProjection(false), 
+        mLinkedObliqueProjPlane(0)
+    {
+        // Initialise material
+        mMaterial = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
+        
+        // Alter superclass members
+        mVisible = false;
+        mParentNode = 0;
+
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        mLastLinkedObliqueProjPlane.normal = Vector3::ZERO;
+
+
+        updateView();
+        updateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    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;
+    }
+
+    //---------------------------------------------------------------------
+    void Frustum::setFrustumOffset(const Vector2& offset)
+    {
+        mFrustumOffset = offset;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::setFrustumOffset(Real horizontal, Real vertical)
+    {
+        setFrustumOffset(Vector2(horizontal, vertical));
+    }
+    //---------------------------------------------------------------------
+    const Vector2& Frustum::getFrustumOffset() const
+    {
+        return mFrustumOffset;
+    }
+    //---------------------------------------------------------------------
+    void Frustum::setFocalLength(Real focalLength)
+    {
+        if (focalLength <= 0)
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+                "Focal length must be greater than zero.",
+                "Frustum::setFocalLength");
+        }
+
+        mFocalLength = focalLength;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    Real Frustum::getFocalLength() const
+    {
+        return mFocalLength;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrixWithRSDepth(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrixRSDepth;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrixRS(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrixRS;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getViewMatrix(void) const
+    {
+        updateView();
+
+        return mViewMatrix;
+
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane* Frustum::getFrustumPlanes(void) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        return mFrustumPlanes;
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane& Frustum::getFrustumPlane(unsigned short plane) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        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 planes
+        updateFrustumPlanes();
+
+        // 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 planes
+        updateFrustumPlanes();
+
+        // 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 planes
+        updateFrustumPlanes();
+
+        // 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::calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const
+    { 
+		if (mCustomProjMatrix)
+		{
+			// Convert clipspace corners to camera space
+			Matrix4 invProj = mProjMatrix.inverse();
+			Vector3 topLeft(-0.5f, 0.5f, 0.0f);
+			Vector3 bottomRight(0.5f, -0.5f, 0.0f);
+
+			topLeft = invProj * topLeft;
+			bottomRight = invProj * bottomRight;
+
+			left = topLeft.x;
+			top = topLeft.y;
+			right = bottomRight.x;
+			bottom = bottomRight.y;
+
+		}
+		else
+		{
+			// Calculate general projection parameters
+
+			Radian thetaY (mFOVy * 0.5f);
+			Real tanThetaY = Math::Tan(thetaY);
+			Real tanThetaX = tanThetaY * mAspect;
+
+			// Unknow how to apply frustum offset to orthographic camera, just ignore here
+			Real nearFocal = (mProjType == PT_PERSPECTIVE) ? mNearDist / mFocalLength : 0;
+			Real nearOffsetX = mFrustumOffset.x * nearFocal;
+			Real nearOffsetY = mFrustumOffset.y * nearFocal;
+			Real half_w = tanThetaX * mNearDist;
+			Real half_h = tanThetaY * mNearDist;
+
+			left   = - half_w + nearOffsetX;
+			right  = + half_w + nearOffsetX;
+			bottom = - half_h + nearOffsetY;
+			top    = + half_h + nearOffsetY;
+		}
+    }
+	//-----------------------------------------------------------------------
+	void Frustum::updateFrustumImpl(void) const
+	{
+		// Common calcs
+		Real left, right, bottom, top;
+		calcProjectionParameters(left, right, bottom, top);
+
+		if (!mCustomProjMatrix)
+		{
+
+			// The code below will dealing with general projection 
+			// parameters, similar glFrustum and glOrtho.
+			// Doesn't optimise manually except division operator, so the 
+			// code more self-explaining.
+
+			Real inv_w = 1 / (right - left);
+			Real inv_h = 1 / (top - bottom);
+			Real inv_d = 1 / (mFarDist - mNearDist);
+
+			// Recalc if frustum params changed
+			if (mProjType == PT_PERSPECTIVE)
+			{
+				// Calc matrix elements
+				Real A = 2 * mNearDist * inv_w;
+				Real B = 2 * mNearDist * inv_h;
+				Real C = (right + left) * inv_w;
+				Real D = (top + bottom) * inv_h;
+				Real q, qn;
+				if (mFarDist == 0)
+				{
+					// Infinite far plane
+					q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+					qn = mNearDist * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
+				}
+				else
+				{
+					q = - (mFarDist + mNearDist) * inv_d;
+					qn = -2 * (mFarDist * mNearDist) * inv_d;
+				}
+
+				// NB: This creates 'uniform' perspective projection matrix,
+				// which depth range [-1,1], right-handed rules
+				//
+				// [ A   0   C   0  ]
+				// [ 0   B   D   0  ]
+				// [ 0   0   q   qn ]
+				// [ 0   0   -1  0  ]
+				//
+				// A = 2 * near / (right - left)
+				// B = 2 * near / (top - bottom)
+				// C = (right + left) / (right - left)
+				// D = (top + bottom) / (top - bottom)
+				// q = - (far + near) / (far - near)
+				// qn = - 2 * (far * near) / (far - near)
+
+				mProjMatrix = Matrix4::ZERO;
+				mProjMatrix[0][0] = A;
+				mProjMatrix[0][2] = C;
+				mProjMatrix[1][1] = B;
+				mProjMatrix[1][2] = D;
+				mProjMatrix[2][2] = q;
+				mProjMatrix[2][3] = qn;
+				mProjMatrix[3][2] = -1;
+
+				if (mObliqueDepthProjection)
+				{
+					// Translate the plane into view space
+
+					// Don't use getViewMatrix here, incase overrided by 
+					// camera and return a cull frustum view matrix
+					updateView();
+					Plane plane = mViewMatrix * mObliqueProjPlane;
+
+					// 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
+
+					/* generalised version
+					Vector4 q = matrix.inverse() * 
+					Vector4(Math::Sign(plane.normal.x), 
+					Math::Sign(plane.normal.y), 1.0f, 1.0f);
+					*/
+					Vector4 q;
+					q.x = (Math::Sign(plane.normal.x) + mProjMatrix[0][2]) / mProjMatrix[0][0];
+					q.y = (Math::Sign(plane.normal.y) + mProjMatrix[1][2]) / mProjMatrix[1][1];
+					q.z = -1;
+					q.w = (1 + mProjMatrix[2][2]) / mProjMatrix[2][3];
+
+					// Calculate the scaled plane vector
+					Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
+					Vector4 c = clipPlane4d * (2 / (clipPlane4d.dotProduct(q)));
+
+					// Replace the third row of the projection matrix
+					mProjMatrix[2][0] = c.x;
+					mProjMatrix[2][1] = c.y;
+					mProjMatrix[2][2] = c.z + 1;
+					mProjMatrix[2][3] = c.w; 
+				}
+			} // perspective
+			else if (mProjType == PT_ORTHOGRAPHIC)
+			{
+				Real A = 2 * inv_w;
+				Real B = 2 * inv_h;
+				Real C = - (right + left) * inv_w;
+				Real D = - (top + bottom) * inv_h;
+				Real q, qn;
+				if (mFarDist == 0)
+				{
+					// Can not do infinite far plane here, avoid divided zero only
+					q = - Frustum::INFINITE_FAR_PLANE_ADJUST / mNearDist;
+					qn = - Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+				}
+				else
+				{
+					q = - 2 * inv_d;
+					qn = - (mFarDist + mNearDist)  * inv_d;
+				}
+
+				// NB: This creates 'uniform' orthographic projection matrix,
+				// which depth range [-1,1], right-handed rules
+				//
+				// [ A   0   0   C  ]
+				// [ 0   B   0   D  ]
+				// [ 0   0   q   qn ]
+				// [ 0   0   0   1  ]
+				//
+				// A = 2 * / (right - left)
+				// B = 2 * / (top - bottom)
+				// C = - (right + left) / (right - left)
+				// D = - (top + bottom) / (top - bottom)
+				// q = - 2 / (far - near)
+				// qn = - (far + near) / (far - near)
+
+				mProjMatrix = Matrix4::ZERO;
+				mProjMatrix[0][0] = A;
+				mProjMatrix[0][3] = C;
+				mProjMatrix[1][1] = B;
+				mProjMatrix[1][3] = D;
+				mProjMatrix[2][2] = q;
+				mProjMatrix[2][3] = qn;
+				mProjMatrix[3][3] = 1;
+			} // ortho
+		} // !mCustomProjMatrix
+
+		RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
+		// API specific
+		renderSystem->_convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
+		// API specific for Gpu Programs
+		renderSystem->_convertProjectionMatrix(mProjMatrix, mProjMatrixRSDepth, 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;
+		// Near plane bounds
+		Vector3 min(left, bottom, -farDist);
+		Vector3 max(right, top, 0);
+		if (mProjType == PT_PERSPECTIVE)
+		{
+			// Merge with far plane bounds
+			Real radio = farDist / mNearDist;
+			min.makeFloor(Vector3(left * radio, bottom * radio, -farDist));
+			max.makeCeil(Vector3(right * radio, top * radio, 0));
+		}
+		mBoundingBox.setExtents(min, max);
+
+		mRecalcFrustum = false;
+
+		// Signal to update frustum clipping planes
+		mRecalcFrustumPlanes = true;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustum(void) const
+    {
+        if (isFrustumOutOfDate())
+        {
+			updateFrustumImpl();
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::updateVertexData(void) const
+    {
+        if (mRecalcVertexData)
+        {
+            if (mVertexData.vertexBufferBinding->getBufferCount() <= 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) );
+            }
+
+            // Note: Even though we can dealing with general projection matrix here,
+            //       but because it's incompatibly with infinite far plane, thus, we
+            //       still need to working with projection parameters.
+
+            // Calc near plane corners
+            Real vpLeft, vpRight, vpBottom, vpTop;
+            calcProjectionParameters(vpLeft, vpRight, vpBottom, vpTop);
+
+            // Treat infinite fardist as some arbitrary far value
+            Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+
+            // Calc far palne corners
+            Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
+            Real farLeft = vpLeft * radio;
+            Real farRight = vpRight * radio;
+            Real farBottom = vpBottom * radio;
+            Real farTop = vpTop * radio;
+
+            // 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();
+
+            mRecalcVertexData = false;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isViewOutOfDate(void) const
+    {
+        // Attached to node?
+        if (mParentNode)
+        {
+            if (mRecalcView ||
+                mParentNode->_getDerivedOrientation() != mLastParentOrientation ||
+                mParentNode->_getDerivedPosition() != mLastParentPosition)
+            {
+                // Ok, we're out of date with SceneNode we're attached to
+                mLastParentOrientation = mParentNode->_getDerivedOrientation();
+                mLastParentPosition = mParentNode->_getDerivedPosition();
+                mRecalcView = true;
+            }
+        }
+        // Deriving reflection from linked plane?
+        if (mLinkedReflectPlane && 
+            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
+        {
+            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mRecalcView = true;
+        }
+
+        return mRecalcView;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isFrustumOutOfDate(void) const
+    {
+        // Deriving custom near plane from linked plane?
+        if (mObliqueDepthProjection)
+        {
+            // Out of date when view out of data since plane needs to be in view space
+            if (isViewOutOfDate())
+            {
+                mRecalcFrustum = true;
+            }
+            // Update derived plane
+            if (mLinkedObliqueProjPlane && 
+                !(mLastLinkedObliqueProjPlane == mLinkedObliqueProjPlane->_getDerivedPlane()))
+            {
+                mObliqueProjPlane = mLinkedObliqueProjPlane->_getDerivedPlane();
+                mLastLinkedObliqueProjPlane = mObliqueProjPlane;
+                mRecalcFrustum = true;
+            }
+        }
+
+        return mRecalcFrustum;
+    }
+
+    //-----------------------------------------------------------------------
+	void Frustum::updateViewImpl(void) const
+	{
+		// ----------------------
+		// 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
+
+		if (!mCustomViewMatrix)
+		{
+			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;
+			}
+		}
+
+		mRecalcView = false;
+
+		// Signal to update frustum clipping planes
+		mRecalcFrustumPlanes = true;
+		// Signal to update world space corners
+		mRecalcWorldSpaceCorners = true;
+		// Signal to update frustum if oblique plane enabled,
+		// since plane needs to be in view space
+		if (mObliqueDepthProjection)
+		{
+			mRecalcFrustum = true;
+		}
+	}
+	//-----------------------------------------------------------------------
+    void Frustum::updateView(void) const
+    {
+        if (isViewOutOfDate())
+        {
+			updateViewImpl();
+        }
+    }
+
+	//-----------------------------------------------------------------------
+	void Frustum::updateFrustumPlanesImpl(void) const
+	{
+		// -------------------------
+		// Update the frustum planes
+		// -------------------------
+		Matrix4 combo = mProjMatrix * mViewMatrix;
+
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
+
+		// Renormalise any normals which were not unit length
+		for(int i=0; i<6; i++ ) 
+		{
+			float length = mFrustumPlanes[i].normal.normalise();
+			mFrustumPlanes[i].d /= length;
+		}
+
+		mRecalcFrustumPlanes = false;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustumPlanes(void) const
+    {
+        updateView();
+        updateFrustum();
+
+        if (mRecalcFrustumPlanes)
+        {
+			updateFrustumPlanesImpl();
+        }
+    }
+	//-----------------------------------------------------------------------
+	void Frustum::updateWorldSpaceCornersImpl(void) const
+	{
+		Matrix4 eyeToWorld = mViewMatrix.inverse();
+
+		// Note: Even though we can dealing with general projection matrix here,
+		//       but because it's incompatibly with infinite far plane, thus, we
+		//       still need to working with projection parameters.
+
+		// Calc near plane corners
+		Real nearLeft, nearRight, nearBottom, nearTop;
+		calcProjectionParameters(nearLeft, nearRight, nearBottom, nearTop);
+
+		// Treat infinite fardist as some arbitrary far value
+		Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+
+		// Calc far palne corners
+		Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
+		Real farLeft = nearLeft * radio;
+		Real farRight = nearRight * radio;
+		Real farBottom = nearBottom * radio;
+		Real farTop = nearTop * radio;
+
+		// near
+		mWorldSpaceCorners[0] = eyeToWorld * Vector3(nearRight, nearTop,    -mNearDist);
+		mWorldSpaceCorners[1] = eyeToWorld * Vector3(nearLeft,  nearTop,    -mNearDist);
+		mWorldSpaceCorners[2] = eyeToWorld * Vector3(nearLeft,  nearBottom, -mNearDist);
+		mWorldSpaceCorners[3] = eyeToWorld * Vector3(nearRight, nearBottom, -mNearDist);
+		// far
+		mWorldSpaceCorners[4] = eyeToWorld * Vector3(farRight,  farTop,     -farDist);
+		mWorldSpaceCorners[5] = eyeToWorld * Vector3(farLeft,   farTop,     -farDist);
+		mWorldSpaceCorners[6] = eyeToWorld * Vector3(farLeft,   farBottom,  -farDist);
+		mWorldSpaceCorners[7] = eyeToWorld * Vector3(farRight,  farBottom,  -farDist);
+
+
+		mRecalcWorldSpaceCorners = false;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateWorldSpaceCorners(void) const
+    {
+        updateView();
+
+        if (mRecalcWorldSpaceCorners)
+        {
+			updateWorldSpaceCornersImpl();
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    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) 
+    {
+        updateVertexData();
+        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;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::_notifyCurrentCamera(Camera* cam)
+    {
+        // Make sure bounding box up-to-date
+        updateFrustum();
+
+        MovableObject::_notifyCurrentCamera(cam);
+    }
+
+    // -------------------------------------------------------------------
+    void Frustum::invalidateFrustum() const
+    {
+        mRecalcFrustum = true;
+        mRecalcFrustumPlanes = true;
+        mRecalcWorldSpaceCorners = true;
+        mRecalcVertexData = true;
+    }
+    // -------------------------------------------------------------------
+    void Frustum::invalidateView() const
+    {
+        mRecalcView = true;
+        mRecalcFrustumPlanes = true;
+        mRecalcWorldSpaceCorners = true;
+    }
+    // -------------------------------------------------------------------
+    const Vector3* Frustum::getWorldSpaceCorners(void) const
+    {
+        updateWorldSpaceCorners();
+
+        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;
+        mLinkedReflectPlane = 0;
+        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
+
+        // Don't use getViewMatrix here, incase overrided by camera and return a cull frustum view matrix
+        updateView();
+        Vector3 eyeSpacePos = mViewMatrix * sphere.getCenter();
+
+        if (eyeSpacePos.z < 0)
+        {
+            Real r = sphere.getRadius();
+            // early-exit
+            if (eyeSpacePos.squaredLength() <= r * r)
+                return false;
+
+            updateFrustum();
+            Vector3 screenSpacePos = mProjMatrix * eyeSpacePos;
+
+
+            // perspective attenuate
+            Vector3 spheresize(r, r, eyeSpacePos.z);
+            spheresize = mProjMatrix * 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();
+    }
+    //---------------------------------------------------------------------
+	void Frustum::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
+	{
+		mCustomViewMatrix = enable;
+		if (enable)
+		{
+			mViewMatrix = viewMatrix;
+		}
+		invalidateView();
+	}
+    //---------------------------------------------------------------------
+	void Frustum::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
+	{
+		mCustomProjMatrix = enable;
+		if (enable)
+		{
+			mProjMatrix = projMatrix;
+		}
+		invalidateFrustum();
+	}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+	//added by matt: 050405
+    bool Frustum::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
+	{
+		// default: box does not intersect frustum
+		intersects = false;
+
+		// Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        // 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/Ogre1.2/OgreMain/src/OgreRenderQueueSortingGrouping.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreRenderQueueSortingGrouping.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreRenderQueueSortingGrouping.cpp	(revision 921)
@@ -0,0 +1,495 @@
+/*
+-----------------------------------------------------------------------------
+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"
+#include "OgreException.h"
+
+namespace Ogre {
+    // Init statics
+    RadixSort<QueuedRenderableCollection::RenderablePassList,
+        RenderablePass, uint32> QueuedRenderableCollection::msRadixSorter1;
+    RadixSort<QueuedRenderableCollection::RenderablePassList,
+        RenderablePass, float> QueuedRenderableCollection::msRadixSorter2;
+
+
+	//-----------------------------------------------------------------------
+	RenderPriorityGroup::RenderPriorityGroup(RenderQueueGroup* parent, 
+            bool splitPassesByLightingType,
+            bool splitNoShadowPasses, 
+			bool shadowCastersNotReceivers)
+	 	: mParent(parent)
+        , mSplitPassesByLightingType(splitPassesByLightingType)
+        , mSplitNoShadowPasses(splitNoShadowPasses)
+        , mShadowCastersNotReceivers(shadowCastersNotReceivers)
+	{
+		// Initialise collection sorting options
+		// this can become dynamic according to invocation later
+		defaultOrganisationMode();
+
+		// Transparents will always be sorted this way
+		mTransparents.addOrganisationMode(QueuedRenderableCollection::OM_SORT_DESCENDING);
+
+		
+	}
+	//-----------------------------------------------------------------------
+	void RenderPriorityGroup::resetOrganisationModes(void)
+	{
+		mSolidsBasic.resetOrganisationModes();
+		mSolidsDiffuseSpecular.resetOrganisationModes();
+		mSolidsDecal.resetOrganisationModes();
+		mSolidsNoShadowReceive.resetOrganisationModes();
+	}
+	//-----------------------------------------------------------------------
+	void RenderPriorityGroup::addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
+	{
+		mSolidsBasic.addOrganisationMode(om);
+		mSolidsDiffuseSpecular.addOrganisationMode(om);
+		mSolidsDecal.addOrganisationMode(om);
+		mSolidsNoShadowReceive.addOrganisationMode(om);
+	}
+	//-----------------------------------------------------------------------
+	void RenderPriorityGroup::defaultOrganisationMode(void)
+	{
+		resetOrganisationModes();
+		addOrganisationMode(QueuedRenderableCollection::OM_PASS_GROUP);
+	}
+	//-----------------------------------------------------------------------
+    void RenderPriorityGroup::addRenderable(Renderable* rend, Technique* pTech)
+    {
+        // Transparent and depth/colour settings mean depth sorting is required?
+        // Note: colour write disabled with depth check/write enabled means
+        //       setup depth buffer for other passes use.
+        if (pTech->isTransparent() && 
+            (!pTech->isDepthWriteEnabled() ||
+             !pTech->isDepthCheckEnabled() ||
+             pTech->hasColourWriteDisabled()))
+        {
+            addTransparentRenderable(pTech, rend);
+        }
+        else
+        {
+            if (mSplitNoShadowPasses &&
+                mParent->getShadowsEnabled() &&
+				(!pTech->getParent()->getReceiveShadows() ||
+				rend->getCastsShadows() && mShadowCastersNotReceivers))
+            {
+                // Add solid renderable and add passes to no-shadow group
+                addSolidRenderable(pTech, rend, true);
+            }
+            else
+            {
+                if (mSplitPassesByLightingType && mParent->getShadowsEnabled())
+                {
+                    addSolidRenderableSplitByLightType(pTech, rend);
+                }
+                else
+                {
+                    addSolidRenderable(pTech, rend, false);
+                }
+            }
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addSolidRenderable(Technique* pTech, 
+        Renderable* rend, bool addToNoShadow)
+    {
+        Technique::PassIterator pi = pTech->getPassIterator();
+
+		QueuedRenderableCollection* collection;
+        if (addToNoShadow)
+        {
+            collection = &mSolidsNoShadowReceive;
+        }
+        else
+        {
+            collection = &mSolidsBasic;
+        }
+
+
+        while (pi.hasMoreElements())
+        {
+            // Insert into solid list
+            Pass* p = pi.getNext();
+			collection->addRenderable(p, 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();
+            QueuedRenderableCollection* collection;
+            switch(p->stage)
+            {
+            case IS_AMBIENT:
+                collection = &mSolidsBasic;
+                break;
+            case IS_PER_LIGHT:
+                collection = &mSolidsDiffuseSpecular;
+                break;
+            case IS_DECAL:
+                collection = &mSolidsDecal;
+                break;
+            };
+
+			collection->addRenderable(p->pass, rend);
+        }
+    }
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::addTransparentRenderable(Technique* pTech, Renderable* rend)
+    {
+        Technique::PassIterator pi = pTech->getPassIterator();
+
+        while (pi.hasMoreElements())
+        {
+            // Insert into transparent list
+            mTransparents.addRenderable(pi.getNext(), rend);
+        }
+    }
+    //-----------------------------------------------------------------------
+	void RenderPriorityGroup::removePassEntry(Pass* p)
+	{
+		mSolidsBasic.removePassGroup(p);
+		mSolidsDiffuseSpecular.removePassGroup(p);
+		mSolidsNoShadowReceive.removePassGroup(p);
+		mSolidsDecal.removePassGroup(p);
+		mTransparents.removePassGroup(p); // shouldn't be any, but for completeness
+	}	
+    //-----------------------------------------------------------------------
+    void RenderPriorityGroup::clear(void)
+    {
+        // 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)
+        {
+            removePassEntry(*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)
+        {
+            removePassEntry(*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
+
+		// Now empty the remaining collections
+		// Note that groups don't get deleted, just emptied hence the difference
+		// between the pass groups which are removed above, and clearing done
+		// here
+		mSolidsBasic.clear();
+        mSolidsDecal.clear();
+        mSolidsDiffuseSpecular.clear();
+        mSolidsNoShadowReceive.clear();
+        mTransparents.clear();
+
+    }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE	
+	//-----------------------------------------------------------------------
+    void RenderPriorityGroup::clear(const int leavePassesInQueue, bool destroy = false)
+    {
+		//-- standard method if no passes are left in queue
+		if (!leavePassesInQueue)
+		{
+			clear();
+
+			// additionally destroy the collections
+			if (destroy)
+			{
+				mSolidsBasic.clear(destroy);
+				mSolidsDecal.clear(destroy);
+				mSolidsDiffuseSpecular.clear(destroy);
+				mSolidsNoShadowReceive.clear(destroy);
+				mTransparents.clear(destroy);
+			}
+
+			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))
+			mSolidsBasic.clear(destroy);
+		if (!(leavePassesInQueue & SOLID_PASSES_DECAL))
+	        mSolidsDecal.clear(destroy);
+    	if (!(leavePassesInQueue & SOLID_PASSES_DIFFUSE_SPECULAR))
+		    mSolidsDiffuseSpecular.clear(destroy);
+		if (!(leavePassesInQueue & SOLID_PASSES_NOSHADOW))
+			mSolidsNoShadowReceive.clear(destroy);
+        if (!(leavePassesInQueue & TRANSPARENT_PASSES))
+			mTransparents.clear(destroy);
+    }
+#endif // GTP_VISIBILITY_MODIFIED_OGRE	
+
+	//-----------------------------------------------------------------------
+	void RenderPriorityGroup::sort(const Camera* cam)
+	{
+		mSolidsBasic.sort(cam);
+		mSolidsDecal.sort(cam);
+		mSolidsDiffuseSpecular.sort(cam);
+		mSolidsNoShadowReceive.sort(cam);
+		mTransparents.sort(cam);
+	}
+    //-----------------------------------------------------------------------
+	QueuedRenderableCollection::QueuedRenderableCollection(void)
+		:mOrganisationMode(0)
+	{
+	}
+    //-----------------------------------------------------------------------
+	QueuedRenderableCollection::~QueuedRenderableCollection(void)
+	{
+        // destroy all the pass map entries (rather than clearing)
+        PassGroupRenderableMap::iterator i, iend;
+        iend = mGrouped.end();
+        for (i = mGrouped.begin(); i != iend; ++i)
+        {
+            // Free the list associated with this pass
+            delete i->second;
+        }
+		
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::clear(void)
+	{
+        PassGroupRenderableMap::iterator i, iend;
+        iend = mGrouped.end();
+        for (i = mGrouped.begin(); i != iend; ++i)
+        {
+            // Clear the list associated with this pass, but leave the pass entry
+            i->second->clear();
+        }
+
+		// Clear sorted list
+		mSortedDescending.clear();
+	}
+	//-----------------------------------------------------------------------
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	void QueuedRenderableCollection::clear(bool destroy)
+	{
+		if (!destroy)
+		{
+			clear();
+			return;
+		}
+
+        PassGroupRenderableMap::iterator i, iend;
+        iend = mGrouped.end();
+        for (i = mGrouped.begin(); i != iend; ++i)
+        {
+            // Clear the list associated with this pass, but leave the pass entry
+            delete i->second;
+        }
+
+
+		mGrouped.clear();
+
+		// Clear sorted list
+		mSortedDescending.clear();
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::removePassGroup(Pass* p)
+	{
+        PassGroupRenderableMap::iterator i;
+
+        i = mGrouped.find(p);
+        if (i != mGrouped.end())
+        {
+            // free memory
+            delete i->second;
+            // erase from map
+            mGrouped.erase(i);
+        }
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::sort(const Camera* cam)
+    {
+		// ascending and descending sort both set bit 1
+		if (mOrganisationMode & OM_SORT_DESCENDING)
+		{
+			
+			// We can either use a stable_sort and the 'less' implementation,
+			// or a 2-pass radix sort (once by pass, then by distance, since
+			// radix sorting is inherently stable this will work)
+			// We use stable_sort if the number of items is 512 or less, since
+			// the complexity of the radix sort is approximately O(10N), since 
+			// each sort is O(5N) (1 pass histograms, 4 passes sort)
+			// Since stable_sort has a worst-case performance of O(N(logN)^2)
+			// the performance tipping point is from about 1500 items, but in
+			// stable_sorts best-case scenario O(NlogN) it would be much higher.
+			// Take a stab at 2000 items.
+			
+			if (mSortedDescending.size() > 2000)
+			{
+				// sort by pass
+				msRadixSorter1.sort(mSortedDescending, RadixSortFunctorPass());
+				// sort by depth
+				msRadixSorter2.sort(mSortedDescending, RadixSortFunctorDistance(cam));
+			}
+			else
+			{
+				std::stable_sort(
+					mSortedDescending.begin(), mSortedDescending.end(), 
+					DepthSortDescendingLess(cam));
+			}
+		}
+
+		// Nothing needs to be done for pass groups, they auto-organise
+
+    }
+    //-----------------------------------------------------------------------
+    void QueuedRenderableCollection::addRenderable(Pass* pass, Renderable* rend)
+	{
+		// ascending and descending sort both set bit 1
+		if (mOrganisationMode & OM_SORT_DESCENDING)
+		{
+			mSortedDescending.push_back(RenderablePass(rend, pass));
+		}
+
+		if (mOrganisationMode & OM_PASS_GROUP)
+		{
+            PassGroupRenderableMap::iterator i = mGrouped.find(pass);
+            if (i == mGrouped.end())
+            {
+                std::pair<PassGroupRenderableMap::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, or a pass is destroyed or has it's hash
+				// recalculated, although the lists will be cleared
+                retPair = mGrouped.insert(
+                    PassGroupRenderableMap::value_type(
+						pass, new RenderableList() ));
+                assert(retPair.second && 
+					"Error inserting new pass entry into PassGroupRenderableMap");
+                i = retPair.first;
+            }
+            // Insert renderable
+            i->second->push_back(rend);
+			
+		}
+		
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::acceptVisitor(
+		QueuedRenderableVisitor* visitor, OrganisationMode om) const
+	{
+		if ((om & mOrganisationMode) == 0)
+		{
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+				"Organisation mode requested in acceptVistor was not notified "
+				"to this class ahead of time, therefore may not be supported.", 
+				"QueuedRenderableCollection::acceptVisitor");
+		}
+
+		switch(om)
+		{
+		case OM_PASS_GROUP:
+			acceptVisitorGrouped(visitor);
+			break;
+		case OM_SORT_DESCENDING:
+			acceptVisitorDescending(visitor);
+			break;
+		case OM_SORT_ASCENDING:
+			acceptVisitorAscending(visitor);
+			break;
+		}
+		
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::acceptVisitorGrouped(
+		QueuedRenderableVisitor* visitor) const
+	{
+		PassGroupRenderableMap::const_iterator ipass, ipassend;
+		ipassend = mGrouped.end();
+		for (ipass = mGrouped.begin(); ipass != ipassend; ++ipass)
+		{
+			// Fast bypass if this group is now empty
+			if (ipass->second->empty()) continue;
+
+			// Visit Pass - allow skip
+			if (!visitor->visit(ipass->first))
+				continue;
+
+			RenderableList* rendList = ipass->second;
+			RenderableList::const_iterator irend, irendend;
+			irendend = rendList->end();
+			for (irend = rendList->begin(); irend != irendend; ++irend)
+			{
+				// Visit Renderable
+				visitor->visit(*irend);
+			}
+		} 
+
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::acceptVisitorDescending(
+		QueuedRenderableVisitor* visitor) const
+	{
+		// List is already in descending order, so iterate forward
+		RenderablePassList::const_iterator i, iend;
+
+		iend = mSortedDescending.end();
+		for (i = mSortedDescending.begin(); i != iend; ++i)
+		{
+			visitor->visit(&(*i));
+		}
+	}
+    //-----------------------------------------------------------------------
+	void QueuedRenderableCollection::acceptVisitorAscending(
+		QueuedRenderableVisitor* visitor) const
+	{
+		// List is in descending order, so iterate in reverse
+		RenderablePassList::const_reverse_iterator i, iend;
+
+		iend = mSortedDescending.rend();
+		for (i = mSortedDescending.rbegin(); i != iend; ++i)
+		{
+			visitor->visit(&(*i));
+		}
+
+	}
+
+
+}
+
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreCamera.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreCamera.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreCamera.cpp	(revision 921)
@@ -0,0 +1,840 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreCamera.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreSceneManager.h"
+#include "OgreSceneNode.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreSphere.h"
+#include "OgreLogManager.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreRenderSystem.h"
+
+namespace Ogre {
+
+    String Camera::msMovableType = "Camera";
+    //-----------------------------------------------------------------------
+    Camera::Camera( const String& name, SceneManager* sm)
+        : mName( name ),
+		mSceneMgr(sm),
+		mOrientation(Quaternion::IDENTITY),
+		mPosition(Vector3::ZERO),
+		mSceneDetail(PM_SOLID),
+		mAutoTrackTarget(0),
+		mAutoTrackOffset(Vector3::ZERO),
+		mSceneLodFactor(1.0f),
+		mSceneLodFactorInv(1.0f),
+		mWindowSet(false),
+		mLastViewport(0),
+		mAutoAspectRatio(false),
+		mCullFrustum(0),
+		mUseRenderingDistance(true)
+
+    {
+
+        // Reasonable defaults to camera params
+        mFOVy = Radian(Math::PI/4.0);
+        mNearDist = 100.0f;
+        mFarDist = 100000.0f;
+        mAspect = 1.33333333333333f;
+        mProjType = PT_PERSPECTIVE;
+        setFixedYawAxis(true);    // Default to fixed yaw, like freelook since most people expect this
+
+        invalidateFrustum();
+        invalidateView();
+
+        // Init matrices
+        mViewMatrix = Matrix4::ZERO;
+        mProjMatrixRS = Matrix4::ZERO;
+
+        mParentNode = 0;
+
+        // no reflection
+        mReflect = false;
+
+        mVisible = false;
+
+    }
+
+    //-----------------------------------------------------------------------
+    Camera::~Camera()
+    {
+        // Do nothing
+    }
+
+    //-----------------------------------------------------------------------
+    SceneManager* Camera::getSceneManager(void) const
+    {
+        return mSceneMgr;
+    }
+    //-----------------------------------------------------------------------
+    const String& Camera::getName(void) const
+    {
+        return mName;
+    }
+
+
+    //-----------------------------------------------------------------------
+    void Camera::setPolygonMode(PolygonMode sd)
+    {
+        mSceneDetail = sd;
+    }
+
+    //-----------------------------------------------------------------------
+    PolygonMode Camera::getPolygonMode(void) const
+    {
+        return mSceneDetail;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setPosition(Real x, Real y, Real z)
+    {
+        mPosition.x = x;
+        mPosition.y = y;
+        mPosition.z = z;
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setPosition(const Vector3& vec)
+    {
+        mPosition = vec;
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    const Vector3& Camera::getPosition(void) const
+    {
+        return mPosition;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::move(const Vector3& vec)
+    {
+        mPosition = mPosition + vec;
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::moveRelative(const Vector3& vec)
+    {
+        // Transform the axes of the relative vector by camera's local axes
+        Vector3 trans = mOrientation * vec;
+
+        mPosition = mPosition + trans;
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setDirection(Real x, Real y, Real z)
+    {
+        setDirection(Vector3(x,y,z));
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setDirection(const Vector3& vec)
+    {
+        // Do nothing if given a zero vector
+        // (Replaced assert since this could happen with auto tracking camera and
+        //  camera passes through the lookAt point)
+        if (vec == Vector3::ZERO) return;
+
+        // Remember, camera points down -Z of local axes!
+        // Therefore reverse direction of direction vector before determining local Z
+        Vector3 zAdjustVec = -vec;
+        zAdjustVec.normalise();
+
+
+        if( mYawFixed )
+        {
+            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
+            xVec.normalise();
+
+            Vector3 yVec = zAdjustVec.crossProduct( xVec );
+            yVec.normalise();
+
+            mOrientation.FromAxes( xVec, yVec, zAdjustVec );
+        }
+        else
+        {
+
+            // Get axes from current quaternion
+            Vector3 axes[3];
+            updateView();
+            mRealOrientation.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);
+
+            }
+            mOrientation = rotQuat * mOrientation;
+        }
+
+        // transform to parent space
+        if (mParentNode)
+        {
+            mOrientation =
+                mParentNode->_getDerivedOrientation().Inverse() * mOrientation;
+        }
+
+        // TODO If we have a fixed yaw axis, we mustn't break it by using the
+        // shortest arc because this will sometimes cause a relative yaw
+        // which will tip the camera
+
+        invalidateView();
+
+    }
+
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getDirection(void) const
+    {
+        // Direction points down -Z by default
+        return mOrientation * -Vector3::UNIT_Z;
+    }
+
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getUp(void) const
+    {
+        return mOrientation * Vector3::UNIT_Y;
+    }
+
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getRight(void) const
+    {
+        return mOrientation * Vector3::UNIT_X;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::lookAt(const Vector3& targetPoint)
+    {
+        updateView();
+        this->setDirection(targetPoint - mRealPosition);
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::lookAt( Real x, Real y, Real z )
+    {
+        Vector3 vTemp( x, y, z );
+        this->lookAt(vTemp);
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::roll(const Radian& angle)
+    {
+        // Rotate around local Z axis
+        Vector3 zAxis = mOrientation * Vector3::UNIT_Z;
+        rotate(zAxis, angle);
+
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::yaw(const Radian& angle)
+    {
+        Vector3 yAxis;
+
+        if (mYawFixed)
+        {
+            // Rotate around fixed yaw axis
+            yAxis = mYawFixedAxis;
+        }
+        else
+        {
+            // Rotate around local Y axis
+            yAxis = mOrientation * Vector3::UNIT_Y;
+        }
+
+        rotate(yAxis, angle);
+
+        invalidateView();
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::pitch(const Radian& angle)
+    {
+        // Rotate around local X axis
+        Vector3 xAxis = mOrientation * Vector3::UNIT_X;
+        rotate(xAxis, angle);
+
+        invalidateView();
+
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::rotate(const Vector3& axis, const Radian& angle)
+    {
+        Quaternion q;
+        q.FromAngleAxis(angle,axis);
+        rotate(q);
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::rotate(const Quaternion& q)
+    {
+        // Note the order of the mult, i.e. q comes after
+        mOrientation = q * mOrientation;
+        invalidateView();
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Camera::isViewOutOfDate(void) const
+    {
+        // Overridden from Frustum to use local orientation / position offsets
+        // Attached to node?
+        if (mParentNode != 0)
+        {
+            if (mRecalcView ||
+                mParentNode->_getDerivedOrientation() != mLastParentOrientation ||
+                mParentNode->_getDerivedPosition() != mLastParentPosition)
+            {
+                // Ok, we're out of date with SceneNode we're attached to
+                mLastParentOrientation = mParentNode->_getDerivedOrientation();
+                mLastParentPosition = mParentNode->_getDerivedPosition();
+                mRealOrientation = mLastParentOrientation * mOrientation;
+                mRealPosition = (mLastParentOrientation * mPosition) + mLastParentPosition;
+                mRecalcView = true;
+                mRecalcWindow = true;
+            }
+        }
+        else
+        {
+            // Rely on own updates
+            mRealOrientation = mOrientation;
+            mRealPosition = mPosition;
+        }
+
+        // Deriving reflection from linked plane?
+        if (mReflect && mLinkedReflectPlane && 
+            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
+        {
+            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
+            mRecalcView = true;
+            mRecalcWindow = true;
+        }
+
+        // Deriving reflected orientation / position
+        if (mRecalcView)
+        {
+            if (mReflect)
+            {
+                // Calculate reflected orientation, use up-vector as fallback axis.
+				Vector3 dir = mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
+				Vector3 rdir = dir.reflect(mReflectPlane.normal);
+                Vector3 up = mRealOrientation * Vector3::UNIT_Y;
+				mDerivedOrientation = dir.getRotationTo(rdir, up) * mRealOrientation;
+
+                // Calculate reflected position.
+                mDerivedPosition = mReflectMatrix * mRealPosition;
+            }
+            else
+            {
+                mDerivedOrientation = mRealOrientation;
+                mDerivedPosition = mRealPosition;
+            }
+        }
+
+        return mRecalcView;
+
+    }
+
+    // -------------------------------------------------------------------
+    void Camera::invalidateView() const
+    {
+        mRecalcWindow = true;
+        Frustum::invalidateView();
+    }
+    // -------------------------------------------------------------------
+    void Camera::invalidateFrustum(void) const
+    {
+        mRecalcWindow = true;
+        Frustum::invalidateFrustum();
+    }
+    //-----------------------------------------------------------------------
+    void Camera::_renderScene(Viewport *vp, bool includeOverlays)
+    {
+
+        mSceneMgr->_renderScene(this, vp, includeOverlays);
+    }
+
+
+    //-----------------------------------------------------------------------
+    std::ostream& operator<<( std::ostream& o, Camera& c )
+    {
+        o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition;
+        Vector3 dir(c.mOrientation*Vector3(0,0,-1));
+        o << ", direction=" << dir << ",near=" << c.mNearDist;
+        o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy.valueDegrees();
+        o << ", aspect=" << c.mAspect << ", ";
+        o << ", xoffset=" << c.mFrustumOffset.x << ", yoffset=" << c.mFrustumOffset.y;
+        o << ", focalLength=" << c.mFocalLength << ", ";
+        o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", ";
+        o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", ";
+        o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", ";
+        o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", ";
+        o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", ";
+        o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM];
+        o << ")";
+
+        return o;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
+    {
+        mYawFixed = useFixed;
+        mYawFixedAxis = fixedAxis;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::_notifyRenderedFaces(unsigned int numfaces)
+    {
+        mVisFacesLastRender = numfaces;
+    }
+
+    //-----------------------------------------------------------------------
+    unsigned int Camera::_getNumRenderedFaces(void) const
+    {
+        return mVisFacesLastRender;
+    }
+
+    //-----------------------------------------------------------------------
+    const Quaternion& Camera::getOrientation(void) const
+    {
+        return mOrientation;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setOrientation(const Quaternion& q)
+    {
+        mOrientation = q;
+        invalidateView();
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Camera::getDerivedOrientation(void) const
+    {
+        updateView();
+        return mDerivedOrientation;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Camera::getDerivedPosition(void) const
+    {
+        updateView();
+        return mDerivedPosition;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getDerivedDirection(void) const
+    {
+        // Direction points down -Z
+        updateView();
+        return mDerivedOrientation * Vector3::NEGATIVE_UNIT_Z;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getDerivedUp(void) const
+    {
+        updateView();
+        return mDerivedOrientation * Vector3::UNIT_Y;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getDerivedRight(void) const
+    {
+        updateView();
+        return mDerivedOrientation * Vector3::UNIT_X;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Camera::getRealOrientation(void) const
+    {
+        updateView();
+        return mRealOrientation;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Camera::getRealPosition(void) const
+    {
+        updateView();
+        return mRealPosition;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getRealDirection(void) const
+    {
+        // Direction points down -Z
+        updateView();
+        return mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getRealUp(void) const
+    {
+        updateView();
+        return mRealOrientation * Vector3::UNIT_Y;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Camera::getRealRight(void) const
+    {
+        updateView();
+        return mRealOrientation * Vector3::UNIT_X;
+    }
+    //-----------------------------------------------------------------------
+    const String& Camera::getMovableType(void) const
+    {
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+    void Camera::setAutoTracking(bool enabled, SceneNode* target, 
+        const Vector3& offset)
+    {
+        if (enabled)
+        {
+            assert (target != 0 && "target cannot be a null pointer if tracking is enabled");
+            mAutoTrackTarget = target;
+            mAutoTrackOffset = offset;
+        }
+        else
+        {
+            mAutoTrackTarget = 0;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Camera::_autoTrack(void)
+    {
+        // NB assumes that all scene nodes have been updated
+        if (mAutoTrackTarget)
+        {
+            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset);
+        }
+    }
+    //-----------------------------------------------------------------------
+	void Camera::setLodBias(Real factor)
+	{
+		assert(factor > 0.0f && "Bias factor must be > 0!");
+		mSceneLodFactor = factor;
+		mSceneLodFactorInv = 1.0f / factor;
+	}
+    //-----------------------------------------------------------------------
+	Real Camera::getLodBias(void) const
+	{
+		return mSceneLodFactor;
+	}
+    //-----------------------------------------------------------------------
+	Real Camera::_getLodBiasInverse(void) const
+	{
+		return mSceneLodFactorInv;
+	}
+    //-----------------------------------------------------------------------
+    Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const
+    {
+        Real centeredScreenX = (screenX - 0.5f);
+        Real centeredScreenY = (0.5f - screenY);
+
+		Real normalizedSlope = Math::Tan(mFOVy / 2);
+        Real viewportYToWorldY = normalizedSlope * mNearDist * 2;
+        Real viewportXToWorldX = viewportYToWorldY * mAspect;
+
+		Vector3 rayDirection, rayOrigin;
+		if (mProjType == PT_PERSPECTIVE)
+		{
+			// Frustum offset (at near plane)
+			Real nearFocal = mNearDist / mFocalLength;
+			Real offsetX = mFrustumOffset.x * nearFocal;
+			Real offsetY = mFrustumOffset.y * nearFocal;
+			// From camera centre
+			rayOrigin = getDerivedPosition();
+			// Point to perspective projected position
+			rayDirection.x = centeredScreenX * viewportXToWorldX + offsetX;
+			rayDirection.y = centeredScreenY * viewportYToWorldY + offsetY;
+			rayDirection.z = -mNearDist;
+			rayDirection = getDerivedOrientation() * rayDirection;
+			rayDirection.normalise();
+		}
+		else
+		{
+			// Ortho always parallel to point on screen
+			rayOrigin.x = centeredScreenX * viewportXToWorldX;
+			rayOrigin.y = centeredScreenY * viewportYToWorldY;
+			rayOrigin.z = 0.0f;
+			rayOrigin = getDerivedOrientation() * rayOrigin;
+			rayOrigin = getDerivedPosition() + rayOrigin;
+			rayDirection = getDerivedDirection();
+		}
+
+        return Ray(rayOrigin, rayDirection);
+    } 
+
+    // -------------------------------------------------------------------
+    void Camera::setWindow (Real Left, Real Top, Real Right, Real Bottom)
+    {
+        mWLeft = Left;
+        mWTop = Top;
+        mWRight = Right;
+        mWBottom = Bottom;
+
+        mWindowSet = true;
+        mRecalcWindow = true;
+    }
+    // -------------------------------------------------------------------
+    void Camera::resetWindow ()
+    {
+        mWindowSet = false;
+    }
+    // -------------------------------------------------------------------
+    void Camera::setWindowImpl() const
+    {
+        if (!mWindowSet || !mRecalcWindow)
+            return;
+
+        // Calculate general projection parameters
+        Real vpLeft, vpRight, vpBottom, vpTop;
+        calcProjectionParameters(vpLeft, vpRight, vpBottom, vpTop);
+
+        Real vpWidth = vpRight - vpLeft;
+        Real vpHeight = vpTop - vpBottom;
+
+        Real wvpLeft   = vpLeft + mWLeft * vpWidth;
+        Real wvpRight  = vpLeft + mWRight * vpWidth;
+        Real wvpTop    = vpTop - mWTop * vpHeight;
+        Real wvpBottom = vpTop - mWBottom * vpHeight;
+
+        Vector3 vp_ul (wvpLeft, wvpTop, -mNearDist);
+        Vector3 vp_ur (wvpRight, wvpTop, -mNearDist);
+        Vector3 vp_bl (wvpLeft, wvpBottom, -mNearDist);
+        Vector3 vp_br (wvpRight, wvpBottom, -mNearDist);
+
+        Matrix4 inv = mViewMatrix.inverse();
+
+        Vector3 vw_ul = inv * vp_ul;
+        Vector3 vw_ur = inv * vp_ur;
+        Vector3 vw_bl = inv * vp_bl;
+        Vector3 vw_br = inv * vp_br;
+
+        if (mProjType == PT_PERSPECTIVE)
+        {
+            Vector3 position = getPosition();
+            mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul));
+            mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur));
+            mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br));
+            mWindowClipPlanes.push_back(Plane(position, vw_br, vw_bl));
+        }
+        else
+        {
+            Vector3 x_axis(inv[0][0], inv[0][1], inv[0][2]);
+            Vector3 y_axis(inv[1][0], inv[1][1], inv[1][2]);
+            x_axis.normalise();
+            y_axis.normalise();
+            mWindowClipPlanes.push_back(Plane( x_axis, vw_bl));
+            mWindowClipPlanes.push_back(Plane(-x_axis, vw_ur));
+            mWindowClipPlanes.push_back(Plane( y_axis, vw_bl));
+            mWindowClipPlanes.push_back(Plane(-y_axis, vw_ur));
+        }
+
+        mRecalcWindow = false;
+
+    }
+    // -------------------------------------------------------------------
+    const std::vector<Plane>& Camera::getWindowPlanes(void) const
+    {
+        updateView();
+        setWindowImpl();
+        return mWindowClipPlanes;
+    }
+    // -------------------------------------------------------------------
+    Real Camera::getBoundingRadius(void) const
+    {
+        // return a little bigger than the near distance
+        // just to keep things just outside
+        return mNearDist * 1.5;
+
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Camera::getPositionForViewUpdate(void) const
+    {
+        // Note no update, because we're calling this from the update!
+        return mRealPosition;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Camera::getOrientationForViewUpdate(void) const
+    {
+        return mRealOrientation;
+    }
+    //-----------------------------------------------------------------------
+    bool Camera::getAutoAspectRatio(void) const
+    {
+        return mAutoAspectRatio;
+    }
+    //-----------------------------------------------------------------------
+    void Camera::setAutoAspectRatio(bool autoratio)
+    {
+        mAutoAspectRatio = autoratio;
+    }
+	//-----------------------------------------------------------------------
+	bool Camera::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->isVisible(bound, culledBy);
+		}
+		else
+		{
+			return Frustum::isVisible(bound, culledBy);
+		}
+	}
+	//-----------------------------------------------------------------------
+	bool Camera::isVisible(const Sphere& bound, FrustumPlane* culledBy) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->isVisible(bound, culledBy);
+		}
+		else
+		{
+			return Frustum::isVisible(bound, culledBy);
+		}
+	}
+	//-----------------------------------------------------------------------
+	bool Camera::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->isVisible(vert, culledBy);
+		}
+		else
+		{
+			return Frustum::isVisible(vert, culledBy);
+		}
+	}
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	bool Camera::isVisible(const AxisAlignedBox& bound, bool &intersects, FrustumPlane* culledBy) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->isVisible(bound, intersects, culledBy);
+		}
+		else
+		{
+			return Frustum::isVisible(bound, intersects, culledBy);
+		}
+	}
+#endif
+	//-----------------------------------------------------------------------
+	const Vector3* Camera::getWorldSpaceCorners(void) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->getWorldSpaceCorners();
+		}
+		else
+		{
+			return Frustum::getWorldSpaceCorners();
+		}
+	}
+	//-----------------------------------------------------------------------
+	const Plane& Camera::getFrustumPlane( unsigned short plane ) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->getFrustumPlane(plane);
+		}
+		else
+		{
+			return Frustum::getFrustumPlane(plane);
+		}
+	}
+	//-----------------------------------------------------------------------
+	bool Camera::projectSphere(const Sphere& sphere, 
+		Real* left, Real* top, Real* right, Real* bottom) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->projectSphere(sphere, left, top, right, bottom);
+		}
+		else
+		{
+			return Frustum::projectSphere(sphere, left, top, right, bottom);
+		}
+	}
+	//-----------------------------------------------------------------------
+	Real Camera::getNearClipDistance(void) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->getNearClipDistance();
+		}
+		else
+		{
+			return Frustum::getNearClipDistance();
+		}
+	}
+	//-----------------------------------------------------------------------
+	Real Camera::getFarClipDistance(void) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->getFarClipDistance();
+		}
+		else
+		{
+			return Frustum::getFarClipDistance();
+		}
+	}
+	//-----------------------------------------------------------------------
+	const Matrix4& Camera::getViewMatrix(void) const
+	{
+		if (mCullFrustum)
+		{
+			return mCullFrustum->getViewMatrix();
+		}
+		else
+		{
+			return Frustum::getViewMatrix();
+		}
+	}
+	//-----------------------------------------------------------------------
+	const Matrix4& Camera::getViewMatrix(bool ownFrustumOnly) const
+	{
+		if (ownFrustumOnly)
+		{
+			return Frustum::getViewMatrix();
+		}
+		else
+		{
+			return getViewMatrix();
+		}
+	}
+	//-----------------------------------------------------------------------
+
+
+
+} // namespace Ogre
Index: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneManager.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneManager.cpp	(revision 768)
+++ OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneManager.cpp	(revision 921)
@@ -1046,11 +1046,5 @@
 
 	// Prepare render queue for receiving new objects
-#ifdef GAMETOOLS_ILLUMINATION_MODULE 
-	if (mFindVisibleObjects)
-		prepareRenderQueue();
-#else
-		prepareRenderQueue();
-#endif
-
+	prepareRenderQueue();
 
     if (mFindVisibleObjects)
@@ -1304,6 +1298,10 @@
             }
             // Set active frame
-            boxMat->getBestTechnique()->getPass(0)->getTextureUnitState(0)
-                ->setCurrentFrame(i);
+			Material::TechniqueIterator ti = boxMat->getSupportedTechniqueIterator();
+			while (ti.hasMoreElements())
+			{
+				Technique* tech = ti.getNext();
+				tech->getPass(0)->getTextureUnitState(0)->setCurrentFrame(i);
+			}
 
             mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
@@ -2207,9 +2205,4 @@
         return false;
     }
-
-#ifdef GAMETOOLS_ILLUMINATION_MODULE
-	if(!pass->isActive())
-		return false;
-#endif
 
     return true;
@@ -4166,5 +4159,5 @@
         mShadowIndexBuffer = HardwareBufferManager::getSingleton().
             createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 
-            mShadowIndexBufferSize, 
+            size, 
             HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
             false);
@@ -4859,3 +4852,75 @@
 }
 
-}
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+//-----------------------------------------------------------------------
+const 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 = static_cast<RenderQueueGroupID>(queueIt.peekNextKey());
+		RenderQueueGroup* pGroup = queueIt.getNext();
+
+		if (isRenderQueueToBeProcessed(qId))
+		{
+			pGroup->clear(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/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctree.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctree.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctree.h	(revision 921)
@@ -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/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeNode.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeNode.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeNode.h	(revision 921)
@@ -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/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreTerrainRenderable.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreTerrainRenderable.h	(revision 921)
@@ -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, TerrainSceneManager* tsm);
+        ~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 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 mBoundingRadius; }
+
+        /** @copydoc Renderable::getLights */
+        const LightList& getLights(void) const;
+
+        /// Overridden from Renderable to allow the morph LOD entry to be set
+        void _updateCustomGpuParameter(
+            const GpuProgramParameters::AutoConstantEntry& constantEntry,
+            GpuProgramParameters* params) const;
+		/// @see MovableObject
+		uint32 getTypeFlags(void) const;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		// resets index of renderlevel used for current pass
+		static void ResetRenderLevelIndex();
+		// next index of renderlevel
+		static void NextRenderLevelIndex();
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+    protected:
+		/// Parent SceneManager
+		TerrainSceneManager* mSceneManager;
+        /// Link to shared options
+        const TerrainOptions* mOptions;
+
+        /** Returns the index into the height array for the given coords. */
+        inline size_t _index( int x, int z ) const
+        {
+            return ( x + z * mOptions->tileSize );
+        };
+
+        /** Returns the  vertex coord for the given coordinates */
+        inline float _vertex( int x, int z, int n )
+        {
+            return mPositionBuffer[x * 3 + z * mOptions->tileSize * 3 + n];
+        };
+
+
+        inline int _numNeighbors() const
+        {
+            int n = 0;
+
+            for ( int i = 0; i < 4; i++ )
+            {
+                if ( mNeighbors[ i ] != 0 )
+                    n++;
+            }
+
+            return n;
+        }
+
+        inline bool _hasNeighborRenderLevel( int i ) const
+        {
+            for ( int j = 0; j < 4; j++ )
+            {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+				if ( mNeighbors[ j ] != 0 && mNeighbors[ j ] ->getRenderLevel() == i )
+                    return true;
+#else
+                if ( mNeighbors[ j ] != 0 && mNeighbors[ j ] ->mRenderLevel == i )
+                    return true;
+#endif //GTP_VISIBILITY_MODIFIED_OGRE
+            }
+
+            return false;
+
+        }
+
+        void _adjustRenderLevel( int i );
+
+        bool _checkSize( int n );
+
+        void _calculateMinLevelDist2( Real C );
+
+        Real _calculateCFactor();
+
+        VertexData* mTerrain;
+
+        /// The current LOD level
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        int mRenderLevel[MAX_RENDERLEVEL_INDEX];
+
+		/*** msz: added for v1-2-0 compatibility ***/
+		// index of renderlevel of current pass
+		static int msCurrentRenderLevelIndex;
+#else
+		int mRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        /// The previous 'next' LOD level down, for frame coherency
+        int mLastNextLevel; 
+        /// The morph factor between this and the next LOD level down
+        Real mLODMorphFactor;
+        /// List of squared distances at which LODs change
+        Real *mMinLevelDistSqr;
+        /// Connection to tiles four neighbours
+        TerrainRenderable *mNeighbors [ 4 ];
+        /// Whether light list need to re-calculate
+        mutable bool mLightListDirty;
+        /// Cached light list
+        mutable LightList mLightList;
+        /// The bounding radius of this tile
+        Real mBoundingRadius;
+        /// Bounding box of this tile
+        AxisAlignedBox mBounds;
+        /// The center point of this tile
+        Vector3 mCenter;
+        /// The MovableObject type
+        static String mType;
+        /// Current material used by this tile
+        MaterialPtr mMaterial;    
+        /// Whether this tile has been initialised    
+        bool mInit;
+        /// The buffer with all the renderable geometry in it
+        HardwareVertexBufferSharedPtr mMainBuffer;
+        /// Optional set of delta buffers, used to morph from one LOD to the next
+        HardwareVertexBufferSharedPtr* mDeltaBuffers;
+        /// System-memory buffer with just positions in it, for CPU operations
+        float* mPositionBuffer;
+        /// Forced rendering LOD level, optional
+        int mForcedRenderLevel;
+        /// Array of LOD indexes specifying which LOD is the next one down
+        /// (deals with clustered error metrics which cause LODs to be skipped)
+        int mNextLevelDown[10];
+        /// Gets the index data for this tile based on current settings
+        IndexData* getIndexData(void);
+        /// Internal method for generating stripified terrain indexes
+        IndexData* generateTriStripIndexes(unsigned int stitchFlags);
+        /// Internal method for generating triangle list terrain indexes
+        IndexData* generateTriListIndexes(unsigned int stitchFlags);
+        /** Utility method to generate stitching indexes on the edge of a tile
+        @param neighbor The neighbor direction to stitch
+        @param hiLOD The LOD of this tile
+        @param loLOD The LOD of the neighbor
+        @param omitFirstTri Whether the first tri of the stitch (always clockwise
+        relative to the centre of this tile) is to be omitted because an 
+        adjoining edge is also being stitched
+        @param omitLastTri Whether the last tri of the stitch (always clockwise
+        relative to the centre of this tile) is to be omitted because an 
+        adjoining edge is also being stitched
+        @param pIdx Pointer to a pointer to the index buffer to push the results 
+        into (this pointer will be updated)
+        @returns The number of indexes added
+        */
+        int stitchEdge(Neighbor neighbor, int hiLOD, int loLOD, 
+            bool omitFirstTri, bool omitLastTri, unsigned short** ppIdx);
+
+        /// Create a blank delta buffer for usein morphing
+        HardwareVertexBufferSharedPtr createDeltaBuffer(void);
+
+    };
+
+}
+
+#endif
Index: OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeCamera.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeCamera.h	(revision 921)
@@ -0,0 +1,92 @@
+/*
+-----------------------------------------------------------------------------
+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/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeSceneManager.h
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/include/OgreOctreeSceneManager.h	(revision 921)
@@ -0,0 +1,291 @@
+/***************************************************************************
+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(const String& name);
+    /** Standard Constructor */
+    OctreeSceneManager(const String& name, AxisAlignedBox &box, int max_depth );
+    /** Standard desctructor */
+    ~OctreeSceneManager();
+
+	/// @copydoc SceneManager::getTypeName
+	const String& getTypeName(void) const;
+
+    /** 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* createAABBQuery(const AxisAlignedBox& box, unsigned long mask);
+    SphereSceneQuery* 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
+};
+
+/// Factory for OctreeSceneManager
+class OctreeSceneManagerFactory : public SceneManagerFactory
+{
+protected:
+	void initMetaData(void) const;
+public:
+	OctreeSceneManagerFactory() {}
+	~OctreeSceneManagerFactory() {}
+	/// Factory type name
+	static const String FACTORY_TYPE_NAME;
+	SceneManager* createInstance(const String& instanceName);
+	void destroyInstance(SceneManager* instance);
+};
+
+
+
+}
+
+#endif
+
Index: OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctree.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctree.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctree.cpp	(revision 921)
@@ -0,0 +1,265 @@
+/*
+-----------------------------------------------------------------------------
+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/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeNode.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeNode.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeNode.cpp	(revision 921)
@@ -0,0 +1,235 @@
+/*
+-----------------------------------------------------------------------------
+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>
+
+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();
+	}
+
+	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/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreTerrainRenderable.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreTerrainRenderable.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreTerrainRenderable.cpp	(revision 921)
@@ -0,0 +1,1563 @@
+/*
+-----------------------------------------------------------------------------
+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
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+    String TerrainRenderable::mType = "TerrainMipMap";
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	int TerrainRenderable::msCurrentRenderLevelIndex = 0;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+    //-----------------------------------------------------------------------
+    TerrainRenderable::TerrainRenderable(const String& name, TerrainSceneManager* tsm)
+        : Renderable(), MovableObject(name), mSceneManager(tsm), mTerrain(0), mDeltaBuffers(0), mPositionBuffer(0)
+    {
+        mForcedRenderLevel = -1;
+        mLastNextLevel = -1;
+
+        mMinLevelDistSqr = 0;
+
+        mInit = false;
+        mLightListDirty = true;
+		MovableObject::mCastShadows = false;
+
+        for ( int i = 0; i < 4; i++ )
+        {
+            mNeighbors[ i ] = 0;
+        }
+
+		mOptions = &(mSceneManager->getOptions());
+
+
+    }
+    //-----------------------------------------------------------------------
+    TerrainRenderable::~TerrainRenderable()
+    {
+
+        deleteGeometry();
+    }
+	//-----------------------------------------------------------------------
+	uint32 TerrainRenderable::getTypeFlags(void) const
+	{
+		// return world flag
+		return SceneManager::WORLD_GEOMETRY_TYPE_MASK;
+	}
+    //-----------------------------------------------------------------------
+    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 ( mOptions->maxGeoMipMapLevel != 0 )
+        {
+            int i = ( int ) 1 << ( mOptions->maxGeoMipMapLevel - 1 ) ;
+
+            if ( ( i + 1 ) > mOptions->tileSize )
+            {
+                printf( "Invalid maximum mipmap specifed, must be n, such that 2^(n-1)+1 < tileSize \n" );
+                return ;
+            }
+        }
+
+        deleteGeometry();
+
+        //calculate min and max heights;
+        Real min = 256000, max = 0;
+
+        mTerrain = new VertexData;
+        mTerrain->vertexStart = 0;
+        mTerrain->vertexCount = mOptions->tileSize * mOptions->tileSize;
+
+        VertexDeclaration* decl = mTerrain->vertexDeclaration;
+        VertexBufferBinding* bind = mTerrain->vertexBufferBinding;
+
+        // positions
+        size_t offset = 0;
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
+        offset += VertexElement::getTypeSize(VET_FLOAT3);
+        if (mOptions->lit)
+        {
+            decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
+            offset += VertexElement::getTypeSize(VET_FLOAT3);
+        }
+        // texture coord sets
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
+        offset += VertexElement::getTypeSize(VET_FLOAT2);
+        decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
+        offset += VertexElement::getTypeSize(VET_FLOAT2);
+        if (mOptions->coloured)
+        {
+            decl->addElement(MAIN_BINDING, offset, VET_COLOUR, VES_DIFFUSE);
+            offset += VertexElement::getTypeSize(VET_COLOUR);
+        }
+
+        // Create shared vertex buffer
+        mMainBuffer =
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+            decl->getVertexSize(MAIN_BINDING),
+            mTerrain->vertexCount, 
+            HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+        // Create system memory copy with just positions in it, for use in simple reads
+        mPositionBuffer = new float[mTerrain->vertexCount * 3];
+
+        bind->setBinding(MAIN_BINDING, mMainBuffer);
+
+        if (mOptions->lodMorph)
+        {
+            // Create additional element for delta
+            decl->addElement(DELTA_BINDING, 0, VET_FLOAT1, VES_BLEND_WEIGHTS);
+            // NB binding is not set here, it is set when deriving the LOD
+        }
+
+
+        mInit = true;
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		for (int i = 0; i < MAX_RENDERLEVEL_INDEX; ++i)
+		{
+			mRenderLevel[i] = 1;
+		}
+#else
+		mRenderLevel = 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        mMinLevelDistSqr = new Real[ mOptions->maxGeoMipMapLevel ];
+
+        int endx = startx + mOptions->tileSize;
+
+        int endz = startz + mOptions->tileSize;
+
+        Vector3 left, down, here;
+
+        const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION);
+        const VertexElement* texelem0 = decl->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
+        const VertexElement* texelem1 = decl->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
+        float* pSysPos = mPositionBuffer;
+
+        unsigned char* pBase = static_cast<unsigned char*>(mMainBuffer->lock(HardwareBuffer::HBL_DISCARD));
+
+        for ( int j = startz; j < endz; j++ )
+        {
+            for ( int i = startx; i < endx; i++ )
+            {
+                float *pPos, *pTex0, *pTex1;
+                poselem->baseVertexPointerToElement(pBase, &pPos);
+                texelem0->baseVertexPointerToElement(pBase, &pTex0);
+                texelem1->baseVertexPointerToElement(pBase, &pTex1);
+    
+                Real height = pageHeightData[j * mOptions->pageSize + i];
+                height = height * mOptions->scale.y; // scale height 
+
+                *pSysPos++ = *pPos++ = ( float ) i * mOptions->scale.x; //x
+                *pSysPos++ = *pPos++ = height; // y
+                *pSysPos++ = *pPos++ = ( float ) j * mOptions->scale.z; //z
+
+                *pTex0++ = ( float ) i / ( float ) ( mOptions->pageSize - 1 );
+                *pTex0++ = ( float ) j / ( float ) ( mOptions->pageSize - 1 );
+
+                *pTex1++ = ( ( float ) i / ( float ) ( mOptions->tileSize - 1 ) ) * mOptions->detailTile;
+                *pTex1++ = ( ( float ) j / ( float ) ( mOptions->tileSize - 1 ) ) * mOptions->detailTile;
+
+                if ( height < min )
+                    min = ( Real ) height;
+
+                if ( height > max )
+                    max = ( Real ) height;
+
+                pBase += mMainBuffer->getVertexSize();
+            }
+        }
+
+        mMainBuffer->unlock();
+
+        mBounds.setExtents( 
+            ( Real ) startx * mOptions->scale.x, 
+            min, 
+            ( Real ) startz * mOptions->scale.z,
+            ( Real ) ( endx - 1 ) * mOptions->scale.x, 
+            max, 
+            ( Real ) ( endz - 1 ) * mOptions->scale.z );
+
+
+        mCenter = Vector3( ( startx * mOptions->scale.x + (endx - 1) * mOptions->scale.x ) / 2,
+            ( min + max ) / 2,
+            ( startz * mOptions->scale.z + (endz - 1) * mOptions->scale.z ) / 2 );
+
+        mBoundingRadius =
+            std::max(max - min,
+                std::max((endx - 1 - startx) * mOptions->scale.x,
+                         (endz - 1 - startz) * mOptions->scale.z)) / 2;
+
+        // Create delta buffer list if required to morph
+        if (mOptions->lodMorph)
+        {
+            // Create delta buffer for all except the lowest mip
+            mDeltaBuffers = new HardwareVertexBufferSharedPtr[mOptions->maxGeoMipMapLevel - 1];
+        }
+
+        Real C = _calculateCFactor();
+
+        _calculateMinLevelDist2( C );
+
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_getNormalAt( float x, float z, Vector3 * result )
+    {
+
+        assert(mOptions->lit && "No normals present");
+
+        Vector3 here, left, down;
+        here.x = x;
+        here.y = getHeightAt( x, z );
+        here.z = z;
+
+        left.x = x - 1;
+        left.y = getHeightAt( x - 1, z );
+        left.z = z;
+
+        down.x = x;
+        down.y = getHeightAt( x, z + 1 );
+        down.z = z + 1;
+
+        left = left - here;
+
+        down = down - here;
+
+        left.normalise();
+        down.normalise();
+
+        *result = left.crossProduct( down );
+        result -> normalise();
+
+        // result->x = - result->x;
+        // result->y = - result->y;
+        // result->z = - result->z;
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_calculateNormals()
+    {
+
+        Vector3 norm;
+
+        assert (mOptions->lit && "No normals present");
+
+        HardwareVertexBufferSharedPtr vbuf = 
+            mTerrain->vertexBufferBinding->getBuffer(MAIN_BINDING);
+        const VertexElement* elem = mTerrain->vertexDeclaration->findElementBySemantic(VES_NORMAL);
+        unsigned char* pBase = static_cast<unsigned char*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) );
+        float* pNorm;
+
+        for ( size_t j = 0; j < mOptions->tileSize; j++ )
+        {
+            for ( size_t i = 0; i < mOptions->tileSize; i++ )
+            {
+
+                _getNormalAt( _vertex( i, j, 0 ), _vertex( i, j, 2 ), &norm );
+
+                //  printf( "Normal = %5f,%5f,%5f\n", norm.x, norm.y, norm.z );
+                elem->baseVertexPointerToElement(pBase, &pNorm);
+                *pNorm++ = norm.x;
+                *pNorm++ = norm.y;
+                *pNorm++ = norm.z;
+                pBase += vbuf->getVertexSize();
+            }
+
+        }
+        vbuf->unlock();
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_notifyCurrentCamera( Camera* cam )
+    {
+		MovableObject::_notifyCurrentCamera(cam);
+
+        if ( mForcedRenderLevel >= 0 )
+        {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            mRenderLevel[msCurrentRenderLevelIndex] = mForcedRenderLevel;
+#else
+			mRenderLevel = mForcedRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+            return ;
+        }
+
+
+        Vector3 cpos = cam -> getDerivedPosition();
+        const AxisAlignedBox& aabb = getWorldBoundingBox(true);
+        Vector3 diff(0, 0, 0);
+        diff.makeFloor(cpos - aabb.getMinimum());
+        diff.makeCeil(cpos - aabb.getMaximum());
+
+        Real L = diff.squaredLength();
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        mRenderLevel[msCurrentRenderLevelIndex] = -1;;
+#else
+		mRenderLevel = -1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+
+        for ( int i = 0; i < mOptions->maxGeoMipMapLevel; i++ )
+        {
+            if ( mMinLevelDistSqr[ i ] > L )
+            {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+                mRenderLevel[msCurrentRenderLevelIndex] = i - 1;
+#else
+				mRenderLevel = i - 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+                break;
+            }
+        }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        if ( getRenderLevel() < 0 )
+            mRenderLevel[msCurrentRenderLevelIndex] = mOptions->maxGeoMipMapLevel - 1;
+#else
+		if ( mRenderLevel < 0 )
+            mRenderLevel = mOptions->maxGeoMipMapLevel - 1;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        if (mOptions->lodMorph)
+        {
+            // Get the next LOD level down
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            int nextLevel = mNextLevelDown[getRenderLevel()];
+#else
+			int nextLevel = mNextLevelDown[mRenderLevel];
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+            if (nextLevel == 0)
+            {
+                // No next level, so never morph
+                mLODMorphFactor = 0;
+            }
+            else
+            {
+                // Set the morph such that the morph happens in the last 0.25 of
+                // the distance range
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+				Real range = mMinLevelDistSqr[nextLevel] - mMinLevelDistSqr[getRenderLevel()];
+#else
+                Real range = mMinLevelDistSqr[nextLevel] - mMinLevelDistSqr[mRenderLevel];
+#endif // GTP_VISIBILITY_MODIFIED_OGRE   
+                if (range)
+                {
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+					Real percent = (L - mMinLevelDistSqr[getRenderLevel()]) / range;
+#else
+                    Real percent = (L - mMinLevelDistSqr[mRenderLevel]) / range;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+                    // scale result so that msLODMorphStart == 0, 1 == 1, clamp to 0 below that
+                    Real rescale = 1.0f / (1.0f - mOptions->lodMorphStart);
+                    mLODMorphFactor = std::max((percent - mOptions->lodMorphStart) * rescale, 
+						static_cast<Real>(0.0));
+                }
+                else
+                {
+                    // Identical ranges
+                    mLODMorphFactor = 0.0f;
+                }
+
+                assert(mLODMorphFactor >= 0 && mLODMorphFactor <= 1);
+            }
+
+            // Bind the correct delta buffer if it has changed
+            // nextLevel - 1 since the first entry is for LOD 1 (since LOD 0 never needs it)
+            if (mLastNextLevel != nextLevel)
+            {
+                if (nextLevel > 0)
+                {
+                    mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, 
+                        mDeltaBuffers[nextLevel - 1]);
+                }
+                else
+                {
+                    // bind dummy (incase bindings checked)
+                    mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, 
+                        mDeltaBuffers[0]);
+                }
+            }
+            mLastNextLevel = nextLevel;
+
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::_updateRenderQueue( RenderQueue* queue )
+    {
+        // Notify need to calculate light list when our sending to render queue
+        mLightListDirty = true;
+
+        queue->addRenderable( this );
+    }
+    //-----------------------------------------------------------------------
+    void TerrainRenderable::getRenderOperation( RenderOperation& op )
+    {
+        //setup indexes for vertices and uvs...
+
+        assert( mInit && "Uninitialized" );
+
+        op.useIndexes = true;
+        op.operationType = mOptions->useTriStrips ? 
+            RenderOperation::OT_TRIANGLE_STRIP : RenderOperation::OT_TRIANGLE_LIST;
+        op.vertexData = mTerrain;
+        op.indexData = getIndexData();
+
+
+    }
+    //-----------------------------------------------------------------------
+    void 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 < mOptions->maxGeoMipMapLevel; level++ )
+        {
+            mMinLevelDistSqr[ level ] = 0;
+
+            int step = 1 << level;
+            // The step of the next higher LOD
+            int higherstep = step >> 1;
+
+            float* pDeltas = 0;
+            if (mOptions->lodMorph)
+            {
+                // Create a set of delta values (store at index - 1 since 0 has none)
+                mDeltaBuffers[level - 1]  = createDeltaBuffer();
+                // Lock, but don't discard (we want the pre-initialised zeros)
+                pDeltas = static_cast<float*>(
+                    mDeltaBuffers[level - 1]->lock(HardwareBuffer::HBL_NORMAL));
+            }
+
+            for ( j = 0; j < mOptions->tileSize - step; j += step )
+            {
+                for ( i = 0; i < mOptions->tileSize - step; i += step )
+                {
+                    /* Form planes relating to the lower detail tris to be produced
+                    For tri lists and even tri strip rows, they are this shape:
+                    x---x
+                    | / |
+                    x---x
+                    For odd tri strip rows, they are this shape:
+                    x---x
+                    | \ |
+                    x---x
+                    */
+
+                    Vector3 v1(_vertex( i, j, 0 ), _vertex( i, j, 1 ), _vertex( i, j, 2 ));
+                    Vector3 v2(_vertex( i + step, j, 0 ), _vertex( i + step, j, 1 ), _vertex( i + step, j, 2 ));
+                    Vector3 v3(_vertex( i, j + step, 0 ), _vertex( i, j + step, 1 ), _vertex( i, j + step, 2 ));
+                    Vector3 v4(_vertex( i + step, j + step, 0 ), _vertex( i + step, j + step, 1 ), _vertex( i + step, j + step, 2 ));
+
+                    Plane t1, t2;
+                    bool backwardTri = false;
+                    if (!mOptions->useTriStrips || j % 2 == 0)
+                    {
+                        t1.redefine(v1, v3, v2);
+                        t2.redefine(v2, v3, v4);
+                    }
+                    else
+                    {
+                        t1.redefine(v1, v3, v4);
+                        t2.redefine(v1, v4, v2);
+                        backwardTri = true;
+                    }
+
+                    // include the bottommost row of vertices if this is the last row
+                    int zubound = (j == (mOptions->tileSize - step)? step : step - 1);
+                    for ( int z = 0; z <= zubound; z++ )
+                    {
+                        // include the rightmost col of vertices if this is the last col
+                        int xubound = (i == (mOptions->tileSize - step)? step : step - 1);
+                        for ( int x = 0; x <= xubound; x++ )
+                        {
+                            int fulldetailx = i + x;
+                            int fulldetailz = j + z;
+                            if ( fulldetailx % step == 0 && 
+                                fulldetailz % step == 0 )
+                            {
+                                // Skip, this one is a vertex at this level
+                                continue;
+                            }
+
+                            Real zpct = (Real)z / (Real)step;
+                            Real xpct = (Real)x / (Real)step;
+
+                            //interpolated height
+                            Vector3 actualPos(
+                                _vertex( fulldetailx, fulldetailz, 0 ), 
+                                _vertex( fulldetailx, fulldetailz, 1 ), 
+                                _vertex( fulldetailx, fulldetailz, 2 ));
+                            Real interp_h;
+                            // Determine which tri we're on 
+                            if ((xpct + zpct <= 1.0f && !backwardTri) ||
+                                (xpct + (1-zpct) <= 1.0f && backwardTri))
+                            {
+                                // Solve for x/z
+                                interp_h = 
+                                    (-(t1.normal.x * actualPos.x)
+                                    - t1.normal.z * actualPos.z
+                                    - t1.d) / t1.normal.y;
+                            }
+                            else
+                            {
+                                // Second tri
+                                interp_h = 
+                                    (-(t2.normal.x * actualPos.x)
+                                    - t2.normal.z * actualPos.z
+                                    - t2.d) / t2.normal.y;
+                            }
+
+                            Real actual_h = _vertex( fulldetailx, fulldetailz, 1 );
+                            Real delta = fabs( interp_h - actual_h );
+
+                            Real D2 = delta * delta * C * C;
+
+                            if ( mMinLevelDistSqr[ level ] < D2 )
+                                mMinLevelDistSqr[ level ] = D2;
+
+                            // Should be save height difference?
+                            // Don't morph along edges
+                            if (mOptions->lodMorph && 
+                                fulldetailx != 0  && fulldetailx != (mOptions->tileSize - 1) && 
+                                fulldetailz != 0  && fulldetailz != (mOptions->tileSize - 1) )
+                            {
+                                // Save height difference 
+                                pDeltas[fulldetailx + (fulldetailz * mOptions->tileSize)] = 
+                                    interp_h - actual_h;
+                            }
+
+                        }
+
+                    }
+                }
+            }
+
+            // Unlock morph deltas if required
+            if (mOptions->lodMorph)
+            {
+                mDeltaBuffers[level - 1]->unlock();
+            }
+        }
+
+
+
+        // Post validate the whole set
+        for ( i = 1; i < mOptions->maxGeoMipMapLevel; i++ )
+        {
+
+            // Make sure no LOD transition within the tile
+            // This is especially a problem when using large tiles with flat areas
+            /* Hmm, this can look bad on some areas, disable for now
+            Vector3 delta(_vertex(0,0,0), mCenter.y, _vertex(0,0,2));
+            delta = delta - mCenter;
+            Real minDist = delta.squaredLength();
+            mMinLevelDistSqr[ i ] = std::max(mMinLevelDistSqr[ i ], minDist);
+            */
+
+            //make sure the levels are increasing...
+            if ( mMinLevelDistSqr[ i ] < mMinLevelDistSqr[ i - 1 ] )
+            {
+                mMinLevelDistSqr[ i ] = mMinLevelDistSqr[ i - 1 ];
+            }
+        }
+
+        // Now reverse traverse the list setting the 'next level down'
+        Real lastDist = -1;
+        int lastIndex = 0;
+        for (i = mOptions->maxGeoMipMapLevel - 1; i >= 0; --i)
+        {
+            if (i == mOptions->maxGeoMipMapLevel - 1)
+            {
+                // Last one is always 0
+                lastIndex = i;
+                lastDist = mMinLevelDistSqr[i];
+                mNextLevelDown[i] = 0;
+            }
+            else
+            {
+                mNextLevelDown[i] = lastIndex;
+                if (mMinLevelDistSqr[i] != lastDist)
+                {
+                    lastIndex = i;
+                    lastDist = mMinLevelDistSqr[i];
+                }
+            }
+
+        }
+
+
+    }
+    //-----------------------------------------------------------------------
+    void 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;
+
+        if (!mOptions->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 = mOptions->primaryCamera->getViewport()->getActualHeight();
+
+        T = 2 * ( Real ) mOptions->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( mOptions->tileSize - 1, mOptions->tileSize - 1, 0 );
+        end.y = _vertex( mOptions->tileSize - 1, mOptions->tileSize - 1, 1 );
+        end.z = _vertex( mOptions->tileSize - 1, mOptions->tileSize - 1, 2 );
+
+        /* Safety catch, if the point asked for is outside
+        * of this tile, it will ask the appropriate tile
+        */
+
+        if ( x < start.x )
+        {
+            if ( mNeighbors[ WEST ] != 0 )
+                return mNeighbors[ WEST ] ->getHeightAt( x, z );
+            else
+                x = start.x;
+        }
+
+        if ( x > end.x )
+        {
+            if ( mNeighbors[ EAST ] != 0 )
+                return mNeighbors[ EAST ] ->getHeightAt( x, z );
+            else
+                x = end.x;
+        }
+
+        if ( z < start.z )
+        {
+            if ( mNeighbors[ NORTH ] != 0 )
+                return mNeighbors[ NORTH ] ->getHeightAt( x, z );
+            else
+                z = start.z;
+        }
+
+        if ( z > end.z )
+        {
+            if ( mNeighbors[ SOUTH ] != 0 )
+                return mNeighbors[ SOUTH ] ->getHeightAt( x, z );
+            else
+                z = end.z;
+        }
+
+
+
+        float x_pct = ( x - start.x ) / ( end.x - start.x );
+        float z_pct = ( z - start.z ) / ( end.z - start.z );
+
+        float x_pt = x_pct * ( float ) ( mOptions->tileSize - 1 );
+        float z_pt = z_pct * ( float ) ( mOptions->tileSize - 1 );
+
+        int x_index = ( int ) x_pt;
+        int z_index = ( int ) z_pt;
+
+        // If we got to the far right / bottom edge, move one back
+        if (x_index == mOptions->tileSize - 1)
+        {
+            --x_index;
+            x_pct = 1.0f;
+        }
+        else
+        {
+            // get remainder
+            x_pct = x_pt - x_index;
+        }
+        if (z_index == mOptions->tileSize - 1)
+        {
+            --z_index;
+            z_pct = 1.0f;
+        }
+        else
+        {
+            z_pct = z_pt - z_index;
+        }
+
+        //bilinear interpolate to find the height.
+
+        float t1 = _vertex( x_index, z_index, 1 );
+        float t2 = _vertex( x_index + 1, z_index, 1 );
+        float b1 = _vertex( x_index, z_index + 1, 1 );
+        float b2 = _vertex( x_index + 1, z_index + 1, 1 );
+
+        float midpoint = (b1 + t2) / 2.0;
+
+        if (x_pct + z_pct <= 1) {
+            b2 = midpoint + (midpoint - t1);
+        } else {
+            t1 = midpoint + (midpoint - b2);
+        }
+
+        float t = ( t1 * ( 1 - x_pct ) ) + ( t2 * ( x_pct ) );
+        float b = ( b1 * ( 1 - x_pct ) ) + ( b2 * ( x_pct ) );
+
+        float h = ( t * ( 1 - z_pct ) ) + ( b * ( z_pct ) );
+
+        return h;
+    }
+    //-----------------------------------------------------------------------
+    bool 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 < mOptions->tileSize; i++ )
+        {
+            for ( size_t j = 0; j < mOptions->tileSize; j++ )
+            {
+                //  printf( "Checking %f,%f,%f ", pt.x, pt.y, pt.z );
+                pt.x = _vertex( i, j, 0 );
+                pt.y = _vertex( i, j, 1 );
+                pt.z = _vertex( i, j, 2 );
+
+                light = sun - pt;
+
+                light.normalise();
+
+                if ( ! intersectSegment( pt, sun, 0 ) )
+                {
+                    //
+                    _getNormalAt( _vertex( i, j, 0 ), _vertex( i, j, 2 ), &normal );
+
+                    float l = light.dotProduct( normal );
+
+                    ColourValue v;
+                    v.r = ambient.r + l;
+                    v.g = ambient.g + l;
+                    v.b = ambient.b + l;
+
+                    if ( v.r > 1 ) v.r = 1;
+
+                    if ( v.g > 1 ) v.g = 1;
+
+                    if ( v.b > 1 ) v.b = 1;
+
+                    if ( v.r < 0 ) v.r = 0;
+
+                    if ( v.g < 0 ) v.g = 0;
+
+                    if ( v.b < 0 ) v.b = 0;
+
+                    RGBA colour;
+                    Root::getSingleton().convertColourValue( v, &colour );
+                    vbuf->writeData(
+                        (_index( i, j ) * vbuf->getVertexSize()) + elem->getOffset(),
+                        sizeof(RGBA), &colour);
+                }
+
+                else
+                {
+                    RGBA colour;
+                    Root::getSingleton().convertColourValue( ambient, &colour );
+
+                    vbuf->writeData(
+                        (_index( i, j ) * vbuf->getVertexSize()) + elem->getOffset(), 
+                        sizeof(RGBA), &colour);
+                }
+
+            }
+
+        }
+
+        printf( "." );
+    }
+    //-----------------------------------------------------------------------
+    Real 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
+    {
+        if (mLightListDirty)
+        {
+            getParentSceneNode()->getCreator()->_populateLightList(
+                mCenter, this->getBoundingRadius(), mLightList);
+            mLightListDirty = false;
+        }
+        return mLightList;
+    }
+    //-----------------------------------------------------------------------
+    IndexData* TerrainRenderable::getIndexData(void)
+    {
+        unsigned int stitchFlags = 0;
+
+        if ( mNeighbors[ EAST ] != 0 && mNeighbors[ EAST ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_EAST;
+            stitchFlags |= 
+                (mNeighbors[ EAST ] -> mRenderLevel - mRenderLevel) << STITCH_EAST_SHIFT;
+        }
+
+        if ( mNeighbors[ WEST ] != 0 && mNeighbors[ WEST ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_WEST;
+            stitchFlags |= 
+                (mNeighbors[ WEST ] -> mRenderLevel - mRenderLevel) << STITCH_WEST_SHIFT;
+        }
+
+        if ( mNeighbors[ NORTH ] != 0 && mNeighbors[ NORTH ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_NORTH;
+            stitchFlags |= 
+                (mNeighbors[ NORTH ] -> mRenderLevel - mRenderLevel) << STITCH_NORTH_SHIFT;
+        }
+
+        if ( mNeighbors[ SOUTH ] != 0 && mNeighbors[ SOUTH ] -> mRenderLevel > mRenderLevel )
+        {
+            stitchFlags |= STITCH_SOUTH;
+            stitchFlags |= 
+                (mNeighbors[ SOUTH ] -> mRenderLevel - mRenderLevel) << STITCH_SOUTH_SHIFT;
+        }
+
+        // Check preexisting
+		LevelArray& levelIndex = mSceneManager->_getLevelIndex();
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		IndexMap::iterator ii = levelIndex[ getRenderLevel() ]->find( stitchFlags );
+#else
+        IndexMap::iterator ii = levelIndex[ mRenderLevel ]->find( stitchFlags );
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        IndexData* indexData;
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		if ( ii == levelIndex[ getRenderLevel() ]->end())
+#else
+		if ( ii == levelIndex[ mRenderLevel ]->end())
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        {
+            // Create
+            if (mOptions->useTriStrips)
+            {
+                indexData = generateTriStripIndexes(stitchFlags);
+            }
+            else
+            {
+                indexData = generateTriListIndexes(stitchFlags);
+            }
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            levelIndex[ getRenderLevel() ]->insert(
+                IndexMap::value_type(stitchFlags, indexData));
+#else
+            levelIndex[ mRenderLevel ]->insert(
+                IndexMap::value_type(stitchFlags, indexData));
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        else
+        {
+            indexData = ii->second;
+        }
+
+
+        return indexData;
+
+
+    }
+    //-----------------------------------------------------------------------
+    IndexData* TerrainRenderable::generateTriStripIndexes(unsigned int stitchFlags)
+    {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+        // The step used for the current level
+        int step = 1 << getRenderLevel();
+        // The step used for the lower level
+        int lowstep = 1 << (getRenderLevel() + 1);
+#else
+        // The step used for the current level
+        int step = 1 << mRenderLevel;
+        // The step used for the lower level
+        int lowstep = 1 << (mRenderLevel + 1);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+        int numIndexes = 0;
+
+        // Calculate the number of indexes required
+        // This is the number of 'cells' at this detail level x 2
+        // plus 3 degenerates to turn corners
+        int numTrisAcross = (((mOptions->tileSize-1) / step) * 2) + 3;
+        // Num indexes is number of tris + 2
+        int new_length = numTrisAcross * ((mOptions->tileSize-1) / step) + 2;
+        //this is the maximum for a level.  It wastes a little, but shouldn't be a problem.
+
+        IndexData* indexData = new IndexData;
+        indexData->indexBuffer = 
+            HardwareBufferManager::getSingleton().createIndexBuffer(
+            HardwareIndexBuffer::IT_16BIT,
+            new_length, HardwareBuffer::HBU_STATIC_WRITE_ONLY);//, false);
+
+        mSceneManager->_getIndexCache().mCache.push_back( indexData );
+
+        unsigned short* pIdx = static_cast<unsigned short*>(
+            indexData->indexBuffer->lock(0, 
+            indexData->indexBuffer->getSizeInBytes(), 
+            HardwareBuffer::HBL_DISCARD));
+
+        // Stripified mesh
+        for ( int j = 0; j < mOptions->tileSize - 1; j += step )
+        {
+            int i;
+            // Forward strip
+            // We just do the |/ here, final | done after
+            for ( i = 0; i < mOptions->tileSize - 1; i += step )
+            {
+                int x[4], y[4];
+                x[0] = x[1] = i;
+                x[2] = x[3] = i + step;
+                y[0] = y[2] = j;
+                y[1] = y[3] = j + step;
+
+                if (j == 0  && (stitchFlags & STITCH_NORTH))
+                {
+                    // North reduction means rounding x[0] and x[2]
+                    if (x[0] % lowstep != 0)
+                    {
+                        // Since we know we only drop down one level of LOD,
+                        // removing 1 step of higher LOD should return to lower
+                        x[0] -= step;
+                    }
+                    if (x[2] % lowstep != 0)
+                    {
+                        x[2] -= step;
+                    }
+                }
+
+                // Never get a south tiling on a forward strip (always finish on 
+                // a backward strip)
+
+                if (i == 0  && (stitchFlags & STITCH_WEST))
+                {
+                    // West reduction means rounding y[0] / y[1]
+                    if (y[0] % lowstep != 0)
+                    {
+                        y[0] -= step;
+                    }
+                    if (y[1] % lowstep != 0)
+                    {
+                        y[1] -= step;
+                    }
+                }
+                if (i == (mOptions->tileSize - 1 - step) && (stitchFlags & STITCH_EAST))
+                {
+                    // East tiling means rounding y[2] & y[3]
+                    if (y[2] % lowstep != 0)
+                    {
+                        y[2] -= step;
+                    }
+                    if (y[3] % lowstep != 0)
+                    {
+                        y[3] -= step;
+                    }
+                }
+
+                //triangles
+                if (i == 0)
+                {
+                    // Starter
+                    *pIdx++ = _index( x[0], y[0] ); numIndexes++;
+                }
+                *pIdx++ = _index( x[1], y[1] ); numIndexes++;
+                *pIdx++ = _index( x[2], y[2] ); numIndexes++;
+
+                if (i == mOptions->tileSize - 1 - step)
+                {
+                    // Emit extra index to finish row
+                    *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    if (j < mOptions->tileSize - 1 - step)
+                    {
+                        // Emit this index twice more (this is to turn around without
+                        // artefacts)
+                        // ** Hmm, looks like we can drop this and it's unnoticeable
+                        //*pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                        //*pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    }
+                }
+
+            }
+            // Increment row
+            j += step;
+            // Backward strip
+            for ( i = mOptions->tileSize - 1; i > 0 ; i -= step )
+            {
+                int x[4], y[4];
+                x[0] = x[1] = i;
+                x[2] = x[3] = i - step;
+                y[0] = y[2] = j;
+                y[1] = y[3] = j + step;
+
+                // Never get a north tiling on a backward strip (always
+                // start on a forward strip)
+                if (j == (mOptions->tileSize - 1 - step) && (stitchFlags & STITCH_SOUTH))
+                {
+                    // South reduction means rounding x[1] / x[3]
+                    if (x[1] % lowstep != 0)
+                    {
+                        x[1] -= step;
+                    }
+                    if (x[3] % lowstep != 0)
+                    {
+                        x[3] -= step;
+                    }
+                }
+
+                if (i == step  && (stitchFlags & STITCH_WEST))
+                {
+                    // West tiling on backward strip is rounding of y[2] / y[3]
+                    if (y[2] % lowstep != 0)
+                    {
+                        y[2] -= step;
+                    }
+                    if (y[3] % lowstep != 0)
+                    {
+                        y[3] -= step;
+                    }
+                }
+                if (i == mOptions->tileSize - 1 && (stitchFlags & STITCH_EAST))
+                {
+                    // East tiling means rounding y[0] and y[1] on backward strip
+                    if (y[0] % lowstep != 0)
+                    {
+                        y[0] -= step;
+                    }
+                    if (y[1] % lowstep != 0)
+                    {
+                        y[1] -= step;
+                    }
+                }
+
+                //triangles
+                if (i == mOptions->tileSize)
+                {
+                    // Starter
+                    *pIdx++ = _index( x[0], y[0] ); numIndexes++;
+                }
+                *pIdx++ = _index( x[1], y[1] ); numIndexes++;
+                *pIdx++ = _index( x[2], y[2] ); numIndexes++;
+
+                if (i == step)
+                {
+                    // Emit extra index to finish row
+                    *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    if (j < mOptions->tileSize - 1 - step)
+                    {
+                        // Emit this index once more (this is to turn around)
+                        *pIdx++ = _index( x[3], y[3] ); numIndexes++;
+                    }
+                }
+            }
+        }
+
+
+        indexData->indexBuffer->unlock();
+        indexData->indexCount = numIndexes;
+        indexData->indexStart = 0;
+
+        return indexData;
+
+    }
+    //-----------------------------------------------------------------------
+    IndexData* TerrainRenderable::generateTriListIndexes(unsigned int stitchFlags)
+    {
+
+        int numIndexes = 0;
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+		int step = 1 << getRenderLevel();
+#else
+        int step = 1 << mRenderLevel;
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        IndexData* indexData = 0;
+
+        int north = stitchFlags & STITCH_NORTH ? step : 0;
+        int south = stitchFlags & STITCH_SOUTH ? step : 0;
+        int east = stitchFlags & STITCH_EAST ? step : 0;
+        int west = stitchFlags & STITCH_WEST ? step : 0;
+
+        int new_length = ( mOptions->tileSize / step ) * ( mOptions->tileSize / step ) * 2 * 2 * 2 ;
+        //this is the maximum for a level.  It wastes a little, but shouldn't be a problem.
+
+        indexData = new IndexData;
+        indexData->indexBuffer = 
+            HardwareBufferManager::getSingleton().createIndexBuffer(
+            HardwareIndexBuffer::IT_16BIT,
+            new_length, HardwareBuffer::HBU_STATIC_WRITE_ONLY);//, false);
+
+        mSceneManager->_getIndexCache().mCache.push_back( indexData );
+
+        unsigned short* pIdx = static_cast<unsigned short*>(
+            indexData->indexBuffer->lock(0, 
+            indexData->indexBuffer->getSizeInBytes(), 
+            HardwareBuffer::HBL_DISCARD));
+
+        // Do the core vertices, minus stitches
+        for ( int j = north; j < mOptions->tileSize - 1 - south; j += step )
+        {
+            for ( int i = west; i < mOptions->tileSize - 1 - east; i += step )
+            {
+                //triangles
+                *pIdx++ = _index( i, j ); numIndexes++;
+                *pIdx++ = _index( i, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j ); numIndexes++;
+
+                *pIdx++ = _index( i, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j + step ); numIndexes++;
+                *pIdx++ = _index( i + step, j ); numIndexes++;
+            }
+        }
+
+        // North stitching
+        if ( north > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(NORTH, getRenderLevel(), mNeighbors[NORTH]->getRenderLevel(),
+                west > 0, east > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(NORTH, mRenderLevel, mNeighbors[NORTH]->mRenderLevel,
+                west > 0, east > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        // East stitching
+        if ( east > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(EAST, getRenderLevel(), mNeighbors[EAST]->getRenderLevel(),
+                north > 0, south > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(EAST, mRenderLevel, mNeighbors[EAST]->mRenderLevel,
+                north > 0, south > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+        // South stitching
+        if ( south > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(SOUTH, getRenderLevel(), mNeighbors[SOUTH]->getRenderLevel(),
+                east > 0, west > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(SOUTH, mRenderLevel, mNeighbors[SOUTH]->mRenderLevel,
+                east > 0, west > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+		}
+        // West stitching
+        if ( west > 0 )
+        {
+/*** msz: added for v1-2-0 compatibility ***/
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+            numIndexes += stitchEdge(WEST, getRenderLevel(), mNeighbors[WEST]->getRenderLevel(),
+                south > 0, north > 0, &pIdx);
+#else
+			numIndexes += stitchEdge(WEST, mRenderLevel, mNeighbors[WEST]->mRenderLevel,
+                south > 0, north > 0, &pIdx);
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+        }
+
+
+        indexData->indexBuffer->unlock();
+        indexData->indexCount = numIndexes;
+        indexData->indexStart = 0;
+
+        return indexData;
+    }
+    //-----------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr TerrainRenderable::createDeltaBuffer(void)
+    {
+        // Delta buffer is a 1D float buffer of height offsets
+        HardwareVertexBufferSharedPtr buf = 
+            HardwareBufferManager::getSingleton().createVertexBuffer(
+            VertexElement::getTypeSize(VET_FLOAT1), 
+            mOptions->tileSize * mOptions->tileSize,
+            HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+        // Fill the buffer with zeros, we will only fill in delta
+        void* pVoid = buf->lock(HardwareBuffer::HBL_DISCARD);
+        memset(pVoid, 0, mOptions->tileSize * mOptions->tileSize * sizeof(float));
+        buf->unlock();
+
+        return buf;
+
+    }
+    //-----------------------------------------------------------------------
+    void 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 = mOptions->tileSize - 1;
+            rowstep = step;
+            horizontal = true;
+            break;
+        case SOUTH:
+            // invert x AND y direction, helps to keep same winding
+            startx = starty = mOptions->tileSize - 1;
+            endx = 0;
+            rowstep = -step;
+            step = -step;
+            superstep = -superstep;
+            halfsuperstep = -halfsuperstep;
+            horizontal = true;
+            break;
+        case EAST:
+            startx = 0;
+            endx = mOptions->tileSize - 1;
+            starty = mOptions->tileSize - 1;
+            rowstep = -step;
+            horizontal = false;
+            break;
+        case WEST:
+            startx = mOptions->tileSize - 1;
+            endx = 0;
+            starty = 0;
+            rowstep = step;
+            step = -step;
+            superstep = -superstep;
+            halfsuperstep = -halfsuperstep;
+            horizontal = false;
+            break;
+        };
+
+        int numIndexes = 0;
+
+        for ( int j = startx; j != endx; j += superstep )
+        {
+            int k;
+            for (k = 0; k != halfsuperstep; k += step)
+            {
+                int jk = j + k;
+                //skip the first bit of the corner?
+                if ( j != startx || k != 0 || !omitFirstTri )
+                {
+                    if (horizontal)
+                    {
+                        *pIdx++ = _index( j , starty ); numIndexes++;
+                        *pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
+                        *pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
+                    }
+                    else
+                    {
+                        *pIdx++ = _index( starty, j ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk + step); numIndexes++;
+                    }
+                }
+            }
+
+            // Middle tri
+            if (horizontal)
+            {
+                *pIdx++ = _index( j, starty ); numIndexes++;
+                *pIdx++ = _index( j + halfsuperstep, starty + rowstep); numIndexes++;
+                *pIdx++ = _index( j + superstep, starty ); numIndexes++;
+            }
+            else
+            {
+                *pIdx++ = _index( starty, j ); numIndexes++;
+                *pIdx++ = _index( starty + rowstep, j + halfsuperstep ); numIndexes++;
+                *pIdx++ = _index( starty, j + superstep ); numIndexes++;
+            }
+
+            for (k = halfsuperstep; k != superstep; k += step)
+            {
+                int jk = j + k;
+                if ( j != endx - superstep || k != superstep - step || !omitLastTri )
+                {
+                    if (horizontal)
+                    {
+                        *pIdx++ = _index( j + superstep, starty ); numIndexes++;
+                        *pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
+                        *pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
+                    }
+                    else
+                    {
+                        *pIdx++ = _index( starty, j + superstep ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
+                        *pIdx++ = _index( starty + rowstep, jk + step ); numIndexes++;
+                    }
+                }
+            }
+        }
+
+        *ppIdx = pIdx;
+
+        return numIndexes;
+
+    }
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	//-----------------------------------------------------------------------
+	void 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/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeSceneManager.cpp
===================================================================
--- OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 921)
+++ OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeSceneManager.cpp	(revision 921)
@@ -0,0 +1,1287 @@
+/*
+-----------------------------------------------------------------------------
+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(const String& name) : SceneManager(name)
+{
+    AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
+    int depth = 8; 
+    mOctree = 0;
+    init( b, depth );
+}
+
+OctreeSceneManager::OctreeSceneManager(const String& name, AxisAlignedBox &box, int max_depth ) 
+: SceneManager(name)
+{
+    mOctree = 0;
+    init( box, max_depth );
+}
+
+const String& OctreeSceneManager::getTypeName(void) const
+{
+	return OctreeSceneManagerFactory::FACTORY_TYPE_NAME;
+}
+
+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 )
+{
+    // 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",
+            "OctreeSceneManager::createSceneNode" );
+    }
+    OctreeNode * on = new OctreeNode( this, name );
+    mSceneNodes[ on->getName() ] = on;
+    return on;
+}
+
+void OctreeSceneManager::_updateSceneGraph( Camera * cam )
+{
+    SceneManager::_updateSceneGraph( cam );
+}
+
+void OctreeSceneManager::_alertVisibleObjects( void )
+{
+    OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
+        "Function doesn't do as advertised",
+        "OctreeSceneManager::_alertVisibleObjects" );
+
+    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 = c;
+    }
+
+    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;
+        }
+
+        Octree* child;
+        bool childfoundvisible = (v == OctreeCamera::FULL);
+        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
+
+        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
+            walkOctree( camera, queue, child, childfoundvisible, 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;
+	}
+
+	Octree* child;
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+}
+
+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;
+	}
+
+	Octree* child;
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+}
+
+
+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;
+	}
+
+	Octree* child;
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+}
+
+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;
+	}
+
+	Octree* child;
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+	if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
+		_findNodes( t, list, exclude, full, child );
+
+}
+
+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;
+
+	const Vector3 min = box.getMinimum();
+	const Vector3 max = box.getMaximum();
+	mOctree->mHalfSize = ( max - min ) * 0.5f;
+
+    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);
+
+	RenderQueueGroup *currentGroup = 
+		getRenderQueue()->getQueueGroup(getRenderQueue()->getDefaultQueueGroup());
+	currentGroup->clear(leavePassesInQueue);
+
+	// Add stuff to be rendered
+	NodeList::const_iterator it, it_end = octant->mNodes.end();
+         
+	for (it = octant->mNodes.begin(); it != it_end; ++ it)
+    {
+		OctreeNode *sn = *it;
+
+        ++ mNumObjects;
+
+		// check bounding box visibility of scene nodes
+		if (cam->isVisible(sn->_getWorldAABB()))
+		{
+			sn->_addToRenderQueue(cam, getRenderQueue(), onlyShadowCasters);
+
+			// add to visible objects
+			mVisible.push_back(sn);
+
+			if (mDisplayNodes)
+			{
+				getRenderQueue()->addRenderable(sn);
+			}
+
+			// check if the scene manager or this node wants the bounding box shown.
+			if (sn->getShowBoundingBox() || mShowBoundingBoxes)
+			{
+				sn->_addBoundingBoxToQueue(getRenderQueue());
+			}
+		}
+	}
+
+	if (mShowBoxes)
+	{
+		octant->getWireBoundingBox()->setMaterial("BaseWhiteNoLighting");
+
+		getRenderQueue()->addRenderable(octant->getWireBoundingBox());
+		mBoxes.push_back(octant->getWireBoundingBox());
+	}
+
+	//-- the actual rendering
+	//SceneManager::_renderVisibleObjects();
+	/*** msz: modified for v1-2-0 compatibility. what value for 2nd param?
+	 *** any preparation necessary?? ***/
+	_renderQueueGroupObjects(currentGroup, QueuedRenderableCollection::OM_PASS_GROUP);
+}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+//-----------------------------------------------------------------------
+const String OctreeSceneManagerFactory::FACTORY_TYPE_NAME = "OctreeSceneManager";
+//-----------------------------------------------------------------------
+void OctreeSceneManagerFactory::initMetaData(void) const
+{
+	mMetaData.typeName = FACTORY_TYPE_NAME;
+	mMetaData.description = "Scene manager organising the scene on the basis of an octree.";
+	mMetaData.sceneTypeMask = 0xFFFF; // support all types
+	mMetaData.worldGeometrySupported = false;
+}
+//-----------------------------------------------------------------------
+SceneManager* OctreeSceneManagerFactory::createInstance(
+	const String& instanceName)
+{
+	return new OctreeSceneManager(instanceName);
+}
+//-----------------------------------------------------------------------
+void OctreeSceneManagerFactory::destroyInstance(SceneManager* instance)
+{
+	delete instance;
+}
+
+
+}
