Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 158)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneNode.cpp	(revision 657)
@@ -296,5 +296,6 @@
             {
                 SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
-                sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
+                sceneChild->_findVisibleObjects(cam, queue, includeChildren, 
+					displayNodes, onlyShadowCasters);
             }
         }
@@ -391,7 +392,10 @@
         ChildNodeMap::iterator i, iend;
         iend = mChildren.end();
-        for (i = mChildren.begin(); i != iend; ++i)
+        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());
@@ -482,67 +486,70 @@
         if (vec == Vector3::ZERO) return;
 
-        // Adjust vector so that it is relative to local Z
-        Vector3 zAdjustVec;
-        if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
-        {
-            zAdjustVec = -vec;
-        }
-        else
-        {
-            Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
-            zAdjustVec = localToUnitZ * vec;
-        }
-        zAdjustVec.normalise();
-
+        // 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 (mParent)
+                targetDir = mParent->_getDerivedOrientation() * targetDir;
+            break;
+        case TS_LOCAL:
+            targetDir = _getDerivedOrientation() * targetDir;
+            break;
+        }
+
+        // Calculate target orientation relative to world space
         Quaternion targetOrientation;
         if( mYawFixed )
         {
-            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
+            // Calculate the quaternion for rotate local Z to target direction
+            Vector3 xVec = mYawFixedAxis.crossProduct(targetDir);
             xVec.normalise();
-
-            Vector3 yVec = zAdjustVec.crossProduct( xVec );
+            Vector3 yVec = targetDir.crossProduct(xVec);
             yVec.normalise();
+            Quaternion unitZToTarget = Quaternion(xVec, yVec, targetDir);
             
-            targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
+            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
         {
-
-            // Get axes from current quaternion
-            Vector3 axes[3];
-            _getDerivedOrientation().ToAxes(axes);
-            Quaternion rotQuat;
-            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f)
+                // 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
-                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
-            }
-            else
-            {
+                targetOrientation =
+                    Quaternion(-currentOrient.y, -currentOrient.z, currentOrient.w, currentOrient.x);
+        }
+        else
+        {
                 // Derive shortest arc to new direction
-                rotQuat = axes[2].getRotationTo(zAdjustVec);
-
-            }
-            targetOrientation = rotQuat * mOrientation;
-        }
-
-        if (relativeTo == TS_LOCAL || !mParent)
-        {
+                Quaternion rotQuat = currentDir.getRotationTo(targetDir);
+                targetOrientation = rotQuat * currentOrient;
+            }
+        }
+
+        // Set target orientation, transformed to parent space
+        if (mParent)
+            setOrientation(mParent->_getDerivedOrientation().UnitInverse() * targetOrientation);
+        else
             setOrientation(targetOrientation);
-        }
-        else
-        {
-            if (relativeTo == TS_PARENT)
-            {
-                setOrientation(targetOrientation * mParent->getOrientation().Inverse());
-            }
-            else if (relativeTo == TS_WORLD)
-            {
-                setOrientation(targetOrientation * mParent->_getDerivedOrientation().Inverse());
-            }
-        }
-
-
     }
     //-----------------------------------------------------------------------
@@ -550,6 +557,21 @@
         const Vector3& localDirectionVector)
     {
-        this->setDirection(targetPoint - _getDerivedPosition(), relativeTo, 
-            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);
     }
     //-----------------------------------------------------------------------
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp	(revision 316)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreRenderSystem.cpp	(revision 657)
@@ -40,4 +40,5 @@
 #include "OgreMaterial.h"
 #include "OgreTimer.h"
+#include "OgreHardwareOcclusionQuery.h"
 
 namespace Ogre {
@@ -69,4 +70,6 @@
     {
         shutdown();
+		delete mCapabilities;
+		mCapabilities = 0;
     }
     //-----------------------------------------------------------------------
@@ -324,4 +327,12 @@
     void RenderSystem::shutdown(void)
     {
+		// Remove occlusion queries
+		for (HardwareOcclusionQueryList::iterator i = mHwOcclusionQueries.begin();
+			i != mHwOcclusionQueries.end(); ++i)
+		{
+			delete *i;
+		}
+		mHwOcclusionQueries.clear();
+
         // Remove all the render targets.
 		// (destroy primary target last since others may depend on it)
@@ -416,4 +427,38 @@
         }
     }
+	//-----------------------------------------------------------------------
+	void RenderSystem::addListener(Listener* l)
+	{
+		mEventListeners.push_back(l);
+	}
+	//-----------------------------------------------------------------------
+	void RenderSystem::removeListener(Listener* l)
+	{
+		mEventListeners.remove(l);
+	}
+	//-----------------------------------------------------------------------
+	void RenderSystem::fireEvent(const String& name, const NameValuePairList* params)
+	{
+		for(ListenerList::iterator i = mEventListeners.begin(); 
+			i != mEventListeners.end(); ++i)
+		{
+			(*i)->eventOccurred(name, params);
+		}
+	}
+	//-----------------------------------------------------------------------
+	void RenderSystem::destroyHardwareOcclusionQuery( HardwareOcclusionQuery *hq)
+	{
+		for (HardwareOcclusionQueryList::iterator i = mHwOcclusionQueries.begin();
+			i != mHwOcclusionQueries.end(); ++i)
+		{
+			if (*i == hq)
+			{
+				delete *i;
+				mHwOcclusionQueries.erase(i);
+				break;
+			}
+		}
+	}
+
 }
 
Index: OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp
===================================================================
--- OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 343)
+++ OGRE/trunk/ogre_changes/OgreMain/src/OgreSceneManager.cpp	(revision 657)
@@ -375,5 +375,4 @@
     // Subclasses could do something smarter
     destList.clear();
-    Real squaredRadius = radius * radius;
 
     SceneLightList::iterator i, iend;
@@ -396,5 +395,6 @@
                 // only add in-range lights
                 Real range = lt->getAttenuationRange();
-                if ((lt->tempSquareDist - squaredRadius) <= (range * range))
+                Real maxDist = range + radius;
+                if (lt->tempSquareDist <= Math::Sqr(maxDist))
                 {
                     destList.push_back(lt);
@@ -554,4 +554,8 @@
     mSkyBoxEnabled = mSkyPlaneEnabled = mSkyDomeEnabled = false; 
 
+	// Clear render queue, empty completely
+	if (mRenderQueue)
+		mRenderQueue->clear(true);
+
 }
 //-----------------------------------------------------------------------
@@ -593,7 +597,9 @@
     AutoTrackingSceneNodes::iterator ai, aiend;
     aiend = mAutoTrackingSceneNodes.end();
-    for (ai = mAutoTrackingSceneNodes.begin(); ai != aiend; ++ai)
-    {
-        SceneNode* n = *ai;
+    for (ai = mAutoTrackingSceneNodes.begin(); ai != aiend; )
+    {
+		// Pre-increment incase we delete
+		AutoTrackingSceneNodes::iterator curri = ai++;
+        SceneNode* n = *curri;
         // Tracking this node
         if (n->getAutoTrackTarget() == i->second)
@@ -601,10 +607,9 @@
             // turn off, this will notify SceneManager to remove
             n->setAutoTracking(false);
-            // no need to reset iterator since set erase does not invalidate
         }
         // node is itself a tracker
         else if (n == i->second)
         {
-            mAutoTrackingSceneNodes.erase(ai);
+            mAutoTrackingSceneNodes.erase(curri);
         }
     }
@@ -814,8 +819,8 @@
     if (thisFrameNumber != lastFrameNumber)
     {
+        // Update controllers 
+        ControllerManager::getSingleton().updateAllControllers();
         // Update animations
         _applySceneAnimations();
-        // Update controllers 
-        ControllerManager::getSingleton().updateAllControllers();
         lastFrameNumber = thisFrameNumber;
     }
@@ -868,4 +873,6 @@
     }
 
+    // Tell params about viewport
+    mAutoParamDataSource.setCurrentViewport(vp);
     // Set the viewport
     setViewport(vp);
@@ -1409,5 +1416,5 @@
             {
                 // Someone requested we skip this queue
-                continue;
+                break;
             }
 
@@ -1713,5 +1720,5 @@
             mShadowReceiverPass->_load();
 
-            if (l->getCastShadows() && pGroup->getShadowsEnabled())
+            if (l->getCastShadows())
             {
                 renderTextureShadowReceiverQueueGroupObjects(pGroup);
@@ -1876,5 +1883,8 @@
         {
             // Ordinary pass
+            if (pGroup->getShadowsEnabled())
             renderModulativeTextureShadowedQueueGroupObjects(pGroup);
+			else
+				renderBasicQueueGroupObjects(pGroup);
         }
     }
@@ -2118,5 +2128,4 @@
 {
     mAmbientLight = colour;
-    mDestRenderSystem->setAmbientLight(colour.r, colour.g, colour.b);
 }
 //-----------------------------------------------------------------------
@@ -2656,4 +2665,9 @@
     {
         createShadowTextures(mShadowTextureSize, mShadowTextureCount, mShadowTextureFormat);
+    }
+    else
+    {
+        // Destroy shadow textures to optimise resource usage
+        destroyShadowTextures();
     }
 
@@ -2764,5 +2778,5 @@
         const Vector3* corners = camera->getWorldSpaceCorners();
         Vector3 min, max;
-        Vector3 extrude = light->getDirection() * -mShadowDirLightExtrudeDist;
+        Vector3 extrude = light->getDerivedDirection() * -mShadowDirLightExtrudeDist;
         // do first corner
         min = max = corners[0];
@@ -2792,5 +2806,5 @@
     else
     {
-        Sphere s(light->getPosition(), light->getAttenuationRange());
+        Sphere s(light->getDerivedPosition(), light->getAttenuationRange());
         // eliminate early if camera cannot see light sphere
         if (camera->isVisible(s))
@@ -2875,4 +2889,9 @@
         {
             mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
+            {
+                mInfiniteExtrusionParams = mShadowDebugPass->getVertexProgramParameters();
+            }
         }
     }
@@ -2915,4 +2934,9 @@
         {
             mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
+
+            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
+            {
+                mFiniteExtrusionParams = mShadowStencilPass->getVertexProgramParameters();
+            }
         }
     }
@@ -3029,28 +3053,90 @@
 Pass* SceneManager::deriveShadowCasterPass(Pass* pass)
 {
+	Pass* retPass = 0;
     switch (mShadowTechnique)
     {
     case SHADOWTYPE_TEXTURE_MODULATIVE:
-		if (mShadowTextureCustomCasterPass)
+		retPass = mShadowTextureCustomCasterPass ? 
+			mShadowTextureCustomCasterPass : mShadowCasterPlainBlackPass;
+
+
+		// Special case alpha-blended passes
+		if ((pass->getSourceBlendFactor() == SBF_SOURCE_ALPHA && 
+			pass->getDestBlendFactor() == SBF_ONE_MINUS_SOURCE_ALPHA) 
+			|| pass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
 		{
-			// Caster pass has been customised
+			// Alpha blended passes must retain their transparency
+			retPass->setAlphaRejectSettings(pass->getAlphaRejectFunction(), 
+				pass->getAlphaRejectValue());
+			retPass->setSceneBlending(pass->getSourceBlendFactor(), pass->getDestBlendFactor());
+			retPass->getParent()->getParent()->setTransparencyCastsShadows(true);
+
+			// So we allow the texture units, but override the colour functions
+			// Copy texture state, shift up one since 0 is shadow texture
+			size_t origPassTUCount = pass->getNumTextureUnitStates();
+			for (size_t t = 0; t < origPassTUCount; ++t)
+			{
+				TextureUnitState* tex;
+				if (retPass->getNumTextureUnitStates() <= t)
+				{
+					tex = retPass->createTextureUnitState();
+				}
+				else
+				{
+					tex = retPass->getTextureUnitState(t);
+				}
+				// copy base state
+				(*tex) = *(pass->getTextureUnitState(t));
+				// override colour function
+				tex->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT,
+					mShadowColour);
+
+			}
+			// Remove any extras
+			while (retPass->getNumTextureUnitStates() > origPassTUCount)
+			{
+				retPass->removeTextureUnitState(origPassTUCount);
+			}
+
+		}
+		else
+		{
+			// reset
+			retPass->setSceneBlending(SBF_ONE, SBF_ZERO);
+			retPass->setAlphaRejectFunction(CMPF_ALWAYS_PASS);
+			while (retPass->getNumTextureUnitStates() > 0)
+			{
+				retPass->removeTextureUnitState(0);
+			}
+		}
+
+		// Propagate culling modes
+		retPass->setCullingMode(pass->getCullingMode());
+		retPass->setManualCullingMode(pass->getManualCullingMode());
+
 
 			if (!pass->getShadowCasterVertexProgramName().empty())
 			{
 				// Have to merge the shadow caster vertex program in
-				mShadowTextureCustomCasterPass->setVertexProgram(
+			retPass->setVertexProgram(
 					pass->getShadowCasterVertexProgramName());
-				const GpuProgramPtr& prg = mShadowTextureCustomCasterPass->getVertexProgram();
+			const GpuProgramPtr& prg = retPass->getVertexProgram();
 				// Load this program if not done already
 				if (!prg->isLoaded())
 					prg->load();
 				// Copy params
-				mShadowTextureCustomCasterPass->setVertexProgramParameters(
+			retPass->setVertexProgramParameters(
 					pass->getShadowCasterVertexProgramParameters());
+			if (retPass == mShadowTextureCustomCasterPass)
+			{
 				// mark that we've overridden the standard
 				mShadowTextureCasterVPDirty = true;
+			}
 				// Also have to hack the light autoparams, that is done later
 			}
-			else if (mShadowTextureCasterVPDirty)
+		else 
+		{
+			retPass->setVertexProgram(StringUtil::BLANK);
+			if (mShadowTextureCasterVPDirty)
 			{
 				// reset
@@ -3065,36 +3151,6 @@
 				mShadowTextureCasterVPDirty = false;
 			}
-			return mShadowTextureCustomCasterPass;
 		}
-		else
-		{
-			// Standard pass
-			if (pass->hasVertexProgram())
-			{
-				// Have to merge the shadow caster vertex program in
-				// This may in fact be blank, in which case it falls back on 
-				// fixed function
-				mShadowCasterPlainBlackPass->setVertexProgram(
-					pass->getShadowCasterVertexProgramName());
-				// Did this result in a new vertex program?
-				if (mShadowCasterPlainBlackPass->hasVertexProgram())
-				{
-					const GpuProgramPtr& prg = mShadowCasterPlainBlackPass->getVertexProgram();
-					// Load this program if not done already
-					if (!prg->isLoaded())
-						prg->load();
-					// Copy params
-					mShadowCasterPlainBlackPass->setVertexProgramParameters(
-						pass->getShadowCasterVertexProgramParameters());
-				}
-				// Also have to hack the light autoparams, that is done later
-			}
-			else if (mShadowCasterPlainBlackPass->hasVertexProgram())
-			{
-				// reset
-				mShadowCasterPlainBlackPass->setVertexProgram("");
-			}
-			return mShadowCasterPlainBlackPass;
-		}
+		return retPass;
     default:
         return pass;
@@ -3301,5 +3357,5 @@
 	{
         ShadowCaster* caster = *si;
-		bool zfailAlgo = false;
+		bool zfailAlgo = camera->isCustomNearClipPlaneEnabled();
 		unsigned long flags = 0;
 
@@ -3705,14 +3761,5 @@
 
     // destroy existing
-    ShadowTextureList::iterator i, iend;
-    iend = mShadowTextures.end();
-    for (i = mShadowTextures.begin(); i != iend; ++i)
-    {
-        RenderTexture* r = *i;
-        // remove camera and destroy texture
-        removeCamera(r->getViewport(0)->getCamera());
-        mDestRenderSystem->destroyRenderTexture(r->getName());
-    }
-    mShadowTextures.clear();
+	destroyShadowTextures();
 
     // Recreate shadow textures
@@ -3762,4 +3809,18 @@
 
     }
+}
+//---------------------------------------------------------------------
+void SceneManager::destroyShadowTextures(void)
+{
+    ShadowTextureList::iterator i, iend;
+    iend = mShadowTextures.end();
+    for (i = mShadowTextures.begin(); i != iend; ++i)
+    {
+        RenderTexture* r = *i;
+        // remove camera and destroy texture
+        removeCamera(r->getViewport(0)->getCamera());
+        mDestRenderSystem->destroyRenderTexture(r->getName());
+    }
+    mShadowTextures.clear();
 }
 //---------------------------------------------------------------------
