Browse Source

First image!

Marko Pintera 13 years ago
parent
commit
a7115d0ee4

+ 2 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -97,6 +97,7 @@
     <ClInclude Include="OgreBitwise.h" />
     <ClInclude Include="OgreBlendMode.h" />
     <ClInclude Include="OgreBuildSettings.h" />
+    <ClInclude Include="OgreCamera.h" />
     <ClInclude Include="OgreColourValue.h" />
     <ClInclude Include="OgreCommon.h" />
     <ClInclude Include="OgreConfig.h" />
@@ -185,6 +186,7 @@
     <ClCompile Include="CmRenderSystemManager.cpp" />
     <ClCompile Include="OgreAlignedAllocator.cpp" />
     <ClCompile Include="OgreAxisAlignedBox.cpp" />
+    <ClCompile Include="OgreCamera.cpp" />
     <ClCompile Include="OgreColourValue.cpp" />
     <ClCompile Include="OgreD3D9Device.cpp" />
     <ClCompile Include="OgreD3D9DeviceManager.cpp" />

+ 6 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -313,6 +313,9 @@
     <ClInclude Include="CmRenderSystemManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="OgreCamera.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
@@ -510,5 +513,8 @@
     <ClCompile Include="CmRenderSystemManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="OgreCamera.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 13 - 0
CamelotRenderer/CmApplication.cpp

@@ -5,6 +5,9 @@
 
 #include "OgreWindowEventUtilities.h"
 #include "OgreHardwareBufferManager.h"
+#include "OgreRenderWindow.h"
+#include "OgreCamera.h"
+#include "OgreViewport.h"
 
 namespace CamelotEngine
 {
@@ -20,9 +23,19 @@ namespace CamelotEngine
 		renderSystem->_initialise(false, "Camelot Renderer");
 		mRenderWindow = renderSystem->_createRenderWindow("Camelot Renderer", 800, 600, false);
 
+		mCamera = new Ogre::Camera("SimpleCam", nullptr);
+		mCamera->setPosition(Ogre::Vector3(0,0,80));
+		mCamera->lookAt(Ogre::Vector3(0,0,-300));
+		mCamera->setNearClipDistance(5);
+		mCamera->setAspectRatio(480.0f / 640.0f);
+
+		mViewport = mRenderWindow->addViewport();
+
 		while(true)
 		{
 			Ogre::WindowEventUtilities::messagePump();
+
+			DBG_renderSimpleFrame();
 		}
 	}
 

+ 2 - 0
CamelotRenderer/CmApplication.h

@@ -6,6 +6,7 @@ namespace Ogre
 {
 	class RenderWindow;
 	class Viewport;
+	class Camera;
 }
 
 namespace CamelotEngine
@@ -23,6 +24,7 @@ namespace CamelotEngine
 		private:
 			Ogre::RenderWindow* mRenderWindow;
 			Ogre::Viewport* mViewport;
+			Ogre::Camera* mCamera;
 	};
 
 	Application& gApplication();

+ 1021 - 0
CamelotRenderer/OgreCamera.cpp

@@ -0,0 +1,1021 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreCamera.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreSphere.h"
+#include "OgreException.h"
+#include "OgreRenderSystem.h"
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
+#include "macUtils.h"
+#endif
+
+namespace Ogre {
+
+    String Camera::msMovableType = "Camera";
+    //-----------------------------------------------------------------------
+    Camera::Camera( const String& name, SceneManager* sm)
+        : Frustum(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),
+		mLodCamera(0)
+    {
+
+        // Reasonable defaults to camera params
+        mFOVy = Radian(Math::PI/4.0f);
+        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;
+
+        // no reflection
+        mReflect = false;
+    }
+
+    //-----------------------------------------------------------------------
+    Camera::~Camera()
+    {
+		for (ListenerList::iterator i = mListeners.begin(); i != mListeners.end(); ++i)
+		{
+			(*i)->cameraDestroyed(this);
+		}
+    }
+    //-----------------------------------------------------------------------
+    SceneManager* Camera::getSceneManager(void) const
+    {
+        return mSceneMgr;
+    }
+
+
+    //-----------------------------------------------------------------------
+    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();
+
+		Quaternion targetWorldOrientation;
+
+
+        if( mYawFixed )
+        {
+            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
+            xVec.normalise();
+
+            Vector3 yVec = zAdjustVec.crossProduct( xVec );
+            yVec.normalise();
+
+            targetWorldOrientation.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);
+
+            }
+            targetWorldOrientation = rotQuat * mRealOrientation;
+        }
+
+        // transform to parent space
+		// TODO PORT -  Can't get orientation from parent until we hook it up properly as a Component
+  //      if (mParentNode)
+  //      {
+  //          mOrientation =
+  //              mParentNode->_getDerivedOrientation().Inverse() * targetWorldOrientation;
+  //      }
+		//else
+		{
+			mOrientation = targetWorldOrientation;
+		}
+
+        // 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
+
+		// Normalise the quat to avoid cumulative problems with precision
+		Quaternion qnorm = q;
+		qnorm.normalise();
+        mOrientation = qnorm * mOrientation;
+
+        invalidateView();
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Camera::isViewOutOfDate(void) const
+    {
+        // Overridden from Frustum to use local orientation / position offsets
+        // Attached to node?
+		// TODO PORT -  Can't get orientation/position from parent until we hook it up properly as a Component
+        //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 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.transformAffine(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)
+    {
+		for (ListenerList::iterator i = mListeners.begin(); i != mListeners.end(); ++i)
+		{
+			(*i)->cameraPreRenderScene(this);
+		}
+
+		// TODO PORT - I'm not going to be rendering the scene like this (yet), but I think I will do it eventually
+        //mSceneMgr->_renderScene(this, vp, includeOverlays);
+
+		for (ListenerList::iterator i = mListeners.begin(); i != mListeners.end(); ++i)
+		{
+			(*i)->cameraPostRenderScene(this);
+		}
+	}
+	//---------------------------------------------------------------------
+	void Camera::addListener(Listener* l)
+	{
+		if (std::find(mListeners.begin(), mListeners.end(), l) == mListeners.end())
+			mListeners.push_back(l);
+	}
+	//---------------------------------------------------------------------
+	void Camera::removeListener(Listener* l)
+	{
+		ListenerList::iterator i = std::find(mListeners.begin(), mListeners.end(), l);
+		if (i != mListeners.end())
+			mListeners.erase(i);
+	}
+    //-----------------------------------------------------------------------
+    std::ostream& operator<<( std::ostream& o, const Camera& c )
+    {
+        o << "Camera(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;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::_notifyRenderedBatches(unsigned int numbatches)
+    {
+        mVisBatchesLastRender = numbatches;
+    }
+
+    //-----------------------------------------------------------------------
+    unsigned int Camera::_getNumRenderedFaces(void) const
+    {
+        return mVisFacesLastRender;
+    }
+    //-----------------------------------------------------------------------
+    unsigned int Camera::_getNumRenderedBatches(void) const
+    {
+        return mVisBatchesLastRender;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Camera::getOrientation(void) const
+    {
+        return mOrientation;
+    }
+
+    //-----------------------------------------------------------------------
+    void Camera::setOrientation(const Quaternion& q)
+    {
+        mOrientation = q;
+		mOrientation.normalise();
+        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;
+	}
+	//-----------------------------------------------------------------------
+	void Camera::setLodCamera(const Camera* lodCam)
+	{
+		if (lodCam == this)
+			mLodCamera = 0;
+		else
+			mLodCamera = lodCam;
+	}
+	//---------------------------------------------------------------------
+	const Camera* Camera::getLodCamera() const
+	{
+		return mLodCamera? mLodCamera : this;
+	}
+    //-----------------------------------------------------------------------
+	Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const
+	{
+		Ray ret;
+		getCameraToViewportRay(screenX, screenY, &ret);
+		return ret;
+	}
+	//---------------------------------------------------------------------
+    void Camera::getCameraToViewportRay(Real screenX, Real screenY, Ray* outRay) const
+    {
+		Matrix4 inverseVP = (getProjectionMatrix() * getViewMatrix(true)).inverse();
+
+#if OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
+        // We need to convert screen point to our oriented viewport (temp solution)
+        Real tX = screenX; Real a = getOrientationMode() * Math::HALF_PI;
+        screenX = Math::Cos(a) * (tX-0.5f) + Math::Sin(a) * (screenY-0.5f) + 0.5f;
+        screenY = Math::Sin(a) * (tX-0.5f) + Math::Cos(a) * (screenY-0.5f) + 0.5f;
+        if ((int)getOrientationMode()&1) screenY = 1.f - screenY;
+#endif
+
+		Real nx = (2.0f * screenX) - 1.0f;
+		Real ny = 1.0f - (2.0f * screenY);
+		Vector3 nearPoint(nx, ny, -1.f);
+		// Use midPoint rather than far point to avoid issues with infinite projection
+		Vector3 midPoint (nx, ny,  0.0f);
+
+		// Get ray origin and ray target on near plane in world space
+		Vector3 rayOrigin, rayTarget;
+		
+		rayOrigin = inverseVP * nearPoint;
+		rayTarget = inverseVP * midPoint;
+
+		Vector3 rayDirection = rayTarget - rayOrigin;
+		rayDirection.normalise();
+
+		outRay->setOrigin(rayOrigin);
+		outRay->setDirection(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.inverseAffine();
+
+        Vector3 vw_ul = inv.transformAffine(vp_ul);
+        Vector3 vw_ur = inv.transformAffine(vp_ur);
+        Vector3 vw_bl = inv.transformAffine(vp_bl);
+        Vector3 vw_br = inv.transformAffine(vp_br);
+
+		mWindowClipPlanes.clear();
+        if (mProjType == PT_PERSPECTIVE)
+        {
+            Vector3 position = getPositionForViewUpdate();
+            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 vector<Plane>::type& 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.5f;
+
+    }
+    //-----------------------------------------------------------------------
+    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);
+		}
+	}
+	//-----------------------------------------------------------------------
+	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();
+		}
+	}
+	//-----------------------------------------------------------------------
+	//_______________________________________________________
+	//|														|
+	//|	getRayForwardIntersect								|
+	//|	-----------------------------						|
+	//|	get the intersections of frustum rays with a plane	|
+	//| of interest.  The plane is assumed to have constant	|
+	//| z.  If this is not the case, rays					|
+	//| should be rotated beforehand to work in a			|
+	//| coordinate system in which this is true.			|
+	//|_____________________________________________________|
+	//
+	vector<Vector4>::type Camera::getRayForwardIntersect(const Vector3& anchor, const Vector3 *dir, Real planeOffset) const
+	{
+		vector<Vector4>::type res;
+
+		if(!dir)
+			return res;
+
+		int infpt[4] = {0, 0, 0, 0}; // 0=finite, 1=infinite, 2=straddles infinity
+		Vector3 vec[4];
+
+		// find how much the anchor point must be displaced in the plane's
+		// constant variable
+		Real delta = planeOffset - anchor.z;
+
+		// now set the intersection point and note whether it is a 
+		// point at infinity or straddles infinity
+		unsigned int i;
+		for (i=0; i<4; i++)
+		{
+			Real test = dir[i].z * delta;
+			if (test == 0.0) {
+				vec[i] = dir[i];
+				infpt[i] = 1;
+			}
+			else {
+				Real lambda = delta / dir[i].z;
+				vec[i] = anchor + (lambda * dir[i]);
+				if(test < 0.0)
+					infpt[i] = 2;
+			}
+		}
+
+		for (i=0; i<4; i++)
+		{
+			// store the finite intersection points
+			if (infpt[i] == 0)
+				res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 1.0));
+			else
+			{
+				// handle the infinite points of intersection;
+				// cases split up into the possible frustum planes 
+				// pieces which may contain a finite intersection point
+				int nextind = (i+1) % 4;
+				int prevind = (i+3) % 4;
+				if ((infpt[prevind] == 0) || (infpt[nextind] == 0))
+				{
+					if (infpt[i] == 1)
+						res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 0.0));
+					else
+					{
+						// handle the intersection points that straddle infinity (back-project)
+						if(infpt[prevind] == 0) 
+						{
+							Vector3 temp = vec[prevind] - vec[i];
+							res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
+						}
+						if(infpt[nextind] == 0)
+						{
+							Vector3 temp = vec[nextind] - vec[i];
+							res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
+						}
+					}
+				} // end if we need to add an intersection point to the list
+			} // end if infinite point needs to be considered
+		} // end loop over frustun corners
+
+		// we end up with either 0, 3, 4, or 5 intersection points
+
+		return res;
+	}
+
+	//_______________________________________________________
+	//|														|
+	//|	forwardIntersect									|
+	//|	-----------------------------						|
+	//|	Forward intersect the camera's frustum rays with	|
+	//| a specified plane of interest.						|
+	//| Note that if the frustum rays shoot out and would	|
+	//| back project onto the plane, this means the forward	|
+	//| intersection of the frustum would occur at the		|
+	//| line at infinity.									|
+	//|_____________________________________________________|
+	//
+	void Camera::forwardIntersect(const Plane& worldPlane, vector<Vector4>::type* intersect3d) const
+	{
+		if(!intersect3d)
+			return;
+
+		Vector3 trCorner = getWorldSpaceCorners()[0];
+		Vector3 tlCorner = getWorldSpaceCorners()[1];
+		Vector3 blCorner = getWorldSpaceCorners()[2];
+		Vector3 brCorner = getWorldSpaceCorners()[3];
+
+		// need some sort of rotation that will bring the plane normal to the z axis
+		Plane pval = worldPlane;
+		if(pval.normal.z < 0.0)
+		{
+			pval.normal *= -1.0;
+			pval.d *= -1.0;
+		}
+		Quaternion invPlaneRot = pval.normal.getRotationTo(Vector3::UNIT_Z);
+
+		// get rotated light
+		Vector3 lPos = invPlaneRot * getDerivedPosition();
+		Vector3 vec[4];
+		vec[0] = invPlaneRot * trCorner - lPos;
+		vec[1] = invPlaneRot * tlCorner - lPos; 
+		vec[2] = invPlaneRot * blCorner - lPos; 
+		vec[3] = invPlaneRot * brCorner - lPos; 
+
+		// compute intersection points on plane
+		vector<Vector4>::type iPnt = getRayForwardIntersect(lPos, vec, -pval.d);
+
+
+		// return wanted data
+		if(intersect3d) 
+		{
+			Quaternion planeRot = invPlaneRot.Inverse();
+			(*intersect3d).clear();
+			for(unsigned int i=0; i<iPnt.size(); i++)
+			{
+				Vector3 intersection = planeRot * Vector3(iPnt[i].x, iPnt[i].y, iPnt[i].z);
+				(*intersect3d).push_back(Vector4(intersection.x, intersection.y, intersection.z, iPnt[i].w));
+			}
+		}
+	}
+	//-----------------------------------------------------------------------
+	void Camera::synchroniseBaseSettingsWith(const Camera* cam)
+	{
+		this->setPosition(cam->getPosition());
+		this->setProjectionType(cam->getProjectionType());
+		this->setOrientation(cam->getOrientation());
+		this->setAspectRatio(cam->getAspectRatio());
+		this->setNearClipDistance(cam->getNearClipDistance());
+		this->setFarClipDistance(cam->getFarClipDistance());
+		this->setUseRenderingDistance(cam->getUseRenderingDistance());
+		this->setFOVy(cam->getFOVy());
+		this->setFocalLength(cam->getFocalLength());
+
+		// Don't do these, they're not base settings and can cause referencing issues
+		//this->setLodCamera(cam->getLodCamera());
+		//this->setCullingFrustum(cam->getCullingFrustum());
+
+	}
+
+
+} // namespace Ogre

+ 618 - 0
CamelotRenderer/OgreCamera.h

@@ -0,0 +1,618 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Camera_H__
+#define __Camera_H__
+
+// Default options
+#include "OgrePrerequisites.h"
+
+#include "OgreString.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 {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Scene
+	*  @{
+	*/
+
+    /** 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 frustum,
+            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
+    {
+	public:
+		/** Listener interface so you can be notified of Camera events. 
+		*/
+		class _OgreExport Listener 
+		{
+		public:
+			Listener() {}
+			virtual ~Listener() {}
+
+			/// Called prior to the scene being rendered with this camera
+			virtual void cameraPreRenderScene(Camera* cam)
+                        { (void)cam; }
+
+			/// Called after the scene has been rendered with this camera
+			virtual void cameraPostRenderScene(Camera* cam)
+                        { (void)cam; }
+
+			/// Called when the camera is being destroyed
+			virtual void cameraDestroyed(Camera* cam)
+                        { (void)cam; }
+
+		};
+    protected:
+        /// 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;
+
+        /// Stored number of visible faces in the last render
+        unsigned int mVisBatchesLastRender;
+
+        /// 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 vector<Plane>::type mWindowClipPlanes;
+        // Was viewing window changed.
+        mutable bool mRecalcWindow;
+        /// The last viewport to be added using this camera
+        Viewport* mLastViewport;
+        /** Whether aspect ratio will automatically be recalculated 
+            when a viewport 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;
+        /// Camera to use for LOD calculation
+        const Camera* mLodCamera;
+
+		typedef vector<Listener*>::type ListenerList;
+		ListenerList mListeners;
+
+
+        // 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;
+
+		/** Helper function for forwardIntersect that intersects rays with canonical plane */
+		virtual vector<Vector4>::type getRayForwardIntersect(const Vector3& anchor, const Vector3 *dir, Real planeOffset) const;
+
+    public:
+        /** Standard constructor.
+        */
+        Camera( const String& name, SceneManager* sm);
+
+        /** Standard destructor.
+        */
+        virtual ~Camera();
+
+		/// Add a listener to this camera
+		virtual void addListener(Listener* l);
+		/// Remove a listener to this camera
+		virtual void removeListener(Listener* l);
+
+        /** Returns a pointer to the SceneManager this camera is rendering through.
+        */
+        SceneManager* getSceneManager(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);
+
+        /** Rotates the camera anticlockwise around it's local y axis.
+        */
+        void yaw(const Radian& angle);
+
+        /** Pitches the camera up/down anticlockwise around it's local z axis.
+        */
+        void pitch(const Radian& angle);
+
+        /** Rotate the camera around an arbitrary axis.
+        */
+        void rotate(const Vector3& axis, const Radian& angle);
+
+        /** Rotate the camera around an arbitrary axis using a Quaternion.
+        */
+        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.
+        */
+        _OgreExport friend std::ostream& operator<<(std::ostream& o, const Camera& c);
+
+        /** Internal method to notify camera of the visible faces in the last render.
+        */
+        void _notifyRenderedFaces(unsigned int numfaces);
+
+        /** Internal method to notify camera of the visible batches in the last render.
+        */
+        void _notifyRenderedBatches(unsigned int numbatches);
+
+        /** Internal method to retrieve the number of visible faces in the last render.
+        */
+        unsigned int _getNumRenderedFaces(void) const;
+
+        /** Internal method to retrieve the number of visible batches in the last render.
+        */
+        unsigned int _getNumRenderedBatches(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;
+
+		/** Get a pointer to the camera which should be used to determine 
+			LOD settings. 
+		@remarks
+			Sometimes you don't want the LOD of a render to be based on the camera
+			that's doing the rendering, you want it to be based on a different
+			camera. A good example is when rendering shadow maps, since they will 
+			be viewed from the perspective of another camera. Therefore this method
+			lets you associate a different camera instance to use to determine the LOD.
+		@par
+			To revert the camera to determining LOD based on itself, call this method with 
+			a pointer to itself. 
+		*/
+		virtual void setLodCamera(const Camera* lodCam);
+
+		/** Get a pointer to the camera which should be used to determine 
+			LOD settings. 
+		@remarks
+			If setLodCamera hasn't been called with a different camera, this
+			method will return 'this'. 
+		*/
+		virtual const Camera* getLodCamera() 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;
+        /** 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]
+		@param outRay Ray instance to populate with result
+        */
+        void getCameraToViewportRay(Real screenx, Real screeny, Ray* outRay) 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 vector<Plane>::type& 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 viewport 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);
+
+        /** Retrieves 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) const { return mCullFrustum; }
+
+		/** Forward projects frustum rays to find forward intersection with plane.
+		 @remarks
+		    Forward projection may lead to intersections at infinity.
+		*/
+		virtual void forwardIntersect(const Plane& worldPlane, vector<Vector4>::type* intersect3d) const;
+
+		/// @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;
+		/// @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; }
+
+		/** Synchronise core camera settings with another. 
+		@remarks
+			Copies the position, orientation, clip distances, projection type, 
+			FOV, focal length and aspect ratio from another camera. Other settings like query flags, 
+			reflection etc are preserved.
+		*/
+		virtual void synchroniseBaseSettingsWith(const Camera* cam);
+
+		/** Get the derived position of this frustum. */
+		const Vector3& getPositionForViewUpdate(void) const;
+		/** Get the derived orientation of this frustum. */
+		const Quaternion& getOrientationForViewUpdate(void) const;
+     };
+	 /** @} */
+	 /** @} */
+
+} // namespace Ogre
+#endif

+ 14 - 14
CamelotRenderer/OgreD3D9DeviceManager.cpp

@@ -491,20 +491,20 @@ namespace Ogre
 	//---------------------------------------------------------------------
 	void D3D9DeviceManager::destroyInactiveRenderDevices()
 	{
-		DeviceIterator itDevice = mRenderDevices.begin();
-		while (itDevice != mRenderDevices.end())
-		{			
-			// TODO PORT - This is supposed to destroy inactive render devices but lastPresentFrame isn't being set properly at the moment, so this wont work properly
-			//if ((*itDevice)->getRenderWindowCount() == 0 &&
-			//	(*itDevice)->getLastPresentFrame() + 1 < Root::getSingleton().getNextFrameNumber())
-			//{		
-			//	if (*itDevice == mActiveRenderWindowDevice)
-			//		setActiveRenderTargetDevice(NULL);
-			//	(*itDevice)->destroy();
-			//	break;
-			//}												
-			//++itDevice;
-		}
+		// TODO PORT - This is supposed to destroy inactive render devices but lastPresentFrame isn't being set properly at the moment, so this wont work properly
+		//DeviceIterator itDevice = mRenderDevices.begin();
+		//while (itDevice != mRenderDevices.end())
+		//{			
+		//	if ((*itDevice)->getRenderWindowCount() == 0 &&
+		//		(*itDevice)->getLastPresentFrame() + 1 < Root::getSingleton().getNextFrameNumber())
+		//	{		
+		//		if (*itDevice == mActiveRenderWindowDevice)
+		//			setActiveRenderTargetDevice(NULL);
+		//		(*itDevice)->destroy();
+		//		break;
+		//	}												
+		//	++itDevice;
+		//}
 	}
 
 }

+ 8 - 0
CamelotRenderer/TODO.txt

@@ -4,6 +4,14 @@
 3. Start stripping down the classes and see what I really need
 4. Port OpenGL render system as well
 
+Camera:
+ - Remove auto tracking
+ - Merge with Viewport
+ - Lod stuff? Probably need to remove as well
+ - Num render batches and other statistics
+ - Position/rotation should be inherit from transform
+ - Listeners
+
 DefaultHardwareBufferManager - Provides emulation of hardware buffers
  - I think this class is okay to stay, although I'm not sure where its used, but its simple enough