Index: sandbox_light/src/external/CMakeLists.txt
===================================================================
--- sandbox_light/src/external/CMakeLists.txt	(revision 5788)
+++ sandbox_light/src/external/CMakeLists.txt	(revision 5789)
@@ -20,3 +20,4 @@
 ################ Sub Directories ################
 
+ADD_SUBDIRECTORY(ogremath)
 ADD_SUBDIRECTORY(tolua)
Index: sandbox_light/src/external/ogremath/CMakeLists.txt
===================================================================
--- sandbox_light/src/external/ogremath/CMakeLists.txt	(revision 5789)
+++ sandbox_light/src/external/ogremath/CMakeLists.txt	(revision 5789)
@@ -0,0 +1,46 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program is free software; you can redistribute it and/or
+ #         modify it under the terms of the GNU 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 General Public License for more details.
+ #
+ #   You should have received a copy of the GNU General Public License along
+ #      with this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET(OGREMATH_SRC_FILES
+  OgreColourValue.cpp
+  OgreMath.cpp
+  OgreMatrix3.cpp
+  OgreMatrix4.cpp
+  OgreQuaternion.cpp
+  OgreVector2.cpp
+  OgreVector3.cpp
+  OgreVector4.cpp
+)
+
+IF(WIN32)
+  LIST(APPEND OGREMATH_SRC_FILES WIN32/OgreTimer.cpp)
+ELSEIF(APPLE)
+  LIST(APPEND OGREMATH_SRC_FILES OSX/OgreTimer.cpp)
+ELSEIF(UNIX)
+  LIST(APPEND OGREMATH_SRC_FILES GLX/OgreTimer.cpp)
+ENDIF()
+
+ORXONOX_ADD_LIBRARY(ogremath_orxonox
+  ORXONOX_EXTERNAL
+  FIND_HEADER_FILES
+  DEFINE_SYMBOL
+    "OGRE_NONCLIENT_BUILD"
+  SOURCE_FILES
+    ${OGREMATH_SRC_FILES}
+) 
Index: sandbox_light/src/external/ogremath/GLX/OgreTimer.cpp
===================================================================
--- sandbox_light/src/external/ogremath/GLX/OgreTimer.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/GLX/OgreTimer.cpp	(revision 5789)
@@ -0,0 +1,80 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+ 
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreTimer.h"
+#include <sys/time.h>
+
+using namespace Ogre;
+
+//--------------------------------------------------------------------------------//
+Timer::Timer()
+{
+	reset();
+}
+
+//--------------------------------------------------------------------------------//
+Timer::~Timer()
+{
+}
+
+//--------------------------------------------------------------------------------//
+void Timer::reset()
+{
+	zeroClock = clock();
+	gettimeofday(&start, NULL);
+}
+
+//--------------------------------------------------------------------------------//
+unsigned long Timer::getMilliseconds()
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	return (now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
+}
+
+//--------------------------------------------------------------------------------//
+unsigned long Timer::getMicroseconds()
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	return (now.tv_sec-start.tv_sec)*1000000+(now.tv_usec-start.tv_usec);
+}
+
+//-- Common Across All Timers ----------------------------------------------------//
+unsigned long Timer::getMillisecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)((float)(newClock-zeroClock) / ((float)CLOCKS_PER_SEC/1000.0)) ;
+}
+
+//-- Common Across All Timers ----------------------------------------------------//
+unsigned long Timer::getMicrosecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)((float)(newClock-zeroClock) / ((float)CLOCKS_PER_SEC/1000000.0)) ;
+}
Index: sandbox_light/src/external/ogremath/GLX/OgreTimerImp.h
===================================================================
--- sandbox_light/src/external/ogremath/GLX/OgreTimerImp.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/GLX/OgreTimerImp.h	(revision 5789)
@@ -0,0 +1,79 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+ 
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __GLXTimer_H__
+#define __GLXTimer_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre
+{
+	/** Timer class */
+	class _OgreExport Timer : public TimerAlloc
+	{
+	private:
+		struct timeval start;
+		clock_t zeroClock;
+	public:
+		Timer();
+		~Timer();
+
+		/** Method for setting a specific option of the Timer. These options are usually
+            specific for a certain implementation of the Timer class, and may (and probably
+            will) not exist across different implementations.  reset() must be called after
+			all setOption() calls.
+            @param
+                strKey The name of the option to set
+            @param
+                pValue A pointer to the value - the size should be calculated by the timer
+                based on the key
+            @return
+                On success, true is returned.
+            @par
+                On failure, false is returned.
+        */
+        bool setOption( const String& strKey, const void* pValue ) { return false; }
+
+		/** Resets timer */
+		void reset();
+
+		/** Returns milliseconds since initialisation or last reset */
+		unsigned long getMilliseconds();
+
+		/** Returns microseconds since initialisation or last reset */
+		unsigned long getMicroseconds();
+
+		/** Returns milliseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMillisecondsCPU();
+
+		/** Returns microseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMicrosecondsCPU();
+	};
+}
+#endif
Index: sandbox_light/src/external/ogremath/OSX/OgreTimer.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OSX/OgreTimer.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OSX/OgreTimer.cpp	(revision 5789)
@@ -0,0 +1,80 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+ 
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreTimer.h"
+#include <sys/time.h>
+
+using namespace Ogre;
+
+//--------------------------------------------------------------------------------//
+Timer::Timer()
+{
+	reset();
+}
+
+//--------------------------------------------------------------------------------//
+Timer::~Timer()
+{
+}
+
+//--------------------------------------------------------------------------------//
+void Timer::reset()
+{
+	zeroClock = clock();
+	gettimeofday(&start, NULL);
+}
+
+//--------------------------------------------------------------------------------//
+unsigned long Timer::getMilliseconds()
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	return (now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
+}
+
+//--------------------------------------------------------------------------------//
+unsigned long Timer::getMicroseconds()
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	return (now.tv_sec-start.tv_sec)*1000000+(now.tv_usec-start.tv_usec);
+}
+
+//-- Common Across All Timers ----------------------------------------------------//
+unsigned long Timer::getMillisecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)((float)(newClock-zeroClock) / ((float)CLOCKS_PER_SEC/1000.0)) ;
+}
+
+//-- Common Across All Timers ----------------------------------------------------//
+unsigned long Timer::getMicrosecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)((float)(newClock-zeroClock) / ((float)CLOCKS_PER_SEC/1000000.0)) ;
+}
Index: sandbox_light/src/external/ogremath/OSX/OgreTimerImp.h
===================================================================
--- sandbox_light/src/external/ogremath/OSX/OgreTimerImp.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OSX/OgreTimerImp.h	(revision 5789)
@@ -0,0 +1,79 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+ 
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __OSXTimer_H__
+#define __OSXTimer_H__
+
+#include <Ogre/OgrePrerequisites.h>
+
+namespace Ogre
+{
+	/** Timer class */
+	class Timer : public TimerAlloc
+	{
+	private:
+		struct timeval start;
+		clock_t zeroClock;
+	public:
+		Timer();
+		~Timer();
+
+		/** Method for setting a specific option of the Timer. These options are usually
+            specific for a certain implementation of the Timer class, and may (and probably
+            will) not exist across different implementations.  reset() must be called after
+			all setOption() calls.
+            @param
+                strKey The name of the option to set
+            @param
+                pValue A pointer to the value - the size should be calculated by the timer
+                based on the key
+            @return
+                On success, true is returned.
+            @par
+                On failure, false is returned.
+        */
+        bool setOption( const String& strKey, const void* pValue ) { return false; }
+
+		/** Resets timer */
+		void reset();
+
+		/** Returns milliseconds since initialisation or last reset */
+		unsigned long getMilliseconds();
+
+		/** Returns microseconds since initialisation or last reset */
+		unsigned long getMicroseconds();
+
+		/** Returns milliseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMillisecondsCPU();
+
+		/** Returns microseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMicrosecondsCPU();
+	};
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgreBitwise.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreBitwise.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreBitwise.h	(revision 5789)
@@ -0,0 +1,323 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef _Bitwise_H__
+#define _Bitwise_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+
+    /** Class for manipulating bit patterns.
+    */
+    class Bitwise {
+    public:
+        /** Returns the most significant bit set in a value.
+        */
+        static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value)
+        {
+            unsigned int result = 0;
+            while (value != 0) {
+                ++result;
+                value >>= 1;
+            }
+            return result-1;
+        }
+        /** Returns the closest power-of-two number greater or equal to value.
+            @note 0 and 1 are powers of two, so 
+                firstPO2From(0)==0 and firstPO2From(1)==1.
+        */
+        static FORCEINLINE uint32 firstPO2From(uint32 n)
+        {
+            --n;            
+            n |= n >> 16;
+            n |= n >> 8;
+            n |= n >> 4;
+            n |= n >> 2;
+            n |= n >> 1;
+            ++n;
+            return n;
+        }
+        /** Determines whether the number is power-of-two or not.
+            @note 0 and 1 are tread as power of two.
+        */
+        template<typename T>
+        static FORCEINLINE bool isPO2(T n)
+        {
+            return (n & (n-1)) == 0;
+        }
+        /** Returns the number of bits a pattern must be shifted right by to
+            remove right-hand zeros.
+        */
+		template<typename T>
+        static FORCEINLINE unsigned int getBitShift(T mask)
+		{
+			if (mask == 0)
+				return 0;
+
+			unsigned int result = 0;
+			while ((mask & 1) == 0) {
+				++result;
+				mask >>= 1;
+			}
+			return result;
+		}
+
+        /** Takes a value with a given src bit mask, and produces another
+            value with a desired bit mask.
+            @remarks
+                This routine is useful for colour conversion.
+        */
+		template<typename SrcT, typename DestT>
+        static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask)
+		{
+			// Mask off irrelevant source value bits (if any)
+			srcValue = srcValue & srcBitMask;
+
+			// Shift source down to bottom of DWORD
+			const unsigned int srcBitShift = getBitShift(srcBitMask);
+			srcValue >>= srcBitShift;
+
+			// Get max value possible in source from srcMask
+			const SrcT srcMax = srcBitMask >> srcBitShift;
+
+			// Get max available in dest
+			const unsigned int destBitShift = getBitShift(destBitMask);
+			const DestT destMax = destBitMask >> destBitShift;
+
+			// Scale source value into destination, and shift back
+			DestT destValue = (srcValue * destMax) / srcMax;
+			return (destValue << destBitShift);
+		}
+
+        /**
+         * Convert N bit colour channel value to P bits. It fills P bits with the
+         * bit pattern repeated. (this is /((1<<n)-1) in fixed point)
+         */
+        static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p) 
+        {
+            if(n > p) 
+            {
+                // Less bits required than available; this is easy
+                value >>= n-p;
+            } 
+            else if(n < p)
+            {
+                // More bits required than are there, do the fill
+                // Use old fashioned division, probably better than a loop
+                if(value == 0)
+                        value = 0;
+                else if(value == (static_cast<unsigned int>(1)<<n)-1)
+                        value = (1<<p)-1;
+                else    value = value*(1<<p)/((1<<n)-1);
+            }
+            return value;    
+        }
+
+        /**
+         * Convert floating point colour channel value between 0.0 and 1.0 (otherwise clamped) 
+         * to integer of a certain number of bits. Works for any value of bits between 0 and 31.
+         */
+        static inline unsigned int floatToFixed(const float value, const unsigned int bits)
+        {
+            if(value <= 0.0f) return 0;
+            else if (value >= 1.0f) return (1<<bits)-1;
+            else return (unsigned int)(value * (1<<bits));     
+        }
+
+        /**
+         * Fixed point to float
+         */
+        static inline float fixedToFloat(unsigned value, unsigned int bits)
+        {
+            return (float)value/(float)((1<<bits)-1);
+        }
+
+        /**
+         * Write a n*8 bits integer value to memory in native endian.
+         */
+        static inline void intWrite(void *dest, const int n, const unsigned int value)
+        {
+            switch(n) {
+                case 1:
+                    ((uint8*)dest)[0] = (uint8)value;
+                    break;
+                case 2:
+                    ((uint16*)dest)[0] = (uint16)value;
+                    break;
+                case 3:
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
+                    ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF);
+                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
+                    ((uint8*)dest)[2] = (uint8)(value & 0xFF);
+#else
+                    ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF);
+                    ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF);
+                    ((uint8*)dest)[0] = (uint8)(value & 0xFF);
+#endif
+                    break;
+                case 4:
+                    ((uint32*)dest)[0] = (uint32)value;                
+                    break;                
+            }        
+        }
+        /**
+         * Read a n*8 bits integer value to memory in native endian.
+         */
+        static inline unsigned int intRead(const void *src, int n) {
+            switch(n) {
+                case 1:
+                    return ((uint8*)src)[0];
+                case 2:
+                    return ((uint16*)src)[0];
+                case 3:
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG      
+                    return ((uint32)((uint8*)src)[0]<<16)|
+                            ((uint32)((uint8*)src)[1]<<8)|
+                            ((uint32)((uint8*)src)[2]);
+#else
+                    return ((uint32)((uint8*)src)[0])|
+                            ((uint32)((uint8*)src)[1]<<8)|
+                            ((uint32)((uint8*)src)[2]<<16);
+#endif
+                case 4:
+                    return ((uint32*)src)[0];
+            } 
+            return 0; // ?
+        }
+
+        /** Convert a float32 to a float16 (NV_half_float)
+         	Courtesy of OpenEXR
+        */
+        static inline uint16 floatToHalf(float i)
+        {
+            union { float f; uint32 i; } v;
+            v.f = i;
+            return floatToHalfI(v.i);
+        }
+		/** Converts float in uint32 format to a a half in uint16 format
+		*/
+        static inline uint16 floatToHalfI(uint32 i)
+        {
+            register int s =  (i >> 16) & 0x00008000;
+            register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
+            register int m =   i        & 0x007fffff;
+        
+            if (e <= 0)
+            {
+                if (e < -10)
+                {
+                    return 0;
+                }
+                m = (m | 0x00800000) >> (1 - e);
+        
+                return s | (m >> 13);
+            }
+            else if (e == 0xff - (127 - 15))
+            {
+                if (m == 0) // Inf
+                {
+                    return s | 0x7c00;
+                } 
+                else    // NAN
+                {
+                    m >>= 13;
+                    return s | 0x7c00 | m | (m == 0);
+                }
+            }
+            else
+            {
+                if (e > 30) // Overflow
+                {
+                    return s | 0x7c00;
+                }
+        
+                return s | (e << 10) | (m >> 13);
+            }
+        }
+        
+        /**
+         * Convert a float16 (NV_half_float) to a float32
+         * Courtesy of OpenEXR
+         */
+        static inline float halfToFloat(uint16 y)
+        {
+            union { float f; uint32 i; } v;
+            v.i = halfToFloatI(y);
+            return v.f;
+        }
+		/** Converts a half in uint16 format to a float
+		 	in uint32 format
+		 */
+        static inline uint32 halfToFloatI(uint16 y)
+        {
+            register int s = (y >> 15) & 0x00000001;
+            register int e = (y >> 10) & 0x0000001f;
+            register int m =  y        & 0x000003ff;
+        
+            if (e == 0)
+            {
+                if (m == 0) // Plus or minus zero
+                {
+                    return s << 31;
+                }
+                else // Denormalized number -- renormalize it
+                {
+                    while (!(m & 0x00000400))
+                    {
+                        m <<= 1;
+                        e -=  1;
+                    }
+        
+                    e += 1;
+                    m &= ~0x00000400;
+                }
+            }
+            else if (e == 31)
+            {
+                if (m == 0) // Inf
+                {
+                    return (s << 31) | 0x7f800000;
+                }
+                else // NaN
+                {
+                    return (s << 31) | 0x7f800000 | (m << 13);
+                }
+            }
+        
+            e = e + (127 - 15);
+            m = m << 13;
+        
+            return (s << 31) | (e << 23) | m;
+        }
+         
+
+    };
+}
+
+#endif
Index: sandbox_light/src/external/ogremath/OgreColourValue.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreColourValue.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreColourValue.cpp	(revision 5789)
@@ -0,0 +1,406 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreColourValue.h"
+#include "OgreMath.h"
+
+namespace Ogre {
+
+    const ColourValue ColourValue::ZERO = ColourValue(0.0,0.0,0.0,0.0);
+    const ColourValue ColourValue::Black = ColourValue(0.0,0.0,0.0);
+    const ColourValue ColourValue::White = ColourValue(1.0,1.0,1.0);
+    const ColourValue ColourValue::Red = ColourValue(1.0,0.0,0.0);
+    const ColourValue ColourValue::Green = ColourValue(0.0,1.0,0.0);
+    const ColourValue ColourValue::Blue = ColourValue(0.0,0.0,1.0);
+
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    ABGR ColourValue::getAsABGR(void) const
+#else
+    RGBA ColourValue::getAsRGBA(void) const
+#endif
+    {
+        uint8 val8;
+        uint32 val32 = 0;
+
+        // Convert to 32bit pattern
+        // (RGBA = 8888)
+
+        // Red
+        val8 = static_cast<uint8>(r * 255);
+        val32 = val8 << 24;
+
+        // Green
+        val8 = static_cast<uint8>(g * 255);
+        val32 += val8 << 16;
+
+        // Blue
+        val8 = static_cast<uint8>(b * 255);
+        val32 += val8 << 8;
+
+        // Alpha
+        val8 = static_cast<uint8>(a * 255);
+        val32 += val8;
+
+        return val32;
+    }
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    BGRA ColourValue::getAsBGRA(void) const
+#else
+    ARGB ColourValue::getAsARGB(void) const
+#endif
+    {
+        uint8 val8;
+        uint32 val32 = 0;
+
+        // Convert to 32bit pattern
+        // (ARGB = 8888)
+
+        // Alpha
+        val8 = static_cast<uint8>(a * 255);
+        val32 = val8 << 24;
+
+        // Red
+        val8 = static_cast<uint8>(r * 255);
+        val32 += val8 << 16;
+
+        // Green
+        val8 = static_cast<uint8>(g * 255);
+        val32 += val8 << 8;
+
+        // Blue
+        val8 = static_cast<uint8>(b * 255);
+        val32 += val8;
+
+
+        return val32;
+    }
+	//---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+	ARGB ColourValue::getAsARGB(void) const
+#else
+	BGRA ColourValue::getAsBGRA(void) const
+#endif
+	{
+		uint8 val8;
+		uint32 val32 = 0;
+
+		// Convert to 32bit pattern
+		// (ARGB = 8888)
+
+		// Blue
+		val8 = static_cast<uint8>(b * 255);
+		val32 = val8 << 24;
+
+		// Green
+		val8 = static_cast<uint8>(g * 255);
+		val32 += val8 << 16;
+
+		// Red
+		val8 = static_cast<uint8>(r * 255);
+		val32 += val8 << 8;
+
+		// Alpha
+		val8 = static_cast<uint8>(a * 255);
+		val32 += val8;
+
+
+		return val32;
+	}
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    RGBA ColourValue::getAsRGBA(void) const
+#else
+    ABGR ColourValue::getAsABGR(void) const
+#endif
+    {
+        uint8 val8;
+        uint32 val32 = 0;
+
+        // Convert to 32bit pattern
+        // (ABRG = 8888)
+
+        // Alpha
+        val8 = static_cast<uint8>(a * 255);
+        val32 = val8 << 24;
+
+        // Blue
+        val8 = static_cast<uint8>(b * 255);
+        val32 += val8 << 16;
+
+        // Green
+        val8 = static_cast<uint8>(g * 255);
+        val32 += val8 << 8;
+
+        // Red
+        val8 = static_cast<uint8>(r * 255);
+        val32 += val8;
+
+
+        return val32;
+    }
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    void ColourValue::setAsABGR(const ABGR val)
+#else
+    void ColourValue::setAsRGBA(const RGBA val)
+#endif
+    {
+        uint32 val32 = val;
+
+        // Convert from 32bit pattern
+        // (RGBA = 8888)
+
+        // Red
+        r = ((val32 >> 24) & 0xFF) / 255.0f;
+
+        // Green
+        g = ((val32 >> 16) & 0xFF) / 255.0f;
+
+        // Blue
+        b = ((val32 >> 8) & 0xFF) / 255.0f;
+
+        // Alpha
+        a = (val32 & 0xFF) / 255.0f;
+    }
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    void ColourValue::setAsBGRA(const BGRA val)
+#else
+    void ColourValue::setAsARGB(const ARGB val)
+#endif
+    {
+        uint32 val32 = val;
+
+        // Convert from 32bit pattern
+        // (ARGB = 8888)
+
+        // Alpha
+        a = ((val32 >> 24) & 0xFF) / 255.0f;
+
+        // Red
+        r = ((val32 >> 16) & 0xFF) / 255.0f;
+
+        // Green
+        g = ((val32 >> 8) & 0xFF) / 255.0f;
+
+        // Blue
+        b = (val32 & 0xFF) / 255.0f;
+    }
+	//---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+	void ColourValue::setAsARGB(const ARGB val)
+#else
+	void ColourValue::setAsBGRA(const BGRA val)
+#endif
+	{
+		uint32 val32 = val;
+
+		// Convert from 32bit pattern
+		// (ARGB = 8888)
+
+		// Blue
+		b = ((val32 >> 24) & 0xFF) / 255.0f;
+
+		// Green
+		g = ((val32 >> 16) & 0xFF) / 255.0f;
+
+		// Red
+		r = ((val32 >> 8) & 0xFF) / 255.0f;
+
+		// Alpha
+		a = (val32 & 0xFF) / 255.0f;
+	}
+    //---------------------------------------------------------------------
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    void ColourValue::setAsRGBA(const RGBA val)
+#else
+    void ColourValue::setAsABGR(const ABGR val)
+#endif
+    {
+        uint32 val32 = val;
+
+        // Convert from 32bit pattern
+        // (ABGR = 8888)
+
+        // Alpha
+        a = ((val32 >> 24) & 0xFF) / 255.0f;
+
+        // Blue
+        b = ((val32 >> 16) & 0xFF) / 255.0f;
+
+        // Green
+        g = ((val32 >> 8) & 0xFF) / 255.0f;
+
+        // Red
+        r = (val32 & 0xFF) / 255.0f;
+    }
+    //---------------------------------------------------------------------
+    bool ColourValue::operator==(const ColourValue& rhs) const
+    {
+        return (r == rhs.r &&
+            g == rhs.g &&
+            b == rhs.b &&
+            a == rhs.a);
+    }
+    //---------------------------------------------------------------------
+    bool ColourValue::operator!=(const ColourValue& rhs) const
+    {
+        return !(*this == rhs);
+    }
+	//---------------------------------------------------------------------
+	void ColourValue::setHSB(Real hue, Real saturation, Real brightness)
+	{
+		// wrap hue
+		if (hue > 1.0f)
+		{
+			hue -= (int)hue;
+		}
+		else if (hue < 0.0f)
+		{
+			hue += (int)hue + 1;
+		}
+		// clamp saturation / brightness
+		saturation = std::min(saturation, (Real)1.0);
+		saturation = std::max(saturation, (Real)0.0);
+		brightness = std::min(brightness, (Real)1.0);
+		brightness = std::max(brightness, (Real)0.0);
+
+		if (brightness == 0.0f)
+		{   
+			// early exit, this has to be black
+			r = g = b = 0.0f;
+			return;
+		}
+
+		if (saturation == 0.0f)
+		{   
+			// early exit, this has to be grey
+
+			r = g = b = brightness;
+			return;
+		}
+
+
+		Real hueDomain  = hue * 6.0f;
+		if (hueDomain >= 6.0f)
+		{
+			// wrap around, and allow mathematical errors
+			hueDomain = 0.0f;
+		}
+		unsigned short domain = (unsigned short)hueDomain;
+		Real f1 = brightness * (1 - saturation);
+		Real f2 = brightness * (1 - saturation * (hueDomain - domain));
+		Real f3 = brightness * (1 - saturation * (1 - (hueDomain - domain)));
+
+		switch (domain)
+		{
+		case 0:
+			// red domain; green ascends
+			r = brightness;
+			g = f3;
+			b = f1;
+			break;
+		case 1:
+			// yellow domain; red descends
+			r = f2;
+			g = brightness;
+			b = f1;
+			break;
+		case 2:
+			// green domain; blue ascends
+			r = f1;
+			g = brightness;
+			b = f3;
+			break;
+		case 3:
+			// cyan domain; green descends
+			r = f1;
+			g = f2;
+			b = brightness;
+			break;
+		case 4:
+			// blue domain; red ascends
+			r = f3;
+			g = f1;
+			b = brightness;
+			break;
+		case 5:
+			// magenta domain; blue descends
+			r = brightness;
+			g = f1;
+			b = f2;
+			break;
+		}
+
+
+	}
+	//---------------------------------------------------------------------
+	void ColourValue::getHSB(Real* hue, Real* saturation, Real* brightness) const
+	{
+
+		Real vMin = std::min(r, std::min(g, b));
+		Real vMax = std::max(r, std::max(g, b));
+		Real delta = vMax - vMin;
+
+		*brightness = vMax;
+
+		if (Math::RealEqual(delta, 0.0f, 1e-6))
+		{
+			// grey
+			*hue = 0;
+			*saturation = 0;
+		}
+		else                                    
+		{
+			// a colour
+			*saturation = delta / vMax;
+
+			Real deltaR = (((vMax - r) / 6.0f) + (delta / 2.0f)) / delta;
+			Real deltaG = (((vMax - g) / 6.0f) + (delta / 2.0f)) / delta;
+			Real deltaB = (((vMax - b) / 6.0f) + (delta / 2.0f)) / delta;
+
+			if (Math::RealEqual(r, vMax))
+				*hue = deltaB - deltaG;
+			else if (Math::RealEqual(g, vMax))
+				*hue = 0.3333333f + deltaR - deltaB;
+			else if (Math::RealEqual(b, vMax)) 
+				*hue = 0.6666667f + deltaG - deltaR;
+
+			if (*hue < 0.0f) 
+				*hue += 1.0f;
+			if (*hue > 1.0f)
+				*hue -= 1.0f;
+		}
+
+		
+	}
+
+}
+
Index: sandbox_light/src/external/ogremath/OgreColourValue.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreColourValue.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreColourValue.h	(revision 5789)
@@ -0,0 +1,330 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef _COLOURVALUE_H__
+#define _COLOURVALUE_H__
+
+#include "OgrePrerequisites.h"
+
+#include <cassert>
+#include <ostream>
+
+namespace Ogre {
+
+    typedef uint32 RGBA;
+    typedef uint32 ARGB;
+    typedef uint32 ABGR;
+	typedef uint32 BGRA;
+
+    /** Class representing colour.
+	    @remarks
+		    Colour is represented as 4 components, each of which is a
+		    floating-point value from 0.0 to 1.0.
+	    @par
+		    The 3 'normal' colour components are red, green and blue, a higher
+		    number indicating greater amounts of that component in the colour.
+		    The forth component is the 'alpha' value, which represents
+		    transparency. In this case, 0.0 is completely transparent and 1.0 is
+		    fully opaque.
+    */
+    class _OgreExport ColourValue
+    {
+    public:
+        static const ColourValue ZERO;
+        static const ColourValue Black;
+        static const ColourValue White;
+        static const ColourValue Red;
+        static const ColourValue Green;
+        static const ColourValue Blue;
+
+	    explicit ColourValue( float red = 1.0f,
+				    float green = 1.0f,
+				    float blue = 1.0f,
+				    float alpha = 1.0f ) : r(red), g(green), b(blue), a(alpha)
+        { }
+
+	    bool operator==(const ColourValue& rhs) const;
+	    bool operator!=(const ColourValue& rhs) const;
+
+        float r,g,b,a;
+
+	    /** Retrieves colour as RGBA.
+	    */
+	    RGBA getAsRGBA(void) const;
+
+	    /** Retrieves colour as ARGB.
+	    */
+	    ARGB getAsARGB(void) const;
+
+		/** Retrieves colour as BGRA.
+		*/
+		BGRA getAsBGRA(void) const;
+
+		/** Retrieves colours as ABGR */
+	    ABGR getAsABGR(void) const;
+
+	    /** Sets colour as RGBA.
+	    */
+        void setAsRGBA(const RGBA val);
+
+	    /** Sets colour as ARGB.
+	    */
+        void setAsARGB(const ARGB val);
+
+		/** Sets colour as BGRA.
+		*/
+		void setAsBGRA(const BGRA val);
+
+	    /** Sets colour as ABGR.
+	    */
+        void setAsABGR(const ABGR val);
+
+        /** Clamps colour value to the range [0, 1].
+        */
+        void saturate(void)
+        {
+            if (r < 0)
+                r = 0;
+            else if (r > 1)
+                r = 1;
+
+            if (g < 0)
+                g = 0;
+            else if (g > 1)
+                g = 1;
+
+            if (b < 0)
+                b = 0;
+            else if (b > 1)
+                b = 1;
+
+            if (a < 0)
+                a = 0;
+            else if (a > 1)
+                a = 1;
+        }
+
+        /** As saturate, except that this colour value is unaffected and
+            the saturated colour value is returned as a copy. */
+        ColourValue saturateCopy(void) const
+        {
+            ColourValue ret = *this;
+            ret.saturate();
+            return ret;
+        }
+
+		/// Array accessor operator
+		inline float operator [] ( const size_t i ) const
+		{
+			assert( i < 4 );
+
+			return *(&r+i);
+		}
+
+		/// Array accessor operator
+		inline float& operator [] ( const size_t i )
+		{
+			assert( i < 4 );
+
+			return *(&r+i);
+		}
+
+		/// Pointer accessor for direct copying
+		inline float* ptr()
+		{
+			return &r;
+		}
+		/// Pointer accessor for direct copying
+		inline const float* ptr() const
+		{
+			return &r;
+		}
+
+		
+		// arithmetic operations
+        inline ColourValue operator + ( const ColourValue& rkVector ) const
+        {
+            ColourValue kSum;
+
+            kSum.r = r + rkVector.r;
+            kSum.g = g + rkVector.g;
+            kSum.b = b + rkVector.b;
+            kSum.a = a + rkVector.a;
+
+            return kSum;
+        }
+
+        inline ColourValue operator - ( const ColourValue& rkVector ) const
+        {
+            ColourValue kDiff;
+
+            kDiff.r = r - rkVector.r;
+            kDiff.g = g - rkVector.g;
+            kDiff.b = b - rkVector.b;
+            kDiff.a = a - rkVector.a;
+
+            return kDiff;
+        }
+
+        inline ColourValue operator * (const float fScalar ) const
+        {
+            ColourValue kProd;
+
+            kProd.r = fScalar*r;
+            kProd.g = fScalar*g;
+            kProd.b = fScalar*b;
+            kProd.a = fScalar*a;
+
+            return kProd;
+        }
+
+        inline ColourValue operator * ( const ColourValue& rhs) const
+        {
+            ColourValue kProd;
+
+            kProd.r = rhs.r * r;
+            kProd.g = rhs.g * g;
+            kProd.b = rhs.b * b;
+            kProd.a = rhs.a * a;
+
+            return kProd;
+        }
+
+        inline ColourValue operator / ( const ColourValue& rhs) const
+        {
+            ColourValue kProd;
+
+            kProd.r = rhs.r / r;
+            kProd.g = rhs.g / g;
+            kProd.b = rhs.b / b;
+            kProd.a = rhs.a / a;
+
+            return kProd;
+        }
+
+        inline ColourValue operator / (const float fScalar ) const
+        {
+            assert( fScalar != 0.0 );
+
+            ColourValue kDiv;
+
+            float fInv = 1.0 / fScalar;
+            kDiv.r = r * fInv;
+            kDiv.g = g * fInv;
+            kDiv.b = b * fInv;
+            kDiv.a = a * fInv;
+
+            return kDiv;
+        }
+
+        inline friend ColourValue operator * (const float fScalar, const ColourValue& rkVector )
+        {
+            ColourValue kProd;
+
+            kProd.r = fScalar * rkVector.r;
+            kProd.g = fScalar * rkVector.g;
+            kProd.b = fScalar * rkVector.b;
+            kProd.a = fScalar * rkVector.a;
+
+            return kProd;
+        }
+
+        // arithmetic updates
+        inline ColourValue& operator += ( const ColourValue& rkVector )
+        {
+            r += rkVector.r;
+            g += rkVector.g;
+            b += rkVector.b;
+            a += rkVector.a;
+
+            return *this;
+        }
+
+        inline ColourValue& operator -= ( const ColourValue& rkVector )
+        {
+            r -= rkVector.r;
+            g -= rkVector.g;
+            b -= rkVector.b;
+            a -= rkVector.a;
+
+            return *this;
+        }
+
+        inline ColourValue& operator *= (const float fScalar )
+        {
+            r *= fScalar;
+            g *= fScalar;
+            b *= fScalar;
+            a *= fScalar;
+            return *this;
+        }
+
+        inline ColourValue& operator /= (const float fScalar )
+        {
+            assert( fScalar != 0.0 );
+
+            float fInv = 1.0 / fScalar;
+
+            r *= fInv;
+            g *= fInv;
+            b *= fInv;
+            a *= fInv;
+
+            return *this;
+        }
+
+		/** Set a colour value from Hue, Saturation and Brightness.
+		@param hue Hue value, scaled to the [0,1] range as opposed to the 0-360
+		@param saturation Saturation level, [0,1]
+		@param brightness Brightness level, [0,1]
+		*/
+		void setHSB(Real hue, Real saturation, Real brightness);
+
+		/** Convert the current colour to Hue, Saturation and Brightness values. 
+		@param hue Output hue value, scaled to the [0,1] range as opposed to the 0-360
+		@param saturation Output saturation level, [0,1]
+		@param brightness Output brightness level, [0,1]
+		*/
+		void getHSB(Real* hue, Real* saturation, Real* brightness) const;
+
+
+
+		/** Function for writing to a stream.
+		*/
+		inline _OgreExport friend std::ostream& operator <<
+			( std::ostream& o, const ColourValue& c )
+		{
+			o << "ColourValue(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")";
+			return o;
+		}
+
+    };
+
+} // namespace
+
+#endif
Index: sandbox_light/src/external/ogremath/OgreConfig.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreConfig.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreConfig.h	(revision 5789)
@@ -0,0 +1,162 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Config_H_
+#define __Config_H_
+
+// Read configuration options; some systems use an auto-generated config.h,
+// other use a manually generated config.h; in any case just define
+// HAVE_CONFIG_H to include the custom config.h file.
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/** If set to 1, profiling code will be included in the application. When you
+	are deploying your application you will probably want to set this to 0 */
+#define OGRE_PROFILING 0
+
+/** There are three modes for handling asserts in OGRE:
+0 - STANDARD - Standard asserts in debug builds, nothing in release builds
+1 - RELEASE_EXCEPTIONS - Standard asserts in debug builds, exceptions in release builds
+2 - EXCEPTIONS - Exceptions in debug builds, exceptions in release builds
+*/
+#define OGRE_ASSERT_MODE 0
+
+/** If set to >0, OGRE will always 'think' that the graphics card only has the
+    number of texture units specified. Very useful for testing multipass fallback.
+*/
+#define OGRE_PRETEND_TEXTURE_UNITS 0
+
+/** If set to 1, Real is typedef'ed to double. Otherwise, Real is typedef'ed
+    to float. Setting this allows you to perform mathematical operations in the
+	CPU (Quaternion, Vector3 etc) with more precision, but bear in mind that the
+	GPU still operates in single-precision mode.
+*/
+#ifndef OGRE_DOUBLE_PRECISION
+#define OGRE_DOUBLE_PRECISION 0
+#endif
+
+/** Define number of texture coordinate sets allowed per vertex.
+*/
+#define OGRE_MAX_TEXTURE_COORD_SETS 6
+
+/** Define max number of texture layers allowed per pass on any card.
+*/
+#define OGRE_MAX_TEXTURE_LAYERS 16
+
+/** Define max number of lights allowed per pass.
+*/
+#define OGRE_MAX_SIMULTANEOUS_LIGHTS 8
+
+/** Define max number of blending weights allowed per vertex.
+*/
+#define OGRE_MAX_BLEND_WEIGHTS 4
+
+/** Define this if you want to link OGRE as a static lib (preferably as a project file)
+*/
+//#define OGRE_STATIC_LIB
+
+
+// define the memory allocator configuration to use
+#define OGRE_MEMORY_ALLOCATOR_STD 1
+#define OGRE_MEMORY_ALLOCATOR_NED 2			 // you need to have nedmalloc on your path for this
+#define OGRE_MEMORY_ALLOCATOR_USER 3
+
+#ifndef OGRE_MEMORY_ALLOCATOR
+#  define OGRE_MEMORY_ALLOCATOR OGRE_MEMORY_ALLOCATOR_NED
+#endif
+
+// enable or disable the memory tracker, recording the memory allocations & tracking leaks
+// default is to disable since it's expensive, but you can enable if needed per build target
+
+#ifndef OGRE_MEMORY_TRACKER_DEBUG_MODE
+#  define OGRE_MEMORY_TRACKER_DEBUG_MODE 0
+#endif
+
+#ifndef OGRE_MEMORY_TRACKER_RELEASE_MODE
+#  define OGRE_MEMORY_TRACKER_RELEASE_MODE 0
+#endif
+/** Define max number of multiple render targets (MRTs) to render to at once.
+*/
+#define OGRE_MAX_MULTIPLE_RENDER_TARGETS 8
+
+/** Support for multithreading, there are 3 options
+
+OGRE_THREAD_SUPPORT = 0
+	No support for threading.		
+OGRE_THREAD_SUPPORT = 1
+	Thread support for background loading, by both loading and constructing resources
+	in a background thread. Resource management and SharedPtr handling becomes
+	thread-safe, and resources may be completely loaded in the background. 
+	The places where threading is available are clearly
+	marked, you should assume state is NOT thread safe unless otherwise
+	stated in relation to this flag.
+OGRE_THREAD_SUPPORT = 2
+	Thread support for background resource preparation. This means that resource
+	data can streamed into memory in the background, but the final resource
+	construction (including RenderSystem dependencies) is still done in the primary
+	thread. Has a lower synchronisation primitive overhead than full threading
+	while still allowing the major blocking aspects of resource management (I/O)
+	to be done in the background.
+*/
+#ifndef OGRE_THREAD_SUPPORT
+#define OGRE_THREAD_SUPPORT 0
+#endif
+#if OGRE_THREAD_SUPPORT != 0 && OGRE_THREAD_SUPPORT != 1 && OGRE_THREAD_SUPPORT != 2
+#define OGRE_THREAD_SUPPORT 1
+#endif
+
+/** Disables use of the FreeImage image library for loading images.
+WARNING: Use only when you want to provide your own image loading code via codecs.
+*/
+#ifndef OGRE_NO_FREEIMAGE
+#define OGRE_NO_FREEIMAGE 0
+#endif
+
+/** Disables use of the DevIL image library for loading images.
+By default DevIL is disabled in Eihort in favour of FreeImage, but you may re-enable
+it if you choose
+*/
+#ifndef OGRE_NO_DEVIL
+#define OGRE_NO_DEVIL 1
+#endif
+
+/** Disables use of the internal image codec for loading DDS files.
+WARNING: Use only when you want to provide your own image loading code via codecs.
+*/
+#ifndef OGRE_NO_DDS_CODEC
+#define OGRE_NO_DDS_CODEC 0
+#endif
+
+/** Enables the use of the new script compilers when Ogre compiles resource scripts.
+*/
+#ifndef OGRE_USE_NEW_COMPILERS
+#define OGRE_USE_NEW_COMPILERS 1
+#endif
+
+#endif
Index: sandbox_light/src/external/ogremath/OgreMath.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreMath.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMath.cpp	(revision 5789)
@@ -0,0 +1,449 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreMath.h"
+#include "asm_math.h"
+#include "OgreVector2.h"
+#include "OgreVector3.h"
+#include "OgreVector4.h"
+#include "OgreMatrix4.h"
+
+
+namespace Ogre
+{
+
+    const Real Math::POS_INFINITY = std::numeric_limits<Real>::infinity();
+    const Real Math::NEG_INFINITY = -std::numeric_limits<Real>::infinity();
+    const Real Math::PI = Real( 4.0 * atan( 1.0 ) );
+    const Real Math::TWO_PI = Real( 2.0 * PI );
+    const Real Math::HALF_PI = Real( 0.5 * PI );
+	const Real Math::fDeg2Rad = PI / Real(180.0);
+	const Real Math::fRad2Deg = Real(180.0) / PI;
+
+    int Math::mTrigTableSize;
+   Math::AngleUnit Math::msAngleUnit;
+
+    Real  Math::mTrigTableFactor;
+    Real *Math::mSinTable = NULL;
+    Real *Math::mTanTable = NULL;
+
+    //-----------------------------------------------------------------------
+    Math::Math( unsigned int trigTableSize )
+    {
+        msAngleUnit = AU_DEGREE;
+
+        mTrigTableSize = trigTableSize;
+        mTrigTableFactor = mTrigTableSize / Math::TWO_PI;
+
+        mSinTable = static_cast<Real*>(malloc(mTrigTableSize * sizeof(Real)));
+        mTanTable = static_cast<Real*>(malloc(mTrigTableSize * sizeof(Real)));
+
+        buildTrigTables();
+    }
+
+    //-----------------------------------------------------------------------
+    Math::~Math()
+    {
+        free(mSinTable);
+        free(mTanTable);
+    }
+
+    //-----------------------------------------------------------------------
+    void Math::buildTrigTables(void)
+    {
+        // Build trig lookup tables
+        // Could get away with building only PI sized Sin table but simpler this 
+        // way. Who cares, it'll ony use an extra 8k of memory anyway and I like 
+        // simplicity.
+        Real angle;
+        for (int i = 0; i < mTrigTableSize; ++i)
+        {
+            angle = Math::TWO_PI * i / mTrigTableSize;
+            mSinTable[i] = sin(angle);
+            mTanTable[i] = tan(angle);
+        }
+    }
+	//-----------------------------------------------------------------------	
+	Real Math::SinTable (Real fValue)
+    {
+        // Convert range to index values, wrap if required
+        int idx;
+        if (fValue >= 0)
+        {
+            idx = int(fValue * mTrigTableFactor) % mTrigTableSize;
+        }
+        else
+        {
+            idx = mTrigTableSize - (int(-fValue * mTrigTableFactor) % mTrigTableSize) - 1;
+        }
+
+        return mSinTable[idx];
+    }
+	//-----------------------------------------------------------------------
+	Real Math::TanTable (Real fValue)
+    {
+        // Convert range to index values, wrap if required
+		int idx = int(fValue *= mTrigTableFactor) % mTrigTableSize;
+		return mTanTable[idx];
+    }
+    //-----------------------------------------------------------------------
+    int Math::ISign (int iValue)
+    {
+        return ( iValue > 0 ? +1 : ( iValue < 0 ? -1 : 0 ) );
+    }
+    //-----------------------------------------------------------------------
+    Radian Math::ACos (Real fValue)
+    {
+        if ( -1.0 < fValue )
+        {
+            if ( fValue < 1.0 )
+                return Radian(acos(fValue));
+            else
+                return Radian(0.0);
+        }
+        else
+        {
+            return Radian(PI);
+        }
+    }
+    //-----------------------------------------------------------------------
+    Radian Math::ASin (Real fValue)
+    {
+        if ( -1.0 < fValue )
+        {
+            if ( fValue < 1.0 )
+                return Radian(asin(fValue));
+            else
+                return Radian(HALF_PI);
+        }
+        else
+        {
+            return Radian(-HALF_PI);
+        }
+    }
+    //-----------------------------------------------------------------------
+    Real Math::Sign (Real fValue)
+    {
+        if ( fValue > 0.0 )
+            return 1.0;
+
+        if ( fValue < 0.0 )
+            return -1.0;
+
+        return 0.0;
+    }
+	//-----------------------------------------------------------------------
+	Real Math::InvSqrt(Real fValue)
+	{
+		return Real(asm_rsq(fValue));
+	}
+    //-----------------------------------------------------------------------
+    Real Math::UnitRandom ()
+    {
+        return asm_rand() / asm_rand_max();
+    }
+    
+    //-----------------------------------------------------------------------
+    Real Math::RangeRandom (Real fLow, Real fHigh)
+    {
+        return (fHigh-fLow)*UnitRandom() + fLow;
+    }
+
+    //-----------------------------------------------------------------------
+    Real Math::SymmetricRandom ()
+    {
+		return 2.0f * UnitRandom() - 1.0f;
+    }
+
+   //-----------------------------------------------------------------------
+    void Math::setAngleUnit(Math::AngleUnit unit)
+   {
+       msAngleUnit = unit;
+   }
+   //-----------------------------------------------------------------------
+   Math::AngleUnit Math::getAngleUnit(void)
+   {
+       return msAngleUnit;
+   }
+    //-----------------------------------------------------------------------
+    Real Math::AngleUnitsToRadians(Real angleunits)
+    {
+       if (msAngleUnit == AU_DEGREE)
+           return angleunits * fDeg2Rad;
+       else
+           return angleunits;
+    }
+
+    //-----------------------------------------------------------------------
+    Real Math::RadiansToAngleUnits(Real radians)
+    {
+       if (msAngleUnit == AU_DEGREE)
+           return radians * fRad2Deg;
+       else
+           return radians;
+    }
+
+    //-----------------------------------------------------------------------
+    Real Math::AngleUnitsToDegrees(Real angleunits)
+    {
+       if (msAngleUnit == AU_RADIAN)
+           return angleunits * fRad2Deg;
+       else
+           return angleunits;
+    }
+
+    //-----------------------------------------------------------------------
+    Real Math::DegreesToAngleUnits(Real degrees)
+    {
+       if (msAngleUnit == AU_RADIAN)
+           return degrees * fDeg2Rad;
+       else
+           return degrees;
+    }
+
+    //-----------------------------------------------------------------------
+	bool Math::pointInTri2D(const Vector2& p, const Vector2& a, 
+		const Vector2& b, const Vector2& c)
+    {
+		// Winding must be consistent from all edges for point to be inside
+		Vector2 v1, v2;
+		Real dot[3];
+		bool zeroDot[3];
+
+		v1 = b - a;
+		v2 = p - a;
+
+		// Note we don't care about normalisation here since sign is all we need
+		// It means we don't have to worry about magnitude of cross products either
+		dot[0] = v1.crossProduct(v2);
+		zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3);
+
+
+		v1 = c - b;
+		v2 = p - b;
+
+		dot[1] = v1.crossProduct(v2);
+		zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3);
+
+		// Compare signs (ignore colinear / coincident points)
+		if(!zeroDot[0] && !zeroDot[1] 
+		&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
+		{
+			return false;
+		}
+
+		v1 = a - c;
+		v2 = p - c;
+
+		dot[2] = v1.crossProduct(v2);
+		zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3);
+		// Compare signs (ignore colinear / coincident points)
+		if((!zeroDot[0] && !zeroDot[2] 
+			&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
+			(!zeroDot[1] && !zeroDot[2] 
+			&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
+		{
+			return false;
+		}
+
+
+		return true;
+    }
+	//-----------------------------------------------------------------------
+	bool Math::pointInTri3D(const Vector3& p, const Vector3& a, 
+		const Vector3& b, const Vector3& c, const Vector3& normal)
+	{
+        // Winding must be consistent from all edges for point to be inside
+		Vector3 v1, v2;
+		Real dot[3];
+		bool zeroDot[3];
+
+        v1 = b - a;
+        v2 = p - a;
+
+		// Note we don't care about normalisation here since sign is all we need
+		// It means we don't have to worry about magnitude of cross products either
+        dot[0] = v1.crossProduct(v2).dotProduct(normal);
+		zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3);
+
+
+        v1 = c - b;
+        v2 = p - b;
+
+		dot[1] = v1.crossProduct(v2).dotProduct(normal);
+		zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3);
+
+		// Compare signs (ignore colinear / coincident points)
+		if(!zeroDot[0] && !zeroDot[1] 
+			&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
+		{
+            return false;
+		}
+
+        v1 = a - c;
+        v2 = p - c;
+
+		dot[2] = v1.crossProduct(v2).dotProduct(normal);
+		zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3);
+		// Compare signs (ignore colinear / coincident points)
+		if((!zeroDot[0] && !zeroDot[2] 
+			&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
+			(!zeroDot[1] && !zeroDot[2] 
+			&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
+		{
+			return false;
+		}
+
+
+        return true;
+	}
+    //-----------------------------------------------------------------------
+    bool Math::RealEqual( Real a, Real b, Real tolerance )
+    {
+        if (fabs(b-a) <= tolerance)
+            return true;
+        else
+            return false;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Math::calculateTangentSpaceVector(
+        const Vector3& position1, const Vector3& position2, const Vector3& position3,
+        Real u1, Real v1, Real u2, Real v2, Real u3, Real v3)
+    {
+	    //side0 is the vector along one side of the triangle of vertices passed in, 
+	    //and side1 is the vector along another side. Taking the cross product of these returns the normal.
+	    Vector3 side0 = position1 - position2;
+	    Vector3 side1 = position3 - position1;
+	    //Calculate face normal
+	    Vector3 normal = side1.crossProduct(side0);
+	    normal.normalise();
+	    //Now we use a formula to calculate the tangent. 
+	    Real deltaV0 = v1 - v2;
+	    Real deltaV1 = v3 - v1;
+	    Vector3 tangent = deltaV1 * side0 - deltaV0 * side1;
+	    tangent.normalise();
+	    //Calculate binormal
+	    Real deltaU0 = u1 - u2;
+	    Real deltaU1 = u3 - u1;
+	    Vector3 binormal = deltaU1 * side0 - deltaU0 * side1;
+	    binormal.normalise();
+	    //Now, we take the cross product of the tangents to get a vector which 
+	    //should point in the same direction as our normal calculated above. 
+	    //If it points in the opposite direction (the dot product between the normals is less than zero), 
+	    //then we need to reverse the s and t tangents. 
+	    //This is because the triangle has been mirrored when going from tangent space to object space.
+	    //reverse tangents if necessary
+	    Vector3 tangentCross = tangent.crossProduct(binormal);
+	    if (tangentCross.dotProduct(normal) < 0.0f)
+	    {
+		    tangent = -tangent;
+		    binormal = -binormal;
+	    }
+
+        return tangent;
+
+    }
+    //-----------------------------------------------------------------------
+    Vector4 Math::calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
+    {
+        Vector3 normal = calculateBasicFaceNormal(v1, v2, v3);
+        // Now set up the w (distance of tri from origin
+        return Vector4(normal.x, normal.y, normal.z, -(normal.dotProduct(v1)));
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Math::calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
+    {
+        Vector3 normal = (v2 - v1).crossProduct(v3 - v1);
+        normal.normalise();
+        return normal;
+    }
+    //-----------------------------------------------------------------------
+    Vector4 Math::calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3)
+    {
+        Vector3 normal = calculateBasicFaceNormalWithoutNormalize(v1, v2, v3);
+        // Now set up the w (distance of tri from origin)
+        return Vector4(normal.x, normal.y, normal.z, -(normal.dotProduct(v1)));
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Math::calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3)
+    {
+        Vector3 normal = (v2 - v1).crossProduct(v3 - v1);
+        return normal;
+    }
+	//-----------------------------------------------------------------------
+	Real Math::gaussianDistribution(Real x, Real offset, Real scale)
+	{
+		Real nom = Math::Exp(
+			-Math::Sqr(x - offset) / (2 * Math::Sqr(scale)));
+		Real denom = scale * Math::Sqrt(2 * Math::PI);
+
+		return nom / denom;
+
+	}
+	//---------------------------------------------------------------------
+	Matrix4 Math::makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
+		const Matrix4* reflectMatrix)
+	{
+		Matrix4 viewMatrix;
+
+		// 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
+		Matrix3 rot;
+		orientation.ToRotationMatrix(rot);
+
+		// Make the translation relative to new axes
+		Matrix3 rotT = rot.Transpose();
+		Vector3 trans = -rotT * position;
+
+		// Make final matrix
+		viewMatrix = Matrix4::IDENTITY;
+		viewMatrix = rotT; // fills upper 3x3
+		viewMatrix[0][3] = trans.x;
+		viewMatrix[1][3] = trans.y;
+		viewMatrix[2][3] = trans.z;
+
+		// Deal with reflections
+		if (reflectMatrix)
+		{
+			viewMatrix = viewMatrix * (*reflectMatrix);
+		}
+
+		return viewMatrix;
+
+	}
+
+}
Index: sandbox_light/src/external/ogremath/OgreMath.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreMath.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMath.h	(revision 5789)
@@ -0,0 +1,510 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Math_H__
+#define __Math_H__
+
+#include "OgrePrerequisites.h"
+
+#include <cassert>
+#include <cmath>
+#include <vector>
+#include <utility>
+#include <list>
+#include <limits>
+
+namespace Ogre
+{
+    /** Wrapper class which indicates a given angle value is in Radians.
+    @remarks
+        Radian values are interchangeable with Degree values, and conversions
+        will be done automatically between them.
+    */
+	class Radian
+	{
+		Real mRad;
+
+	public:
+		explicit Radian ( Real r=0 ) : mRad(r) {}
+		Radian ( const Degree& d );
+		Radian& operator = ( const Real& f ) { mRad = f; return *this; }
+		Radian& operator = ( const Radian& r ) { mRad = r.mRad; return *this; }
+		Radian& operator = ( const Degree& d );
+
+		Real valueDegrees() const; // see bottom of this file
+		Real valueRadians() const { return mRad; }
+		Real valueAngleUnits() const;
+
+        const Radian& operator + () const { return *this; }
+		Radian operator + ( const Radian& r ) const { return Radian ( mRad + r.mRad ); }
+		Radian operator + ( const Degree& d ) const;
+		Radian& operator += ( const Radian& r ) { mRad += r.mRad; return *this; }
+		Radian& operator += ( const Degree& d );
+		Radian operator - () const { return Radian(-mRad); }
+		Radian operator - ( const Radian& r ) const { return Radian ( mRad - r.mRad ); }
+		Radian operator - ( const Degree& d ) const;
+		Radian& operator -= ( const Radian& r ) { mRad -= r.mRad; return *this; }
+		Radian& operator -= ( const Degree& d );
+		Radian operator * ( Real f ) const { return Radian ( mRad * f ); }
+        Radian operator * ( const Radian& f ) const { return Radian ( mRad * f.mRad ); }
+		Radian& operator *= ( Real f ) { mRad *= f; return *this; }
+		Radian operator / ( Real f ) const { return Radian ( mRad / f ); }
+		Radian& operator /= ( Real f ) { mRad /= f; return *this; }
+
+		bool operator <  ( const Radian& r ) const { return mRad <  r.mRad; }
+		bool operator <= ( const Radian& r ) const { return mRad <= r.mRad; }
+		bool operator == ( const Radian& r ) const { return mRad == r.mRad; }
+		bool operator != ( const Radian& r ) const { return mRad != r.mRad; }
+		bool operator >= ( const Radian& r ) const { return mRad >= r.mRad; }
+		bool operator >  ( const Radian& r ) const { return mRad >  r.mRad; }
+	};
+
+    /** Wrapper class which indicates a given angle value is in Degrees.
+    @remarks
+        Degree values are interchangeable with Radian values, and conversions
+        will be done automatically between them.
+    */
+	class Degree
+	{
+		Real mDeg; // if you get an error here - make sure to define/typedef 'Real' first
+
+	public:
+		explicit Degree ( Real d=0 ) : mDeg(d) {}
+		Degree ( const Radian& r ) : mDeg(r.valueDegrees()) {}
+		Degree& operator = ( const Real& f ) { mDeg = f; return *this; }
+		Degree& operator = ( const Degree& d ) { mDeg = d.mDeg; return *this; }
+		Degree& operator = ( const Radian& r ) { mDeg = r.valueDegrees(); return *this; }
+
+		Real valueDegrees() const { return mDeg; }
+		Real valueRadians() const; // see bottom of this file
+		Real valueAngleUnits() const;
+
+		const Degree& operator + () const { return *this; }
+		Degree operator + ( const Degree& d ) const { return Degree ( mDeg + d.mDeg ); }
+		Degree operator + ( const Radian& r ) const { return Degree ( mDeg + r.valueDegrees() ); }
+		Degree& operator += ( const Degree& d ) { mDeg += d.mDeg; return *this; }
+		Degree& operator += ( const Radian& r ) { mDeg += r.valueDegrees(); return *this; }
+		Degree operator - () const { return Degree(-mDeg); }
+		Degree operator - ( const Degree& d ) const { return Degree ( mDeg - d.mDeg ); }
+		Degree operator - ( const Radian& r ) const { return Degree ( mDeg - r.valueDegrees() ); }
+		Degree& operator -= ( const Degree& d ) { mDeg -= d.mDeg; return *this; }
+		Degree& operator -= ( const Radian& r ) { mDeg -= r.valueDegrees(); return *this; }
+		Degree operator * ( Real f ) const { return Degree ( mDeg * f ); }
+        Degree operator * ( const Degree& f ) const { return Degree ( mDeg * f.mDeg ); }
+		Degree& operator *= ( Real f ) { mDeg *= f; return *this; }
+		Degree operator / ( Real f ) const { return Degree ( mDeg / f ); }
+		Degree& operator /= ( Real f ) { mDeg /= f; return *this; }
+
+		bool operator <  ( const Degree& d ) const { return mDeg <  d.mDeg; }
+		bool operator <= ( const Degree& d ) const { return mDeg <= d.mDeg; }
+		bool operator == ( const Degree& d ) const { return mDeg == d.mDeg; }
+		bool operator != ( const Degree& d ) const { return mDeg != d.mDeg; }
+		bool operator >= ( const Degree& d ) const { return mDeg >= d.mDeg; }
+		bool operator >  ( const Degree& d ) const { return mDeg >  d.mDeg; }
+	};
+
+    /** Wrapper class which identifies a value as the currently default angle 
+        type, as defined by Math::setAngleUnit.
+    @remarks
+        Angle values will be automatically converted between radians and degrees,
+        as appropriate.
+    */
+	class Angle
+	{
+		Real mAngle;
+	public:
+		explicit Angle ( Real angle ) : mAngle(angle) {}
+		operator Radian() const;
+		operator Degree() const;
+	};
+
+	// these functions could not be defined within the class definition of class
+	// Radian because they required class Degree to be defined
+	inline Radian::Radian ( const Degree& d ) : mRad(d.valueRadians()) {
+	}
+	inline Radian& Radian::operator = ( const Degree& d ) {
+		mRad = d.valueRadians(); return *this;
+	}
+	inline Radian Radian::operator + ( const Degree& d ) const {
+		return Radian ( mRad + d.valueRadians() );
+	}
+	inline Radian& Radian::operator += ( const Degree& d ) {
+		mRad += d.valueRadians();
+		return *this;
+	}
+	inline Radian Radian::operator - ( const Degree& d ) const {
+		return Radian ( mRad - d.valueRadians() );
+	}
+	inline Radian& Radian::operator -= ( const Degree& d ) {
+		mRad -= d.valueRadians();
+		return *this;
+	}
+
+    /** Class to provide access to common mathematical functions.
+        @remarks
+            Most of the maths functions are aliased versions of the C runtime
+            library functions. They are aliased here to provide future
+            optimisation opportunities, either from faster RTLs or custom
+            math approximations.
+        @note
+            <br>This is based on MgcMath.h from
+            <a href="http://www.geometrictools.com/">Wild Magic</a>.
+    */
+    class _OgreExport Math 
+    {
+   public:
+       /** The angular units used by the API. This functionality is now deprecated in favor
+	       of discreet angular unit types ( see Degree and Radian above ). The only place
+		   this functionality is actually still used is when parsing files. Search for
+		   usage of the Angle class for those instances
+       */
+       enum AngleUnit
+       {
+           AU_DEGREE,
+           AU_RADIAN
+       };
+
+    protected:
+       // angle units used by the api
+       static AngleUnit msAngleUnit;
+
+        /// Size of the trig tables as determined by constructor.
+        static int mTrigTableSize;
+
+        /// Radian -> index factor value ( mTrigTableSize / 2 * PI )
+        static Real mTrigTableFactor;
+        static Real* mSinTable;
+        static Real* mTanTable;
+
+        /** Private function to build trig tables.
+        */
+        void buildTrigTables();
+
+		static Real SinTable (Real fValue);
+		static Real TanTable (Real fValue);
+    public:
+        /** Default constructor.
+            @param
+                trigTableSize Optional parameter to set the size of the
+                tables used to implement Sin, Cos, Tan
+        */
+        Math(unsigned int trigTableSize = 4096);
+
+        /** Default destructor.
+        */
+        ~Math();
+
+		static inline int IAbs (int iValue) { return ( iValue >= 0 ? iValue : -iValue ); }
+		static inline int ICeil (float fValue) { return int(ceil(fValue)); }
+		static inline int IFloor (float fValue) { return int(floor(fValue)); }
+        static int ISign (int iValue);
+
+		static inline Real Abs (Real fValue) { return Real(fabs(fValue)); }
+		static inline Degree Abs (const Degree& dValue) { return Degree(fabs(dValue.valueDegrees())); }
+		static inline Radian Abs (const Radian& rValue) { return Radian(fabs(rValue.valueRadians())); }
+		static Radian ACos (Real fValue);
+		static Radian ASin (Real fValue);
+		static inline Radian ATan (Real fValue) { return Radian(atan(fValue)); }
+		static inline Radian ATan2 (Real fY, Real fX) { return Radian(atan2(fY,fX)); }
+		static inline Real Ceil (Real fValue) { return Real(ceil(fValue)); }
+
+        /** Cosine function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+        static inline Real Cos (const Radian& fValue, bool useTables = false) {
+			return (!useTables) ? Real(cos(fValue.valueRadians())) : SinTable(fValue.valueRadians() + HALF_PI);
+		}
+        /** Cosine function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+        static inline Real Cos (Real fValue, bool useTables = false) {
+			return (!useTables) ? Real(cos(fValue)) : SinTable(fValue + HALF_PI);
+		}
+
+		static inline Real Exp (Real fValue) { return Real(exp(fValue)); }
+
+		static inline Real Floor (Real fValue) { return Real(floor(fValue)); }
+
+		static inline Real Log (Real fValue) { return Real(log(fValue)); }
+
+		static inline Real Pow (Real fBase, Real fExponent) { return Real(pow(fBase,fExponent)); }
+
+        static Real Sign (Real fValue);
+		static inline Radian Sign ( const Radian& rValue )
+		{
+			return Radian(Sign(rValue.valueRadians()));
+		}
+		static inline Degree Sign ( const Degree& dValue )
+		{
+			return Degree(Sign(dValue.valueDegrees()));
+		}
+
+        /** Sine function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+        static inline Real Sin (const Radian& fValue, bool useTables = false) {
+			return (!useTables) ? Real(sin(fValue.valueRadians())) : SinTable(fValue.valueRadians());
+		}
+        /** Sine function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+        static inline Real Sin (Real fValue, bool useTables = false) {
+			return (!useTables) ? Real(sin(fValue)) : SinTable(fValue);
+		}
+
+		static inline Real Sqr (Real fValue) { return fValue*fValue; }
+
+		static inline Real Sqrt (Real fValue) { return Real(sqrt(fValue)); }
+
+        static inline Radian Sqrt (const Radian& fValue) { return Radian(sqrt(fValue.valueRadians())); }
+
+        static inline Degree Sqrt (const Degree& fValue) { return Degree(sqrt(fValue.valueDegrees())); }
+
+        /** Inverse square root i.e. 1 / Sqrt(x), good for vector
+            normalisation.
+        */
+		static Real InvSqrt(Real fValue);
+
+        static Real UnitRandom ();  // in [0,1]
+
+        static Real RangeRandom (Real fLow, Real fHigh);  // in [fLow,fHigh]
+
+        static Real SymmetricRandom ();  // in [-1,1]
+
+        /** Tangent function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+		static inline Real Tan (const Radian& fValue, bool useTables = false) {
+			return (!useTables) ? Real(tan(fValue.valueRadians())) : TanTable(fValue.valueRadians());
+		}
+        /** Tangent function.
+            @param
+                fValue Angle in radians
+            @param
+                useTables If true, uses lookup tables rather than
+                calculation - faster but less accurate.
+        */
+		static inline Real Tan (Real fValue, bool useTables = false) {
+			return (!useTables) ? Real(tan(fValue)) : TanTable(fValue);
+		}
+
+		static inline Real DegreesToRadians(Real degrees) { return degrees * fDeg2Rad; }
+        static inline Real RadiansToDegrees(Real radians) { return radians * fRad2Deg; }
+
+       /** These functions used to set the assumed angle units (radians or degrees) 
+            expected when using the Angle type.
+       @par
+            You can set this directly after creating a new Root, and also before/after resource creation,
+            depending on whether you want the change to affect resource files.
+       */
+       static void setAngleUnit(AngleUnit unit);
+       /** Get the unit being used for angles. */
+       static AngleUnit getAngleUnit(void);
+
+       /** Convert from the current AngleUnit to radians. */
+       static Real AngleUnitsToRadians(Real units);
+       /** Convert from radians to the current AngleUnit . */
+       static Real RadiansToAngleUnits(Real radians);
+       /** Convert from the current AngleUnit to degrees. */
+       static Real AngleUnitsToDegrees(Real units);
+       /** Convert from degrees to the current AngleUnit. */
+       static Real DegreesToAngleUnits(Real degrees);
+
+       /** Checks whether a given point is inside a triangle, in a
+            2-dimensional (Cartesian) space.
+            @remarks
+                The vertices of the triangle must be given in either
+                trigonometrical (anticlockwise) or inverse trigonometrical
+                (clockwise) order.
+            @param
+                p The point.
+            @param
+                a The triangle's first vertex.
+            @param
+                b The triangle's second vertex.
+            @param
+                c The triangle's third vertex.
+            @returns
+                If the point resides in the triangle, <b>true</b> is
+                returned.
+            @par
+                If the point is outside the triangle, <b>false</b> is
+                returned.
+        */
+        static bool pointInTri2D(const Vector2& p, const Vector2& a, 
+			const Vector2& b, const Vector2& c);
+
+       /** Checks whether a given 3D point is inside a triangle.
+       @remarks
+            The vertices of the triangle must be given in either
+            trigonometrical (anticlockwise) or inverse trigonometrical
+            (clockwise) order, and the point must be guaranteed to be in the
+			same plane as the triangle
+        @param
+            p The point.
+        @param
+            a The triangle's first vertex.
+        @param
+            b The triangle's second vertex.
+        @param
+            c The triangle's third vertex.
+		@param 
+			normal The triangle plane's normal (passed in rather than calculated
+				on demand since the caller may already have it)
+        @returns
+            If the point resides in the triangle, <b>true</b> is
+            returned.
+        @par
+            If the point is outside the triangle, <b>false</b> is
+            returned.
+        */
+        static bool pointInTri3D(const Vector3& p, const Vector3& a, 
+			const Vector3& b, const Vector3& c, const Vector3& normal);
+
+        /** Compare 2 reals, using tolerance for inaccuracies.
+        */
+        static bool RealEqual(Real a, Real b,
+            Real tolerance = std::numeric_limits<Real>::epsilon());
+
+        /** Calculates the tangent space vector for a given set of positions / texture coords. */
+        static Vector3 calculateTangentSpaceVector(
+            const Vector3& position1, const Vector3& position2, const Vector3& position3,
+            Real u1, Real v1, Real u2, Real v2, Real u3, Real v3);
+
+        /** Calculate a face normal, including the w component which is the offset from the origin. */
+        static Vector4 calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
+        /** Calculate a face normal, no w-information. */
+        static Vector3 calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
+        /** Calculate a face normal without normalize, including the w component which is the offset from the origin. */
+        static Vector4 calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
+        /** Calculate a face normal without normalize, no w-information. */
+        static Vector3 calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
+
+		/** Generates a value based on the Gaussian (normal) distribution function
+			with the given offset and scale parameters.
+		*/
+		static Real gaussianDistribution(Real x, Real offset = 0.0f, Real scale = 1.0f);
+
+		/** Clamp a value within an inclusive range. */
+		template <typename T>
+		static T Clamp(T val, T minval, T maxval)
+		{
+			assert (minval < maxval && "Invalid clamp range");
+			return std::max(std::min(val, maxval), minval);
+		}
+
+		static Matrix4 makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
+			const Matrix4* reflectMatrix = 0);
+
+
+
+        static const Real POS_INFINITY;
+        static const Real NEG_INFINITY;
+        static const Real PI;
+        static const Real TWO_PI;
+        static const Real HALF_PI;
+		static const Real fDeg2Rad;
+		static const Real fRad2Deg;
+
+    };
+
+	// these functions must be defined down here, because they rely on the
+	// angle unit conversion functions in class Math:
+
+	inline Real Radian::valueDegrees() const
+	{
+		return Math::RadiansToDegrees ( mRad );
+	}
+
+	inline Real Radian::valueAngleUnits() const
+	{
+		return Math::RadiansToAngleUnits ( mRad );
+	}
+
+	inline Real Degree::valueRadians() const
+	{
+		return Math::DegreesToRadians ( mDeg );
+	}
+
+	inline Real Degree::valueAngleUnits() const
+	{
+		return Math::DegreesToAngleUnits ( mDeg );
+	}
+
+	inline Angle::operator Radian() const
+	{
+		return Radian(Math::AngleUnitsToRadians(mAngle));
+	}
+
+	inline Angle::operator Degree() const
+	{
+		return Degree(Math::AngleUnitsToDegrees(mAngle));
+	}
+
+	inline Radian operator * ( Real a, const Radian& b )
+	{
+		return Radian ( a * b.valueRadians() );
+	}
+
+	inline Radian operator / ( Real a, const Radian& b )
+	{
+		return Radian ( a / b.valueRadians() );
+	}
+
+	inline Degree operator * ( Real a, const Degree& b )
+	{
+		return Degree ( a * b.valueDegrees() );
+	}
+
+	inline Degree operator / ( Real a, const Degree& b )
+	{
+		return Degree ( a / b.valueDegrees() );
+	}
+
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgreMatrix3.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreMatrix3.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMatrix3.cpp	(revision 5789)
@@ -0,0 +1,1511 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreMatrix3.h"
+
+#include "OgreMath.h"
+
+// Adapted from Matrix math by Wild Magic http://www.geometrictools.com/
+
+namespace Ogre
+{
+    const Real Matrix3::EPSILON = 1e-06;
+    const Matrix3 Matrix3::ZERO(0,0,0,0,0,0,0,0,0);
+    const Matrix3 Matrix3::IDENTITY(1,0,0,0,1,0,0,0,1);
+    const Real Matrix3::ms_fSvdEpsilon = 1e-04;
+    const unsigned int Matrix3::ms_iSvdMaxIterations = 32;
+
+    //-----------------------------------------------------------------------
+    Vector3 Matrix3::GetColumn (size_t iCol) const
+    {
+        assert( 0 <= iCol && iCol < 3 );
+        return Vector3(m[0][iCol],m[1][iCol],
+            m[2][iCol]);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::SetColumn(size_t iCol, const Vector3& vec)
+    {
+        assert( 0 <= iCol && iCol < 3 );
+        m[0][iCol] = vec.x;
+        m[1][iCol] = vec.y;
+        m[2][iCol] = vec.z;
+
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis)
+    {
+        SetColumn(0,xAxis);
+        SetColumn(1,yAxis);
+        SetColumn(2,zAxis);
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Matrix3::operator== (const Matrix3& rkMatrix) const
+    {
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+            {
+                if ( m[iRow][iCol] != rkMatrix.m[iRow][iCol] )
+                    return false;
+            }
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const
+    {
+        Matrix3 kSum;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+            {
+                kSum.m[iRow][iCol] = m[iRow][iCol] +
+                    rkMatrix.m[iRow][iCol];
+            }
+        }
+        return kSum;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const
+    {
+        Matrix3 kDiff;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+            {
+                kDiff.m[iRow][iCol] = m[iRow][iCol] -
+                    rkMatrix.m[iRow][iCol];
+            }
+        }
+        return kDiff;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const
+    {
+        Matrix3 kProd;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+            {
+                kProd.m[iRow][iCol] =
+                    m[iRow][0]*rkMatrix.m[0][iCol] +
+                    m[iRow][1]*rkMatrix.m[1][iCol] +
+                    m[iRow][2]*rkMatrix.m[2][iCol];
+            }
+        }
+        return kProd;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Matrix3::operator* (const Vector3& rkPoint) const
+    {
+        Vector3 kProd;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            kProd[iRow] =
+                m[iRow][0]*rkPoint[0] +
+                m[iRow][1]*rkPoint[1] +
+                m[iRow][2]*rkPoint[2];
+        }
+        return kProd;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix)
+    {
+        Vector3 kProd;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            kProd[iRow] =
+                rkPoint[0]*rkMatrix.m[0][iRow] +
+                rkPoint[1]*rkMatrix.m[1][iRow] +
+                rkPoint[2]*rkMatrix.m[2][iRow];
+        }
+        return kProd;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::operator- () const
+    {
+        Matrix3 kNeg;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                kNeg[iRow][iCol] = -m[iRow][iCol];
+        }
+        return kNeg;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::operator* (Real fScalar) const
+    {
+        Matrix3 kProd;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                kProd[iRow][iCol] = fScalar*m[iRow][iCol];
+        }
+        return kProd;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 operator* (Real fScalar, const Matrix3& rkMatrix)
+    {
+        Matrix3 kProd;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                kProd[iRow][iCol] = fScalar*rkMatrix.m[iRow][iCol];
+        }
+        return kProd;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::Transpose () const
+    {
+        Matrix3 kTranspose;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                kTranspose[iRow][iCol] = m[iCol][iRow];
+        }
+        return kTranspose;
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::Inverse (Matrix3& rkInverse, Real fTolerance) const
+    {
+        // Invert a 3x3 using cofactors.  This is about 8 times faster than
+        // the Numerical Recipes code which uses Gaussian elimination.
+
+        rkInverse[0][0] = m[1][1]*m[2][2] -
+            m[1][2]*m[2][1];
+        rkInverse[0][1] = m[0][2]*m[2][1] -
+            m[0][1]*m[2][2];
+        rkInverse[0][2] = m[0][1]*m[1][2] -
+            m[0][2]*m[1][1];
+        rkInverse[1][0] = m[1][2]*m[2][0] -
+            m[1][0]*m[2][2];
+        rkInverse[1][1] = m[0][0]*m[2][2] -
+            m[0][2]*m[2][0];
+        rkInverse[1][2] = m[0][2]*m[1][0] -
+            m[0][0]*m[1][2];
+        rkInverse[2][0] = m[1][0]*m[2][1] -
+            m[1][1]*m[2][0];
+        rkInverse[2][1] = m[0][1]*m[2][0] -
+            m[0][0]*m[2][1];
+        rkInverse[2][2] = m[0][0]*m[1][1] -
+            m[0][1]*m[1][0];
+
+        Real fDet =
+            m[0][0]*rkInverse[0][0] +
+            m[0][1]*rkInverse[1][0]+
+            m[0][2]*rkInverse[2][0];
+
+        if ( Math::Abs(fDet) <= fTolerance )
+            return false;
+
+        Real fInvDet = 1.0/fDet;
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                rkInverse[iRow][iCol] *= fInvDet;
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 Matrix3::Inverse (Real fTolerance) const
+    {
+        Matrix3 kInverse = Matrix3::ZERO;
+        Inverse(kInverse,fTolerance);
+        return kInverse;
+    }
+    //-----------------------------------------------------------------------
+    Real Matrix3::Determinant () const
+    {
+        Real fCofactor00 = m[1][1]*m[2][2] -
+            m[1][2]*m[2][1];
+        Real fCofactor10 = m[1][2]*m[2][0] -
+            m[1][0]*m[2][2];
+        Real fCofactor20 = m[1][0]*m[2][1] -
+            m[1][1]*m[2][0];
+
+        Real fDet =
+            m[0][0]*fCofactor00 +
+            m[0][1]*fCofactor10 +
+            m[0][2]*fCofactor20;
+
+        return fDet;
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::Bidiagonalize (Matrix3& kA, Matrix3& kL,
+        Matrix3& kR)
+    {
+        Real afV[3], afW[3];
+        Real fLength, fSign, fT1, fInvT1, fT2;
+        bool bIdentity;
+
+        // map first column to (*,0,0)
+        fLength = Math::Sqrt(kA[0][0]*kA[0][0] + kA[1][0]*kA[1][0] +
+            kA[2][0]*kA[2][0]);
+        if ( fLength > 0.0 )
+        {
+            fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0);
+            fT1 = kA[0][0] + fSign*fLength;
+            fInvT1 = 1.0/fT1;
+            afV[1] = kA[1][0]*fInvT1;
+            afV[2] = kA[2][0]*fInvT1;
+
+            fT2 = -2.0/(1.0+afV[1]*afV[1]+afV[2]*afV[2]);
+            afW[0] = fT2*(kA[0][0]+kA[1][0]*afV[1]+kA[2][0]*afV[2]);
+            afW[1] = fT2*(kA[0][1]+kA[1][1]*afV[1]+kA[2][1]*afV[2]);
+            afW[2] = fT2*(kA[0][2]+kA[1][2]*afV[1]+kA[2][2]*afV[2]);
+            kA[0][0] += afW[0];
+            kA[0][1] += afW[1];
+            kA[0][2] += afW[2];
+            kA[1][1] += afV[1]*afW[1];
+            kA[1][2] += afV[1]*afW[2];
+            kA[2][1] += afV[2]*afW[1];
+            kA[2][2] += afV[2]*afW[2];
+
+            kL[0][0] = 1.0+fT2;
+            kL[0][1] = kL[1][0] = fT2*afV[1];
+            kL[0][2] = kL[2][0] = fT2*afV[2];
+            kL[1][1] = 1.0+fT2*afV[1]*afV[1];
+            kL[1][2] = kL[2][1] = fT2*afV[1]*afV[2];
+            kL[2][2] = 1.0+fT2*afV[2]*afV[2];
+            bIdentity = false;
+        }
+        else
+        {
+            kL = Matrix3::IDENTITY;
+            bIdentity = true;
+        }
+
+        // map first row to (*,*,0)
+        fLength = Math::Sqrt(kA[0][1]*kA[0][1]+kA[0][2]*kA[0][2]);
+        if ( fLength > 0.0 )
+        {
+            fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0);
+            fT1 = kA[0][1] + fSign*fLength;
+            afV[2] = kA[0][2]/fT1;
+
+            fT2 = -2.0/(1.0+afV[2]*afV[2]);
+            afW[0] = fT2*(kA[0][1]+kA[0][2]*afV[2]);
+            afW[1] = fT2*(kA[1][1]+kA[1][2]*afV[2]);
+            afW[2] = fT2*(kA[2][1]+kA[2][2]*afV[2]);
+            kA[0][1] += afW[0];
+            kA[1][1] += afW[1];
+            kA[1][2] += afW[1]*afV[2];
+            kA[2][1] += afW[2];
+            kA[2][2] += afW[2]*afV[2];
+
+            kR[0][0] = 1.0;
+            kR[0][1] = kR[1][0] = 0.0;
+            kR[0][2] = kR[2][0] = 0.0;
+            kR[1][1] = 1.0+fT2;
+            kR[1][2] = kR[2][1] = fT2*afV[2];
+            kR[2][2] = 1.0+fT2*afV[2]*afV[2];
+        }
+        else
+        {
+            kR = Matrix3::IDENTITY;
+        }
+
+        // map second column to (*,*,0)
+        fLength = Math::Sqrt(kA[1][1]*kA[1][1]+kA[2][1]*kA[2][1]);
+        if ( fLength > 0.0 )
+        {
+            fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0);
+            fT1 = kA[1][1] + fSign*fLength;
+            afV[2] = kA[2][1]/fT1;
+
+            fT2 = -2.0/(1.0+afV[2]*afV[2]);
+            afW[1] = fT2*(kA[1][1]+kA[2][1]*afV[2]);
+            afW[2] = fT2*(kA[1][2]+kA[2][2]*afV[2]);
+            kA[1][1] += afW[1];
+            kA[1][2] += afW[2];
+            kA[2][2] += afV[2]*afW[2];
+
+            Real fA = 1.0+fT2;
+            Real fB = fT2*afV[2];
+            Real fC = 1.0+fB*afV[2];
+
+            if ( bIdentity )
+            {
+                kL[0][0] = 1.0;
+                kL[0][1] = kL[1][0] = 0.0;
+                kL[0][2] = kL[2][0] = 0.0;
+                kL[1][1] = fA;
+                kL[1][2] = kL[2][1] = fB;
+                kL[2][2] = fC;
+            }
+            else
+            {
+                for (int iRow = 0; iRow < 3; iRow++)
+                {
+                    Real fTmp0 = kL[iRow][1];
+                    Real fTmp1 = kL[iRow][2];
+                    kL[iRow][1] = fA*fTmp0+fB*fTmp1;
+                    kL[iRow][2] = fB*fTmp0+fC*fTmp1;
+                }
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::GolubKahanStep (Matrix3& kA, Matrix3& kL,
+        Matrix3& kR)
+    {
+        Real fT11 = kA[0][1]*kA[0][1]+kA[1][1]*kA[1][1];
+        Real fT22 = kA[1][2]*kA[1][2]+kA[2][2]*kA[2][2];
+        Real fT12 = kA[1][1]*kA[1][2];
+        Real fTrace = fT11+fT22;
+        Real fDiff = fT11-fT22;
+        Real fDiscr = Math::Sqrt(fDiff*fDiff+4.0*fT12*fT12);
+        Real fRoot1 = 0.5*(fTrace+fDiscr);
+        Real fRoot2 = 0.5*(fTrace-fDiscr);
+
+        // adjust right
+        Real fY = kA[0][0] - (Math::Abs(fRoot1-fT22) <=
+            Math::Abs(fRoot2-fT22) ? fRoot1 : fRoot2);
+        Real fZ = kA[0][1];
+		Real fInvLength = Math::InvSqrt(fY*fY+fZ*fZ);
+        Real fSin = fZ*fInvLength;
+        Real fCos = -fY*fInvLength;
+
+        Real fTmp0 = kA[0][0];
+        Real fTmp1 = kA[0][1];
+        kA[0][0] = fCos*fTmp0-fSin*fTmp1;
+        kA[0][1] = fSin*fTmp0+fCos*fTmp1;
+        kA[1][0] = -fSin*kA[1][1];
+        kA[1][1] *= fCos;
+
+        size_t iRow;
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            fTmp0 = kR[0][iRow];
+            fTmp1 = kR[1][iRow];
+            kR[0][iRow] = fCos*fTmp0-fSin*fTmp1;
+            kR[1][iRow] = fSin*fTmp0+fCos*fTmp1;
+        }
+
+        // adjust left
+        fY = kA[0][0];
+        fZ = kA[1][0];
+        fInvLength = Math::InvSqrt(fY*fY+fZ*fZ);
+        fSin = fZ*fInvLength;
+        fCos = -fY*fInvLength;
+
+        kA[0][0] = fCos*kA[0][0]-fSin*kA[1][0];
+        fTmp0 = kA[0][1];
+        fTmp1 = kA[1][1];
+        kA[0][1] = fCos*fTmp0-fSin*fTmp1;
+        kA[1][1] = fSin*fTmp0+fCos*fTmp1;
+        kA[0][2] = -fSin*kA[1][2];
+        kA[1][2] *= fCos;
+
+        size_t iCol;
+        for (iCol = 0; iCol < 3; iCol++)
+        {
+            fTmp0 = kL[iCol][0];
+            fTmp1 = kL[iCol][1];
+            kL[iCol][0] = fCos*fTmp0-fSin*fTmp1;
+            kL[iCol][1] = fSin*fTmp0+fCos*fTmp1;
+        }
+
+        // adjust right
+        fY = kA[0][1];
+        fZ = kA[0][2];
+        fInvLength = Math::InvSqrt(fY*fY+fZ*fZ);
+        fSin = fZ*fInvLength;
+        fCos = -fY*fInvLength;
+
+        kA[0][1] = fCos*kA[0][1]-fSin*kA[0][2];
+        fTmp0 = kA[1][1];
+        fTmp1 = kA[1][2];
+        kA[1][1] = fCos*fTmp0-fSin*fTmp1;
+        kA[1][2] = fSin*fTmp0+fCos*fTmp1;
+        kA[2][1] = -fSin*kA[2][2];
+        kA[2][2] *= fCos;
+
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            fTmp0 = kR[1][iRow];
+            fTmp1 = kR[2][iRow];
+            kR[1][iRow] = fCos*fTmp0-fSin*fTmp1;
+            kR[2][iRow] = fSin*fTmp0+fCos*fTmp1;
+        }
+
+        // adjust left
+        fY = kA[1][1];
+        fZ = kA[2][1];
+        fInvLength = Math::InvSqrt(fY*fY+fZ*fZ);
+        fSin = fZ*fInvLength;
+        fCos = -fY*fInvLength;
+
+        kA[1][1] = fCos*kA[1][1]-fSin*kA[2][1];
+        fTmp0 = kA[1][2];
+        fTmp1 = kA[2][2];
+        kA[1][2] = fCos*fTmp0-fSin*fTmp1;
+        kA[2][2] = fSin*fTmp0+fCos*fTmp1;
+
+        for (iCol = 0; iCol < 3; iCol++)
+        {
+            fTmp0 = kL[iCol][1];
+            fTmp1 = kL[iCol][2];
+            kL[iCol][1] = fCos*fTmp0-fSin*fTmp1;
+            kL[iCol][2] = fSin*fTmp0+fCos*fTmp1;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::SingularValueDecomposition (Matrix3& kL, Vector3& kS,
+        Matrix3& kR) const
+    {
+        // temas: currently unused
+        //const int iMax = 16;
+		size_t iRow, iCol;
+
+        Matrix3 kA = *this;
+        Bidiagonalize(kA,kL,kR);
+
+        for (unsigned int i = 0; i < ms_iSvdMaxIterations; i++)
+        {
+            Real fTmp, fTmp0, fTmp1;
+            Real fSin0, fCos0, fTan0;
+            Real fSin1, fCos1, fTan1;
+
+            bool bTest1 = (Math::Abs(kA[0][1]) <=
+                ms_fSvdEpsilon*(Math::Abs(kA[0][0])+Math::Abs(kA[1][1])));
+            bool bTest2 = (Math::Abs(kA[1][2]) <=
+                ms_fSvdEpsilon*(Math::Abs(kA[1][1])+Math::Abs(kA[2][2])));
+            if ( bTest1 )
+            {
+                if ( bTest2 )
+                {
+                    kS[0] = kA[0][0];
+                    kS[1] = kA[1][1];
+                    kS[2] = kA[2][2];
+                    break;
+                }
+                else
+                {
+                    // 2x2 closed form factorization
+                    fTmp = (kA[1][1]*kA[1][1] - kA[2][2]*kA[2][2] +
+                        kA[1][2]*kA[1][2])/(kA[1][2]*kA[2][2]);
+                    fTan0 = 0.5*(fTmp+Math::Sqrt(fTmp*fTmp + 4.0));
+                    fCos0 = Math::InvSqrt(1.0+fTan0*fTan0);
+                    fSin0 = fTan0*fCos0;
+
+                    for (iCol = 0; iCol < 3; iCol++)
+                    {
+                        fTmp0 = kL[iCol][1];
+                        fTmp1 = kL[iCol][2];
+                        kL[iCol][1] = fCos0*fTmp0-fSin0*fTmp1;
+                        kL[iCol][2] = fSin0*fTmp0+fCos0*fTmp1;
+                    }
+
+                    fTan1 = (kA[1][2]-kA[2][2]*fTan0)/kA[1][1];
+                    fCos1 = Math::InvSqrt(1.0+fTan1*fTan1);
+                    fSin1 = -fTan1*fCos1;
+
+                    for (iRow = 0; iRow < 3; iRow++)
+                    {
+                        fTmp0 = kR[1][iRow];
+                        fTmp1 = kR[2][iRow];
+                        kR[1][iRow] = fCos1*fTmp0-fSin1*fTmp1;
+                        kR[2][iRow] = fSin1*fTmp0+fCos1*fTmp1;
+                    }
+
+                    kS[0] = kA[0][0];
+                    kS[1] = fCos0*fCos1*kA[1][1] -
+                        fSin1*(fCos0*kA[1][2]-fSin0*kA[2][2]);
+                    kS[2] = fSin0*fSin1*kA[1][1] +
+                        fCos1*(fSin0*kA[1][2]+fCos0*kA[2][2]);
+                    break;
+                }
+            }
+            else
+            {
+                if ( bTest2 )
+                {
+                    // 2x2 closed form factorization
+                    fTmp = (kA[0][0]*kA[0][0] + kA[1][1]*kA[1][1] -
+                        kA[0][1]*kA[0][1])/(kA[0][1]*kA[1][1]);
+                    fTan0 = 0.5*(-fTmp+Math::Sqrt(fTmp*fTmp + 4.0));
+                    fCos0 = Math::InvSqrt(1.0+fTan0*fTan0);
+                    fSin0 = fTan0*fCos0;
+
+                    for (iCol = 0; iCol < 3; iCol++)
+                    {
+                        fTmp0 = kL[iCol][0];
+                        fTmp1 = kL[iCol][1];
+                        kL[iCol][0] = fCos0*fTmp0-fSin0*fTmp1;
+                        kL[iCol][1] = fSin0*fTmp0+fCos0*fTmp1;
+                    }
+
+                    fTan1 = (kA[0][1]-kA[1][1]*fTan0)/kA[0][0];
+                    fCos1 = Math::InvSqrt(1.0+fTan1*fTan1);
+                    fSin1 = -fTan1*fCos1;
+
+                    for (iRow = 0; iRow < 3; iRow++)
+                    {
+                        fTmp0 = kR[0][iRow];
+                        fTmp1 = kR[1][iRow];
+                        kR[0][iRow] = fCos1*fTmp0-fSin1*fTmp1;
+                        kR[1][iRow] = fSin1*fTmp0+fCos1*fTmp1;
+                    }
+
+                    kS[0] = fCos0*fCos1*kA[0][0] -
+                        fSin1*(fCos0*kA[0][1]-fSin0*kA[1][1]);
+                    kS[1] = fSin0*fSin1*kA[0][0] +
+                        fCos1*(fSin0*kA[0][1]+fCos0*kA[1][1]);
+                    kS[2] = kA[2][2];
+                    break;
+                }
+                else
+                {
+                    GolubKahanStep(kA,kL,kR);
+                }
+            }
+        }
+
+        // positize diagonal
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            if ( kS[iRow] < 0.0 )
+            {
+                kS[iRow] = -kS[iRow];
+                for (iCol = 0; iCol < 3; iCol++)
+                    kR[iRow][iCol] = -kR[iRow][iCol];
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::SingularValueComposition (const Matrix3& kL,
+        const Vector3& kS, const Matrix3& kR)
+    {
+        size_t iRow, iCol;
+        Matrix3 kTmp;
+
+        // product S*R
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            for (iCol = 0; iCol < 3; iCol++)
+                kTmp[iRow][iCol] = kS[iRow]*kR[iRow][iCol];
+        }
+
+        // product L*S*R
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            for (iCol = 0; iCol < 3; iCol++)
+            {
+                m[iRow][iCol] = 0.0;
+                for (int iMid = 0; iMid < 3; iMid++)
+                    m[iRow][iCol] += kL[iRow][iMid]*kTmp[iMid][iCol];
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::Orthonormalize ()
+    {
+        // Algorithm uses Gram-Schmidt orthogonalization.  If 'this' matrix is
+        // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
+        //
+        //   q0 = m0/|m0|
+        //   q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
+        //   q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
+        //
+        // where |V| indicates length of vector V and A*B indicates dot
+        // product of vectors A and B.
+
+        // compute q0
+        Real fInvLength = Math::InvSqrt(m[0][0]*m[0][0]
+            + m[1][0]*m[1][0] +
+            m[2][0]*m[2][0]);
+
+        m[0][0] *= fInvLength;
+        m[1][0] *= fInvLength;
+        m[2][0] *= fInvLength;
+
+        // compute q1
+        Real fDot0 =
+            m[0][0]*m[0][1] +
+            m[1][0]*m[1][1] +
+            m[2][0]*m[2][1];
+
+        m[0][1] -= fDot0*m[0][0];
+        m[1][1] -= fDot0*m[1][0];
+        m[2][1] -= fDot0*m[2][0];
+
+        fInvLength = Math::InvSqrt(m[0][1]*m[0][1] +
+            m[1][1]*m[1][1] +
+            m[2][1]*m[2][1]);
+
+        m[0][1] *= fInvLength;
+        m[1][1] *= fInvLength;
+        m[2][1] *= fInvLength;
+
+        // compute q2
+        Real fDot1 =
+            m[0][1]*m[0][2] +
+            m[1][1]*m[1][2] +
+            m[2][1]*m[2][2];
+
+        fDot0 =
+            m[0][0]*m[0][2] +
+            m[1][0]*m[1][2] +
+            m[2][0]*m[2][2];
+
+        m[0][2] -= fDot0*m[0][0] + fDot1*m[0][1];
+        m[1][2] -= fDot0*m[1][0] + fDot1*m[1][1];
+        m[2][2] -= fDot0*m[2][0] + fDot1*m[2][1];
+
+        fInvLength = Math::InvSqrt(m[0][2]*m[0][2] +
+            m[1][2]*m[1][2] +
+            m[2][2]*m[2][2]);
+
+        m[0][2] *= fInvLength;
+        m[1][2] *= fInvLength;
+        m[2][2] *= fInvLength;
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::QDUDecomposition (Matrix3& kQ,
+        Vector3& kD, Vector3& kU) const
+    {
+        // Factor M = QR = QDU where Q is orthogonal, D is diagonal,
+        // and U is upper triangular with ones on its diagonal.  Algorithm uses
+        // Gram-Schmidt orthogonalization (the QR algorithm).
+        //
+        // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then
+        //
+        //   q0 = m0/|m0|
+        //   q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
+        //   q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
+        //
+        // where |V| indicates length of vector V and A*B indicates dot
+        // product of vectors A and B.  The matrix R has entries
+        //
+        //   r00 = q0*m0  r01 = q0*m1  r02 = q0*m2
+        //   r10 = 0      r11 = q1*m1  r12 = q1*m2
+        //   r20 = 0      r21 = 0      r22 = q2*m2
+        //
+        // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00,
+        // u02 = r02/r00, and u12 = r12/r11.
+
+        // Q = rotation
+        // D = scaling
+        // U = shear
+
+        // D stores the three diagonal entries r00, r11, r22
+        // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12
+
+        // build orthogonal matrix Q
+        Real fInvLength = Math::InvSqrt(m[0][0]*m[0][0]
+            + m[1][0]*m[1][0] +
+            m[2][0]*m[2][0]);
+        kQ[0][0] = m[0][0]*fInvLength;
+        kQ[1][0] = m[1][0]*fInvLength;
+        kQ[2][0] = m[2][0]*fInvLength;
+
+        Real fDot = kQ[0][0]*m[0][1] + kQ[1][0]*m[1][1] +
+            kQ[2][0]*m[2][1];
+        kQ[0][1] = m[0][1]-fDot*kQ[0][0];
+        kQ[1][1] = m[1][1]-fDot*kQ[1][0];
+        kQ[2][1] = m[2][1]-fDot*kQ[2][0];
+        fInvLength = Math::InvSqrt(kQ[0][1]*kQ[0][1] + kQ[1][1]*kQ[1][1] +
+            kQ[2][1]*kQ[2][1]);
+        kQ[0][1] *= fInvLength;
+        kQ[1][1] *= fInvLength;
+        kQ[2][1] *= fInvLength;
+
+        fDot = kQ[0][0]*m[0][2] + kQ[1][0]*m[1][2] +
+            kQ[2][0]*m[2][2];
+        kQ[0][2] = m[0][2]-fDot*kQ[0][0];
+        kQ[1][2] = m[1][2]-fDot*kQ[1][0];
+        kQ[2][2] = m[2][2]-fDot*kQ[2][0];
+        fDot = kQ[0][1]*m[0][2] + kQ[1][1]*m[1][2] +
+            kQ[2][1]*m[2][2];
+        kQ[0][2] -= fDot*kQ[0][1];
+        kQ[1][2] -= fDot*kQ[1][1];
+        kQ[2][2] -= fDot*kQ[2][1];
+        fInvLength = Math::InvSqrt(kQ[0][2]*kQ[0][2] + kQ[1][2]*kQ[1][2] +
+            kQ[2][2]*kQ[2][2]);
+        kQ[0][2] *= fInvLength;
+        kQ[1][2] *= fInvLength;
+        kQ[2][2] *= fInvLength;
+
+        // guarantee that orthogonal matrix has determinant 1 (no reflections)
+        Real fDet = kQ[0][0]*kQ[1][1]*kQ[2][2] + kQ[0][1]*kQ[1][2]*kQ[2][0] +
+            kQ[0][2]*kQ[1][0]*kQ[2][1] - kQ[0][2]*kQ[1][1]*kQ[2][0] -
+            kQ[0][1]*kQ[1][0]*kQ[2][2] - kQ[0][0]*kQ[1][2]*kQ[2][1];
+
+        if ( fDet < 0.0 )
+        {
+            for (size_t iRow = 0; iRow < 3; iRow++)
+                for (size_t iCol = 0; iCol < 3; iCol++)
+                    kQ[iRow][iCol] = -kQ[iRow][iCol];
+        }
+
+        // build "right" matrix R
+        Matrix3 kR;
+        kR[0][0] = kQ[0][0]*m[0][0] + kQ[1][0]*m[1][0] +
+            kQ[2][0]*m[2][0];
+        kR[0][1] = kQ[0][0]*m[0][1] + kQ[1][0]*m[1][1] +
+            kQ[2][0]*m[2][1];
+        kR[1][1] = kQ[0][1]*m[0][1] + kQ[1][1]*m[1][1] +
+            kQ[2][1]*m[2][1];
+        kR[0][2] = kQ[0][0]*m[0][2] + kQ[1][0]*m[1][2] +
+            kQ[2][0]*m[2][2];
+        kR[1][2] = kQ[0][1]*m[0][2] + kQ[1][1]*m[1][2] +
+            kQ[2][1]*m[2][2];
+        kR[2][2] = kQ[0][2]*m[0][2] + kQ[1][2]*m[1][2] +
+            kQ[2][2]*m[2][2];
+
+        // the scaling component
+        kD[0] = kR[0][0];
+        kD[1] = kR[1][1];
+        kD[2] = kR[2][2];
+
+        // the shear component
+        Real fInvD0 = 1.0/kD[0];
+        kU[0] = kR[0][1]*fInvD0;
+        kU[1] = kR[0][2]*fInvD0;
+        kU[2] = kR[1][2]/kD[1];
+    }
+    //-----------------------------------------------------------------------
+    Real Matrix3::MaxCubicRoot (Real afCoeff[3])
+    {
+        // Spectral norm is for A^T*A, so characteristic polynomial
+        // P(x) = c[0]+c[1]*x+c[2]*x^2+x^3 has three positive real roots.
+        // This yields the assertions c[0] < 0 and c[2]*c[2] >= 3*c[1].
+
+        // quick out for uniform scale (triple root)
+        const Real fOneThird = 1.0/3.0;
+        const Real fEpsilon = 1e-06;
+        Real fDiscr = afCoeff[2]*afCoeff[2] - 3.0*afCoeff[1];
+        if ( fDiscr <= fEpsilon )
+            return -fOneThird*afCoeff[2];
+
+        // Compute an upper bound on roots of P(x).  This assumes that A^T*A
+        // has been scaled by its largest entry.
+        Real fX = 1.0;
+        Real fPoly = afCoeff[0]+fX*(afCoeff[1]+fX*(afCoeff[2]+fX));
+        if ( fPoly < 0.0 )
+        {
+            // uses a matrix norm to find an upper bound on maximum root
+            fX = Math::Abs(afCoeff[0]);
+            Real fTmp = 1.0+Math::Abs(afCoeff[1]);
+            if ( fTmp > fX )
+                fX = fTmp;
+            fTmp = 1.0+Math::Abs(afCoeff[2]);
+            if ( fTmp > fX )
+                fX = fTmp;
+        }
+
+        // Newton's method to find root
+        Real fTwoC2 = 2.0*afCoeff[2];
+        for (int i = 0; i < 16; i++)
+        {
+            fPoly = afCoeff[0]+fX*(afCoeff[1]+fX*(afCoeff[2]+fX));
+            if ( Math::Abs(fPoly) <= fEpsilon )
+                return fX;
+
+            Real fDeriv = afCoeff[1]+fX*(fTwoC2+3.0*fX);
+            fX -= fPoly/fDeriv;
+        }
+
+        return fX;
+    }
+    //-----------------------------------------------------------------------
+    Real Matrix3::SpectralNorm () const
+    {
+        Matrix3 kP;
+        size_t iRow, iCol;
+        Real fPmax = 0.0;
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            for (iCol = 0; iCol < 3; iCol++)
+            {
+                kP[iRow][iCol] = 0.0;
+                for (int iMid = 0; iMid < 3; iMid++)
+                {
+                    kP[iRow][iCol] +=
+                        m[iMid][iRow]*m[iMid][iCol];
+                }
+                if ( kP[iRow][iCol] > fPmax )
+                    fPmax = kP[iRow][iCol];
+            }
+        }
+
+        Real fInvPmax = 1.0/fPmax;
+        for (iRow = 0; iRow < 3; iRow++)
+        {
+            for (iCol = 0; iCol < 3; iCol++)
+                kP[iRow][iCol] *= fInvPmax;
+        }
+
+        Real afCoeff[3];
+        afCoeff[0] = -(kP[0][0]*(kP[1][1]*kP[2][2]-kP[1][2]*kP[2][1]) +
+            kP[0][1]*(kP[2][0]*kP[1][2]-kP[1][0]*kP[2][2]) +
+            kP[0][2]*(kP[1][0]*kP[2][1]-kP[2][0]*kP[1][1]));
+        afCoeff[1] = kP[0][0]*kP[1][1]-kP[0][1]*kP[1][0] +
+            kP[0][0]*kP[2][2]-kP[0][2]*kP[2][0] +
+            kP[1][1]*kP[2][2]-kP[1][2]*kP[2][1];
+        afCoeff[2] = -(kP[0][0]+kP[1][1]+kP[2][2]);
+
+        Real fRoot = MaxCubicRoot(afCoeff);
+        Real fNorm = Math::Sqrt(fPmax*fRoot);
+        return fNorm;
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::ToAxisAngle (Vector3& rkAxis, Radian& rfRadians) const
+    {
+        // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
+        // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
+        // I is the identity and
+        //
+        //       +-        -+
+        //   P = |  0 -z +y |
+        //       | +z  0 -x |
+        //       | -y +x  0 |
+        //       +-        -+
+        //
+        // If A > 0, R represents a counterclockwise rotation about the axis in
+        // the sense of looking from the tip of the axis vector towards the
+        // origin.  Some algebra will show that
+        //
+        //   cos(A) = (trace(R)-1)/2  and  R - R^t = 2*sin(A)*P
+        //
+        // In the event that A = pi, R-R^t = 0 which prevents us from extracting
+        // the axis through P.  Instead note that R = I+2*P^2 when A = pi, so
+        // P^2 = (R-I)/2.  The diagonal entries of P^2 are x^2-1, y^2-1, and
+        // z^2-1.  We can solve these for axis (x,y,z).  Because the angle is pi,
+        // it does not matter which sign you choose on the square roots.
+
+        Real fTrace = m[0][0] + m[1][1] + m[2][2];
+        Real fCos = 0.5*(fTrace-1.0);
+        rfRadians = Math::ACos(fCos);  // in [0,PI]
+
+        if ( rfRadians > Radian(0.0) )
+        {
+            if ( rfRadians < Radian(Math::PI) )
+            {
+                rkAxis.x = m[2][1]-m[1][2];
+                rkAxis.y = m[0][2]-m[2][0];
+                rkAxis.z = m[1][0]-m[0][1];
+                rkAxis.normalise();
+            }
+            else
+            {
+                // angle is PI
+                float fHalfInverse;
+                if ( m[0][0] >= m[1][1] )
+                {
+                    // r00 >= r11
+                    if ( m[0][0] >= m[2][2] )
+                    {
+                        // r00 is maximum diagonal term
+                        rkAxis.x = 0.5*Math::Sqrt(m[0][0] -
+                            m[1][1] - m[2][2] + 1.0);
+                        fHalfInverse = 0.5/rkAxis.x;
+                        rkAxis.y = fHalfInverse*m[0][1];
+                        rkAxis.z = fHalfInverse*m[0][2];
+                    }
+                    else
+                    {
+                        // r22 is maximum diagonal term
+                        rkAxis.z = 0.5*Math::Sqrt(m[2][2] -
+                            m[0][0] - m[1][1] + 1.0);
+                        fHalfInverse = 0.5/rkAxis.z;
+                        rkAxis.x = fHalfInverse*m[0][2];
+                        rkAxis.y = fHalfInverse*m[1][2];
+                    }
+                }
+                else
+                {
+                    // r11 > r00
+                    if ( m[1][1] >= m[2][2] )
+                    {
+                        // r11 is maximum diagonal term
+                        rkAxis.y = 0.5*Math::Sqrt(m[1][1] -
+                            m[0][0] - m[2][2] + 1.0);
+                        fHalfInverse  = 0.5/rkAxis.y;
+                        rkAxis.x = fHalfInverse*m[0][1];
+                        rkAxis.z = fHalfInverse*m[1][2];
+                    }
+                    else
+                    {
+                        // r22 is maximum diagonal term
+                        rkAxis.z = 0.5*Math::Sqrt(m[2][2] -
+                            m[0][0] - m[1][1] + 1.0);
+                        fHalfInverse = 0.5/rkAxis.z;
+                        rkAxis.x = fHalfInverse*m[0][2];
+                        rkAxis.y = fHalfInverse*m[1][2];
+                    }
+                }
+            }
+        }
+        else
+        {
+            // The angle is 0 and the matrix is the identity.  Any axis will
+            // work, so just use the x-axis.
+            rkAxis.x = 1.0;
+            rkAxis.y = 0.0;
+            rkAxis.z = 0.0;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromAxisAngle (const Vector3& rkAxis, const Radian& fRadians)
+    {
+        Real fCos = Math::Cos(fRadians);
+        Real fSin = Math::Sin(fRadians);
+        Real fOneMinusCos = 1.0-fCos;
+        Real fX2 = rkAxis.x*rkAxis.x;
+        Real fY2 = rkAxis.y*rkAxis.y;
+        Real fZ2 = rkAxis.z*rkAxis.z;
+        Real fXYM = rkAxis.x*rkAxis.y*fOneMinusCos;
+        Real fXZM = rkAxis.x*rkAxis.z*fOneMinusCos;
+        Real fYZM = rkAxis.y*rkAxis.z*fOneMinusCos;
+        Real fXSin = rkAxis.x*fSin;
+        Real fYSin = rkAxis.y*fSin;
+        Real fZSin = rkAxis.z*fSin;
+
+        m[0][0] = fX2*fOneMinusCos+fCos;
+        m[0][1] = fXYM-fZSin;
+        m[0][2] = fXZM+fYSin;
+        m[1][0] = fXYM+fZSin;
+        m[1][1] = fY2*fOneMinusCos+fCos;
+        m[1][2] = fYZM-fXSin;
+        m[2][0] = fXZM-fYSin;
+        m[2][1] = fYZM+fXSin;
+        m[2][2] = fZ2*fOneMinusCos+fCos;
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesXYZ (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz          -cy*sz           sy
+        //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+        //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+
+        rfPAngle = Radian(Math::ASin(m[0][2]));
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(-m[1][2],m[2][2]);
+                rfRAngle = Math::ATan2(-m[0][1],m[0][0]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(m[1][0],m[1][1]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(m[1][0],m[1][1]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesXZY (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz          -sz              cz*sy
+        //        sx*sy+cx*cy*sz  cx*cz          -cy*sx+cx*sy*sz
+        //       -cx*sy+cy*sx*sz  cz*sx           cx*cy+sx*sy*sz
+
+        rfPAngle = Math::ASin(-m[0][1]);
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(m[2][1],m[1][1]);
+                rfRAngle = Math::ATan2(m[0][2],m[0][0]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(-m[2][0],m[2][2]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(-m[2][0],m[2][2]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesYXZ (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz+sx*sy*sz  cz*sx*sy-cy*sz  cx*sy
+        //        cx*sz           cx*cz          -sx
+        //       -cz*sy+cy*sx*sz  cy*cz*sx+sy*sz  cx*cy
+
+        rfPAngle = Math::ASin(-m[1][2]);
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(m[0][2],m[2][2]);
+                rfRAngle = Math::ATan2(m[1][0],m[1][1]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(-m[0][1],m[0][0]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(-m[0][1],m[0][0]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesYZX (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz           sx*sy-cx*cy*sz  cx*sy+cy*sx*sz
+        //        sz              cx*cz          -cz*sx
+        //       -cz*sy           cy*sx+cx*sy*sz  cx*cy-sx*sy*sz
+
+        rfPAngle = Math::ASin(m[1][0]);
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(-m[2][0],m[0][0]);
+                rfRAngle = Math::ATan2(-m[1][2],m[1][1]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(m[2][1],m[2][2]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(m[2][1],m[2][2]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesZXY (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz-sx*sy*sz -cx*sz           cz*sy+cy*sx*sz
+        //        cz*sx*sy+cy*sz  cx*cz          -cy*cz*sx+sy*sz
+        //       -cx*sy           sx              cx*cy
+
+        rfPAngle = Math::ASin(m[2][1]);
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(-m[0][1],m[1][1]);
+                rfRAngle = Math::ATan2(-m[2][0],m[2][2]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(m[0][2],m[0][0]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(m[0][2],m[0][0]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::ToEulerAnglesZYX (Radian& rfYAngle, Radian& rfPAngle,
+        Radian& rfRAngle) const
+    {
+        // rot =  cy*cz           cz*sx*sy-cx*sz  cx*cz*sy+sx*sz
+        //        cy*sz           cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
+        //       -sy              cy*sx           cx*cy
+
+        rfPAngle = Math::ASin(-m[2][0]);
+        if ( rfPAngle < Radian(Math::HALF_PI) )
+        {
+            if ( rfPAngle > Radian(-Math::HALF_PI) )
+            {
+                rfYAngle = Math::ATan2(m[1][0],m[0][0]);
+                rfRAngle = Math::ATan2(m[2][1],m[2][2]);
+                return true;
+            }
+            else
+            {
+                // WARNING.  Not a unique solution.
+                Radian fRmY = Math::ATan2(-m[0][1],m[0][2]);
+                rfRAngle = Radian(0.0);  // any angle works
+                rfYAngle = rfRAngle - fRmY;
+                return false;
+            }
+        }
+        else
+        {
+            // WARNING.  Not a unique solution.
+            Radian fRpY = Math::ATan2(-m[0][1],m[0][2]);
+            rfRAngle = Radian(0.0);  // any angle works
+            rfYAngle = fRpY - rfRAngle;
+            return false;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesXYZ (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        *this = kXMat*(kYMat*kZMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesXZY (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        *this = kXMat*(kZMat*kYMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesYXZ (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        *this = kYMat*(kXMat*kZMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesYZX (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        *this = kYMat*(kZMat*kXMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesZXY (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        *this = kZMat*(kXMat*kYMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::FromEulerAnglesZYX (const Radian& fYAngle, const Radian& fPAngle,
+        const Radian& fRAngle)
+    {
+        Real fCos, fSin;
+
+        fCos = Math::Cos(fYAngle);
+        fSin = Math::Sin(fYAngle);
+        Matrix3 kZMat(fCos,-fSin,0.0,fSin,fCos,0.0,0.0,0.0,1.0);
+
+        fCos = Math::Cos(fPAngle);
+        fSin = Math::Sin(fPAngle);
+        Matrix3 kYMat(fCos,0.0,fSin,0.0,1.0,0.0,-fSin,0.0,fCos);
+
+        fCos = Math::Cos(fRAngle);
+        fSin = Math::Sin(fRAngle);
+        Matrix3 kXMat(1.0,0.0,0.0,0.0,fCos,-fSin,0.0,fSin,fCos);
+
+        *this = kZMat*(kYMat*kXMat);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::Tridiagonal (Real afDiag[3], Real afSubDiag[3])
+    {
+        // Householder reduction T = Q^t M Q
+        //   Input:
+        //     mat, symmetric 3x3 matrix M
+        //   Output:
+        //     mat, orthogonal matrix Q
+        //     diag, diagonal entries of T
+        //     subd, subdiagonal entries of T (T is symmetric)
+
+        Real fA = m[0][0];
+        Real fB = m[0][1];
+        Real fC = m[0][2];
+        Real fD = m[1][1];
+        Real fE = m[1][2];
+        Real fF = m[2][2];
+
+        afDiag[0] = fA;
+        afSubDiag[2] = 0.0;
+        if ( Math::Abs(fC) >= EPSILON )
+        {
+            Real fLength = Math::Sqrt(fB*fB+fC*fC);
+            Real fInvLength = 1.0/fLength;
+            fB *= fInvLength;
+            fC *= fInvLength;
+            Real fQ = 2.0*fB*fE+fC*(fF-fD);
+            afDiag[1] = fD+fC*fQ;
+            afDiag[2] = fF-fC*fQ;
+            afSubDiag[0] = fLength;
+            afSubDiag[1] = fE-fB*fQ;
+            m[0][0] = 1.0;
+            m[0][1] = 0.0;
+            m[0][2] = 0.0;
+            m[1][0] = 0.0;
+            m[1][1] = fB;
+            m[1][2] = fC;
+            m[2][0] = 0.0;
+            m[2][1] = fC;
+            m[2][2] = -fB;
+        }
+        else
+        {
+            afDiag[1] = fD;
+            afDiag[2] = fF;
+            afSubDiag[0] = fB;
+            afSubDiag[1] = fE;
+            m[0][0] = 1.0;
+            m[0][1] = 0.0;
+            m[0][2] = 0.0;
+            m[1][0] = 0.0;
+            m[1][1] = 1.0;
+            m[1][2] = 0.0;
+            m[2][0] = 0.0;
+            m[2][1] = 0.0;
+            m[2][2] = 1.0;
+        }
+    }
+    //-----------------------------------------------------------------------
+    bool Matrix3::QLAlgorithm (Real afDiag[3], Real afSubDiag[3])
+    {
+        // QL iteration with implicit shifting to reduce matrix from tridiagonal
+        // to diagonal
+
+        for (int i0 = 0; i0 < 3; i0++)
+        {
+            const unsigned int iMaxIter = 32;
+            unsigned int iIter;
+            for (iIter = 0; iIter < iMaxIter; iIter++)
+            {
+                int i1;
+                for (i1 = i0; i1 <= 1; i1++)
+                {
+                    Real fSum = Math::Abs(afDiag[i1]) +
+                        Math::Abs(afDiag[i1+1]);
+                    if ( Math::Abs(afSubDiag[i1]) + fSum == fSum )
+                        break;
+                }
+                if ( i1 == i0 )
+                    break;
+
+                Real fTmp0 = (afDiag[i0+1]-afDiag[i0])/(2.0*afSubDiag[i0]);
+                Real fTmp1 = Math::Sqrt(fTmp0*fTmp0+1.0);
+                if ( fTmp0 < 0.0 )
+                    fTmp0 = afDiag[i1]-afDiag[i0]+afSubDiag[i0]/(fTmp0-fTmp1);
+                else
+                    fTmp0 = afDiag[i1]-afDiag[i0]+afSubDiag[i0]/(fTmp0+fTmp1);
+                Real fSin = 1.0;
+                Real fCos = 1.0;
+                Real fTmp2 = 0.0;
+                for (int i2 = i1-1; i2 >= i0; i2--)
+                {
+                    Real fTmp3 = fSin*afSubDiag[i2];
+                    Real fTmp4 = fCos*afSubDiag[i2];
+                    if ( Math::Abs(fTmp3) >= Math::Abs(fTmp0) )
+                    {
+                        fCos = fTmp0/fTmp3;
+                        fTmp1 = Math::Sqrt(fCos*fCos+1.0);
+                        afSubDiag[i2+1] = fTmp3*fTmp1;
+                        fSin = 1.0/fTmp1;
+                        fCos *= fSin;
+                    }
+                    else
+                    {
+                        fSin = fTmp3/fTmp0;
+                        fTmp1 = Math::Sqrt(fSin*fSin+1.0);
+                        afSubDiag[i2+1] = fTmp0*fTmp1;
+                        fCos = 1.0/fTmp1;
+                        fSin *= fCos;
+                    }
+                    fTmp0 = afDiag[i2+1]-fTmp2;
+                    fTmp1 = (afDiag[i2]-fTmp0)*fSin+2.0*fTmp4*fCos;
+                    fTmp2 = fSin*fTmp1;
+                    afDiag[i2+1] = fTmp0+fTmp2;
+                    fTmp0 = fCos*fTmp1-fTmp4;
+
+                    for (int iRow = 0; iRow < 3; iRow++)
+                    {
+                        fTmp3 = m[iRow][i2+1];
+                        m[iRow][i2+1] = fSin*m[iRow][i2] +
+                            fCos*fTmp3;
+                        m[iRow][i2] = fCos*m[iRow][i2] -
+                            fSin*fTmp3;
+                    }
+                }
+                afDiag[i0] -= fTmp2;
+                afSubDiag[i0] = fTmp0;
+                afSubDiag[i1] = 0.0;
+            }
+
+            if ( iIter == iMaxIter )
+            {
+                // should not get here under normal circumstances
+                return false;
+            }
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::EigenSolveSymmetric (Real afEigenvalue[3],
+        Vector3 akEigenvector[3]) const
+    {
+        Matrix3 kMatrix = *this;
+        Real afSubDiag[3];
+        kMatrix.Tridiagonal(afEigenvalue,afSubDiag);
+        kMatrix.QLAlgorithm(afEigenvalue,afSubDiag);
+
+        for (size_t i = 0; i < 3; i++)
+        {
+            akEigenvector[i][0] = kMatrix[0][i];
+            akEigenvector[i][1] = kMatrix[1][i];
+            akEigenvector[i][2] = kMatrix[2][i];
+        }
+
+        // make eigenvectors form a right--handed system
+        Vector3 kCross = akEigenvector[1].crossProduct(akEigenvector[2]);
+        Real fDet = akEigenvector[0].dotProduct(kCross);
+        if ( fDet < 0.0 )
+        {
+            akEigenvector[2][0] = - akEigenvector[2][0];
+            akEigenvector[2][1] = - akEigenvector[2][1];
+            akEigenvector[2][2] = - akEigenvector[2][2];
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Matrix3::TensorProduct (const Vector3& rkU, const Vector3& rkV,
+        Matrix3& rkProduct)
+    {
+        for (size_t iRow = 0; iRow < 3; iRow++)
+        {
+            for (size_t iCol = 0; iCol < 3; iCol++)
+                rkProduct[iRow][iCol] = rkU[iRow]*rkV[iCol];
+        }
+    }
+    //-----------------------------------------------------------------------
+}
Index: sandbox_light/src/external/ogremath/OgreMatrix3.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreMatrix3.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMatrix3.h	(revision 5789)
@@ -0,0 +1,241 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Matrix3_H__
+#define __Matrix3_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+#include <ostream>
+
+// NB All code adapted from Wild Magic 0.2 Matrix math (free source code)
+// http://www.geometrictools.com/
+
+// NOTE.  The (x,y,z) coordinate system is assumed to be right-handed.
+// Coordinate axis rotation matrices are of the form
+//   RX =    1       0       0
+//           0     cos(t) -sin(t)
+//           0     sin(t)  cos(t)
+// where t > 0 indicates a counterclockwise rotation in the yz-plane
+//   RY =  cos(t)    0     sin(t)
+//           0       1       0
+//        -sin(t)    0     cos(t)
+// where t > 0 indicates a counterclockwise rotation in the zx-plane
+//   RZ =  cos(t) -sin(t)    0
+//         sin(t)  cos(t)    0
+//           0       0       1
+// where t > 0 indicates a counterclockwise rotation in the xy-plane.
+
+namespace Ogre
+{
+    /** A 3x3 matrix which can represent rotations around axes.
+        @note
+            <b>All the code is adapted from the Wild Magic 0.2 Matrix
+            library (http://www.geometrictools.com/).</b>
+        @par
+            The coordinate system is assumed to be <b>right-handed</b>.
+    */
+    class _OgreExport Matrix3
+    {
+    public:
+        /** Default constructor.
+            @note
+                It does <b>NOT</b> initialize the matrix for efficiency.
+        */
+		inline Matrix3 () {};
+        inline explicit Matrix3 (const Real arr[3][3])
+		{
+			memcpy(m,arr,9*sizeof(Real));
+		}
+        inline Matrix3 (const Matrix3& rkMatrix)
+		{
+			memcpy(m,rkMatrix.m,9*sizeof(Real));
+		}
+        Matrix3 (Real fEntry00, Real fEntry01, Real fEntry02,
+                    Real fEntry10, Real fEntry11, Real fEntry12,
+                    Real fEntry20, Real fEntry21, Real fEntry22)
+		{
+			m[0][0] = fEntry00;
+			m[0][1] = fEntry01;
+			m[0][2] = fEntry02;
+			m[1][0] = fEntry10;
+			m[1][1] = fEntry11;
+			m[1][2] = fEntry12;
+			m[2][0] = fEntry20;
+			m[2][1] = fEntry21;
+			m[2][2] = fEntry22;
+		}
+
+        // member access, allows use of construct mat[r][c]
+        inline Real* operator[] (size_t iRow) const
+		{
+			return (Real*)m[iRow];
+		}
+        /*inline operator Real* ()
+		{
+			return (Real*)m[0];
+		}*/
+        Vector3 GetColumn (size_t iCol) const;
+        void SetColumn(size_t iCol, const Vector3& vec);
+        void FromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
+
+        // assignment and comparison
+        inline Matrix3& operator= (const Matrix3& rkMatrix)
+		{
+			memcpy(m,rkMatrix.m,9*sizeof(Real));
+			return *this;
+		}
+        bool operator== (const Matrix3& rkMatrix) const;
+        inline bool operator!= (const Matrix3& rkMatrix) const
+		{
+			return !operator==(rkMatrix);
+		}
+
+        // arithmetic operations
+        Matrix3 operator+ (const Matrix3& rkMatrix) const;
+        Matrix3 operator- (const Matrix3& rkMatrix) const;
+        Matrix3 operator* (const Matrix3& rkMatrix) const;
+        Matrix3 operator- () const;
+
+        // matrix * vector [3x3 * 3x1 = 3x1]
+        Vector3 operator* (const Vector3& rkVector) const;
+
+        // vector * matrix [1x3 * 3x3 = 1x3]
+        _OgreExport friend Vector3 operator* (const Vector3& rkVector,
+            const Matrix3& rkMatrix);
+
+        // matrix * scalar
+        Matrix3 operator* (Real fScalar) const;
+
+        // scalar * matrix
+        _OgreExport friend Matrix3 operator* (Real fScalar, const Matrix3& rkMatrix);
+
+        // utilities
+        Matrix3 Transpose () const;
+        bool Inverse (Matrix3& rkInverse, Real fTolerance = 1e-06) const;
+        Matrix3 Inverse (Real fTolerance = 1e-06) const;
+        Real Determinant () const;
+
+        // singular value decomposition
+        void SingularValueDecomposition (Matrix3& rkL, Vector3& rkS,
+            Matrix3& rkR) const;
+        void SingularValueComposition (const Matrix3& rkL,
+            const Vector3& rkS, const Matrix3& rkR);
+
+        // Gram-Schmidt orthonormalization (applied to columns of rotation matrix)
+        void Orthonormalize ();
+
+        // orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12)
+        void QDUDecomposition (Matrix3& rkQ, Vector3& rkD,
+            Vector3& rkU) const;
+
+        Real SpectralNorm () const;
+
+        // matrix must be orthonormal
+        void ToAxisAngle (Vector3& rkAxis, Radian& rfAngle) const;
+		inline void ToAxisAngle (Vector3& rkAxis, Degree& rfAngle) const {
+			Radian r;
+			ToAxisAngle ( rkAxis, r );
+			rfAngle = r;
+		}
+        void FromAxisAngle (const Vector3& rkAxis, const Radian& fRadians);
+
+        // The matrix must be orthonormal.  The decomposition is yaw*pitch*roll
+        // where yaw is rotation about the Up vector, pitch is rotation about the
+        // Right axis, and roll is rotation about the Direction axis.
+        bool ToEulerAnglesXYZ (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        bool ToEulerAnglesXZY (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        bool ToEulerAnglesYXZ (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        bool ToEulerAnglesYZX (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        bool ToEulerAnglesZXY (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        bool ToEulerAnglesZYX (Radian& rfYAngle, Radian& rfPAngle,
+            Radian& rfRAngle) const;
+        void FromEulerAnglesXYZ (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        void FromEulerAnglesXZY (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        void FromEulerAnglesYXZ (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        void FromEulerAnglesYZX (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        void FromEulerAnglesZXY (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        void FromEulerAnglesZYX (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle);
+        // eigensolver, matrix must be symmetric
+        void EigenSolveSymmetric (Real afEigenvalue[3],
+            Vector3 akEigenvector[3]) const;
+
+        static void TensorProduct (const Vector3& rkU, const Vector3& rkV,
+            Matrix3& rkProduct);
+
+		/** Determines if this matrix involves a scaling. */
+		inline bool hasScale() const
+		{
+			// check magnitude of column vectors (==local axes)
+			Real t = m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+			t = m[0][1] * m[0][1] + m[1][1] * m[1][1] + m[2][1] * m[2][1];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+			t = m[0][2] * m[0][2] + m[1][2] * m[1][2] + m[2][2] * m[2][2];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+
+			return false;
+		}
+
+
+        static const Real EPSILON;
+        static const Matrix3 ZERO;
+        static const Matrix3 IDENTITY;
+
+    protected:
+        // support for eigensolver
+        void Tridiagonal (Real afDiag[3], Real afSubDiag[3]);
+        bool QLAlgorithm (Real afDiag[3], Real afSubDiag[3]);
+
+        // support for singular value decomposition
+        static const Real ms_fSvdEpsilon;
+        static const unsigned int ms_iSvdMaxIterations;
+        static void Bidiagonalize (Matrix3& kA, Matrix3& kL,
+            Matrix3& kR);
+        static void GolubKahanStep (Matrix3& kA, Matrix3& kL,
+            Matrix3& kR);
+
+        // support for spectral norm
+        static Real MaxCubicRoot (Real afCoeff[3]);
+
+        Real m[3][3];
+
+        // for faster access
+        friend class Matrix4;
+    };
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgreMatrix4.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreMatrix4.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMatrix4.cpp	(revision 5789)
@@ -0,0 +1,252 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreMatrix4.h"
+
+#include "OgreVector3.h"
+#include "OgreMatrix3.h"
+
+namespace Ogre
+{
+
+    const Matrix4 Matrix4::ZERO(
+        0, 0, 0, 0,
+        0, 0, 0, 0,
+        0, 0, 0, 0,
+        0, 0, 0, 0 );
+
+    const Matrix4 Matrix4::IDENTITY(
+        1, 0, 0, 0,
+        0, 1, 0, 0,
+        0, 0, 1, 0,
+        0, 0, 0, 1 );
+
+    const Matrix4 Matrix4::CLIPSPACE2DTOIMAGESPACE(
+        0.5,    0,  0, 0.5, 
+          0, -0.5,  0, 0.5, 
+          0,    0,  1,   0,
+          0,    0,  0,   1);
+
+    //-----------------------------------------------------------------------
+    inline static Real
+        MINOR(const Matrix4& m, const size_t r0, const size_t r1, const size_t r2, 
+								const size_t c0, const size_t c1, const size_t c2)
+    {
+        return m[r0][c0] * (m[r1][c1] * m[r2][c2] - m[r2][c1] * m[r1][c2]) -
+            m[r0][c1] * (m[r1][c0] * m[r2][c2] - m[r2][c0] * m[r1][c2]) +
+            m[r0][c2] * (m[r1][c0] * m[r2][c1] - m[r2][c0] * m[r1][c1]);
+    }
+    //-----------------------------------------------------------------------
+    Matrix4 Matrix4::adjoint() const
+    {
+        return Matrix4( MINOR(*this, 1, 2, 3, 1, 2, 3),
+            -MINOR(*this, 0, 2, 3, 1, 2, 3),
+            MINOR(*this, 0, 1, 3, 1, 2, 3),
+            -MINOR(*this, 0, 1, 2, 1, 2, 3),
+
+            -MINOR(*this, 1, 2, 3, 0, 2, 3),
+            MINOR(*this, 0, 2, 3, 0, 2, 3),
+            -MINOR(*this, 0, 1, 3, 0, 2, 3),
+            MINOR(*this, 0, 1, 2, 0, 2, 3),
+
+            MINOR(*this, 1, 2, 3, 0, 1, 3),
+            -MINOR(*this, 0, 2, 3, 0, 1, 3),
+            MINOR(*this, 0, 1, 3, 0, 1, 3),
+            -MINOR(*this, 0, 1, 2, 0, 1, 3),
+
+            -MINOR(*this, 1, 2, 3, 0, 1, 2),
+            MINOR(*this, 0, 2, 3, 0, 1, 2),
+            -MINOR(*this, 0, 1, 3, 0, 1, 2),
+            MINOR(*this, 0, 1, 2, 0, 1, 2));
+    }
+    //-----------------------------------------------------------------------
+    Real Matrix4::determinant() const
+    {
+        return m[0][0] * MINOR(*this, 1, 2, 3, 1, 2, 3) -
+            m[0][1] * MINOR(*this, 1, 2, 3, 0, 2, 3) +
+            m[0][2] * MINOR(*this, 1, 2, 3, 0, 1, 3) -
+            m[0][3] * MINOR(*this, 1, 2, 3, 0, 1, 2);
+    }
+    //-----------------------------------------------------------------------
+    Matrix4 Matrix4::inverse() const
+    {
+        Real m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
+        Real m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
+        Real m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
+        Real m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
+
+        Real v0 = m20 * m31 - m21 * m30;
+        Real v1 = m20 * m32 - m22 * m30;
+        Real v2 = m20 * m33 - m23 * m30;
+        Real v3 = m21 * m32 - m22 * m31;
+        Real v4 = m21 * m33 - m23 * m31;
+        Real v5 = m22 * m33 - m23 * m32;
+
+        Real t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
+        Real t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
+        Real t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
+        Real t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
+
+        Real invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
+
+        Real d00 = t00 * invDet;
+        Real d10 = t10 * invDet;
+        Real d20 = t20 * invDet;
+        Real d30 = t30 * invDet;
+
+        Real d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+        Real d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+        Real d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+        Real d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
+
+        v0 = m10 * m31 - m11 * m30;
+        v1 = m10 * m32 - m12 * m30;
+        v2 = m10 * m33 - m13 * m30;
+        v3 = m11 * m32 - m12 * m31;
+        v4 = m11 * m33 - m13 * m31;
+        v5 = m12 * m33 - m13 * m32;
+
+        Real d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+        Real d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+        Real d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+        Real d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
+
+        v0 = m21 * m10 - m20 * m11;
+        v1 = m22 * m10 - m20 * m12;
+        v2 = m23 * m10 - m20 * m13;
+        v3 = m22 * m11 - m21 * m12;
+        v4 = m23 * m11 - m21 * m13;
+        v5 = m23 * m12 - m22 * m13;
+
+        Real d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+        Real d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+        Real d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+        Real d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
+
+        return Matrix4(
+            d00, d01, d02, d03,
+            d10, d11, d12, d13,
+            d20, d21, d22, d23,
+            d30, d31, d32, d33);
+    }
+    //-----------------------------------------------------------------------
+    Matrix4 Matrix4::inverseAffine(void) const
+    {
+        assert(isAffine());
+
+        Real m10 = m[1][0], m11 = m[1][1], m12 = m[1][2];
+        Real m20 = m[2][0], m21 = m[2][1], m22 = m[2][2];
+
+        Real t00 = m22 * m11 - m21 * m12;
+        Real t10 = m20 * m12 - m22 * m10;
+        Real t20 = m21 * m10 - m20 * m11;
+
+        Real m00 = m[0][0], m01 = m[0][1], m02 = m[0][2];
+
+        Real invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
+
+        t00 *= invDet; t10 *= invDet; t20 *= invDet;
+
+        m00 *= invDet; m01 *= invDet; m02 *= invDet;
+
+        Real r00 = t00;
+        Real r01 = m02 * m21 - m01 * m22;
+        Real r02 = m01 * m12 - m02 * m11;
+
+        Real r10 = t10;
+        Real r11 = m00 * m22 - m02 * m20;
+        Real r12 = m02 * m10 - m00 * m12;
+
+        Real r20 = t20;
+        Real r21 = m01 * m20 - m00 * m21;
+        Real r22 = m00 * m11 - m01 * m10;
+
+        Real m03 = m[0][3], m13 = m[1][3], m23 = m[2][3];
+
+        Real r03 = - (r00 * m03 + r01 * m13 + r02 * m23);
+        Real r13 = - (r10 * m03 + r11 * m13 + r12 * m23);
+        Real r23 = - (r20 * m03 + r21 * m13 + r22 * m23);
+
+        return Matrix4(
+            r00, r01, r02, r03,
+            r10, r11, r12, r13,
+            r20, r21, r22, r23,
+              0,   0,   0,   1);
+    }
+    //-----------------------------------------------------------------------
+    void Matrix4::makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation)
+    {
+        // Ordering:
+        //    1. Scale
+        //    2. Rotate
+        //    3. Translate
+
+        Matrix3 rot3x3, scale3x3;
+        orientation.ToRotationMatrix(rot3x3);
+        scale3x3 = Matrix3::ZERO;
+        scale3x3[0][0] = scale.x;
+        scale3x3[1][1] = scale.y;
+        scale3x3[2][2] = scale.z;
+
+        // Set up final matrix with scale, rotation and translation
+        *this = rot3x3 * scale3x3;
+        this->setTrans(position);
+
+        // No projection term
+        m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
+    }
+    //-----------------------------------------------------------------------
+    void Matrix4::makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation)
+    {
+        // Invert the parameters
+        Vector3 invTranslate = -position;
+        Vector3 invScale(1 / scale.x, 1 / scale.y, 1 / scale.z);
+        Quaternion invRot = orientation.Inverse();
+
+        // Because we're inverting, order is translation, rotation, scale
+        // So make translation relative to scale & rotation
+        invTranslate *= invScale; // scale
+        invTranslate = invRot * invTranslate; // rotate
+
+        // Next, make a 3x3 rotation matrix and apply inverse scale
+        Matrix3 rot3x3, scale3x3;
+        invRot.ToRotationMatrix(rot3x3);
+        scale3x3 = Matrix3::ZERO;
+        scale3x3[0][0] = invScale.x;
+        scale3x3[1][1] = invScale.y;
+        scale3x3[2][2] = invScale.z;
+
+        // Set up final matrix with scale, rotation and translation
+        *this = scale3x3 * rot3x3;
+        this->setTrans(invTranslate);
+
+        // No projection term
+        m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
+    }
+
+}
Index: sandbox_light/src/external/ogremath/OgreMatrix4.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreMatrix4.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreMatrix4.h	(revision 5789)
@@ -0,0 +1,614 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Matrix4__
+#define __Matrix4__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+#include "OgreMatrix3.h"
+#include "OgreVector4.h"
+#include <ostream>
+
+namespace Ogre
+{
+    /** Class encapsulating a standard 4x4 homogeneous matrix.
+        @remarks
+            OGRE uses column vectors when applying matrix multiplications,
+            This means a vector is represented as a single column, 4-row
+            matrix. This has the effect that the transformations implemented
+            by the matrices happens right-to-left e.g. if vector V is to be
+            transformed by M1 then M2 then M3, the calculation would be
+            M3 * M2 * M1 * V. The order that matrices are concatenated is
+            vital since matrix multiplication is not cummatative, i.e. you
+            can get a different result if you concatenate in the wrong order.
+        @par
+            The use of column vectors and right-to-left ordering is the
+            standard in most mathematical texts, and id the same as used in
+            OpenGL. It is, however, the opposite of Direct3D, which has
+            inexplicably chosen to differ from the accepted standard and uses
+            row vectors and left-to-right matrix multiplication.
+        @par
+            OGRE deals with the differences between D3D and OpenGL etc.
+            internally when operating through different render systems. OGRE
+            users only need to conform to standard maths conventions, i.e.
+            right-to-left matrix multiplication, (OGRE transposes matrices it
+            passes to D3D to compensate).
+        @par
+            The generic form M * V which shows the layout of the matrix 
+            entries is shown below:
+            <pre>
+                [ m[0][0]  m[0][1]  m[0][2]  m[0][3] ]   {x}
+                | m[1][0]  m[1][1]  m[1][2]  m[1][3] | * {y}
+                | m[2][0]  m[2][1]  m[2][2]  m[2][3] |   {z}
+                [ m[3][0]  m[3][1]  m[3][2]  m[3][3] ]   {1}
+            </pre>
+    */
+    class _OgreExport Matrix4
+    {
+    protected:
+        /// The matrix entries, indexed by [row][col].
+        union {
+            Real m[4][4];
+            Real _m[16];
+        };
+    public:
+        /** Default constructor.
+            @note
+                It does <b>NOT</b> initialize the matrix for efficiency.
+        */
+        inline Matrix4()
+        {
+        }
+
+        inline Matrix4(
+            Real m00, Real m01, Real m02, Real m03,
+            Real m10, Real m11, Real m12, Real m13,
+            Real m20, Real m21, Real m22, Real m23,
+            Real m30, Real m31, Real m32, Real m33 )
+        {
+            m[0][0] = m00;
+            m[0][1] = m01;
+            m[0][2] = m02;
+            m[0][3] = m03;
+            m[1][0] = m10;
+            m[1][1] = m11;
+            m[1][2] = m12;
+            m[1][3] = m13;
+            m[2][0] = m20;
+            m[2][1] = m21;
+            m[2][2] = m22;
+            m[2][3] = m23;
+            m[3][0] = m30;
+            m[3][1] = m31;
+            m[3][2] = m32;
+            m[3][3] = m33;
+        }
+
+        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
+         */
+
+        inline Matrix4(const Matrix3& m3x3)
+        {
+          operator=(IDENTITY);
+          operator=(m3x3);
+        }
+
+        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Quaternion.
+         */
+        
+        inline Matrix4(const Quaternion& rot)
+        {
+          Matrix3 m3x3;
+          rot.ToRotationMatrix(m3x3);
+          operator=(IDENTITY);
+          operator=(m3x3);
+        }
+        
+
+        inline Real* operator [] ( size_t iRow )
+        {
+            assert( iRow < 4 );
+            return m[iRow];
+        }
+
+        inline const Real *const operator [] ( size_t iRow ) const
+        {
+            assert( iRow < 4 );
+            return m[iRow];
+        }
+
+        inline Matrix4 concatenate(const Matrix4 &m2) const
+        {
+            Matrix4 r;
+            r.m[0][0] = m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0] + m[0][3] * m2.m[3][0];
+            r.m[0][1] = m[0][0] * m2.m[0][1] + m[0][1] * m2.m[1][1] + m[0][2] * m2.m[2][1] + m[0][3] * m2.m[3][1];
+            r.m[0][2] = m[0][0] * m2.m[0][2] + m[0][1] * m2.m[1][2] + m[0][2] * m2.m[2][2] + m[0][3] * m2.m[3][2];
+            r.m[0][3] = m[0][0] * m2.m[0][3] + m[0][1] * m2.m[1][3] + m[0][2] * m2.m[2][3] + m[0][3] * m2.m[3][3];
+
+            r.m[1][0] = m[1][0] * m2.m[0][0] + m[1][1] * m2.m[1][0] + m[1][2] * m2.m[2][0] + m[1][3] * m2.m[3][0];
+            r.m[1][1] = m[1][0] * m2.m[0][1] + m[1][1] * m2.m[1][1] + m[1][2] * m2.m[2][1] + m[1][3] * m2.m[3][1];
+            r.m[1][2] = m[1][0] * m2.m[0][2] + m[1][1] * m2.m[1][2] + m[1][2] * m2.m[2][2] + m[1][3] * m2.m[3][2];
+            r.m[1][3] = m[1][0] * m2.m[0][3] + m[1][1] * m2.m[1][3] + m[1][2] * m2.m[2][3] + m[1][3] * m2.m[3][3];
+
+            r.m[2][0] = m[2][0] * m2.m[0][0] + m[2][1] * m2.m[1][0] + m[2][2] * m2.m[2][0] + m[2][3] * m2.m[3][0];
+            r.m[2][1] = m[2][0] * m2.m[0][1] + m[2][1] * m2.m[1][1] + m[2][2] * m2.m[2][1] + m[2][3] * m2.m[3][1];
+            r.m[2][2] = m[2][0] * m2.m[0][2] + m[2][1] * m2.m[1][2] + m[2][2] * m2.m[2][2] + m[2][3] * m2.m[3][2];
+            r.m[2][3] = m[2][0] * m2.m[0][3] + m[2][1] * m2.m[1][3] + m[2][2] * m2.m[2][3] + m[2][3] * m2.m[3][3];
+
+            r.m[3][0] = m[3][0] * m2.m[0][0] + m[3][1] * m2.m[1][0] + m[3][2] * m2.m[2][0] + m[3][3] * m2.m[3][0];
+            r.m[3][1] = m[3][0] * m2.m[0][1] + m[3][1] * m2.m[1][1] + m[3][2] * m2.m[2][1] + m[3][3] * m2.m[3][1];
+            r.m[3][2] = m[3][0] * m2.m[0][2] + m[3][1] * m2.m[1][2] + m[3][2] * m2.m[2][2] + m[3][3] * m2.m[3][2];
+            r.m[3][3] = m[3][0] * m2.m[0][3] + m[3][1] * m2.m[1][3] + m[3][2] * m2.m[2][3] + m[3][3] * m2.m[3][3];
+
+            return r;
+        }
+
+        /** Matrix concatenation using '*'.
+        */
+        inline Matrix4 operator * ( const Matrix4 &m2 ) const
+        {
+            return concatenate( m2 );
+        }
+
+        /** Vector transformation using '*'.
+            @remarks
+                Transforms the given 3-D vector by the matrix, projecting the 
+                result back into <i>w</i> = 1.
+            @note
+                This means that the initial <i>w</i> is considered to be 1.0,
+                and then all the tree elements of the resulting 3-D vector are
+                divided by the resulting <i>w</i>.
+        */
+        inline Vector3 operator * ( const Vector3 &v ) const
+        {
+            Vector3 r;
+
+            Real fInvW = 1.0 / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] );
+
+            r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
+            r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
+            r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
+
+            return r;
+        }
+        inline Vector4 operator * (const Vector4& v) const
+        {
+            return Vector4(
+                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
+                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
+                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
+                m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
+                );
+        }
+
+
+        /** Matrix addition.
+        */
+        inline Matrix4 operator + ( const Matrix4 &m2 ) const
+        {
+            Matrix4 r;
+
+            r.m[0][0] = m[0][0] + m2.m[0][0];
+            r.m[0][1] = m[0][1] + m2.m[0][1];
+            r.m[0][2] = m[0][2] + m2.m[0][2];
+            r.m[0][3] = m[0][3] + m2.m[0][3];
+
+            r.m[1][0] = m[1][0] + m2.m[1][0];
+            r.m[1][1] = m[1][1] + m2.m[1][1];
+            r.m[1][2] = m[1][2] + m2.m[1][2];
+            r.m[1][3] = m[1][3] + m2.m[1][3];
+
+            r.m[2][0] = m[2][0] + m2.m[2][0];
+            r.m[2][1] = m[2][1] + m2.m[2][1];
+            r.m[2][2] = m[2][2] + m2.m[2][2];
+            r.m[2][3] = m[2][3] + m2.m[2][3];
+
+            r.m[3][0] = m[3][0] + m2.m[3][0];
+            r.m[3][1] = m[3][1] + m2.m[3][1];
+            r.m[3][2] = m[3][2] + m2.m[3][2];
+            r.m[3][3] = m[3][3] + m2.m[3][3];
+
+            return r;
+        }
+
+        /** Matrix subtraction.
+        */
+        inline Matrix4 operator - ( const Matrix4 &m2 ) const
+        {
+            Matrix4 r;
+            r.m[0][0] = m[0][0] - m2.m[0][0];
+            r.m[0][1] = m[0][1] - m2.m[0][1];
+            r.m[0][2] = m[0][2] - m2.m[0][2];
+            r.m[0][3] = m[0][3] - m2.m[0][3];
+
+            r.m[1][0] = m[1][0] - m2.m[1][0];
+            r.m[1][1] = m[1][1] - m2.m[1][1];
+            r.m[1][2] = m[1][2] - m2.m[1][2];
+            r.m[1][3] = m[1][3] - m2.m[1][3];
+
+            r.m[2][0] = m[2][0] - m2.m[2][0];
+            r.m[2][1] = m[2][1] - m2.m[2][1];
+            r.m[2][2] = m[2][2] - m2.m[2][2];
+            r.m[2][3] = m[2][3] - m2.m[2][3];
+
+            r.m[3][0] = m[3][0] - m2.m[3][0];
+            r.m[3][1] = m[3][1] - m2.m[3][1];
+            r.m[3][2] = m[3][2] - m2.m[3][2];
+            r.m[3][3] = m[3][3] - m2.m[3][3];
+
+            return r;
+        }
+
+        /** Tests 2 matrices for equality.
+        */
+        inline bool operator == ( const Matrix4& m2 ) const
+        {
+            if( 
+                m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
+                m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
+                m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
+                m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
+                return false;
+            return true;
+        }
+
+        /** Tests 2 matrices for inequality.
+        */
+        inline bool operator != ( const Matrix4& m2 ) const
+        {
+            if( 
+                m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
+                m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
+                m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
+                m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
+                return true;
+            return false;
+        }
+
+        /** Assignment from 3x3 matrix.
+        */
+        inline void operator = ( const Matrix3& mat3 )
+        {
+            m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2];
+            m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2];
+            m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2];
+        }
+
+        inline Matrix4 transpose(void) const
+        {
+            return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
+                           m[0][1], m[1][1], m[2][1], m[3][1],
+                           m[0][2], m[1][2], m[2][2], m[3][2],
+                           m[0][3], m[1][3], m[2][3], m[3][3]);
+        }
+
+        /*
+        -----------------------------------------------------------------------
+        Translation Transformation
+        -----------------------------------------------------------------------
+        */
+        /** Sets the translation transformation part of the matrix.
+        */
+        inline void setTrans( const Vector3& v )
+        {
+            m[0][3] = v.x;
+            m[1][3] = v.y;
+            m[2][3] = v.z;
+        }
+
+        /** Extracts the translation transformation part of the matrix.
+         */
+        inline Vector3 getTrans() const
+        {
+          return Vector3(m[0][3], m[1][3], m[2][3]);
+        }
+        
+
+        /** Builds a translation matrix
+        */
+        inline void makeTrans( const Vector3& v )
+        {
+            m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = v.x;
+            m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = v.y;
+            m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = v.z;
+            m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
+        }
+
+        inline void makeTrans( Real tx, Real ty, Real tz )
+        {
+            m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = tx;
+            m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = ty;
+            m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = tz;
+            m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
+        }
+
+        /** Gets a translation matrix.
+        */
+        inline static Matrix4 getTrans( const Vector3& v )
+        {
+            Matrix4 r;
+
+            r.m[0][0] = 1.0; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = v.x;
+            r.m[1][0] = 0.0; r.m[1][1] = 1.0; r.m[1][2] = 0.0; r.m[1][3] = v.y;
+            r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = 1.0; r.m[2][3] = v.z;
+            r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
+
+            return r;
+        }
+
+        /** Gets a translation matrix - variation for not using a vector.
+        */
+        inline static Matrix4 getTrans( Real t_x, Real t_y, Real t_z )
+        {
+            Matrix4 r;
+
+            r.m[0][0] = 1.0; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = t_x;
+            r.m[1][0] = 0.0; r.m[1][1] = 1.0; r.m[1][2] = 0.0; r.m[1][3] = t_y;
+            r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = 1.0; r.m[2][3] = t_z;
+            r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
+
+            return r;
+        }
+
+        /*
+        -----------------------------------------------------------------------
+        Scale Transformation
+        -----------------------------------------------------------------------
+        */
+        /** Sets the scale part of the matrix.
+        */
+        inline void setScale( const Vector3& v )
+        {
+            m[0][0] = v.x;
+            m[1][1] = v.y;
+            m[2][2] = v.z;
+        }
+
+        /** Gets a scale matrix.
+        */
+        inline static Matrix4 getScale( const Vector3& v )
+        {
+            Matrix4 r;
+            r.m[0][0] = v.x; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = 0.0;
+            r.m[1][0] = 0.0; r.m[1][1] = v.y; r.m[1][2] = 0.0; r.m[1][3] = 0.0;
+            r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = v.z; r.m[2][3] = 0.0;
+            r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
+
+            return r;
+        }
+
+        /** Gets a scale matrix - variation for not using a vector.
+        */
+        inline static Matrix4 getScale( Real s_x, Real s_y, Real s_z )
+        {
+            Matrix4 r;
+            r.m[0][0] = s_x; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = 0.0;
+            r.m[1][0] = 0.0; r.m[1][1] = s_y; r.m[1][2] = 0.0; r.m[1][3] = 0.0;
+            r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = s_z; r.m[2][3] = 0.0;
+            r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
+
+            return r;
+        }
+
+        /** Extracts the rotation / scaling part of the Matrix as a 3x3 matrix. 
+        @param m3x3 Destination Matrix3
+        */
+        inline void extract3x3Matrix(Matrix3& m3x3) const
+        {
+            m3x3.m[0][0] = m[0][0];
+            m3x3.m[0][1] = m[0][1];
+            m3x3.m[0][2] = m[0][2];
+            m3x3.m[1][0] = m[1][0];
+            m3x3.m[1][1] = m[1][1];
+            m3x3.m[1][2] = m[1][2];
+            m3x3.m[2][0] = m[2][0];
+            m3x3.m[2][1] = m[2][1];
+            m3x3.m[2][2] = m[2][2];
+
+        }
+
+		/** Determines if this matrix involves a scaling. */
+		inline bool hasScale() const
+		{
+			// check magnitude of column vectors (==local axes)
+			Real t = m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+			t = m[0][1] * m[0][1] + m[1][1] * m[1][1] + m[2][1] * m[2][1];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+			t = m[0][2] * m[0][2] + m[1][2] * m[1][2] + m[2][2] * m[2][2];
+			if (!Math::RealEqual(t, 1.0, 1e-04))
+				return true;
+
+			return false;
+		}
+
+		/** Determines if this matrix involves a negative scaling. */
+		inline bool hasNegativeScale() const
+		{
+			return determinant() < 0;
+		}
+
+		/** Extracts the rotation / scaling part as a quaternion from the Matrix.
+         */
+        inline Quaternion extractQuaternion() const
+        {
+          Matrix3 m3x3;
+          extract3x3Matrix(m3x3);
+          return Quaternion(m3x3);
+        }
+
+        static const Matrix4 ZERO;
+        static const Matrix4 IDENTITY;
+        /** Useful little matrix which takes 2D clipspace {-1, 1} to {0,1}
+            and inverts the Y. */
+        static const Matrix4 CLIPSPACE2DTOIMAGESPACE;
+
+        inline Matrix4 operator*(Real scalar) const
+        {
+            return Matrix4(
+                scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3],
+                scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3],
+                scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3],
+                scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]);
+        }
+
+        /** Function for writing to a stream.
+        */
+        inline _OgreExport friend std::ostream& operator <<
+            ( std::ostream& o, const Matrix4& m )
+        {
+            o << "Matrix4(";
+			for (size_t i = 0; i < 4; ++i)
+            {
+                o << " row" << (unsigned)i << "{";
+                for(size_t j = 0; j < 4; ++j)
+                {
+                    o << m[i][j] << " ";
+                }
+                o << "}";
+            }
+            o << ")";
+            return o;
+        }
+		
+		Matrix4 adjoint() const;
+		Real determinant() const;
+		Matrix4 inverse() const;
+
+        /** Building a Matrix4 from orientation / scale / position.
+        @remarks
+            Transform is performed in the order scale, rotate, translation, i.e. translation is independent
+            of orientation axes, scale does not affect size of translation, rotation and scaling are always
+            centered on the origin.
+        */
+        void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
+
+        /** Building an inverse Matrix4 from orientation / scale / position.
+        @remarks
+            As makeTransform except it build the inverse given the same data as makeTransform, so
+            performing -translation, -rotate, 1/scale in that order.
+        */
+        void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
+
+        /** Check whether or not the matrix is affine matrix.
+            @remarks
+                An affine matrix is a 4x4 matrix with row 3 equal to (0, 0, 0, 1),
+                e.g. no projective coefficients.
+        */
+        inline bool isAffine(void) const
+        {
+            return m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0 && m[3][3] == 1;
+        }
+
+        /** Returns the inverse of the affine matrix.
+            @note
+                The matrix must be an affine matrix. @see Matrix4::isAffine.
+        */
+        Matrix4 inverseAffine(void) const;
+
+        /** Concatenate two affine matrix.
+            @note
+                The matrices must be affine matrix. @see Matrix4::isAffine.
+        */
+        inline Matrix4 concatenateAffine(const Matrix4 &m2) const
+        {
+            assert(isAffine() && m2.isAffine());
+
+            return Matrix4(
+                m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0],
+                m[0][0] * m2.m[0][1] + m[0][1] * m2.m[1][1] + m[0][2] * m2.m[2][1],
+                m[0][0] * m2.m[0][2] + m[0][1] * m2.m[1][2] + m[0][2] * m2.m[2][2],
+                m[0][0] * m2.m[0][3] + m[0][1] * m2.m[1][3] + m[0][2] * m2.m[2][3] + m[0][3],
+
+                m[1][0] * m2.m[0][0] + m[1][1] * m2.m[1][0] + m[1][2] * m2.m[2][0],
+                m[1][0] * m2.m[0][1] + m[1][1] * m2.m[1][1] + m[1][2] * m2.m[2][1],
+                m[1][0] * m2.m[0][2] + m[1][1] * m2.m[1][2] + m[1][2] * m2.m[2][2],
+                m[1][0] * m2.m[0][3] + m[1][1] * m2.m[1][3] + m[1][2] * m2.m[2][3] + m[1][3],
+
+                m[2][0] * m2.m[0][0] + m[2][1] * m2.m[1][0] + m[2][2] * m2.m[2][0],
+                m[2][0] * m2.m[0][1] + m[2][1] * m2.m[1][1] + m[2][2] * m2.m[2][1],
+                m[2][0] * m2.m[0][2] + m[2][1] * m2.m[1][2] + m[2][2] * m2.m[2][2],
+                m[2][0] * m2.m[0][3] + m[2][1] * m2.m[1][3] + m[2][2] * m2.m[2][3] + m[2][3],
+
+                0, 0, 0, 1);
+        }
+
+        /** 3-D Vector transformation specially for affine matrix.
+            @remarks
+                Transforms the given 3-D vector by the matrix, projecting the 
+                result back into <i>w</i> = 1.
+            @note
+                The matrix must be an affine matrix. @see Matrix4::isAffine.
+        */
+        inline Vector3 transformAffine(const Vector3& v) const
+        {
+            assert(isAffine());
+
+            return Vector3(
+                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3], 
+                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
+                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
+        }
+
+        /** 4-D Vector transformation specially for affine matrix.
+            @note
+                The matrix must be an affine matrix. @see Matrix4::isAffine.
+        */
+        inline Vector4 transformAffine(const Vector4& v) const
+        {
+            assert(isAffine());
+
+            return Vector4(
+                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
+                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
+                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
+                v.w);
+        }
+    };
+
+    /* Removed from Vector4 and made a non-member here because otherwise
+       OgreMatrix4.h and OgreVector4.h have to try to include and inline each 
+       other, which frankly doesn't work ;)
+   */
+    inline Vector4 operator * (const Vector4& v, const Matrix4& mat)
+    {
+        return Vector4(
+            v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + v.w*mat[3][0],
+            v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + v.w*mat[3][1],
+            v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + v.w*mat[3][2],
+            v.x*mat[0][3] + v.y*mat[1][3] + v.z*mat[2][3] + v.w*mat[3][3]
+            );
+    }
+
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgrePlatform.h
===================================================================
--- sandbox_light/src/external/ogremath/OgrePlatform.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgrePlatform.h	(revision 5789)
@@ -0,0 +1,226 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Platform_H_
+#define __Platform_H_
+
+#include "OgreConfig.h"
+
+namespace Ogre {
+/* Initial platform/compiler-related stuff to set.
+*/
+#define OGRE_PLATFORM_WIN32 1
+#define OGRE_PLATFORM_LINUX 2
+#define OGRE_PLATFORM_APPLE 3
+
+#define OGRE_COMPILER_MSVC 1
+#define OGRE_COMPILER_GNUC 2
+#define OGRE_COMPILER_BORL 3
+
+#define OGRE_ENDIAN_LITTLE 1
+#define OGRE_ENDIAN_BIG 2
+
+#define OGRE_ARCHITECTURE_32 1
+#define OGRE_ARCHITECTURE_64 2
+
+/* Finds the compiler type and version.
+*/
+#if defined( _MSC_VER )
+#   define OGRE_COMPILER OGRE_COMPILER_MSVC
+#   define OGRE_COMP_VER _MSC_VER
+
+#elif defined( __GNUC__ )
+#   define OGRE_COMPILER OGRE_COMPILER_GNUC
+#   define OGRE_COMP_VER (((__GNUC__)*100) + \
+        (__GNUC_MINOR__*10) + \
+        __GNUC_PATCHLEVEL__)
+
+#elif defined( __BORLANDC__ )
+#   define OGRE_COMPILER OGRE_COMPILER_BORL
+#   define OGRE_COMP_VER __BCPLUSPLUS__
+#   define __FUNCTION__ __FUNC__ 
+#else
+#   pragma error "No known compiler. Abort! Abort!"
+
+#endif
+
+/* See if we can use __forceinline or if we need to use __inline instead */
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+#   if OGRE_COMP_VER >= 1200
+#       define FORCEINLINE __forceinline
+#   endif
+#elif defined(__MINGW32__)
+#   if !defined(FORCEINLINE)
+#       define FORCEINLINE __inline
+#   endif
+#else
+#   define FORCEINLINE __inline
+#endif
+
+/* Finds the current platform */
+
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#   define OGRE_PLATFORM OGRE_PLATFORM_WIN32
+
+#elif defined( __APPLE_CC__)
+#   define OGRE_PLATFORM OGRE_PLATFORM_APPLE
+
+#else
+#   define OGRE_PLATFORM OGRE_PLATFORM_LINUX
+#endif
+
+    /* Find the arch type */
+#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || defined(__alpha__) || defined(__ia64__) || defined(__s390__) || defined(__s390x__)
+#   define OGRE_ARCH_TYPE OGRE_ARCHITECTURE_64
+#else
+#   define OGRE_ARCH_TYPE OGRE_ARCHITECTURE_32
+#endif
+
+// For generating compiler warnings - should work on any compiler
+// As a side note, if you start your message with 'Warning: ', the MSVC
+// IDE actually does catch a warning :)
+#define OGRE_QUOTE_INPLACE(x) # x
+#define OGRE_QUOTE(x) OGRE_QUOTE_INPLACE(x)
+#define OGRE_WARN( x )  message( __FILE__ "(" QUOTE( __LINE__ ) ") : " x "\n" )
+
+//----------------------------------------------------------------------------
+// Windows Settings
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+
+// If we're not including this from a client build, specify that the stuff
+// should get exported. Otherwise, import it.
+#	if defined( OGRE_STATIC_LIB )
+		// Linux compilers don't have symbol import/export directives.
+#   	define _OgreExport
+#   	define _OgrePrivate
+#   else
+#   	if defined( OGRE_NONCLIENT_BUILD )
+#       	define _OgreExport __declspec( dllexport )
+#   	else
+#           if defined( __MINGW32__ )
+#               define _OgreExport
+#           else
+#       	    define _OgreExport __declspec( dllimport )
+#           endif
+#   	endif
+#   	define _OgrePrivate
+#	endif
+// Win32 compilers use _DEBUG for specifying debug builds.
+#   ifdef _DEBUG
+#       define OGRE_DEBUG_MODE 1
+#   else
+#       define OGRE_DEBUG_MODE 0
+#   endif
+
+// Disable unicode support on MingW at the moment, poorly supported in stdlibc++
+// STLPORT fixes this though so allow if found
+// MinGW C++ Toolkit supports unicode and sets the define __MINGW32_TOOLKIT_UNICODE__ in _mingw.h
+#if defined( __MINGW32__ ) && !defined(_STLPORT_VERSION)
+#   include<_mingw.h>
+#   if defined(__MINGW32_TOOLBOX_UNICODE__)
+#	    define OGRE_UNICODE_SUPPORT 1
+#   else
+#       define OGRE_UNICODE_SUPPORT 0
+#   endif
+#else
+#	define OGRE_UNICODE_SUPPORT 1
+#endif
+
+#endif
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Linux/Apple Settings
+#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+
+// Enable GCC symbol visibility
+#   if defined( OGRE_GCC_VISIBILITY )
+#       define _OgreExport  __attribute__ ((visibility("default")))
+#       define _OgrePrivate __attribute__ ((visibility("hidden")))
+#   else
+#       define _OgreExport
+#       define _OgrePrivate
+#   endif
+
+// A quick define to overcome different names for the same function
+#   define stricmp strcasecmp
+
+// Unlike the Win32 compilers, Linux compilers seem to use DEBUG for when
+// specifying a debug build.
+// (??? this is wrong, on Linux debug builds aren't marked in any way unless
+// you mark it yourself any way you like it -- zap ???)
+#   ifdef DEBUG
+#       define OGRE_DEBUG_MODE 1
+#   else
+#       define OGRE_DEBUG_MODE 0
+#   endif
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+    #define OGRE_PLATFORM_LIB "OgrePlatform.bundle"
+#else
+    //OGRE_PLATFORM_LINUX
+    #define OGRE_PLATFORM_LIB "libOgrePlatform.so"
+#endif
+
+// Always enable unicode support for the moment
+// Perhaps disable in old versions of gcc if necessary
+#define OGRE_UNICODE_SUPPORT 1
+
+#endif
+
+//For apple, we always have a custom config.h file
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+#    include "config.h"
+#endif
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Endian Settings
+// check for BIG_ENDIAN config flag, set OGRE_ENDIAN correctly
+#ifdef OGRE_CONFIG_BIG_ENDIAN
+#    define OGRE_ENDIAN OGRE_ENDIAN_BIG
+#else
+#    define OGRE_ENDIAN OGRE_ENDIAN_LITTLE
+#endif
+
+// Integer formats of fixed bit width
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+// define uint64 type
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+	typedef unsigned __int64 uint64;
+#else
+	typedef unsigned long long uint64;
+#endif
+
+
+}
+
+#endif
Index: sandbox_light/src/external/ogremath/OgrePrerequisites.h
===================================================================
--- sandbox_light/src/external/ogremath/OgrePrerequisites.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgrePrerequisites.h	(revision 5789)
@@ -0,0 +1,407 @@
+/*-------------------------------------------------------------------------
+This source file is a part of OGRE
+(Object-oriented Graphics Rendering Engine)
+
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+This library is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License (LGPL) as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
+http://www.gnu.org/copyleft/lesser.txt
+-------------------------------------------------------------------------*/
+#ifndef __OgrePrerequisites_H__
+#define __OgrePrerequisites_H__
+
+// Platform-specific stuff
+#include "OgrePlatform.h"
+
+// Needed for OGRE_WCHAR_T_STRINGS below
+#include <string>
+
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+// Turn off warnings generated by long std templates
+// This warns about truncation to 255 characters in debug/browse info
+#   pragma warning (disable : 4786)
+
+// Turn off warnings generated by long std templates
+// This warns about truncation to 255 characters in debug/browse info
+#   pragma warning (disable : 4503)
+
+// disable: "conversion from 'double' to 'float', possible loss of data
+#   pragma warning (disable : 4244)
+
+// disable: "truncation from 'double' to 'float'
+#   pragma warning (disable : 4305)
+
+// disable: "<type> needs to have dll-interface to be used by clients'
+// Happens on STL member variables which are not public therefore is ok
+#   pragma warning (disable : 4251)
+
+// disable: "non dll-interface class used as base for dll-interface class"
+// Happens when deriving from Singleton because bug in compiler ignores
+// template export
+#   pragma warning (disable : 4275)
+
+// disable: "C++ Exception Specification ignored"
+// This is because MSVC 6 did not implement all the C++ exception
+// specifications in the ANSI C++ draft.
+#   pragma warning( disable : 4290 )
+
+// disable: "no suitable definition provided for explicit template
+// instantiation request" Occurs in VC7 for no justifiable reason on all
+// #includes of Singleton
+#   pragma warning( disable: 4661)
+
+// disable: deprecation warnings when using CRT calls in VC8
+// These show up on all C runtime lib code in VC8, disable since they clutter
+// the warnings with things we may not be able to do anything about (e.g.
+// generated code from nvparse etc). I doubt very much that these calls
+// will ever be actually removed from VC anyway, it would break too much code.
+#	pragma warning( disable: 4996)
+
+// disable: "conditional expression constant", always occurs on 
+// OGRE_MUTEX_CONDITIONAL when no threading enabled
+#   pragma warning (disable : 201)
+
+#endif
+
+// configure memory tracking
+#if OGRE_DEBUG_MODE 
+#	if OGRE_MEMORY_TRACKER_DEBUG_MODE
+#		define OGRE_MEMORY_TRACKER 1
+#	else
+#		define OGRE_MEMORY_TRACKER 0
+#	endif
+#else
+#	if OGRE_MEMORY_TRACKER_RELEASE_MODE
+#		define OGRE_MEMORY_TRACKER 1
+#	else
+#		define OGRE_MEMORY_TRACKER 0
+#	endif
+#endif
+
+
+
+
+namespace Ogre {
+    // Define ogre version
+    #define OGRE_VERSION_MAJOR 1
+    #define OGRE_VERSION_MINOR 6
+    #define OGRE_VERSION_PATCH 1
+	#define OGRE_VERSION_SUFFIX ""
+    #define OGRE_VERSION_NAME "Shoggoth"
+
+    #define OGRE_VERSION    ((OGRE_VERSION_MAJOR << 16) | (OGRE_VERSION_MINOR << 8) | OGRE_VERSION_PATCH)
+
+    // define the real number values to be used
+    // default to use 'float' unless precompiler option set
+    #if OGRE_DOUBLE_PRECISION == 1
+		/** Software floating point type.
+		@note Not valid as a pointer to GPU buffers / parameters
+		*/
+        typedef double Real;
+    #else
+		/** Software floating point type.
+		@note Not valid as a pointer to GPU buffers / parameters
+		*/
+        typedef float Real;
+    #endif
+
+    #if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 310 && !defined(STLPORT)
+	#   if OGRE_COMP_VER >= 430
+	#       define HashMap ::std::tr1::unordered_map
+	#		define HashSet ::std::tr1::unordered_set
+	#    else
+	#       define HashMap ::__gnu_cxx::hash_map
+	#       define HashSet ::__gnu_cxx::hash_set
+	#    endif
+    #else
+    #   if OGRE_COMPILER == OGRE_COMPILER_MSVC
+    #       if OGRE_COMP_VER > 1300 && !defined(_STLP_MSVC)
+    #           define HashMap ::stdext::hash_map
+	#           define HashSet ::stdext::hash_set
+    #       else
+    #           define HashMap ::std::hash_map
+	#           define HashSet ::std::hash_set
+    #       endif
+    #   else
+    #       define HashMap ::std::hash_map
+	#       define HashSet ::std::hash_set
+    #   endif
+    #endif
+
+    /** In order to avoid finger-aches :)
+    */
+    typedef unsigned char uchar;
+    typedef unsigned short ushort;
+    typedef unsigned int uint;
+	typedef unsigned long ulong;
+
+	#if OGRE_WCHAR_T_STRINGS
+		typedef std::wstring _StringBase;
+	#else
+		typedef std::string _StringBase;
+	#endif
+
+	typedef _StringBase String;
+
+	// Useful threading defines
+	#define OGRE_AUTO_MUTEX_NAME mutex
+	#if OGRE_THREAD_SUPPORT
+		#define OGRE_AUTO_MUTEX mutable boost::recursive_mutex OGRE_AUTO_MUTEX_NAME;
+		#define OGRE_LOCK_AUTO_MUTEX boost::recursive_mutex::scoped_lock ogreAutoMutexLock(OGRE_AUTO_MUTEX_NAME);
+		#define OGRE_MUTEX(name) mutable boost::recursive_mutex name;
+		#define OGRE_STATIC_MUTEX(name) static boost::recursive_mutex name;
+		#define OGRE_STATIC_MUTEX_INSTANCE(name) boost::recursive_mutex name;
+		#define OGRE_LOCK_MUTEX(name) boost::recursive_mutex::scoped_lock ogrenameLock(name);
+		#define OGRE_LOCK_MUTEX_NAMED(mutexName, lockName) boost::recursive_mutex::scoped_lock lockName(mutexName);
+		// like OGRE_AUTO_MUTEX but mutex held by pointer
+		#define OGRE_AUTO_SHARED_MUTEX mutable boost::recursive_mutex *OGRE_AUTO_MUTEX_NAME;
+		#define OGRE_LOCK_AUTO_SHARED_MUTEX assert(OGRE_AUTO_MUTEX_NAME); boost::recursive_mutex::scoped_lock ogreAutoMutexLock(*OGRE_AUTO_MUTEX_NAME);
+		#define OGRE_NEW_AUTO_SHARED_MUTEX assert(!OGRE_AUTO_MUTEX_NAME); OGRE_AUTO_MUTEX_NAME = new boost::recursive_mutex();
+        #define OGRE_DELETE_AUTO_SHARED_MUTEX assert(OGRE_AUTO_MUTEX_NAME); delete OGRE_AUTO_MUTEX_NAME;
+		#define OGRE_COPY_AUTO_SHARED_MUTEX(from) assert(!OGRE_AUTO_MUTEX_NAME); OGRE_AUTO_MUTEX_NAME = from;
+        #define OGRE_SET_AUTO_SHARED_MUTEX_NULL OGRE_AUTO_MUTEX_NAME = 0;
+        #define OGRE_MUTEX_CONDITIONAL(mutex) if (mutex)
+		#define OGRE_THREAD_SYNCHRONISER(sync) boost::condition sync;
+		#define OGRE_THREAD_WAIT(sync, lock) sync.wait(lock);
+		#define OGRE_THREAD_NOTIFY_ONE(sync) sync.notify_one(); 
+		#define OGRE_THREAD_NOTIFY_ALL(sync) sync.notify_all(); 
+		// Thread-local pointer
+		#define OGRE_THREAD_POINTER(T, var) boost::thread_specific_ptr<T> var
+		#define OGRE_THREAD_POINTER_SET(var, expr) var.reset(expr)
+		#define OGRE_THREAD_POINTER_DELETE(var) var.reset(0)
+		#define OGRE_THREAD_POINTER_GET(var) var.get()
+	#else
+		#define OGRE_AUTO_MUTEX
+		#define OGRE_LOCK_AUTO_MUTEX
+		#define OGRE_MUTEX(name)
+		#define OGRE_STATIC_MUTEX(name)
+		#define OGRE_STATIC_MUTEX_INSTANCE(name)
+		#define OGRE_LOCK_MUTEX(name)
+		#define OGRE_LOCK_MUTEX_NAMED(mutexName, lockName)
+		#define OGRE_AUTO_SHARED_MUTEX
+		#define OGRE_LOCK_AUTO_SHARED_MUTEX
+		#define OGRE_NEW_AUTO_SHARED_MUTEX
+		#define OGRE_DELETE_AUTO_SHARED_MUTEX
+		#define OGRE_COPY_AUTO_SHARED_MUTEX(from)
+        #define OGRE_SET_AUTO_SHARED_MUTEX_NULL
+        #define OGRE_MUTEX_CONDITIONAL(name) if(true)
+		#define OGRE_THREAD_SYNCHRONISER(sync) 
+		#define OGRE_THREAD_WAIT(sync, lock) 
+		#define OGRE_THREAD_NOTIFY_ONE(sync) 
+		#define OGRE_THREAD_NOTIFY_ALL(sync) 
+		#define OGRE_THREAD_POINTER(T, var) T* var
+		#define OGRE_THREAD_POINTER_SET(var, expr) var = expr
+		#define OGRE_THREAD_POINTER_DELETE(var) OGRE_DELETE var; var = 0
+		#define OGRE_THREAD_POINTER_GET(var) var
+	#endif
+
+
+// Pre-declare classes
+// Allows use of pointers in header files without including individual .h
+// so decreases dependencies between files
+    class Angle;
+    class Animation;
+    class AnimationState;
+    class AnimationStateSet;
+    class AnimationTrack;
+    class Archive;
+    class ArchiveFactory;
+    class ArchiveManager;
+    class AutoParamDataSource;
+    class AxisAlignedBox;
+    class AxisAlignedBoxSceneQuery;
+    class Billboard;
+    class BillboardChain;
+    class BillboardSet;
+    class Bone;
+    class Camera;
+    class Codec;
+    class ColourValue;
+    class ConfigDialog;
+    template <typename T> class Controller;
+    template <typename T> class ControllerFunction;
+    class ControllerManager;
+    template <typename T> class ControllerValue;
+    class Degree;
+    class DynLib;
+    class DynLibManager;
+    class EdgeData;
+    class EdgeListBuilder;
+    class Entity;
+    class ErrorDialog;
+    class ExternalTextureSourceManager;
+    class Factory;
+    class Font;
+    class FontPtr;
+    class FontManager;
+    struct FrameEvent;
+    class FrameListener;
+    class Frustum;
+    class GpuProgram;
+    class GpuProgramPtr;
+    class GpuProgramManager;
+	class GpuProgramUsage;
+    class HardwareIndexBuffer;
+    class HardwareOcclusionQuery;
+    class HardwareVertexBuffer;
+	class HardwarePixelBuffer;
+    class HardwarePixelBufferSharedPtr;
+	class HighLevelGpuProgram;
+    class HighLevelGpuProgramPtr;
+	class HighLevelGpuProgramManager;
+	class HighLevelGpuProgramFactory;
+    class IndexData;
+    class IntersectionSceneQuery;
+    class IntersectionSceneQueryListener;
+    class Image;
+    class KeyFrame;
+    class Light;
+    class Log;
+    class LogManager;
+	class ManualResourceLoader;
+	class ManualObject;
+    class Material;
+    class MaterialPtr;
+    class MaterialManager;
+    class Math;
+    class Matrix3;
+    class Matrix4;
+    class MemoryManager;
+    class Mesh;
+    class MeshPtr;
+    class MeshSerializer;
+    class MeshSerializerImpl;
+    class MeshManager;
+    class MovableObject;
+    class MovablePlane;
+    class Node;
+	class NodeAnimationTrack;
+	class NodeKeyFrame;
+	class NumericAnimationTrack;
+	class NumericKeyFrame;
+    class Overlay;
+    class OverlayContainer;
+    class OverlayElement;
+    class OverlayElementFactory;
+    class OverlayManager;
+    class Particle;
+    class ParticleAffector;
+    class ParticleAffectorFactory;
+    class ParticleEmitter;
+    class ParticleEmitterFactory;
+    class ParticleSystem;
+    class ParticleSystemManager;
+    class ParticleSystemRenderer;
+    class ParticleSystemRendererFactory;
+    class ParticleVisualData;
+    class Pass;
+    class PatchMesh;
+    class PixelBox;
+    class Plane;
+    class PlaneBoundedVolume;
+	class Plugin;
+    class Pose;
+    class ProgressiveMesh;
+    class Profile;
+	class Profiler;
+    class Quaternion;
+	class Radian;
+    class Ray;
+    class RaySceneQuery;
+    class RaySceneQueryListener;
+    class Renderable;
+    class RenderPriorityGroup;
+    class RenderQueue;
+    class RenderQueueGroup;
+	class RenderQueueInvocation;
+	class RenderQueueInvocationSequence;
+    class RenderQueueListener;
+    class RenderSystem;
+    class RenderSystemCapabilities;
+    class RenderSystemCapabilitiesManager;
+    class RenderSystemCapabilitiesSerializer;
+    class RenderTarget;
+    class RenderTargetListener;
+    class RenderTexture;
+	class MultiRenderTarget;
+    class RenderWindow;
+    class RenderOperation;
+    class Resource;
+	class ResourceBackgroundQueue;
+	class ResourceGroupManager;
+    class ResourceManager;
+    class RibbonTrail;
+	class Root;
+    class SceneManager;
+    class SceneManagerEnumerator;
+    class SceneNode;
+    class SceneQuery;
+    class SceneQueryListener;
+	class ScriptCompiler;
+	class ScriptCompilerManager;
+	class ScriptLoader;
+    class Serializer;
+    class ShadowCaster;
+    class ShadowRenderable;
+	class ShadowTextureManager;
+    class SimpleRenderable;
+    class SimpleSpline;
+    class Skeleton;
+    class SkeletonPtr;
+    class SkeletonInstance;
+    class SkeletonManager;
+    class Sphere;
+    class SphereSceneQuery;
+	class StaticGeometry;
+    class StringConverter;
+    class StringInterface;
+    class SubEntity;
+    class SubMesh;
+	class TagPoint;
+    class Technique;
+	class TempBlendedBufferInfo;
+	class ExternalTextureSource;
+    class TextureUnitState;
+    class Texture;
+    class TexturePtr;
+    class TextureManager;
+    class TransformKeyFrame;
+	class Timer;
+    class UserDefinedObject;
+    class Vector2;
+    class Vector3;
+    class Vector4;
+    class Viewport;
+	class VertexAnimationTrack;
+    class VertexBufferBinding;
+    class VertexData;
+    class VertexDeclaration;
+	class VertexMorphKeyFrame;
+    class WireBoundingBox;
+    class Compositor;
+    class CompositorManager;
+    class CompositorChain;
+    class CompositorInstance;
+    class CompositionTechnique;
+    class CompositionPass;
+    class CompositionTargetPass;
+}
+
+#endif // __OgrePrerequisites_H__
+
+
Index: sandbox_light/src/external/ogremath/OgreQuaternion.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreQuaternion.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreQuaternion.cpp	(revision 5789)
@@ -0,0 +1,615 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+// NOTE THAT THIS FILE IS BASED ON MATERIAL FROM:
+
+// Magic Software, Inc.
+// http://www.geometrictools.com
+// Copyright (c) 2000, All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement.  The various license agreements may be found at
+// the Magic Software web site.  This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.geometrictools.com/License/WildMagic3License.pdf
+
+#include "OgreQuaternion.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreVector3.h"
+
+namespace Ogre {
+
+    const Real Quaternion::ms_fEpsilon = 1e-03;
+    const Quaternion Quaternion::ZERO(0.0,0.0,0.0,0.0);
+    const Quaternion Quaternion::IDENTITY(1.0,0.0,0.0,0.0);
+
+    //-----------------------------------------------------------------------
+    void Quaternion::FromRotationMatrix (const Matrix3& kRot)
+    {
+        // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+        // article "Quaternion Calculus and Fast Animation".
+
+        Real fTrace = kRot[0][0]+kRot[1][1]+kRot[2][2];
+        Real fRoot;
+
+        if ( fTrace > 0.0 )
+        {
+            // |w| > 1/2, may as well choose w > 1/2
+            fRoot = Math::Sqrt(fTrace + 1.0);  // 2w
+            w = 0.5*fRoot;
+            fRoot = 0.5/fRoot;  // 1/(4w)
+            x = (kRot[2][1]-kRot[1][2])*fRoot;
+            y = (kRot[0][2]-kRot[2][0])*fRoot;
+            z = (kRot[1][0]-kRot[0][1])*fRoot;
+        }
+        else
+        {
+            // |w| <= 1/2
+            static size_t s_iNext[3] = { 1, 2, 0 };
+            size_t i = 0;
+            if ( kRot[1][1] > kRot[0][0] )
+                i = 1;
+            if ( kRot[2][2] > kRot[i][i] )
+                i = 2;
+            size_t j = s_iNext[i];
+            size_t k = s_iNext[j];
+
+            fRoot = Math::Sqrt(kRot[i][i]-kRot[j][j]-kRot[k][k] + 1.0);
+            Real* apkQuat[3] = { &x, &y, &z };
+            *apkQuat[i] = 0.5*fRoot;
+            fRoot = 0.5/fRoot;
+            w = (kRot[k][j]-kRot[j][k])*fRoot;
+            *apkQuat[j] = (kRot[j][i]+kRot[i][j])*fRoot;
+            *apkQuat[k] = (kRot[k][i]+kRot[i][k])*fRoot;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::ToRotationMatrix (Matrix3& kRot) const
+    {
+        Real fTx  = 2.0*x;
+        Real fTy  = 2.0*y;
+        Real fTz  = 2.0*z;
+        Real fTwx = fTx*w;
+        Real fTwy = fTy*w;
+        Real fTwz = fTz*w;
+        Real fTxx = fTx*x;
+        Real fTxy = fTy*x;
+        Real fTxz = fTz*x;
+        Real fTyy = fTy*y;
+        Real fTyz = fTz*y;
+        Real fTzz = fTz*z;
+
+        kRot[0][0] = 1.0-(fTyy+fTzz);
+        kRot[0][1] = fTxy-fTwz;
+        kRot[0][2] = fTxz+fTwy;
+        kRot[1][0] = fTxy+fTwz;
+        kRot[1][1] = 1.0-(fTxx+fTzz);
+        kRot[1][2] = fTyz-fTwx;
+        kRot[2][0] = fTxz-fTwy;
+        kRot[2][1] = fTyz+fTwx;
+        kRot[2][2] = 1.0-(fTxx+fTyy);
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::FromAngleAxis (const Radian& rfAngle,
+        const Vector3& rkAxis)
+    {
+        // assert:  axis[] is unit length
+        //
+        // The quaternion representing the rotation is
+        //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
+
+        Radian fHalfAngle ( 0.5*rfAngle );
+        Real fSin = Math::Sin(fHalfAngle);
+        w = Math::Cos(fHalfAngle);
+        x = fSin*rkAxis.x;
+        y = fSin*rkAxis.y;
+        z = fSin*rkAxis.z;
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::ToAngleAxis (Radian& rfAngle, Vector3& rkAxis) const
+    {
+        // The quaternion representing the rotation is
+        //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
+
+        Real fSqrLength = x*x+y*y+z*z;
+        if ( fSqrLength > 0.0 )
+        {
+            rfAngle = 2.0*Math::ACos(w);
+            Real fInvLength = Math::InvSqrt(fSqrLength);
+            rkAxis.x = x*fInvLength;
+            rkAxis.y = y*fInvLength;
+            rkAxis.z = z*fInvLength;
+        }
+        else
+        {
+            // angle is 0 (mod 2*pi), so any axis will do
+            rfAngle = Radian(0.0);
+            rkAxis.x = 1.0;
+            rkAxis.y = 0.0;
+            rkAxis.z = 0.0;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::FromAxes (const Vector3* akAxis)
+    {
+        Matrix3 kRot;
+
+        for (size_t iCol = 0; iCol < 3; iCol++)
+        {
+            kRot[0][iCol] = akAxis[iCol].x;
+            kRot[1][iCol] = akAxis[iCol].y;
+            kRot[2][iCol] = akAxis[iCol].z;
+        }
+
+        FromRotationMatrix(kRot);
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::FromAxes (const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
+    {
+        Matrix3 kRot;
+
+        kRot[0][0] = xaxis.x;
+        kRot[1][0] = xaxis.y;
+        kRot[2][0] = xaxis.z;
+
+        kRot[0][1] = yaxis.x;
+        kRot[1][1] = yaxis.y;
+        kRot[2][1] = yaxis.z;
+
+        kRot[0][2] = zaxis.x;
+        kRot[1][2] = zaxis.y;
+        kRot[2][2] = zaxis.z;
+
+        FromRotationMatrix(kRot);
+
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::ToAxes (Vector3* akAxis) const
+    {
+        Matrix3 kRot;
+
+        ToRotationMatrix(kRot);
+
+        for (size_t iCol = 0; iCol < 3; iCol++)
+        {
+            akAxis[iCol].x = kRot[0][iCol];
+            akAxis[iCol].y = kRot[1][iCol];
+            akAxis[iCol].z = kRot[2][iCol];
+        }
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::xAxis(void) const
+    {
+        //Real fTx  = 2.0*x;
+        Real fTy  = 2.0*y;
+        Real fTz  = 2.0*z;
+        Real fTwy = fTy*w;
+        Real fTwz = fTz*w;
+        Real fTxy = fTy*x;
+        Real fTxz = fTz*x;
+        Real fTyy = fTy*y;
+        Real fTzz = fTz*z;
+
+        return Vector3(1.0-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy);
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::yAxis(void) const
+    {
+        Real fTx  = 2.0*x;
+        Real fTy  = 2.0*y;
+        Real fTz  = 2.0*z;
+        Real fTwx = fTx*w;
+        Real fTwz = fTz*w;
+        Real fTxx = fTx*x;
+        Real fTxy = fTy*x;
+        Real fTyz = fTz*y;
+        Real fTzz = fTz*z;
+
+        return Vector3(fTxy-fTwz, 1.0-(fTxx+fTzz), fTyz+fTwx);
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::zAxis(void) const
+    {
+        Real fTx  = 2.0*x;
+        Real fTy  = 2.0*y;
+        Real fTz  = 2.0*z;
+        Real fTwx = fTx*w;
+        Real fTwy = fTy*w;
+        Real fTxx = fTx*x;
+        Real fTxz = fTz*x;
+        Real fTyy = fTy*y;
+        Real fTyz = fTz*y;
+
+        return Vector3(fTxz+fTwy, fTyz-fTwx, 1.0-(fTxx+fTyy));
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::ToAxes (Vector3& xaxis, Vector3& yaxis, Vector3& zaxis) const
+    {
+        Matrix3 kRot;
+
+        ToRotationMatrix(kRot);
+
+        xaxis.x = kRot[0][0];
+        xaxis.y = kRot[1][0];
+        xaxis.z = kRot[2][0];
+
+        yaxis.x = kRot[0][1];
+        yaxis.y = kRot[1][1];
+        yaxis.z = kRot[2][1];
+
+        zaxis.x = kRot[0][2];
+        zaxis.y = kRot[1][2];
+        zaxis.z = kRot[2][2];
+    }
+
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::operator+ (const Quaternion& rkQ) const
+    {
+        return Quaternion(w+rkQ.w,x+rkQ.x,y+rkQ.y,z+rkQ.z);
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::operator- (const Quaternion& rkQ) const
+    {
+        return Quaternion(w-rkQ.w,x-rkQ.x,y-rkQ.y,z-rkQ.z);
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::operator* (const Quaternion& rkQ) const
+    {
+        // NOTE:  Multiplication is not generally commutative, so in most
+        // cases p*q != q*p.
+
+        return Quaternion
+        (
+            w * rkQ.w - x * rkQ.x - y * rkQ.y - z * rkQ.z,
+            w * rkQ.x + x * rkQ.w + y * rkQ.z - z * rkQ.y,
+            w * rkQ.y + y * rkQ.w + z * rkQ.x - x * rkQ.z,
+            w * rkQ.z + z * rkQ.w + x * rkQ.y - y * rkQ.x
+        );
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::operator* (Real fScalar) const
+    {
+        return Quaternion(fScalar*w,fScalar*x,fScalar*y,fScalar*z);
+    }
+    //-----------------------------------------------------------------------
+    Quaternion operator* (Real fScalar, const Quaternion& rkQ)
+    {
+        return Quaternion(fScalar*rkQ.w,fScalar*rkQ.x,fScalar*rkQ.y,
+            fScalar*rkQ.z);
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::operator- () const
+    {
+        return Quaternion(-w,-x,-y,-z);
+    }
+    //-----------------------------------------------------------------------
+    Real Quaternion::Dot (const Quaternion& rkQ) const
+    {
+        return w*rkQ.w+x*rkQ.x+y*rkQ.y+z*rkQ.z;
+    }
+    //-----------------------------------------------------------------------
+    Real Quaternion::Norm () const
+    {
+        return w*w+x*x+y*y+z*z;
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::Inverse () const
+    {
+        Real fNorm = w*w+x*x+y*y+z*z;
+        if ( fNorm > 0.0 )
+        {
+            Real fInvNorm = 1.0/fNorm;
+            return Quaternion(w*fInvNorm,-x*fInvNorm,-y*fInvNorm,-z*fInvNorm);
+        }
+        else
+        {
+            // return an invalid result to flag the error
+            return ZERO;
+        }
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::UnitInverse () const
+    {
+        // assert:  'this' is unit length
+        return Quaternion(w,-x,-y,-z);
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::Exp () const
+    {
+        // If q = A*(x*i+y*j+z*k) where (x,y,z) is unit length, then
+        // exp(q) = cos(A)+sin(A)*(x*i+y*j+z*k).  If sin(A) is near zero,
+        // use exp(q) = cos(A)+A*(x*i+y*j+z*k) since A/sin(A) has limit 1.
+
+        Radian fAngle ( Math::Sqrt(x*x+y*y+z*z) );
+        Real fSin = Math::Sin(fAngle);
+
+        Quaternion kResult;
+        kResult.w = Math::Cos(fAngle);
+
+        if ( Math::Abs(fSin) >= ms_fEpsilon )
+        {
+            Real fCoeff = fSin/(fAngle.valueRadians());
+            kResult.x = fCoeff*x;
+            kResult.y = fCoeff*y;
+            kResult.z = fCoeff*z;
+        }
+        else
+        {
+            kResult.x = x;
+            kResult.y = y;
+            kResult.z = z;
+        }
+
+        return kResult;
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::Log () const
+    {
+        // If q = cos(A)+sin(A)*(x*i+y*j+z*k) where (x,y,z) is unit length, then
+        // log(q) = A*(x*i+y*j+z*k).  If sin(A) is near zero, use log(q) =
+        // sin(A)*(x*i+y*j+z*k) since sin(A)/A has limit 1.
+
+        Quaternion kResult;
+        kResult.w = 0.0;
+
+        if ( Math::Abs(w) < 1.0 )
+        {
+            Radian fAngle ( Math::ACos(w) );
+            Real fSin = Math::Sin(fAngle);
+            if ( Math::Abs(fSin) >= ms_fEpsilon )
+            {
+                Real fCoeff = fAngle.valueRadians()/fSin;
+                kResult.x = fCoeff*x;
+                kResult.y = fCoeff*y;
+                kResult.z = fCoeff*z;
+                return kResult;
+            }
+        }
+
+        kResult.x = x;
+        kResult.y = y;
+        kResult.z = z;
+
+        return kResult;
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::operator* (const Vector3& v) const
+    {
+		// nVidia SDK implementation
+		Vector3 uv, uuv;
+		Vector3 qvec(x, y, z);
+		uv = qvec.crossProduct(v);
+		uuv = qvec.crossProduct(uv);
+		uv *= (2.0f * w);
+		uuv *= 2.0f;
+
+		return v + uv + uuv;
+
+    }
+    //-----------------------------------------------------------------------
+	bool Quaternion::equals(const Quaternion& rhs, const Radian& tolerance) const
+	{
+        Real fCos = Dot(rhs);
+        Radian angle = Math::ACos(fCos);
+
+		return (Math::Abs(angle.valueRadians()) <= tolerance.valueRadians())
+            || Math::RealEqual(angle.valueRadians(), Math::PI, tolerance.valueRadians());
+
+
+	}
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::Slerp (Real fT, const Quaternion& rkP,
+        const Quaternion& rkQ, bool shortestPath)
+    {
+        Real fCos = rkP.Dot(rkQ);
+        Quaternion rkT;
+
+        // Do we need to invert rotation?
+        if (fCos < 0.0f && shortestPath)
+        {
+            fCos = -fCos;
+            rkT = -rkQ;
+        }
+        else
+        {
+            rkT = rkQ;
+        }
+
+        if (Math::Abs(fCos) < 1 - ms_fEpsilon)
+        {
+            // Standard case (slerp)
+            Real fSin = Math::Sqrt(1 - Math::Sqr(fCos));
+            Radian fAngle = Math::ATan2(fSin, fCos);
+            Real fInvSin = 1.0f / fSin;
+            Real fCoeff0 = Math::Sin((1.0f - fT) * fAngle) * fInvSin;
+            Real fCoeff1 = Math::Sin(fT * fAngle) * fInvSin;
+            return fCoeff0 * rkP + fCoeff1 * rkT;
+        }
+        else
+        {
+            // There are two situations:
+            // 1. "rkP" and "rkQ" are very close (fCos ~= +1), so we can do a linear
+            //    interpolation safely.
+            // 2. "rkP" and "rkQ" are almost inverse of each other (fCos ~= -1), there
+            //    are an infinite number of possibilities interpolation. but we haven't
+            //    have method to fix this case, so just use linear interpolation here.
+            Quaternion t = (1.0f - fT) * rkP + fT * rkT;
+            // taking the complement requires renormalisation
+            t.normalise();
+            return t;
+        }
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::SlerpExtraSpins (Real fT,
+        const Quaternion& rkP, const Quaternion& rkQ, int iExtraSpins)
+    {
+        Real fCos = rkP.Dot(rkQ);
+        Radian fAngle ( Math::ACos(fCos) );
+
+        if ( Math::Abs(fAngle.valueRadians()) < ms_fEpsilon )
+            return rkP;
+
+        Real fSin = Math::Sin(fAngle);
+        Radian fPhase ( Math::PI*iExtraSpins*fT );
+        Real fInvSin = 1.0/fSin;
+        Real fCoeff0 = Math::Sin((1.0-fT)*fAngle - fPhase)*fInvSin;
+        Real fCoeff1 = Math::Sin(fT*fAngle + fPhase)*fInvSin;
+        return fCoeff0*rkP + fCoeff1*rkQ;
+    }
+    //-----------------------------------------------------------------------
+    void Quaternion::Intermediate (const Quaternion& rkQ0,
+        const Quaternion& rkQ1, const Quaternion& rkQ2,
+        Quaternion& rkA, Quaternion& rkB)
+    {
+        // assert:  q0, q1, q2 are unit quaternions
+
+        Quaternion kQ0inv = rkQ0.UnitInverse();
+        Quaternion kQ1inv = rkQ1.UnitInverse();
+        Quaternion rkP0 = kQ0inv*rkQ1;
+        Quaternion rkP1 = kQ1inv*rkQ2;
+        Quaternion kArg = 0.25*(rkP0.Log()-rkP1.Log());
+        Quaternion kMinusArg = -kArg;
+
+        rkA = rkQ1*kArg.Exp();
+        rkB = rkQ1*kMinusArg.Exp();
+    }
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::Squad (Real fT,
+        const Quaternion& rkP, const Quaternion& rkA,
+        const Quaternion& rkB, const Quaternion& rkQ, bool shortestPath)
+    {
+        Real fSlerpT = 2.0*fT*(1.0-fT);
+        Quaternion kSlerpP = Slerp(fT, rkP, rkQ, shortestPath);
+        Quaternion kSlerpQ = Slerp(fT, rkA, rkB);
+        return Slerp(fSlerpT, kSlerpP ,kSlerpQ);
+    }
+    //-----------------------------------------------------------------------
+    Real Quaternion::normalise(void)
+    {
+        Real len = Norm();
+        Real factor = 1.0f / Math::Sqrt(len);
+        *this = *this * factor;
+        return len;
+    }
+    //-----------------------------------------------------------------------
+	Radian Quaternion::getRoll(bool reprojectAxis) const
+	{
+		if (reprojectAxis)
+		{
+			// roll = atan2(localx.y, localx.x)
+			// pick parts of xAxis() implementation that we need
+			Real fTx  = 2.0*x;
+			Real fTy  = 2.0*y;
+			Real fTz  = 2.0*z;
+			Real fTwz = fTz*w;
+			Real fTxy = fTy*x;
+			Real fTyy = fTy*y;
+			Real fTzz = fTz*z;
+
+			// Vector3(1.0-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy);
+
+			return Radian(Math::ATan2(fTxy+fTwz, 1.0-(fTyy+fTzz)));
+
+		}
+		else
+		{
+			return Radian(Math::ATan2(2*(x*y + w*z), w*w + x*x - y*y - z*z));
+		}
+	}
+    //-----------------------------------------------------------------------
+	Radian Quaternion::getPitch(bool reprojectAxis) const
+	{
+		if (reprojectAxis)
+		{
+			// pitch = atan2(localy.z, localy.y)
+			// pick parts of yAxis() implementation that we need
+			Real fTx  = 2.0*x;
+			Real fTy  = 2.0*y;
+			Real fTz  = 2.0*z;
+			Real fTwx = fTx*w;
+			Real fTxx = fTx*x;
+			Real fTyz = fTz*y;
+			Real fTzz = fTz*z;
+
+			// Vector3(fTxy-fTwz, 1.0-(fTxx+fTzz), fTyz+fTwx);
+			return Radian(Math::ATan2(fTyz+fTwx, 1.0-(fTxx+fTzz)));
+		}
+		else
+		{
+			// internal version
+			return Radian(Math::ATan2(2*(y*z + w*x), w*w - x*x - y*y + z*z));
+		}
+	}
+    //-----------------------------------------------------------------------
+	Radian Quaternion::getYaw(bool reprojectAxis) const
+	{
+		if (reprojectAxis)
+		{
+			// yaw = atan2(localz.x, localz.z)
+			// pick parts of zAxis() implementation that we need
+			Real fTx  = 2.0*x;
+			Real fTy  = 2.0*y;
+			Real fTz  = 2.0*z;
+			Real fTwy = fTy*w;
+			Real fTxx = fTx*x;
+			Real fTxz = fTz*x;
+			Real fTyy = fTy*y;
+
+			// Vector3(fTxz+fTwy, fTyz-fTwx, 1.0-(fTxx+fTyy));
+
+			return Radian(Math::ATan2(fTxz+fTwy, 1.0-(fTxx+fTyy)));
+
+		}
+		else
+		{
+			// internal version
+			return Radian(Math::ASin(-2*(x*z - w*y)));
+		}
+	}
+    //-----------------------------------------------------------------------
+    Quaternion Quaternion::nlerp(Real fT, const Quaternion& rkP,
+        const Quaternion& rkQ, bool shortestPath)
+    {
+		Quaternion result;
+        Real fCos = rkP.Dot(rkQ);
+		if (fCos < 0.0f && shortestPath)
+		{
+			result = rkP + fT * ((-rkQ) - rkP);
+		}
+		else
+		{
+			result = rkP + fT * (rkQ - rkP);
+		}
+        result.normalise();
+        return result;
+    }
+}
Index: sandbox_light/src/external/ogremath/OgreQuaternion.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreQuaternion.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreQuaternion.h	(revision 5789)
@@ -0,0 +1,257 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+// NOTE THAT THIS FILE IS BASED ON MATERIAL FROM:
+
+// Magic Software, Inc.
+// http://www.geometrictools.com/
+// Copyright (c) 2000, All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement.  The various license agreements may be found at
+// the Magic Software web site.  This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.geometrictools.com/License/WildMagic3License.pdf
+
+#ifndef __Quaternion_H__
+#define __Quaternion_H__
+
+#include "OgrePrerequisites.h"
+
+#include <cassert>
+#include "OgreMath.h"
+#include <ostream>
+
+namespace Ogre {
+
+    /** Implementation of a Quaternion, i.e. a rotation around an axis.
+    */
+    class _OgreExport Quaternion
+    {
+    public:
+        inline Quaternion (
+            Real fW = 1.0,
+            Real fX = 0.0, Real fY = 0.0, Real fZ = 0.0)
+		{
+			w = fW;
+			x = fX;
+			y = fY;
+			z = fZ;
+		}
+        /// Construct a quaternion from a rotation matrix
+        inline Quaternion(const Matrix3& rot)
+        {
+            this->FromRotationMatrix(rot);
+        }
+        /// Construct a quaternion from an angle/axis
+        inline Quaternion(const Radian& rfAngle, const Vector3& rkAxis)
+        {
+            this->FromAngleAxis(rfAngle, rkAxis);
+        }
+        /// Construct a quaternion from 3 orthonormal local axes
+        inline Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
+        {
+            this->FromAxes(xaxis, yaxis, zaxis);
+        }
+        /// Construct a quaternion from 3 orthonormal local axes
+        inline Quaternion(const Vector3* akAxis)
+        {
+            this->FromAxes(akAxis);
+        }
+		/// Construct a quaternion from 4 manual w/x/y/z values
+		inline Quaternion(Real* valptr)
+		{
+			memcpy(&w, valptr, sizeof(Real)*4);
+		}
+
+		/// Array accessor operator
+		inline Real operator [] ( const size_t i ) const
+		{
+			assert( i < 4 );
+
+			return *(&w+i);
+		}
+
+		/// Array accessor operator
+		inline Real& operator [] ( const size_t i )
+		{
+			assert( i < 4 );
+
+			return *(&w+i);
+		}
+
+		/// Pointer accessor for direct copying
+		inline Real* ptr()
+		{
+			return &w;
+		}
+
+		/// Pointer accessor for direct copying
+		inline const Real* ptr() const
+		{
+			return &w;
+		}
+
+		void FromRotationMatrix (const Matrix3& kRot);
+        void ToRotationMatrix (Matrix3& kRot) const;
+        void FromAngleAxis (const Radian& rfAngle, const Vector3& rkAxis);
+        void ToAngleAxis (Radian& rfAngle, Vector3& rkAxis) const;
+        inline void ToAngleAxis (Degree& dAngle, Vector3& rkAxis) const {
+            Radian rAngle;
+            ToAngleAxis ( rAngle, rkAxis );
+            dAngle = rAngle;
+        }
+        void FromAxes (const Vector3* akAxis);
+        void FromAxes (const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
+        void ToAxes (Vector3* akAxis) const;
+        void ToAxes (Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) const;
+        /// Get the local x-axis
+        Vector3 xAxis(void) const;
+        /// Get the local y-axis
+        Vector3 yAxis(void) const;
+        /// Get the local z-axis
+        Vector3 zAxis(void) const;
+
+        inline Quaternion& operator= (const Quaternion& rkQ)
+		{
+			w = rkQ.w;
+			x = rkQ.x;
+			y = rkQ.y;
+			z = rkQ.z;
+			return *this;
+		}
+        Quaternion operator+ (const Quaternion& rkQ) const;
+        Quaternion operator- (const Quaternion& rkQ) const;
+        Quaternion operator* (const Quaternion& rkQ) const;
+        Quaternion operator* (Real fScalar) const;
+        _OgreExport friend Quaternion operator* (Real fScalar,
+            const Quaternion& rkQ);
+        Quaternion operator- () const;
+        inline bool operator== (const Quaternion& rhs) const
+		{
+			return (rhs.x == x) && (rhs.y == y) &&
+				(rhs.z == z) && (rhs.w == w);
+		}
+        inline bool operator!= (const Quaternion& rhs) const
+		{
+			return !operator==(rhs);
+		}
+        // functions of a quaternion
+        Real Dot (const Quaternion& rkQ) const;  // dot product
+        Real Norm () const;  // squared-length
+        /// Normalises this quaternion, and returns the previous length
+        Real normalise(void); 
+        Quaternion Inverse () const;  // apply to non-zero quaternion
+        Quaternion UnitInverse () const;  // apply to unit-length quaternion
+        Quaternion Exp () const;
+        Quaternion Log () const;
+
+        // rotation of a vector by a quaternion
+        Vector3 operator* (const Vector3& rkVector) const;
+
+   		/** Calculate the local roll element of this quaternion.
+		@param reprojectAxis By default the method returns the 'intuitive' result
+			that is, if you projected the local Y of the quaternion onto the X and
+			Y axes, the angle between them is returned. If set to false though, the
+			result is the actual yaw that will be used to implement the quaternion,
+			which is the shortest possible path to get to the same orientation and 
+			may involve less axial rotation. 
+		*/
+		Radian getRoll(bool reprojectAxis = true) const;
+   		/** Calculate the local pitch element of this quaternion
+		@param reprojectAxis By default the method returns the 'intuitive' result
+			that is, if you projected the local Z of the quaternion onto the X and
+			Y axes, the angle between them is returned. If set to true though, the
+			result is the actual yaw that will be used to implement the quaternion,
+			which is the shortest possible path to get to the same orientation and 
+			may involve less axial rotation. 
+		*/
+		Radian getPitch(bool reprojectAxis = true) const;
+   		/** Calculate the local yaw element of this quaternion
+		@param reprojectAxis By default the method returns the 'intuitive' result
+			that is, if you projected the local Z of the quaternion onto the X and
+			Z axes, the angle between them is returned. If set to true though, the
+			result is the actual yaw that will be used to implement the quaternion,
+			which is the shortest possible path to get to the same orientation and 
+			may involve less axial rotation. 
+		*/
+		Radian getYaw(bool reprojectAxis = true) const;		
+		/// Equality with tolerance (tolerance is max angle difference)
+		bool equals(const Quaternion& rhs, const Radian& tolerance) const;
+		
+	    // spherical linear interpolation
+        static Quaternion Slerp (Real fT, const Quaternion& rkP,
+            const Quaternion& rkQ, bool shortestPath = false);
+
+        static Quaternion SlerpExtraSpins (Real fT,
+            const Quaternion& rkP, const Quaternion& rkQ,
+            int iExtraSpins);
+
+        // setup for spherical quadratic interpolation
+        static void Intermediate (const Quaternion& rkQ0,
+            const Quaternion& rkQ1, const Quaternion& rkQ2,
+            Quaternion& rka, Quaternion& rkB);
+
+        // spherical quadratic interpolation
+        static Quaternion Squad (Real fT, const Quaternion& rkP,
+            const Quaternion& rkA, const Quaternion& rkB,
+            const Quaternion& rkQ, bool shortestPath = false);
+
+        // normalised linear interpolation - faster but less accurate (non-constant rotation velocity)
+        static Quaternion nlerp(Real fT, const Quaternion& rkP, 
+            const Quaternion& rkQ, bool shortestPath = false);
+
+        // cutoff for sine near zero
+        static const Real ms_fEpsilon;
+
+        // special values
+        static const Quaternion ZERO;
+        static const Quaternion IDENTITY;
+
+		Real w, x, y, z;
+
+        /** Function for writing to a stream. Outputs "Quaternion(w, x, y, z)" with w,x,y,z
+            being the member values of the quaternion.
+        */
+        inline _OgreExport friend std::ostream& operator <<
+            ( std::ostream& o, const Quaternion& q )
+        {
+            o << "Quaternion(" << q.w << ", " << q.x << ", " << q.y << ", " << q.z << ")";
+            return o;
+        }
+
+    };
+
+}
+
+
+
+
+#endif 
Index: sandbox_light/src/external/ogremath/OgreTimer.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreTimer.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreTimer.h	(revision 5789)
@@ -0,0 +1,44 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __OgreCommonTimer_H__
+#define __OgreCommonTimer_H__
+
+#include "OgrePrerequisites.h"
+#include "OgrePlatform.h"
+
+//Bring in the specific platform's header file
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+# include "WIN32/OgreTimerImp.h"
+#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
+# include "GLX/OgreTimerImp.h"
+#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+# include "OSX/OgreTimerImp.h"
+#endif
+
+#endif
Index: sandbox_light/src/external/ogremath/OgreVector2.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector2.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector2.cpp	(revision 5789)
@@ -0,0 +1,43 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreVector2.h"
+#include "OgreMath.h"
+
+namespace Ogre
+{
+    const Vector2 Vector2::ZERO( 0, 0);
+
+    const Vector2 Vector2::UNIT_X( 1, 0);
+    const Vector2 Vector2::UNIT_Y( 0, 1);
+    const Vector2 Vector2::NEGATIVE_UNIT_X( -1,  0);
+    const Vector2 Vector2::NEGATIVE_UNIT_Y(  0, -1);
+    const Vector2 Vector2::UNIT_SCALE(1, 1);
+
+}
Index: sandbox_light/src/external/ogremath/OgreVector2.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector2.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector2.h	(revision 5789)
@@ -0,0 +1,528 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector2_H__
+#define __Vector2_H__
+
+
+#include "OgrePrerequisites.h"
+#include "OgreMath.h"
+#include <ostream>
+
+namespace Ogre
+{
+
+    /** Standard 2-dimensional vector.
+        @remarks
+            A direction in 2D space represented as distances along the 2
+            orthogonal axes (x, y). Note that positions, directions and
+            scaling factors can be represented by a vector, depending on how
+            you interpret the values.
+    */
+    class _OgreExport Vector2
+    {
+    public:
+        Real x, y;
+
+    public:
+        inline Vector2()
+        {
+        }
+
+        inline Vector2(const Real fX, const Real fY )
+            : x( fX ), y( fY )
+        {
+        }
+
+        inline explicit Vector2( const Real scaler )
+            : x( scaler), y( scaler )
+        {
+        }
+
+        inline explicit Vector2( const Real afCoordinate[2] )
+            : x( afCoordinate[0] ),
+              y( afCoordinate[1] )
+        {
+        }
+
+        inline explicit Vector2( const int afCoordinate[2] )
+        {
+            x = (Real)afCoordinate[0];
+            y = (Real)afCoordinate[1];
+        }
+
+        inline explicit Vector2( Real* const r )
+            : x( r[0] ), y( r[1] )
+        {
+        }
+
+		inline Real operator [] ( const size_t i ) const
+        {
+            assert( i < 2 );
+
+            return *(&x+i);
+        }
+
+		inline Real& operator [] ( const size_t i )
+        {
+            assert( i < 2 );
+
+            return *(&x+i);
+        }
+
+		/// Pointer accessor for direct copying
+		inline Real* ptr()
+		{
+			return &x;
+		}
+		/// Pointer accessor for direct copying
+		inline const Real* ptr() const
+		{
+			return &x;
+		}
+
+        /** Assigns the value of the other vector.
+            @param
+                rkVector The other vector
+        */
+        inline Vector2& operator = ( const Vector2& rkVector )
+        {
+            x = rkVector.x;
+            y = rkVector.y;
+
+            return *this;
+        }
+
+		inline Vector2& operator = ( const Real fScalar)
+		{
+			x = fScalar;
+			y = fScalar;
+
+			return *this;
+		}
+
+        inline bool operator == ( const Vector2& rkVector ) const
+        {
+            return ( x == rkVector.x && y == rkVector.y );
+        }
+
+        inline bool operator != ( const Vector2& rkVector ) const
+        {
+            return ( x != rkVector.x || y != rkVector.y  );
+        }
+
+        // arithmetic operations
+        inline Vector2 operator + ( const Vector2& rkVector ) const
+        {
+            return Vector2(
+                x + rkVector.x,
+                y + rkVector.y);
+        }
+
+        inline Vector2 operator - ( const Vector2& rkVector ) const
+        {
+            return Vector2(
+                x - rkVector.x,
+                y - rkVector.y);
+        }
+
+        inline Vector2 operator * ( const Real fScalar ) const
+        {
+            return Vector2(
+                x * fScalar,
+                y * fScalar);
+        }
+
+        inline Vector2 operator * ( const Vector2& rhs) const
+        {
+            return Vector2(
+                x * rhs.x,
+                y * rhs.y);
+        }
+
+        inline Vector2 operator / ( const Real fScalar ) const
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            return Vector2(
+                x * fInv,
+                y * fInv);
+        }
+
+        inline Vector2 operator / ( const Vector2& rhs) const
+        {
+            return Vector2(
+                x / rhs.x,
+                y / rhs.y);
+        }
+
+        inline const Vector2& operator + () const
+        {
+            return *this;
+        }
+
+        inline Vector2 operator - () const
+        {
+            return Vector2(-x, -y);
+        }
+
+        // overloaded operators to help Vector2
+        inline friend Vector2 operator * ( const Real fScalar, const Vector2& rkVector )
+        {
+            return Vector2(
+                fScalar * rkVector.x,
+                fScalar * rkVector.y);
+        }
+
+        inline friend Vector2 operator / ( const Real fScalar, const Vector2& rkVector )
+        {
+            return Vector2(
+                fScalar / rkVector.x,
+                fScalar / rkVector.y);
+        }
+
+        inline friend Vector2 operator + (const Vector2& lhs, const Real rhs)
+        {
+            return Vector2(
+                lhs.x + rhs,
+                lhs.y + rhs);
+        }
+
+        inline friend Vector2 operator + (const Real lhs, const Vector2& rhs)
+        {
+            return Vector2(
+                lhs + rhs.x,
+                lhs + rhs.y);
+        }
+
+        inline friend Vector2 operator - (const Vector2& lhs, const Real rhs)
+        {
+            return Vector2(
+                lhs.x - rhs,
+                lhs.y - rhs);
+        }
+
+        inline friend Vector2 operator - (const Real lhs, const Vector2& rhs)
+        {
+            return Vector2(
+                lhs - rhs.x,
+                lhs - rhs.y);
+        }
+        // arithmetic updates
+        inline Vector2& operator += ( const Vector2& rkVector )
+        {
+            x += rkVector.x;
+            y += rkVector.y;
+
+            return *this;
+        }
+
+        inline Vector2& operator += ( const Real fScaler )
+        {
+            x += fScaler;
+            y += fScaler;
+
+            return *this;
+        }
+
+        inline Vector2& operator -= ( const Vector2& rkVector )
+        {
+            x -= rkVector.x;
+            y -= rkVector.y;
+
+            return *this;
+        }
+
+        inline Vector2& operator -= ( const Real fScaler )
+        {
+            x -= fScaler;
+            y -= fScaler;
+
+            return *this;
+        }
+
+        inline Vector2& operator *= ( const Real fScalar )
+        {
+            x *= fScalar;
+            y *= fScalar;
+
+            return *this;
+        }
+
+        inline Vector2& operator *= ( const Vector2& rkVector )
+        {
+            x *= rkVector.x;
+            y *= rkVector.y;
+
+            return *this;
+        }
+
+        inline Vector2& operator /= ( const Real fScalar )
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            x *= fInv;
+            y *= fInv;
+
+            return *this;
+        }
+
+        inline Vector2& operator /= ( const Vector2& rkVector )
+        {
+            x /= rkVector.x;
+            y /= rkVector.y;
+
+            return *this;
+        }
+
+        /** Returns the length (magnitude) of the vector.
+            @warning
+                This operation requires a square root and is expensive in
+                terms of CPU operations. If you don't need to know the exact
+                length (e.g. for just comparing lengths) use squaredLength()
+                instead.
+        */
+        inline Real length () const
+        {
+            return Math::Sqrt( x * x + y * y );
+        }
+
+        /** Returns the square of the length(magnitude) of the vector.
+            @remarks
+                This  method is for efficiency - calculating the actual
+                length of a vector requires a square root, which is expensive
+                in terms of the operations required. This method returns the
+                square of the length of the vector, i.e. the same as the
+                length but before the square root is taken. Use this if you
+                want to find the longest / shortest vector without incurring
+                the square root.
+        */
+        inline Real squaredLength () const
+        {
+            return x * x + y * y;
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another.
+            @remarks
+                The dot product can be used to calculate the angle between 2
+                vectors. If both are unit vectors, the dot product is the
+                cosine of the angle; otherwise the dot product must be
+                divided by the product of the lengths of both vectors to get
+                the cosine of the angle. This result can further be used to
+                calculate the distance of a point from a plane.
+            @param
+                vec Vector with which to calculate the dot product (together
+                with this one).
+            @returns
+                A float representing the dot product value.
+        */
+        inline Real dotProduct(const Vector2& vec) const
+        {
+            return x * vec.x + y * vec.y;
+        }
+
+        /** Normalises the vector.
+            @remarks
+                This method normalises the vector such that it's
+                length / magnitude is 1. The result is called a unit vector.
+            @note
+                This function will not crash for zero-sized vectors, but there
+                will be no changes made to their components.
+            @returns The previous length of the vector.
+        */
+        inline Real normalise()
+        {
+            Real fLength = Math::Sqrt( x * x + y * y);
+
+            // Will also work for zero-sized vectors, but will change nothing
+            if ( fLength > 1e-08 )
+            {
+                Real fInvLength = 1.0 / fLength;
+                x *= fInvLength;
+                y *= fInvLength;
+            }
+
+            return fLength;
+        }
+
+
+
+        /** Returns a vector at a point half way between this and the passed
+            in vector.
+        */
+        inline Vector2 midPoint( const Vector2& vec ) const
+        {
+            return Vector2(
+                ( x + vec.x ) * 0.5,
+                ( y + vec.y ) * 0.5 );
+        }
+
+        /** Returns true if the vector's scalar components are all greater
+            that the ones of the vector it is compared against.
+        */
+        inline bool operator < ( const Vector2& rhs ) const
+        {
+            if( x < rhs.x && y < rhs.y )
+                return true;
+            return false;
+        }
+
+        /** Returns true if the vector's scalar components are all smaller
+            that the ones of the vector it is compared against.
+        */
+        inline bool operator > ( const Vector2& rhs ) const
+        {
+            if( x > rhs.x && y > rhs.y )
+                return true;
+            return false;
+        }
+
+        /** Sets this vector's components to the minimum of its own and the
+            ones of the passed in vector.
+            @remarks
+                'Minimum' in this case means the combination of the lowest
+                value of x, y and z from both vectors. Lowest is taken just
+                numerically, not magnitude, so -1 < 0.
+        */
+        inline void makeFloor( const Vector2& cmp )
+        {
+            if( cmp.x < x ) x = cmp.x;
+            if( cmp.y < y ) y = cmp.y;
+        }
+
+        /** Sets this vector's components to the maximum of its own and the
+            ones of the passed in vector.
+            @remarks
+                'Maximum' in this case means the combination of the highest
+                value of x, y and z from both vectors. Highest is taken just
+                numerically, not magnitude, so 1 > -3.
+        */
+        inline void makeCeil( const Vector2& cmp )
+        {
+            if( cmp.x > x ) x = cmp.x;
+            if( cmp.y > y ) y = cmp.y;
+        }
+
+        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
+            @remarks
+                This method will return a vector which is perpendicular to this
+                vector. There are an infinite number of possibilities but this
+                method will guarantee to generate one of them. If you need more
+                control you should use the Quaternion class.
+        */
+        inline Vector2 perpendicular(void) const
+        {
+            return Vector2 (-y, x);
+        }
+        /** Calculates the 2 dimensional cross-product of 2 vectors, which results
+			in a single floating point value which is 2 times the area of the triangle.
+        */
+        inline Real crossProduct( const Vector2& rkVector ) const
+        {
+            return x * rkVector.y - y * rkVector.x;
+        }
+        /** Generates a new random vector which deviates from this vector by a
+            given angle in a random direction.
+            @remarks
+                This method assumes that the random number generator has already
+                been seeded appropriately.
+            @param
+                angle The angle at which to deviate in radians
+            @param
+                up Any vector perpendicular to this one (which could generated
+                by cross-product of this vector and any other non-colinear
+                vector). If you choose not to provide this the function will
+                derive one on it's own, however if you provide one yourself the
+                function will be faster (this allows you to reuse up vectors if
+                you call this method more than once)
+            @returns
+                A random vector which deviates from this vector by angle. This
+                vector will not be normalised, normalise it if you wish
+                afterwards.
+        */
+        inline Vector2 randomDeviant(
+            Real angle) const
+        {
+
+            angle *=  Math::UnitRandom() * Math::TWO_PI;
+            Real cosa = cos(angle);
+            Real sina = sin(angle);
+            return  Vector2(cosa * x - sina * y,
+                            sina * x + cosa * y);
+        }
+
+        /** Returns true if this vector is zero length. */
+        inline bool isZeroLength(void) const
+        {
+            Real sqlen = (x * x) + (y * y);
+            return (sqlen < (1e-06 * 1e-06));
+
+        }
+
+        /** As normalise, except that this vector is unaffected and the
+            normalised vector is returned as a copy. */
+        inline Vector2 normalisedCopy(void) const
+        {
+            Vector2 ret = *this;
+            ret.normalise();
+            return ret;
+        }
+
+        /** Calculates a reflection vector to the plane with the given normal .
+        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
+        */
+        inline Vector2 reflect(const Vector2& normal) const
+        {
+            return Vector2( *this - ( 2 * this->dotProduct(normal) * normal ) );
+        }
+
+        // special points
+        static const Vector2 ZERO;
+        static const Vector2 UNIT_X;
+        static const Vector2 UNIT_Y;
+        static const Vector2 NEGATIVE_UNIT_X;
+        static const Vector2 NEGATIVE_UNIT_Y;
+        static const Vector2 UNIT_SCALE;
+
+        /** Function for writing to a stream.
+        */
+        inline _OgreExport friend std::ostream& operator <<
+            ( std::ostream& o, const Vector2& v )
+        {
+            o << "Vector2(" << v.x << ", " << v.y <<  ")";
+            return o;
+        }
+
+    };
+
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgreVector3.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector3.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector3.cpp	(revision 5789)
@@ -0,0 +1,43 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreVector3.h"
+#include "OgreMath.h"
+
+namespace Ogre
+{
+    const Vector3 Vector3::ZERO( 0, 0, 0 );
+
+    const Vector3 Vector3::UNIT_X( 1, 0, 0 );
+    const Vector3 Vector3::UNIT_Y( 0, 1, 0 );
+    const Vector3 Vector3::UNIT_Z( 0, 0, 1 );
+    const Vector3 Vector3::NEGATIVE_UNIT_X( -1,  0,  0 );
+    const Vector3 Vector3::NEGATIVE_UNIT_Y(  0, -1,  0 );
+    const Vector3 Vector3::NEGATIVE_UNIT_Z(  0,  0, -1 );
+    const Vector3 Vector3::UNIT_SCALE(1, 1, 1);
+}
Index: sandbox_light/src/external/ogremath/OgreVector3.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector3.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector3.h	(revision 5789)
@@ -0,0 +1,775 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector3_H__
+#define __Vector3_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreMath.h"
+#include "OgreQuaternion.h"
+#include <ostream>
+
+namespace Ogre
+{
+
+    /** Standard 3-dimensional vector.
+        @remarks
+            A direction in 3D space represented as distances along the 3
+            orthogonal axes (x, y, z). Note that positions, directions and
+            scaling factors can be represented by a vector, depending on how
+            you interpret the values.
+    */
+    class _OgreExport Vector3
+    {
+    public:
+		Real x, y, z;
+
+    public:
+        inline Vector3()
+        {
+        }
+
+        inline Vector3( const Real fX, const Real fY, const Real fZ )
+            : x( fX ), y( fY ), z( fZ )
+        {
+        }
+
+        inline explicit Vector3( const Real afCoordinate[3] )
+            : x( afCoordinate[0] ),
+              y( afCoordinate[1] ),
+              z( afCoordinate[2] )
+        {
+        }
+
+        inline explicit Vector3( const int afCoordinate[3] )
+        {
+            x = (Real)afCoordinate[0];
+            y = (Real)afCoordinate[1];
+            z = (Real)afCoordinate[2];
+        }
+
+        inline explicit Vector3( Real* const r )
+            : x( r[0] ), y( r[1] ), z( r[2] )
+        {
+        }
+
+        inline explicit Vector3( const Real scaler )
+            : x( scaler )
+            , y( scaler )
+            , z( scaler )
+        {
+        }
+
+
+		inline Real operator [] ( const size_t i ) const
+        {
+            assert( i < 3 );
+
+            return *(&x+i);
+        }
+
+		inline Real& operator [] ( const size_t i )
+        {
+            assert( i < 3 );
+
+            return *(&x+i);
+        }
+		/// Pointer accessor for direct copying
+		inline Real* ptr()
+		{
+			return &x;
+		}
+		/// Pointer accessor for direct copying
+		inline const Real* ptr() const
+		{
+			return &x;
+		}
+
+        /** Assigns the value of the other vector.
+            @param
+                rkVector The other vector
+        */
+        inline Vector3& operator = ( const Vector3& rkVector )
+        {
+            x = rkVector.x;
+            y = rkVector.y;
+            z = rkVector.z;
+
+            return *this;
+        }
+
+        inline Vector3& operator = ( const Real fScaler )
+        {
+            x = fScaler;
+            y = fScaler;
+            z = fScaler;
+
+            return *this;
+        }
+
+        inline bool operator == ( const Vector3& rkVector ) const
+        {
+            return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
+        }
+
+        inline bool operator != ( const Vector3& rkVector ) const
+        {
+            return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
+        }
+
+        // arithmetic operations
+        inline Vector3 operator + ( const Vector3& rkVector ) const
+        {
+            return Vector3(
+                x + rkVector.x,
+                y + rkVector.y,
+                z + rkVector.z);
+        }
+
+        inline Vector3 operator - ( const Vector3& rkVector ) const
+        {
+            return Vector3(
+                x - rkVector.x,
+                y - rkVector.y,
+                z - rkVector.z);
+        }
+
+        inline Vector3 operator * ( const Real fScalar ) const
+        {
+            return Vector3(
+                x * fScalar,
+                y * fScalar,
+                z * fScalar);
+        }
+
+        inline Vector3 operator * ( const Vector3& rhs) const
+        {
+            return Vector3(
+                x * rhs.x,
+                y * rhs.y,
+                z * rhs.z);
+        }
+
+        inline Vector3 operator / ( const Real fScalar ) const
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            return Vector3(
+                x * fInv,
+                y * fInv,
+                z * fInv);
+        }
+
+        inline Vector3 operator / ( const Vector3& rhs) const
+        {
+            return Vector3(
+                x / rhs.x,
+                y / rhs.y,
+                z / rhs.z);
+        }
+
+        inline const Vector3& operator + () const
+        {
+            return *this;
+        }
+
+        inline Vector3 operator - () const
+        {
+            return Vector3(-x, -y, -z);
+        }
+
+        // overloaded operators to help Vector3
+        inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
+        {
+            return Vector3(
+                fScalar * rkVector.x,
+                fScalar * rkVector.y,
+                fScalar * rkVector.z);
+        }
+
+        inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
+        {
+            return Vector3(
+                fScalar / rkVector.x,
+                fScalar / rkVector.y,
+                fScalar / rkVector.z);
+        }
+
+        inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
+        {
+            return Vector3(
+                lhs.x + rhs,
+                lhs.y + rhs,
+                lhs.z + rhs);
+        }
+
+        inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
+        {
+            return Vector3(
+                lhs + rhs.x,
+                lhs + rhs.y,
+                lhs + rhs.z);
+        }
+
+        inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
+        {
+            return Vector3(
+                lhs.x - rhs,
+                lhs.y - rhs,
+                lhs.z - rhs);
+        }
+
+        inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
+        {
+            return Vector3(
+                lhs - rhs.x,
+                lhs - rhs.y,
+                lhs - rhs.z);
+        }
+
+        // arithmetic updates
+        inline Vector3& operator += ( const Vector3& rkVector )
+        {
+            x += rkVector.x;
+            y += rkVector.y;
+            z += rkVector.z;
+
+            return *this;
+        }
+
+        inline Vector3& operator += ( const Real fScalar )
+        {
+            x += fScalar;
+            y += fScalar;
+            z += fScalar;
+            return *this;
+        }
+
+        inline Vector3& operator -= ( const Vector3& rkVector )
+        {
+            x -= rkVector.x;
+            y -= rkVector.y;
+            z -= rkVector.z;
+
+            return *this;
+        }
+
+        inline Vector3& operator -= ( const Real fScalar )
+        {
+            x -= fScalar;
+            y -= fScalar;
+            z -= fScalar;
+            return *this;
+        }
+
+        inline Vector3& operator *= ( const Real fScalar )
+        {
+            x *= fScalar;
+            y *= fScalar;
+            z *= fScalar;
+            return *this;
+        }
+
+        inline Vector3& operator *= ( const Vector3& rkVector )
+        {
+            x *= rkVector.x;
+            y *= rkVector.y;
+            z *= rkVector.z;
+
+            return *this;
+        }
+
+        inline Vector3& operator /= ( const Real fScalar )
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            x *= fInv;
+            y *= fInv;
+            z *= fInv;
+
+            return *this;
+        }
+
+        inline Vector3& operator /= ( const Vector3& rkVector )
+        {
+            x /= rkVector.x;
+            y /= rkVector.y;
+            z /= rkVector.z;
+
+            return *this;
+        }
+
+
+        /** Returns the length (magnitude) of the vector.
+            @warning
+                This operation requires a square root and is expensive in
+                terms of CPU operations. If you don't need to know the exact
+                length (e.g. for just comparing lengths) use squaredLength()
+                instead.
+        */
+        inline Real length () const
+        {
+            return Math::Sqrt( x * x + y * y + z * z );
+        }
+
+        /** Returns the square of the length(magnitude) of the vector.
+            @remarks
+                This  method is for efficiency - calculating the actual
+                length of a vector requires a square root, which is expensive
+                in terms of the operations required. This method returns the
+                square of the length of the vector, i.e. the same as the
+                length but before the square root is taken. Use this if you
+                want to find the longest / shortest vector without incurring
+                the square root.
+        */
+        inline Real squaredLength () const
+        {
+            return x * x + y * y + z * z;
+        }
+
+        /** Returns the distance to another vector.
+            @warning
+                This operation requires a square root and is expensive in
+                terms of CPU operations. If you don't need to know the exact
+                distance (e.g. for just comparing distances) use squaredDistance()
+                instead.
+        */
+        inline Real distance(const Vector3& rhs) const
+        {
+            return (*this - rhs).length();
+        }
+
+        /** Returns the square of the distance to another vector.
+            @remarks
+                This method is for efficiency - calculating the actual
+                distance to another vector requires a square root, which is
+                expensive in terms of the operations required. This method
+                returns the square of the distance to another vector, i.e.
+                the same as the distance but before the square root is taken.
+                Use this if you want to find the longest / shortest distance
+                without incurring the square root.
+        */
+        inline Real squaredDistance(const Vector3& rhs) const
+        {
+            return (*this - rhs).squaredLength();
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another.
+            @remarks
+                The dot product can be used to calculate the angle between 2
+                vectors. If both are unit vectors, the dot product is the
+                cosine of the angle; otherwise the dot product must be
+                divided by the product of the lengths of both vectors to get
+                the cosine of the angle. This result can further be used to
+                calculate the distance of a point from a plane.
+            @param
+                vec Vector with which to calculate the dot product (together
+                with this one).
+            @returns
+                A float representing the dot product value.
+        */
+        inline Real dotProduct(const Vector3& vec) const
+        {
+            return x * vec.x + y * vec.y + z * vec.z;
+        }
+
+        /** Calculates the absolute dot (scalar) product of this vector with another.
+            @remarks
+                This function work similar dotProduct, except it use absolute value
+                of each component of the vector to computing.
+            @param
+                vec Vector with which to calculate the absolute dot product (together
+                with this one).
+            @returns
+                A Real representing the absolute dot product value.
+        */
+        inline Real absDotProduct(const Vector3& vec) const
+        {
+            return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
+        }
+
+        /** Normalises the vector.
+            @remarks
+                This method normalises the vector such that it's
+                length / magnitude is 1. The result is called a unit vector.
+            @note
+                This function will not crash for zero-sized vectors, but there
+                will be no changes made to their components.
+            @returns The previous length of the vector.
+        */
+        inline Real normalise()
+        {
+            Real fLength = Math::Sqrt( x * x + y * y + z * z );
+
+            // Will also work for zero-sized vectors, but will change nothing
+            if ( fLength > 1e-08 )
+            {
+                Real fInvLength = 1.0 / fLength;
+                x *= fInvLength;
+                y *= fInvLength;
+                z *= fInvLength;
+            }
+
+            return fLength;
+        }
+
+        /** Calculates the cross-product of 2 vectors, i.e. the vector that
+            lies perpendicular to them both.
+            @remarks
+                The cross-product is normally used to calculate the normal
+                vector of a plane, by calculating the cross-product of 2
+                non-equivalent vectors which lie on the plane (e.g. 2 edges
+                of a triangle).
+            @param
+                vec Vector which, together with this one, will be used to
+                calculate the cross-product.
+            @returns
+                A vector which is the result of the cross-product. This
+                vector will <b>NOT</b> be normalised, to maximise efficiency
+                - call Vector3::normalise on the result if you wish this to
+                be done. As for which side the resultant vector will be on, the
+                returned vector will be on the side from which the arc from 'this'
+                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
+                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
+				This is because OGRE uses a right-handed coordinate system.
+            @par
+                For a clearer explanation, look a the left and the bottom edges
+                of your monitor's screen. Assume that the first vector is the
+                left edge and the second vector is the bottom edge, both of
+                them starting from the lower-left corner of the screen. The
+                resulting vector is going to be perpendicular to both of them
+                and will go <i>inside</i> the screen, towards the cathode tube
+                (assuming you're using a CRT monitor, of course).
+        */
+        inline Vector3 crossProduct( const Vector3& rkVector ) const
+        {
+            return Vector3(
+                y * rkVector.z - z * rkVector.y,
+                z * rkVector.x - x * rkVector.z,
+                x * rkVector.y - y * rkVector.x);
+        }
+
+        /** Returns a vector at a point half way between this and the passed
+            in vector.
+        */
+        inline Vector3 midPoint( const Vector3& vec ) const
+        {
+            return Vector3(
+                ( x + vec.x ) * 0.5,
+                ( y + vec.y ) * 0.5,
+                ( z + vec.z ) * 0.5 );
+        }
+
+        /** Returns true if the vector's scalar components are all greater
+            that the ones of the vector it is compared against.
+        */
+        inline bool operator < ( const Vector3& rhs ) const
+        {
+            if( x < rhs.x && y < rhs.y && z < rhs.z )
+                return true;
+            return false;
+        }
+
+        /** Returns true if the vector's scalar components are all smaller
+            that the ones of the vector it is compared against.
+        */
+        inline bool operator > ( const Vector3& rhs ) const
+        {
+            if( x > rhs.x && y > rhs.y && z > rhs.z )
+                return true;
+            return false;
+        }
+
+        /** Sets this vector's components to the minimum of its own and the
+            ones of the passed in vector.
+            @remarks
+                'Minimum' in this case means the combination of the lowest
+                value of x, y and z from both vectors. Lowest is taken just
+                numerically, not magnitude, so -1 < 0.
+        */
+        inline void makeFloor( const Vector3& cmp )
+        {
+            if( cmp.x < x ) x = cmp.x;
+            if( cmp.y < y ) y = cmp.y;
+            if( cmp.z < z ) z = cmp.z;
+        }
+
+        /** Sets this vector's components to the maximum of its own and the
+            ones of the passed in vector.
+            @remarks
+                'Maximum' in this case means the combination of the highest
+                value of x, y and z from both vectors. Highest is taken just
+                numerically, not magnitude, so 1 > -3.
+        */
+        inline void makeCeil( const Vector3& cmp )
+        {
+            if( cmp.x > x ) x = cmp.x;
+            if( cmp.y > y ) y = cmp.y;
+            if( cmp.z > z ) z = cmp.z;
+        }
+
+        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
+            @remarks
+                This method will return a vector which is perpendicular to this
+                vector. There are an infinite number of possibilities but this
+                method will guarantee to generate one of them. If you need more
+                control you should use the Quaternion class.
+        */
+        inline Vector3 perpendicular(void) const
+        {
+            static const Real fSquareZero = 1e-06 * 1e-06;
+
+            Vector3 perp = this->crossProduct( Vector3::UNIT_X );
+
+            // Check length
+            if( perp.squaredLength() < fSquareZero )
+            {
+                /* This vector is the Y axis multiplied by a scalar, so we have
+                   to use another axis.
+                */
+                perp = this->crossProduct( Vector3::UNIT_Y );
+            }
+			perp.normalise();
+
+            return perp;
+        }
+        /** Generates a new random vector which deviates from this vector by a
+            given angle in a random direction.
+            @remarks
+                This method assumes that the random number generator has already
+                been seeded appropriately.
+            @param
+                angle The angle at which to deviate
+            @param
+                up Any vector perpendicular to this one (which could generated
+                by cross-product of this vector and any other non-colinear
+                vector). If you choose not to provide this the function will
+                derive one on it's own, however if you provide one yourself the
+                function will be faster (this allows you to reuse up vectors if
+                you call this method more than once)
+            @returns
+                A random vector which deviates from this vector by angle. This
+                vector will not be normalised, normalise it if you wish
+                afterwards.
+        */
+        inline Vector3 randomDeviant(
+            const Radian& angle,
+            const Vector3& up = Vector3::ZERO ) const
+        {
+            Vector3 newUp;
+
+            if (up == Vector3::ZERO)
+            {
+                // Generate an up vector
+                newUp = this->perpendicular();
+            }
+            else
+            {
+                newUp = up;
+            }
+
+            // Rotate up vector by random amount around this
+            Quaternion q;
+            q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
+            newUp = q * newUp;
+
+            // Finally rotate this by given angle around randomised up
+            q.FromAngleAxis( angle, newUp );
+            return q * (*this);
+        }
+
+		/** Gets the angle between 2 vectors.
+		@remarks
+			Vectors do not have to be unit-length but must represent directions.
+		*/
+		inline Radian angleBetween(const Vector3& dest)
+		{
+			Real lenProduct = length() * dest.length();
+
+			// Divide by zero check
+			if(lenProduct < 1e-6f)
+				lenProduct = 1e-6f;
+
+			Real f = dotProduct(dest) / lenProduct;
+
+			f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
+			return Math::ACos(f);
+
+		}
+        /** Gets the shortest arc quaternion to rotate this vector to the destination
+            vector.
+        @remarks
+            If you call this with a dest vector that is close to the inverse
+            of this vector, we will rotate 180 degrees around the 'fallbackAxis'
+			(if specified, or a generated axis if not) since in this case
+			ANY axis of rotation is valid.
+        */
+        Quaternion getRotationTo(const Vector3& dest,
+			const Vector3& fallbackAxis = Vector3::ZERO) const
+        {
+            // Based on Stan Melax's article in Game Programming Gems
+            Quaternion q;
+            // Copy, since cannot modify local
+            Vector3 v0 = *this;
+            Vector3 v1 = dest;
+            v0.normalise();
+            v1.normalise();
+
+            Real d = v0.dotProduct(v1);
+            // If dot == 1, vectors are the same
+            if (d >= 1.0f)
+            {
+                return Quaternion::IDENTITY;
+            }
+			if (d < (1e-6f - 1.0f))
+			{
+				if (fallbackAxis != Vector3::ZERO)
+				{
+					// rotate 180 degrees about the fallback axis
+					q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
+				}
+				else
+				{
+					// Generate an axis
+					Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
+					if (axis.isZeroLength()) // pick another if colinear
+						axis = Vector3::UNIT_Y.crossProduct(*this);
+					axis.normalise();
+					q.FromAngleAxis(Radian(Math::PI), axis);
+				}
+			}
+			else
+			{
+                Real s = Math::Sqrt( (1+d)*2 );
+	            Real invs = 1 / s;
+
+				Vector3 c = v0.crossProduct(v1);
+
+    	        q.x = c.x * invs;
+        	    q.y = c.y * invs;
+            	q.z = c.z * invs;
+            	q.w = s * 0.5;
+				q.normalise();
+			}
+            return q;
+        }
+
+        /** Returns true if this vector is zero length. */
+        inline bool isZeroLength(void) const
+        {
+            Real sqlen = (x * x) + (y * y) + (z * z);
+            return (sqlen < (1e-06 * 1e-06));
+
+        }
+
+        /** As normalise, except that this vector is unaffected and the
+            normalised vector is returned as a copy. */
+        inline Vector3 normalisedCopy(void) const
+        {
+            Vector3 ret = *this;
+            ret.normalise();
+            return ret;
+        }
+
+        /** Calculates a reflection vector to the plane with the given normal .
+        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
+        */
+        inline Vector3 reflect(const Vector3& normal) const
+        {
+            return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
+        }
+
+		/** Returns whether this vector is within a positional tolerance
+			of another vector.
+		@param rhs The vector to compare with
+		@param tolerance The amount that each element of the vector may vary by
+			and still be considered equal
+		*/
+		inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
+		{
+			return Math::RealEqual(x, rhs.x, tolerance) &&
+				Math::RealEqual(y, rhs.y, tolerance) &&
+				Math::RealEqual(z, rhs.z, tolerance);
+
+		}
+
+		/** Returns whether this vector is within a positional tolerance
+			of another vector, also take scale of the vectors into account.
+		@param rhs The vector to compare with
+		@param tolerance The amount (related to the scale of vectors) that distance
+            of the vector may vary by and still be considered close
+		*/
+		inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
+		{
+			return squaredDistance(rhs) <=
+                (squaredLength() + rhs.squaredLength()) * tolerance;
+		}
+
+		/** Returns whether this vector is within a directional tolerance
+			of another vector.
+		@param rhs The vector to compare with
+		@param tolerance The maximum angle by which the vectors may vary and
+			still be considered equal
+		@note Both vectors should be normalised.
+		*/
+		inline bool directionEquals(const Vector3& rhs,
+			const Radian& tolerance) const
+		{
+			Real dot = dotProduct(rhs);
+			Radian angle = Math::ACos(dot);
+
+			return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
+
+		}
+
+        // special points
+        static const Vector3 ZERO;
+        static const Vector3 UNIT_X;
+        static const Vector3 UNIT_Y;
+        static const Vector3 UNIT_Z;
+        static const Vector3 NEGATIVE_UNIT_X;
+        static const Vector3 NEGATIVE_UNIT_Y;
+        static const Vector3 NEGATIVE_UNIT_Z;
+        static const Vector3 UNIT_SCALE;
+
+        /** Function for writing to a stream.
+        */
+        inline _OgreExport friend std::ostream& operator <<
+            ( std::ostream& o, const Vector3& v )
+        {
+            o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
+            return o;
+        }
+    };
+
+}
+#endif
Index: sandbox_light/src/external/ogremath/OgreVector4.cpp
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector4.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector4.cpp	(revision 5789)
@@ -0,0 +1,35 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "OgreVector4.h"
+#include "OgreMath.h"
+
+namespace Ogre
+{
+    const Vector4 Vector4::ZERO( 0, 0, 0, 0 );
+}
Index: sandbox_light/src/external/ogremath/OgreVector4.h
===================================================================
--- sandbox_light/src/external/ogremath/OgreVector4.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/OgreVector4.h	(revision 5789)
@@ -0,0 +1,392 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector4_H__
+#define __Vector4_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreVector3.h"
+#include <ostream>
+
+namespace Ogre
+{
+
+    /** 4-dimensional homogeneous vector.
+    */
+    class _OgreExport Vector4
+    {
+    public:
+        Real x, y, z, w;
+
+    public:
+        inline Vector4()
+        {
+        }
+
+        inline Vector4( const Real fX, const Real fY, const Real fZ, const Real fW )
+            : x( fX ), y( fY ), z( fZ ), w( fW)
+        {
+        }
+
+        inline explicit Vector4( const Real afCoordinate[4] )
+            : x( afCoordinate[0] ),
+              y( afCoordinate[1] ),
+              z( afCoordinate[2] ),
+              w( afCoordinate[3] )
+        {
+        }
+
+        inline explicit Vector4( const int afCoordinate[4] )
+        {
+            x = (Real)afCoordinate[0];
+            y = (Real)afCoordinate[1];
+            z = (Real)afCoordinate[2];
+            w = (Real)afCoordinate[3];
+        }
+
+        inline explicit Vector4( Real* const r )
+            : x( r[0] ), y( r[1] ), z( r[2] ), w( r[3] )
+        {
+        }
+
+        inline explicit Vector4( const Real scaler )
+            : x( scaler )
+            , y( scaler )
+            , z( scaler )
+            , w( scaler )
+        {
+        }
+
+        inline explicit Vector4(const Vector3& rhs)
+            : x(rhs.x), y(rhs.y), z(rhs.z), w(1.0f)
+        {
+        }
+
+		inline Real operator [] ( const size_t i ) const
+        {
+            assert( i < 4 );
+
+            return *(&x+i);
+        }
+
+		inline Real& operator [] ( const size_t i )
+        {
+            assert( i < 4 );
+
+            return *(&x+i);
+        }
+
+		/// Pointer accessor for direct copying
+		inline Real* ptr()
+		{
+			return &x;
+		}
+		/// Pointer accessor for direct copying
+		inline const Real* ptr() const
+		{
+			return &x;
+		}
+
+        /** Assigns the value of the other vector.
+            @param
+                rkVector The other vector
+        */
+        inline Vector4& operator = ( const Vector4& rkVector )
+        {
+            x = rkVector.x;
+            y = rkVector.y;
+            z = rkVector.z;
+            w = rkVector.w;
+
+            return *this;
+        }
+
+		inline Vector4& operator = ( const Real fScalar)
+		{
+			x = fScalar;
+			y = fScalar;
+			z = fScalar;
+			w = fScalar;
+			return *this;
+		}
+
+        inline bool operator == ( const Vector4& rkVector ) const
+        {
+            return ( x == rkVector.x &&
+                y == rkVector.y &&
+                z == rkVector.z &&
+                w == rkVector.w );
+        }
+
+        inline bool operator != ( const Vector4& rkVector ) const
+        {
+            return ( x != rkVector.x ||
+                y != rkVector.y ||
+                z != rkVector.z ||
+                w != rkVector.w );
+        }
+
+        inline Vector4& operator = (const Vector3& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+            z = rhs.z;
+            w = 1.0f;
+            return *this;
+        }
+
+        // arithmetic operations
+        inline Vector4 operator + ( const Vector4& rkVector ) const
+        {
+            return Vector4(
+                x + rkVector.x,
+                y + rkVector.y,
+                z + rkVector.z,
+                w + rkVector.w);
+        }
+
+        inline Vector4 operator - ( const Vector4& rkVector ) const
+        {
+            return Vector4(
+                x - rkVector.x,
+                y - rkVector.y,
+                z - rkVector.z,
+                w - rkVector.w);
+        }
+
+        inline Vector4 operator * ( const Real fScalar ) const
+        {
+            return Vector4(
+                x * fScalar,
+                y * fScalar,
+                z * fScalar,
+                w * fScalar);
+        }
+
+        inline Vector4 operator * ( const Vector4& rhs) const
+        {
+            return Vector4(
+                rhs.x * x,
+                rhs.y * y,
+                rhs.z * z,
+                rhs.w * w);
+        }
+
+        inline Vector4 operator / ( const Real fScalar ) const
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            return Vector4(
+                x * fInv,
+                y * fInv,
+                z * fInv,
+                w * fInv);
+        }
+
+        inline Vector4 operator / ( const Vector4& rhs) const
+        {
+            return Vector4(
+                x / rhs.x,
+                y / rhs.y,
+                z / rhs.z,
+                w / rhs.w);
+        }
+
+        inline const Vector4& operator + () const
+        {
+            return *this;
+        }
+
+        inline Vector4 operator - () const
+        {
+            return Vector4(-x, -y, -z, -w);
+        }
+
+        inline friend Vector4 operator * ( const Real fScalar, const Vector4& rkVector )
+        {
+            return Vector4(
+                fScalar * rkVector.x,
+                fScalar * rkVector.y,
+                fScalar * rkVector.z,
+                fScalar * rkVector.w);
+        }
+
+        inline friend Vector4 operator / ( const Real fScalar, const Vector4& rkVector )
+        {
+            return Vector4(
+                fScalar / rkVector.x,
+                fScalar / rkVector.y,
+                fScalar / rkVector.z,
+                fScalar / rkVector.w);
+        }
+
+        inline friend Vector4 operator + (const Vector4& lhs, const Real rhs)
+        {
+            return Vector4(
+                lhs.x + rhs,
+                lhs.y + rhs,
+                lhs.z + rhs,
+                lhs.w + rhs);
+        }
+
+        inline friend Vector4 operator + (const Real lhs, const Vector4& rhs)
+        {
+            return Vector4(
+                lhs + rhs.x,
+                lhs + rhs.y,
+                lhs + rhs.z,
+                lhs + rhs.w);
+        }
+
+        inline friend Vector4 operator - (const Vector4& lhs, Real rhs)
+        {
+            return Vector4(
+                lhs.x - rhs,
+                lhs.y - rhs,
+                lhs.z - rhs,
+                lhs.w - rhs);
+        }
+
+        inline friend Vector4 operator - (const Real lhs, const Vector4& rhs)
+        {
+            return Vector4(
+                lhs - rhs.x,
+                lhs - rhs.y,
+                lhs - rhs.z,
+                lhs - rhs.w);
+        }
+
+        // arithmetic updates
+        inline Vector4& operator += ( const Vector4& rkVector )
+        {
+            x += rkVector.x;
+            y += rkVector.y;
+            z += rkVector.z;
+            w += rkVector.w;
+
+            return *this;
+        }
+
+        inline Vector4& operator -= ( const Vector4& rkVector )
+        {
+            x -= rkVector.x;
+            y -= rkVector.y;
+            z -= rkVector.z;
+            w -= rkVector.w;
+
+            return *this;
+        }
+
+        inline Vector4& operator *= ( const Real fScalar )
+        {
+            x *= fScalar;
+            y *= fScalar;
+            z *= fScalar;
+            w *= fScalar;
+            return *this;
+        }
+
+        inline Vector4& operator += ( const Real fScalar )
+        {
+            x += fScalar;
+            y += fScalar;
+            z += fScalar;
+            w += fScalar;
+            return *this;
+        }
+
+        inline Vector4& operator -= ( const Real fScalar )
+        {
+            x -= fScalar;
+            y -= fScalar;
+            z -= fScalar;
+            w -= fScalar;
+            return *this;
+        }
+
+        inline Vector4& operator *= ( const Vector4& rkVector )
+        {
+            x *= rkVector.x;
+            y *= rkVector.y;
+            z *= rkVector.z;
+            w *= rkVector.w;
+
+            return *this;
+        }
+
+        inline Vector4& operator /= ( const Real fScalar )
+        {
+            assert( fScalar != 0.0 );
+
+            Real fInv = 1.0 / fScalar;
+
+            x *= fInv;
+            y *= fInv;
+            z *= fInv;
+            w *= fInv;
+
+            return *this;
+        }
+
+        inline Vector4& operator /= ( const Vector4& rkVector )
+        {
+            x /= rkVector.x;
+            y /= rkVector.y;
+            z /= rkVector.z;
+            w /= rkVector.w;
+
+            return *this;
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another.
+            @param
+                vec Vector with which to calculate the dot product (together
+                with this one).
+            @returns
+                A float representing the dot product value.
+        */
+        inline Real dotProduct(const Vector4& vec) const
+        {
+            return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
+        }
+        /** Function for writing to a stream.
+        */
+        inline _OgreExport friend std::ostream& operator <<
+            ( std::ostream& o, const Vector4& v )
+        {
+            o << "Vector4(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")";
+            return o;
+        }
+        // special
+        static const Vector4 ZERO;
+    };
+
+}
+#endif
Index: sandbox_light/src/external/ogremath/WIN32/OgreTimer.cpp
===================================================================
--- sandbox_light/src/external/ogremath/WIN32/OgreTimer.cpp	(revision 5789)
+++ sandbox_light/src/external/ogremath/WIN32/OgreTimer.cpp	(revision 5789)
@@ -0,0 +1,220 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#include "ogremath/OgreTimer.h"
+
+#include "ogremath/OgreBitwise.h"
+
+using namespace Ogre;
+
+//-------------------------------------------------------------------------
+Timer::Timer()
+	: mTimerMask( 0 )
+{
+	reset();
+}
+
+//-------------------------------------------------------------------------
+Timer::~Timer()
+{
+}
+
+//-------------------------------------------------------------------------
+bool Timer::setOption( const String & key, const void * val )
+{
+	if ( key == "QueryAffinityMask" )
+	{
+		// Telling timer what core to use for a timer read
+		DWORD newTimerMask = * static_cast < const DWORD * > ( val );
+
+		// Get the current process core mask
+		DWORD procMask;
+		DWORD sysMask;
+#if _MSC_VER >= 1400 && defined (_M_X64)
+		GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
+#else
+		GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
+#endif
+
+		// If new mask is 0, then set to default behavior, otherwise check
+		// to make sure new timer core mask overlaps with process core mask
+		// and that new timer core mask is a power of 2 (i.e. a single core)
+		if( ( newTimerMask == 0 ) ||
+			( ( ( newTimerMask & procMask ) != 0 ) && Bitwise::isPO2( newTimerMask ) ) )
+		{
+			mTimerMask = newTimerMask;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+//-------------------------------------------------------------------------
+void Timer::reset()
+{
+    // Get the current process core mask
+	DWORD procMask;
+	DWORD sysMask;
+#if _MSC_VER >= 1400 && defined (_M_X64)
+	GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
+#else
+	GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
+#endif
+
+	// If procMask is 0, consider there is only one core available
+	// (using 0 as procMask will cause an infinite loop below)
+	if (procMask == 0)
+		procMask = 1;
+
+	// Find the lowest core that this process uses
+	if( mTimerMask == 0 )
+	{
+		mTimerMask = 1;
+		while( ( mTimerMask & procMask ) == 0 )
+		{
+			mTimerMask <<= 1;
+		}
+	}
+
+	HANDLE thread = GetCurrentThread();
+
+	// Set affinity to the first core
+	DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
+
+	// Get the constant frequency
+	QueryPerformanceFrequency(&mFrequency);
+
+	// Query the timer
+	QueryPerformanceCounter(&mStartTime);
+	mStartTick = GetTickCount();
+
+	// Reset affinity
+	SetThreadAffinityMask(thread, oldMask);
+
+	mLastTime = 0;
+	mZeroClock = clock();
+}
+
+//-------------------------------------------------------------------------
+unsigned long Timer::getMilliseconds()
+{
+    LARGE_INTEGER curTime;
+
+	HANDLE thread = GetCurrentThread();
+
+	// Set affinity to the first core
+	DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
+
+	// Query the timer
+	QueryPerformanceCounter(&curTime);
+
+	// Reset affinity
+	SetThreadAffinityMask(thread, oldMask);
+
+    LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
+    
+    // scale by 1000 for milliseconds
+    unsigned long newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
+
+    // detect and compensate for performance counter leaps
+    // (surprisingly common, see Microsoft KB: Q274323)
+    unsigned long check = GetTickCount() - mStartTick;
+    signed long msecOff = (signed long)(newTicks - check);
+    if (msecOff < -100 || msecOff > 100)
+    {
+        // We must keep the timer running forward :)
+        LONGLONG adjust = (std::min)(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
+        mStartTime.QuadPart += adjust;
+        newTime -= adjust;
+
+        // Re-calculate milliseconds
+        newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
+    }
+
+    // Record last time for adjust
+    mLastTime = newTime;
+
+    return newTicks;
+}
+
+//-------------------------------------------------------------------------
+unsigned long Timer::getMicroseconds()
+{
+    LARGE_INTEGER curTime;
+
+	HANDLE thread = GetCurrentThread();
+
+	// Set affinity to the first core
+	DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
+
+	// Query the timer
+	QueryPerformanceCounter(&curTime);
+
+	// Reset affinity
+	SetThreadAffinityMask(thread, oldMask);
+
+	LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
+    
+    // get milliseconds to check against GetTickCount
+    unsigned long newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
+    
+    // detect and compensate for performance counter leaps
+    // (surprisingly common, see Microsoft KB: Q274323)
+    unsigned long check = GetTickCount() - mStartTick;
+    signed long msecOff = (signed long)(newTicks - check);
+    if (msecOff < -100 || msecOff > 100)
+    {
+        // We must keep the timer running forward :)
+        LONGLONG adjust = (std::min)(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
+        mStartTime.QuadPart += adjust;
+        newTime -= adjust;
+    }
+
+    // Record last time for adjust
+    mLastTime = newTime;
+
+    // scale by 1000000 for microseconds
+    unsigned long newMicro = (unsigned long) (1000000 * newTime / mFrequency.QuadPart);
+
+    return newMicro;
+}
+
+//-------------------------------------------------------------------------
+unsigned long Timer::getMillisecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)( (float)( newClock - mZeroClock ) / ( (float)CLOCKS_PER_SEC / 1000.0 ) ) ;
+}
+
+//-------------------------------------------------------------------------
+unsigned long Timer::getMicrosecondsCPU()
+{
+	clock_t newClock = clock();
+	return (unsigned long)( (float)( newClock - mZeroClock ) / ( (float)CLOCKS_PER_SEC / 1000000.0 ) ) ;
+}
Index: sandbox_light/src/external/ogremath/WIN32/OgreTimerImp.h
===================================================================
--- sandbox_light/src/external/ogremath/WIN32/OgreTimerImp.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/WIN32/OgreTimerImp.h	(revision 5789)
@@ -0,0 +1,103 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+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.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Win32Timer_H__
+#define __Win32Timer_H__
+
+#include <ctime>
+
+#ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+
+//Get around Windows hackery
+#ifdef max
+#  undef max
+#endif
+#ifdef min
+#  undef min
+#endif
+
+namespace Ogre
+{
+	class _OgreExport Timer
+    {
+    private:
+		clock_t mZeroClock;
+
+        DWORD mStartTick;
+		LONGLONG mLastTime;
+        LARGE_INTEGER mStartTime;
+        LARGE_INTEGER mFrequency;
+
+		DWORD mTimerMask;
+    public:
+		/** Timer constructor.  MUST be called on same thread that calls getMilliseconds() */
+		Timer();
+		~Timer();
+
+		/** Method for setting a specific option of the Timer. These options are usually
+            specific for a certain implementation of the Timer class, and may (and probably
+            will) not exist across different implementations.  reset() must be called after
+			all setOption() calls.
+			@par
+			Current options supported are:
+			<ul><li>"QueryAffinityMask" (DWORD): Set the thread affinity mask to be used
+			to check the timer. If 'reset' has been called already this mask should
+			overlap with the process mask that was in force at that point, and should
+			be a power of two (a single core).</li></ul>
+            @param
+                strKey The name of the option to set
+            @param
+                pValue A pointer to the value - the size should be calculated by the timer
+                based on the key
+            @return
+                On success, true is returned.
+            @par
+                On failure, false is returned.
+        */
+        bool setOption( const String& strKey, const void* pValue );
+
+		/** Resets timer */
+		void reset();
+
+		/** Returns milliseconds since initialisation or last reset */
+		unsigned long getMilliseconds();
+
+		/** Returns microseconds since initialisation or last reset */
+		unsigned long getMicroseconds();
+
+		/** Returns milliseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMillisecondsCPU();
+
+		/** Returns microseconds since initialisation or last reset, only CPU time measured */	
+		unsigned long getMicrosecondsCPU();
+    };
+} 
+#endif
Index: sandbox_light/src/external/ogremath/asm_math.h
===================================================================
--- sandbox_light/src/external/ogremath/asm_math.h	(revision 5789)
+++ sandbox_light/src/external/ogremath/asm_math.h	(revision 5789)
@@ -0,0 +1,367 @@
+#ifndef __asm_math_H__
+#define __asm_math_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre
+{
+
+/*=============================================================================
+ ASM math routines posted by davepermen et al on flipcode forums
+=============================================================================*/
+const float pi = 4.0 * atan( 1.0 );
+const float half_pi = 0.5 * pi;
+
+/*=============================================================================
+	NO EXPLICIT RETURN REQUIRED FROM THESE METHODS!! 
+=============================================================================*/
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+#	pragma warning( push )
+#	pragma warning( disable: 4035 ) 
+#endif
+
+float asm_arccos( float r ) {
+    // return half_pi + arctan( r / -sqr( 1.f - r * r ) );
+	
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    float asm_one = 1.f;
+    float asm_half_pi = half_pi;
+    __asm {
+        fld r // r0 = r
+        fld r // r1 = r0, r0 = r
+        fmul r // r0 = r0 * r
+        fsubr asm_one // r0 = r0 - 1.f
+        fsqrt // r0 = sqrtf( r0 )
+        fchs // r0 = - r0
+        fdiv // r0 = r1 / r0
+        fld1 // {{ r0 = atan( r0 )
+        fpatan // }}
+        fadd asm_half_pi // r0 = r0 + pi / 2
+    } // returns r0
+
+#else
+
+	return float( acos( r ) );
+
+#endif
+}
+
+float asm_arcsin( float r ) {
+    // return arctan( r / sqr( 1.f - r * r ) );
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    const float asm_one = 1.f;
+    __asm {
+        fld r // r0 = r
+        fld r // r1 = r0, r0 = r
+        fmul r // r0 = r0 * r
+        fsubr asm_one // r0 = r0 - 1.f
+        fsqrt // r0 = sqrtf( r0 )
+        fdiv // r0 = r1 / r0
+        fld1 // {{ r0 = atan( r0 )
+        fpatan // }}
+    } // returns r0
+
+#else
+
+	return float( asin( r ) );
+
+#endif
+
+}
+
+float asm_arctan( float r ) {
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    __asm {
+        fld r // r0 = r
+        fld1 // {{ r0 = atan( r0 )
+        fpatan // }}
+    } // returns r0
+
+#else
+
+	return float( atan( r ) );
+
+#endif
+
+}
+
+float asm_sin( float r ) {
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    __asm {
+        fld r // r0 = r
+        fsin // r0 = sinf( r0 )
+    } // returns r0
+
+#else
+
+	return sin( r );
+
+#endif
+
+}
+
+float asm_cos( float r ) {
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    __asm {
+        fld r // r0 = r
+        fcos // r0 = cosf( r0 )
+    } // returns r0
+
+#else
+	
+	return cos( r );
+
+#endif
+}
+
+float asm_tan( float r ) {
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    // return sin( r ) / cos( r );
+    __asm {
+        fld r // r0 = r
+        fsin // r0 = sinf( r0 )
+        fld r // r1 = r0, r0 = r
+        fcos // r0 = cosf( r0 )
+        fdiv // r0 = r1 / r0
+    } // returns r0
+
+#else
+	
+	return tan( r );
+
+#endif
+}
+
+// returns a for a * a = r
+float asm_sqrt( float r )
+{
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    __asm {
+        fld r // r0 = r
+        fsqrt // r0 = sqrtf( r0 )
+    } // returns r0
+
+#else
+
+	return sqrt( r );
+
+#endif
+}
+
+// returns 1 / a for a * a = r
+// -- Use this for Vector normalisation!!!
+float asm_rsq( float r )
+{
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    __asm {
+        fld1 // r0 = 1.f
+        fld r // r1 = r0, r0 = r
+        fsqrt // r0 = sqrtf( r0 )
+        fdiv // r0 = r1 / r0
+    } // returns r0
+
+#else
+
+	return 1. / sqrt( r );
+
+#endif
+}
+
+// returns 1 / a for a * a = r
+// Another version
+float apx_rsq( float r ) {
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    const float asm_dot5 = 0.5f;
+    const float asm_1dot5 = 1.5f;
+
+    __asm {
+        fld r // r0 = r
+        fmul asm_dot5 // r0 = r0 * .5f
+        mov eax, r // eax = r
+        shr eax, 0x1 // eax = eax >> 1
+        neg eax // eax = -eax
+        add eax, 0x5F400000 // eax = eax & MAGICAL NUMBER
+        mov r, eax // r = eax
+        fmul r // r0 = r0 * r
+        fmul r // r0 = r0 * r
+        fsubr asm_1dot5 // r0 = 1.5f - r0
+        fmul r // r0 = r0 * r
+    } // returns r0
+
+#else
+
+	return 1. / sqrt( r );
+
+#endif
+}
+
+/* very MS-specific, commented out for now
+   Finally the best InvSqrt implementation?
+   Use for vector normalisation instead of 1/length() * x,y,z
+*/
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+__declspec(naked) float __fastcall InvSqrt(float fValue)
+{
+    __asm
+    {
+        mov        eax, 0be6eb508h
+        mov        dword ptr[esp-12],03fc00000h
+        sub        eax, dword ptr[esp + 4]
+        sub        dword ptr[esp+4], 800000h
+        shr        eax, 1
+        mov        dword ptr[esp -  8], eax
+
+        fld        dword ptr[esp -  8]
+        fmul    st, st
+        fld        dword ptr[esp -  8]
+        fxch    st(1)
+        fmul    dword ptr[esp +  4]
+        fld        dword ptr[esp - 12]
+        fld        st(0)
+        fsub    st,st(2)
+
+        fld        st(1)
+        fxch    st(1)
+        fmul    st(3),st
+        fmul    st(3),st
+        fmulp    st(4),st
+        fsub    st,st(2)
+
+        fmul    st(2),st
+        fmul    st(3),st
+        fmulp    st(2),st
+        fxch    st(1)
+        fsubp    st(1),st
+
+        fmulp    st(1), st
+        ret 4
+    }
+}
+
+#endif
+
+// returns a random number
+FORCEINLINE float asm_rand()
+{
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+  #if 0
+    #if OGRE_COMP_VER >= 1300
+
+	static unsigned __int64 q = time( NULL );
+
+	_asm {
+		movq mm0, q
+
+		// do the magic MMX thing
+		pshufw mm1, mm0, 0x1E
+		paddd mm0, mm1
+
+		// move to integer memory location and free MMX
+		movq q, mm0
+		emms
+	}
+
+	return float( q );
+    #endif
+  #else
+    // VC6 does not support pshufw
+    return float( rand() );
+  #endif
+#else
+    // GCC etc
+
+	return float( rand() );
+
+#endif
+}
+
+// returns the maximum random number
+FORCEINLINE float asm_rand_max()
+{
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+  #if 0
+    #if OGRE_COMP_VER >= 1300
+
+	return (std::numeric_limits< unsigned __int64 >::max)();
+	return 9223372036854775807.0f;
+    #endif
+  #else
+    // VC6 does not support unsigned __int64
+    return float( RAND_MAX );
+  #endif
+
+#else
+    // GCC etc
+	return float( RAND_MAX );
+
+#endif
+}
+
+// returns log2( r ) / log2( e )
+float asm_ln( float r ) {    
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+
+    const float asm_e = 2.71828182846f;
+    const float asm_1_div_log2_e = .693147180559f;
+    const float asm_neg1_div_3 = -.33333333333333333333333333333f;
+    const float asm_neg2_div_3 = -.66666666666666666666666666667f;
+    const float asm_2 = 2.f;
+
+    int log_2 = 0;
+
+    __asm {
+        // log_2 = ( ( r >> 0x17 ) & 0xFF ) - 0x80;
+        mov eax, r
+        sar eax, 0x17
+        and eax, 0xFF
+        sub eax, 0x80
+        mov log_2, eax
+
+        // r = ( r & 0x807fffff ) + 0x3f800000;
+        mov ebx, r
+        and ebx, 0x807FFFFF
+        add ebx, 0x3F800000
+        mov r, ebx
+
+        // r = ( asm_neg1_div_3 * r + asm_2 ) * r + asm_neg2_div_3;   // (1)
+        fld r
+        fmul asm_neg1_div_3
+        fadd asm_2
+        fmul r
+        fadd asm_neg2_div_3
+        fild log_2
+        fadd
+        fmul asm_1_div_log2_e
+    }
+
+#else
+
+	return log( r );
+
+#endif
+}
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC &&  OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_32
+#	pragma warning( pop )
+#endif
+} // namespace
+#endif
