Marko Pintera 13 سال پیش
کامیت
06131ddf18
73فایلهای تغییر یافته به همراه21919 افزوده شده و 0 حذف شده
  1. 24 0
      CamelotRenderer.sln
  2. 33 0
      CamelotRenderer/CamelotRenderer.cpp
  3. 158 0
      CamelotRenderer/CamelotRenderer.vcxproj
  4. 249 0
      CamelotRenderer/CamelotRenderer.vcxproj.filters
  5. 81 0
      CamelotRenderer/OgreAlignedAllocator.cpp
  6. 108 0
      CamelotRenderer/OgreAlignedAllocator.h
  7. 35 0
      CamelotRenderer/OgreAxisAlignedBox.cpp
  8. 813 0
      CamelotRenderer/OgreAxisAlignedBox.h
  9. 331 0
      CamelotRenderer/OgreBitwise.h
  10. 58 0
      CamelotRenderer/OgreBuildSettings.h
  11. 406 0
      CamelotRenderer/OgreColourValue.cpp
  12. 334 0
      CamelotRenderer/OgreColourValue.h
  13. 197 0
      CamelotRenderer/OgreConfig.h
  14. 119 0
      CamelotRenderer/OgreD3D9Prerequisites.h
  15. 55 0
      CamelotRenderer/OgreD3D9Resource.cpp
  16. 76 0
      CamelotRenderer/OgreD3D9Resource.h
  17. 55 0
      CamelotRenderer/OgreD3D9VideoMode.cpp
  18. 63 0
      CamelotRenderer/OgreD3D9VideoMode.h
  19. 169 0
      CamelotRenderer/OgreDefaultHardwareBufferManager.cpp
  20. 138 0
      CamelotRenderer/OgreDefaultHardwareBufferManager.h
  21. 114 0
      CamelotRenderer/OgreException.cpp
  22. 351 0
      CamelotRenderer/OgreException.h
  23. 1282 0
      CamelotRenderer/OgreFrustum.cpp
  24. 640 0
      CamelotRenderer/OgreFrustum.h
  25. 348 0
      CamelotRenderer/OgreHardwareBuffer.h
  26. 547 0
      CamelotRenderer/OgreHardwareBufferManager.cpp
  27. 529 0
      CamelotRenderer/OgreHardwareBufferManager.h
  28. 87 0
      CamelotRenderer/OgreHardwareIndexBuffer.cpp
  29. 89 0
      CamelotRenderer/OgreHardwareIndexBuffer.h
  30. 686 0
      CamelotRenderer/OgreHardwareVertexBuffer.cpp
  31. 560 0
      CamelotRenderer/OgreHardwareVertexBuffer.h
  32. 82 0
      CamelotRenderer/OgreHeaderPrefix.h
  33. 44 0
      CamelotRenderer/OgreHeaderSuffix.h
  34. 987 0
      CamelotRenderer/OgreMath.cpp
  35. 656 0
      CamelotRenderer/OgreMath.h
  36. 1510 0
      CamelotRenderer/OgreMatrix3.cpp
  37. 272 0
      CamelotRenderer/OgreMatrix3.h
  38. 260 0
      CamelotRenderer/OgreMatrix4.cpp
  39. 659 0
      CamelotRenderer/OgreMatrix4.h
  40. 170 0
      CamelotRenderer/OgrePlane.cpp
  41. 166 0
      CamelotRenderer/OgrePlane.h
  42. 264 0
      CamelotRenderer/OgrePlatform.h
  43. 200 0
      CamelotRenderer/OgrePlatformInformation.h
  44. 77 0
      CamelotRenderer/OgrePortMemory.h
  45. 386 0
      CamelotRenderer/OgrePrerequisites.h
  46. 608 0
      CamelotRenderer/OgreQuaternion.cpp
  47. 271 0
      CamelotRenderer/OgreQuaternion.h
  48. 111 0
      CamelotRenderer/OgreRay.h
  49. 110 0
      CamelotRenderer/OgreRenderSystemCapabilities.cpp
  50. 705 0
      CamelotRenderer/OgreRenderSystemCapabilities.h
  51. 278 0
      CamelotRenderer/OgreSharedPtr.h
  52. 104 0
      CamelotRenderer/OgreSingleton.h
  53. 108 0
      CamelotRenderer/OgreSphere.h
  54. 120 0
      CamelotRenderer/OgreStdHeaders.h
  55. 367 0
      CamelotRenderer/OgreString.cpp
  56. 202 0
      CamelotRenderer/OgreString.h
  57. 438 0
      CamelotRenderer/OgreStringConverter.cpp
  58. 270 0
      CamelotRenderer/OgreStringConverter.h
  59. 53 0
      CamelotRenderer/OgreStringVector.h
  60. 61 0
      CamelotRenderer/OgreThreadDefines.h
  61. 42 0
      CamelotRenderer/OgreVector2.cpp
  62. 573 0
      CamelotRenderer/OgreVector2.h
  63. 42 0
      CamelotRenderer/OgreVector3.cpp
  64. 796 0
      CamelotRenderer/OgreVector3.h
  65. 34 0
      CamelotRenderer/OgreVector4.cpp
  66. 414 0
      CamelotRenderer/OgreVector4.h
  67. 976 0
      CamelotRenderer/OgreVertexIndexData.cpp
  68. 321 0
      CamelotRenderer/OgreVertexIndexData.h
  69. 40 0
      CamelotRenderer/ReadMe.txt
  70. 376 0
      CamelotRenderer/asm_math.h
  71. 8 0
      CamelotRenderer/stdafx.cpp
  72. 15 0
      CamelotRenderer/stdafx.h
  73. 8 0
      CamelotRenderer/targetver.h

+ 24 - 0
CamelotRenderer.sln

@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CamelotRenderer", "CamelotRenderer\CamelotRenderer.vcxproj", "{9B21D41C-516B-43BF-9B10-E99B599C7589}"
+EndProject
+Global
+	GlobalSection(SubversionScc) = preSolution
+		Svn-Managed = True
+		Manager = AnkhSVN - Subversion Support for Visual Studio
+	EndGlobalSection
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{9B21D41C-516B-43BF-9B10-E99B599C7589}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9B21D41C-516B-43BF-9B10-E99B599C7589}.Debug|Win32.Build.0 = Debug|Win32
+		{9B21D41C-516B-43BF-9B10-E99B599C7589}.Release|Win32.ActiveCfg = Release|Win32
+		{9B21D41C-516B-43BF-9B10-E99B599C7589}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 33 - 0
CamelotRenderer/CamelotRenderer.cpp

@@ -0,0 +1,33 @@
+// CamelotRenderer.cpp : Defines the entry point for the console application.
+//
+
+#include "stdafx.h"
+
+#include "OgreBuildSettings.h"
+#include "OgreColourValue.h"
+#include "OgreConfig.h"
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreMatrix4.h"
+#include "OgrePlane.h"
+#include "OgrePlatform.h"
+#include "OgrePrerequisites.h"
+#include "OgreQuaternion.h"
+#include "OgreSharedPtr.h"
+#include "OgreString.h"
+#include "OgreStringConverter.h"
+#include "OgreStringVector.h"
+#include "OgreThreadDefines.h"
+#include "OgreVector2.h"
+#include "OgreVector3.h"
+#include "OgreVector4.h"
+#include "OgreHardwareBuffer.h"
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreD3D9VideoMode.h"
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+	return 0;
+}
+

+ 158 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9B21D41C-516B-43BF-9B10-E99B599C7589}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>CamelotRenderer</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;OGRE_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;OGRE_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="asm_math.h" />
+    <ClInclude Include="OgreAlignedAllocator.h" />
+    <ClInclude Include="OgreAxisAlignedBox.h" />
+    <ClInclude Include="OgreBitwise.h" />
+    <ClInclude Include="OgreBuildSettings.h" />
+    <ClInclude Include="OgreColourValue.h" />
+    <ClInclude Include="OgreConfig.h" />
+    <ClInclude Include="OgreD3D9Prerequisites.h" />
+    <ClInclude Include="OgreD3D9Resource.h" />
+    <ClInclude Include="OgreD3D9VideoMode.h" />
+    <ClInclude Include="OgreDefaultHardwareBufferManager.h" />
+    <ClInclude Include="OgreException.h" />
+    <ClInclude Include="OgreFrustum.h" />
+    <ClInclude Include="OgreHardwareBuffer.h" />
+    <ClInclude Include="OgreHardwareBufferManager.h" />
+    <ClInclude Include="OgreHardwareIndexBuffer.h" />
+    <ClInclude Include="OgreHardwareVertexBuffer.h" />
+    <ClInclude Include="OgreHeaderPrefix.h" />
+    <ClInclude Include="OgreHeaderSuffix.h" />
+    <ClInclude Include="OgreMath.h" />
+    <ClInclude Include="OgreMatrix3.h" />
+    <ClInclude Include="OgreMatrix4.h" />
+    <ClInclude Include="OgrePlane.h" />
+    <ClInclude Include="OgrePlatform.h" />
+    <ClInclude Include="OgrePlatformInformation.h" />
+    <ClInclude Include="OgrePortMemory.h" />
+    <ClInclude Include="OgrePrerequisites.h" />
+    <ClInclude Include="OgreQuaternion.h" />
+    <ClInclude Include="OgreRay.h" />
+    <ClInclude Include="OgreRenderSystemCapabilities.h" />
+    <ClInclude Include="OgreSharedPtr.h" />
+    <ClInclude Include="OgreSingleton.h" />
+    <ClInclude Include="OgreSphere.h" />
+    <ClInclude Include="OgreStdHeaders.h" />
+    <ClInclude Include="OgreString.h" />
+    <ClInclude Include="OgreStringConverter.h" />
+    <ClInclude Include="OgreStringVector.h" />
+    <ClInclude Include="OgreThreadDefines.h" />
+    <ClInclude Include="OgreVector2.h" />
+    <ClInclude Include="OgreVector3.h" />
+    <ClInclude Include="OgreVector4.h" />
+    <ClInclude Include="OgreVertexIndexData.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="CamelotRenderer.cpp" />
+    <ClCompile Include="OgreAlignedAllocator.cpp" />
+    <ClCompile Include="OgreAxisAlignedBox.cpp" />
+    <ClCompile Include="OgreColourValue.cpp" />
+    <ClCompile Include="OgreD3D9Resource.cpp" />
+    <ClCompile Include="OgreD3D9VideoMode.cpp" />
+    <ClCompile Include="OgreDefaultHardwareBufferManager.cpp" />
+    <ClCompile Include="OgreException.cpp" />
+    <ClCompile Include="OgreFrustum.cpp" />
+    <ClCompile Include="OgreHardwareBufferManager.cpp" />
+    <ClCompile Include="OgreHardwareIndexBuffer.cpp" />
+    <ClCompile Include="OgreHardwareVertexBuffer.cpp" />
+    <ClCompile Include="OgreMath.cpp" />
+    <ClCompile Include="OgreMatrix3.cpp" />
+    <ClCompile Include="OgreMatrix4.cpp" />
+    <ClCompile Include="OgrePlane.cpp" />
+    <ClCompile Include="OgreQuaternion.cpp" />
+    <ClCompile Include="OgreRenderSystemCapabilities.cpp" />
+    <ClCompile Include="OgreString.cpp" />
+    <ClCompile Include="OgreStringConverter.cpp" />
+    <ClCompile Include="OgreVector2.cpp" />
+    <ClCompile Include="OgreVector3.cpp" />
+    <ClCompile Include="OgreVector4.cpp" />
+    <ClCompile Include="OgreVertexIndexData.cpp" />
+    <ClCompile Include="stdafx.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 249 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="Header Files\D3D9RenderSystem">
+      <UniqueIdentifier>{e3f1eefd-4271-435c-a2e4-ce6770542e1f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\D3D9RenderSystem">
+      <UniqueIdentifier>{5ab8878b-6adb-4f4a-84c4-9315abf782d2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Math">
+      <UniqueIdentifier>{7b4cde3b-6ac1-46bc-aa5b-c642d1e86d27}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Math">
+      <UniqueIdentifier>{8eee0d37-16d4-4894-aa09-7103c1d2b9c4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\ForRemoval">
+      <UniqueIdentifier>{f916bd59-03a7-42a7-9b9c-60abe94020bc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\ForRemoval">
+      <UniqueIdentifier>{004ec8e4-409f-4bc2-b697-f24c707a2429}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreColourValue.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreD3D9Prerequisites.h">
+      <Filter>Header Files\D3D9RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreD3D9VideoMode.h">
+      <Filter>Header Files\D3D9RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreRenderSystemCapabilities.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreD3D9Resource.h">
+      <Filter>Header Files\D3D9RenderSystem</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHardwareBuffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHardwareVertexBuffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHardwareIndexBuffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHardwareBufferManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreVertexIndexData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreDefaultHardwareBufferManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="asm_math.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreAxisAlignedBox.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreMath.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreMatrix3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreMatrix4.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgrePlane.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreQuaternion.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreRay.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreSphere.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreVector2.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreVector3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreVector4.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreBitwise.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreAlignedAllocator.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreBuildSettings.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreConfig.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreException.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHeaderPrefix.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHeaderSuffix.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgrePlatform.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgrePlatformInformation.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgrePortMemory.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgrePrerequisites.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreSharedPtr.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreSingleton.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreStdHeaders.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreString.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreStringConverter.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreStringVector.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreThreadDefines.h">
+      <Filter>Header Files\ForRemoval</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreFrustum.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="CamelotRenderer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreD3D9VideoMode.cpp">
+      <Filter>Source Files\D3D9RenderSystem</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreRenderSystemCapabilities.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreD3D9Resource.cpp">
+      <Filter>Source Files\D3D9RenderSystem</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreHardwareVertexBuffer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreHardwareIndexBuffer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreHardwareBufferManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreVertexIndexData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreDefaultHardwareBufferManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreColourValue.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreMath.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreMatrix3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreMatrix4.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgrePlane.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreQuaternion.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreVector2.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreVector3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreVector4.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreAxisAlignedBox.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreAlignedAllocator.cpp">
+      <Filter>Source Files\ForRemoval</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreException.cpp">
+      <Filter>Source Files\ForRemoval</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreString.cpp">
+      <Filter>Source Files\ForRemoval</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreStringConverter.cpp">
+      <Filter>Source Files\ForRemoval</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreFrustum.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 81 - 0
CamelotRenderer/OgreAlignedAllocator.cpp

@@ -0,0 +1,81 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgrePrerequisites.h"
+#include "OgreAlignedAllocator.h"
+
+#include "OgrePlatformInformation.h"
+#include "OgreBitwise.h"
+
+
+/**
+*
+* |___2___|3|_________5__________|__6__|
+* ^         ^
+* 1         4
+*
+* 1 -> Pointer to start of the block allocated by new.
+* 2 -> Gap used to get 4 aligned on given alignment
+* 3 -> Byte offset between 1 and 4
+* 4 -> Pointer to the start of data block.
+* 5 -> Data block.
+* 6 -> Wasted memory at rear of data block.
+*/
+
+namespace Ogre {
+
+    //---------------------------------------------------------------------
+    void* AlignedMemory::allocate(size_t size, size_t alignment)
+    {
+        assert(0 < alignment && alignment <= 128 && Bitwise::isPO2(alignment));
+
+        unsigned char* p = new unsigned char[size + alignment];
+        size_t offset = alignment - (size_t(p) & (alignment-1));
+
+        unsigned char* result = p + offset;
+        result[-1] = (unsigned char)offset;
+
+        return result;
+    }
+    //---------------------------------------------------------------------
+    void* AlignedMemory::allocate(size_t size)
+    {
+        return allocate(size, OGRE_SIMD_ALIGNMENT);
+    }
+    //---------------------------------------------------------------------
+    void AlignedMemory::deallocate(void* p)
+    {
+        if (p)
+        {
+            unsigned char* mem = (unsigned char*)p;
+            mem = mem - mem[-1];
+            delete [] mem;
+        }
+    }
+
+}

+ 108 - 0
CamelotRenderer/OgreAlignedAllocator.h

@@ -0,0 +1,108 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __AlignedAllocator_H__
+#define __AlignedAllocator_H__
+
+// Now we're only including this within OgreMemoryAllocatorConfig.h which is already in
+// the prerequisites header (circlar reference)
+//#include "OgrePrerequisites.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+
+	/** \addtogroup Memory
+	*  @{
+	*/
+
+	/** Class to provide aligned memory allocate functionality.
+    @remarks
+        All SIMD processing are friendly with aligned memory, and some SIMD routines
+        are designed for working with aligned memory only. If the data are intended to
+        use SIMD processing, it's need to be aligned for better performance boost.
+        In additional, most time cache boundary aligned data also lead to better
+        performance even if didn't used SIMD processing. So this class provides a couple
+        of functions for allocate aligned memory.
+    @par
+        Anyways, in general, you don't need to use this class directly, Ogre internally
+        will take care with most SIMD and cache friendly optimisation if possible.
+    @par
+        This isn't a "one-step" optimisation, there are a lot of underlying work to
+        achieve performance boost. If you didn't know what are you doing or what there
+        are going, just ignore this class.
+    @note
+        This class intended to use by advanced user only.
+    */
+	class _OgreExport AlignedMemory
+	{
+	public:
+        /** Allocate memory with given alignment.
+            @param
+                size The size of memory need to allocate.
+            @param
+                alignment The alignment of result pointer, must be power of two
+                and in range [1, 128].
+            @returns
+                The allocated memory pointer.
+            @par
+                On failure, exception will be throw.
+        */
+        static void* allocate(size_t size, size_t alignment);
+
+        /** Allocate memory with default platform dependent alignment.
+            @remarks
+                The default alignment depend on target machine, this function
+                guarantee aligned memory according with SIMD processing and
+                cache boundary friendly.
+            @param
+                size The size of memory need to allocate.
+            @returns
+                The allocated memory pointer.
+            @par
+                On failure, exception will be throw.
+        */
+        static void* allocate(size_t size);
+
+        /** Deallocate memory that allocated by this class.
+            @param
+                p Pointer to the memory allocated by this class or <b>NULL</b> pointer.
+            @par
+                On <b>NULL</b> pointer, nothing happen.
+        */
+        static void deallocate(void* p);
+	};
+
+	/** @} */
+	/** @} */
+
+}
+
+#endif  // __AlignedAllocator_H__

+ 35 - 0
CamelotRenderer/OgreAxisAlignedBox.cpp

@@ -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-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreAxisAlignedBox.h"
+
+namespace Ogre
+{
+	const AxisAlignedBox AxisAlignedBox::BOX_NULL;
+	const AxisAlignedBox AxisAlignedBox::BOX_INFINITE(AxisAlignedBox::EXTENT_INFINITE);
+}
+

+ 813 - 0
CamelotRenderer/OgreAxisAlignedBox.h

@@ -0,0 +1,813 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __AxisAlignedBox_H_
+#define __AxisAlignedBox_H_
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+#include "OgreMatrix4.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+
+	/** A 3D box aligned with the x/y/z axes.
+	@remarks
+	This class represents a simple box which is aligned with the
+	axes. Internally it only stores 2 points as the extremeties of
+	the box, one which is the minima of all 3 axes, and the other
+	which is the maxima of all 3 axes. This class is typically used
+	for an axis-aligned bounding box (AABB) for collision and
+	visibility determination.
+	*/
+	class _OgreExport AxisAlignedBox
+	{
+	public:
+		enum Extent
+		{
+			EXTENT_NULL,
+			EXTENT_FINITE,
+			EXTENT_INFINITE
+		};
+	protected:
+
+		Vector3 mMinimum;
+		Vector3 mMaximum;
+		Extent mExtent;
+		mutable Vector3* mpCorners;
+
+	public:
+		/*
+		1-----2
+		/|    /|
+		/ |   / |
+		5-----4  |
+		|  0--|--3
+		| /   | /
+		|/    |/
+		6-----7
+		*/
+		typedef enum {
+			FAR_LEFT_BOTTOM = 0,
+			FAR_LEFT_TOP = 1,
+			FAR_RIGHT_TOP = 2,
+			FAR_RIGHT_BOTTOM = 3,
+			NEAR_RIGHT_BOTTOM = 7,
+			NEAR_LEFT_BOTTOM = 6,
+			NEAR_LEFT_TOP = 5,
+			NEAR_RIGHT_TOP = 4
+		} CornerEnum;
+		inline AxisAlignedBox() : mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE), mpCorners(0)
+		{
+			// Default to a null box 
+			setMinimum( -0.5, -0.5, -0.5 );
+			setMaximum( 0.5, 0.5, 0.5 );
+			mExtent = EXTENT_NULL;
+		}
+		inline AxisAlignedBox(Extent e) : mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE), mpCorners(0)
+		{
+			setMinimum( -0.5, -0.5, -0.5 );
+			setMaximum( 0.5, 0.5, 0.5 );
+			mExtent = e;
+		}
+
+		inline AxisAlignedBox(const AxisAlignedBox & rkBox) : mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE), mpCorners(0)
+
+		{
+			if (rkBox.isNull())
+				setNull();
+			else if (rkBox.isInfinite())
+				setInfinite();
+			else
+				setExtents( rkBox.mMinimum, rkBox.mMaximum );
+		}
+
+		inline AxisAlignedBox( const Vector3& min, const Vector3& max ) : mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE), mpCorners(0)
+		{
+			setExtents( min, max );
+		}
+
+		inline AxisAlignedBox(
+			Real mx, Real my, Real mz,
+			Real Mx, Real My, Real Mz ) : mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE), mpCorners(0)
+		{
+			setExtents( mx, my, mz, Mx, My, Mz );
+		}
+
+		AxisAlignedBox& operator=(const AxisAlignedBox& rhs)
+		{
+			// Specifically override to avoid copying mpCorners
+			if (rhs.isNull())
+				setNull();
+			else if (rhs.isInfinite())
+				setInfinite();
+			else
+				setExtents(rhs.mMinimum, rhs.mMaximum);
+
+			return *this;
+		}
+
+		~AxisAlignedBox()
+		{
+			if (mpCorners)
+				OGRE_FREE(mpCorners, MEMCATEGORY_SCENE_CONTROL);
+		}
+
+
+		/** Gets the minimum corner of the box.
+		*/
+		inline const Vector3& getMinimum(void) const
+		{ 
+			return mMinimum; 
+		}
+
+		/** Gets a modifiable version of the minimum
+		corner of the box.
+		*/
+		inline Vector3& getMinimum(void)
+		{ 
+			return mMinimum; 
+		}
+
+		/** Gets the maximum corner of the box.
+		*/
+		inline const Vector3& getMaximum(void) const
+		{ 
+			return mMaximum;
+		}
+
+		/** Gets a modifiable version of the maximum
+		corner of the box.
+		*/
+		inline Vector3& getMaximum(void)
+		{ 
+			return mMaximum;
+		}
+
+
+		/** Sets the minimum corner of the box.
+		*/
+		inline void setMinimum( const Vector3& vec )
+		{
+			mExtent = EXTENT_FINITE;
+			mMinimum = vec;
+		}
+
+		inline void setMinimum( Real x, Real y, Real z )
+		{
+			mExtent = EXTENT_FINITE;
+			mMinimum.x = x;
+			mMinimum.y = y;
+			mMinimum.z = z;
+		}
+
+		/** Changes one of the components of the minimum corner of the box
+		used to resize only one dimension of the box
+		*/
+		inline void setMinimumX(Real x)
+		{
+			mMinimum.x = x;
+		}
+
+		inline void setMinimumY(Real y)
+		{
+			mMinimum.y = y;
+		}
+
+		inline void setMinimumZ(Real z)
+		{
+			mMinimum.z = z;
+		}
+
+		/** Sets the maximum corner of the box.
+		*/
+		inline void setMaximum( const Vector3& vec )
+		{
+			mExtent = EXTENT_FINITE;
+			mMaximum = vec;
+		}
+
+		inline void setMaximum( Real x, Real y, Real z )
+		{
+			mExtent = EXTENT_FINITE;
+			mMaximum.x = x;
+			mMaximum.y = y;
+			mMaximum.z = z;
+		}
+
+		/** Changes one of the components of the maximum corner of the box
+		used to resize only one dimension of the box
+		*/
+		inline void setMaximumX( Real x )
+		{
+			mMaximum.x = x;
+		}
+
+		inline void setMaximumY( Real y )
+		{
+			mMaximum.y = y;
+		}
+
+		inline void setMaximumZ( Real z )
+		{
+			mMaximum.z = z;
+		}
+
+		/** Sets both minimum and maximum extents at once.
+		*/
+		inline void setExtents( const Vector3& min, const Vector3& max )
+		{
+            assert( (min.x <= max.x && min.y <= max.y && min.z <= max.z) &&
+                "The minimum corner of the box must be less than or equal to maximum corner" );
+
+			mExtent = EXTENT_FINITE;
+			mMinimum = min;
+			mMaximum = max;
+		}
+
+		inline void setExtents(
+			Real mx, Real my, Real mz,
+			Real Mx, Real My, Real Mz )
+		{
+            assert( (mx <= Mx && my <= My && mz <= Mz) &&
+                "The minimum corner of the box must be less than or equal to maximum corner" );
+
+			mExtent = EXTENT_FINITE;
+
+			mMinimum.x = mx;
+			mMinimum.y = my;
+			mMinimum.z = mz;
+
+			mMaximum.x = Mx;
+			mMaximum.y = My;
+			mMaximum.z = Mz;
+
+		}
+
+		/** Returns a pointer to an array of 8 corner points, useful for
+		collision vs. non-aligned objects.
+		@remarks
+		If the order of these corners is important, they are as
+		follows: The 4 points of the minimum Z face (note that
+		because Ogre uses right-handed coordinates, the minimum Z is
+		at the 'back' of the box) starting with the minimum point of
+		all, then anticlockwise around this face (if you are looking
+		onto the face from outside the box). Then the 4 points of the
+		maximum Z face, starting with maximum point of all, then
+		anticlockwise around this face (looking onto the face from
+		outside the box). Like this:
+		<pre>
+		1-----2
+		/|    /|
+		/ |   / |
+		5-----4  |
+		|  0--|--3
+		| /   | /
+		|/    |/
+		6-----7
+		</pre>
+		@remarks as this implementation uses a static member, make sure to use your own copy !
+		*/
+		inline const Vector3* getAllCorners(void) const
+		{
+			assert( (mExtent == EXTENT_FINITE) && "Can't get corners of a null or infinite AAB" );
+
+			// The order of these items is, using right-handed co-ordinates:
+			// Minimum Z face, starting with Min(all), then anticlockwise
+			//   around face (looking onto the face)
+			// Maximum Z face, starting with Max(all), then anticlockwise
+			//   around face (looking onto the face)
+			// Only for optimization/compatibility.
+			if (!mpCorners)
+				mpCorners = OGRE_ALLOC_T(Vector3, 8, MEMCATEGORY_SCENE_CONTROL);
+
+			mpCorners[0] = mMinimum;
+			mpCorners[1].x = mMinimum.x; mpCorners[1].y = mMaximum.y; mpCorners[1].z = mMinimum.z;
+			mpCorners[2].x = mMaximum.x; mpCorners[2].y = mMaximum.y; mpCorners[2].z = mMinimum.z;
+			mpCorners[3].x = mMaximum.x; mpCorners[3].y = mMinimum.y; mpCorners[3].z = mMinimum.z;            
+
+			mpCorners[4] = mMaximum;
+			mpCorners[5].x = mMinimum.x; mpCorners[5].y = mMaximum.y; mpCorners[5].z = mMaximum.z;
+			mpCorners[6].x = mMinimum.x; mpCorners[6].y = mMinimum.y; mpCorners[6].z = mMaximum.z;
+			mpCorners[7].x = mMaximum.x; mpCorners[7].y = mMinimum.y; mpCorners[7].z = mMaximum.z;
+
+			return mpCorners;
+		}
+
+		/** gets the position of one of the corners
+		*/
+		Vector3 getCorner(CornerEnum cornerToGet) const
+		{
+			switch(cornerToGet)
+			{
+			case FAR_LEFT_BOTTOM:
+				return mMinimum;
+			case FAR_LEFT_TOP:
+				return Vector3(mMinimum.x, mMaximum.y, mMinimum.z);
+			case FAR_RIGHT_TOP:
+				return Vector3(mMaximum.x, mMaximum.y, mMinimum.z);
+			case FAR_RIGHT_BOTTOM:
+				return Vector3(mMaximum.x, mMinimum.y, mMinimum.z);
+			case NEAR_RIGHT_BOTTOM:
+				return Vector3(mMaximum.x, mMinimum.y, mMaximum.z);
+			case NEAR_LEFT_BOTTOM:
+				return Vector3(mMinimum.x, mMinimum.y, mMaximum.z);
+			case NEAR_LEFT_TOP:
+				return Vector3(mMinimum.x, mMaximum.y, mMaximum.z);
+			case NEAR_RIGHT_TOP:
+				return mMaximum;
+			default:
+				return Vector3();
+			}
+		}
+
+		_OgreExport friend std::ostream& operator<<( std::ostream& o, const AxisAlignedBox aab )
+		{
+			switch (aab.mExtent)
+			{
+			case EXTENT_NULL:
+				o << "AxisAlignedBox(null)";
+				return o;
+
+			case EXTENT_FINITE:
+				o << "AxisAlignedBox(min=" << aab.mMinimum << ", max=" << aab.mMaximum << ")";
+				return o;
+
+			case EXTENT_INFINITE:
+				o << "AxisAlignedBox(infinite)";
+				return o;
+
+			default: // shut up compiler
+				assert( false && "Never reached" );
+				return o;
+			}
+		}
+
+		/** Merges the passed in box into the current box. The result is the
+		box which encompasses both.
+		*/
+		void merge( const AxisAlignedBox& rhs )
+		{
+			// Do nothing if rhs null, or this is infinite
+			if ((rhs.mExtent == EXTENT_NULL) || (mExtent == EXTENT_INFINITE))
+			{
+				return;
+			}
+			// Otherwise if rhs is infinite, make this infinite, too
+			else if (rhs.mExtent == EXTENT_INFINITE)
+			{
+				mExtent = EXTENT_INFINITE;
+			}
+			// Otherwise if current null, just take rhs
+			else if (mExtent == EXTENT_NULL)
+			{
+				setExtents(rhs.mMinimum, rhs.mMaximum);
+			}
+			// Otherwise merge
+			else
+			{
+				Vector3 min = mMinimum;
+				Vector3 max = mMaximum;
+				max.makeCeil(rhs.mMaximum);
+				min.makeFloor(rhs.mMinimum);
+
+				setExtents(min, max);
+			}
+
+		}
+
+		/** Extends the box to encompass the specified point (if needed).
+		*/
+		inline void merge( const Vector3& point )
+		{
+			switch (mExtent)
+			{
+			case EXTENT_NULL: // if null, use this point
+				setExtents(point, point);
+				return;
+
+			case EXTENT_FINITE:
+				mMaximum.makeCeil(point);
+				mMinimum.makeFloor(point);
+				return;
+
+			case EXTENT_INFINITE: // if infinite, makes no difference
+				return;
+			}
+
+			assert( false && "Never reached" );
+		}
+
+		/** Transforms the box according to the matrix supplied.
+		@remarks
+		By calling this method you get the axis-aligned box which
+		surrounds the transformed version of this box. Therefore each
+		corner of the box is transformed by the matrix, then the
+		extents are mapped back onto the axes to produce another
+		AABB. Useful when you have a local AABB for an object which
+		is then transformed.
+		*/
+		inline void transform( const Matrix4& matrix )
+		{
+			// Do nothing if current null or infinite
+			if( mExtent != EXTENT_FINITE )
+				return;
+
+			Vector3 oldMin, oldMax, currentCorner;
+
+			// Getting the old values so that we can use the existing merge method.
+			oldMin = mMinimum;
+			oldMax = mMaximum;
+
+			// reset
+			setNull();
+
+			// We sequentially compute the corners in the following order :
+			// 0, 6, 5, 1, 2, 4 ,7 , 3
+			// This sequence allows us to only change one member at a time to get at all corners.
+
+			// For each one, we transform it using the matrix
+			// Which gives the resulting point and merge the resulting point.
+
+			// First corner 
+			// min min min
+			currentCorner = oldMin;
+			merge( matrix * currentCorner );
+
+			// min,min,max
+			currentCorner.z = oldMax.z;
+			merge( matrix * currentCorner );
+
+			// min max max
+			currentCorner.y = oldMax.y;
+			merge( matrix * currentCorner );
+
+			// min max min
+			currentCorner.z = oldMin.z;
+			merge( matrix * currentCorner );
+
+			// max max min
+			currentCorner.x = oldMax.x;
+			merge( matrix * currentCorner );
+
+			// max max max
+			currentCorner.z = oldMax.z;
+			merge( matrix * currentCorner );
+
+			// max min max
+			currentCorner.y = oldMin.y;
+			merge( matrix * currentCorner );
+
+			// max min min
+			currentCorner.z = oldMin.z;
+			merge( matrix * currentCorner ); 
+		}
+
+		/** Transforms the box according to the affine matrix supplied.
+		@remarks
+		By calling this method you get the axis-aligned box which
+		surrounds the transformed version of this box. Therefore each
+		corner of the box is transformed by the matrix, then the
+		extents are mapped back onto the axes to produce another
+		AABB. Useful when you have a local AABB for an object which
+		is then transformed.
+		@note
+		The matrix must be an affine matrix. @see Matrix4::isAffine.
+		*/
+		void transformAffine(const Matrix4& m)
+		{
+			assert(m.isAffine());
+
+			// Do nothing if current null or infinite
+			if ( mExtent != EXTENT_FINITE )
+				return;
+
+			Vector3 centre = getCenter();
+			Vector3 halfSize = getHalfSize();
+
+			Vector3 newCentre = m.transformAffine(centre);
+			Vector3 newHalfSize(
+				Math::Abs(m[0][0]) * halfSize.x + Math::Abs(m[0][1]) * halfSize.y + Math::Abs(m[0][2]) * halfSize.z, 
+				Math::Abs(m[1][0]) * halfSize.x + Math::Abs(m[1][1]) * halfSize.y + Math::Abs(m[1][2]) * halfSize.z,
+				Math::Abs(m[2][0]) * halfSize.x + Math::Abs(m[2][1]) * halfSize.y + Math::Abs(m[2][2]) * halfSize.z);
+
+			setExtents(newCentre - newHalfSize, newCentre + newHalfSize);
+		}
+
+		/** Sets the box to a 'null' value i.e. not a box.
+		*/
+		inline void setNull()
+		{
+			mExtent = EXTENT_NULL;
+		}
+
+		/** Returns true if the box is null i.e. empty.
+		*/
+		inline bool isNull(void) const
+		{
+			return (mExtent == EXTENT_NULL);
+		}
+
+		/** Returns true if the box is finite.
+		*/
+		bool isFinite(void) const
+		{
+			return (mExtent == EXTENT_FINITE);
+		}
+
+		/** Sets the box to 'infinite'
+		*/
+		inline void setInfinite()
+		{
+			mExtent = EXTENT_INFINITE;
+		}
+
+		/** Returns true if the box is infinite.
+		*/
+		bool isInfinite(void) const
+		{
+			return (mExtent == EXTENT_INFINITE);
+		}
+
+		/** Returns whether or not this box intersects another. */
+		inline bool intersects(const AxisAlignedBox& b2) const
+		{
+			// Early-fail for nulls
+			if (this->isNull() || b2.isNull())
+				return false;
+
+			// Early-success for infinites
+			if (this->isInfinite() || b2.isInfinite())
+				return true;
+
+			// Use up to 6 separating planes
+			if (mMaximum.x < b2.mMinimum.x)
+				return false;
+			if (mMaximum.y < b2.mMinimum.y)
+				return false;
+			if (mMaximum.z < b2.mMinimum.z)
+				return false;
+
+			if (mMinimum.x > b2.mMaximum.x)
+				return false;
+			if (mMinimum.y > b2.mMaximum.y)
+				return false;
+			if (mMinimum.z > b2.mMaximum.z)
+				return false;
+
+			// otherwise, must be intersecting
+			return true;
+
+		}
+
+		/// Calculate the area of intersection of this box and another
+		inline AxisAlignedBox intersection(const AxisAlignedBox& b2) const
+		{
+            if (this->isNull() || b2.isNull())
+			{
+				return AxisAlignedBox();
+			}
+			else if (this->isInfinite())
+			{
+				return b2;
+			}
+			else if (b2.isInfinite())
+			{
+				return *this;
+			}
+
+			Vector3 intMin = mMinimum;
+            Vector3 intMax = mMaximum;
+
+            intMin.makeCeil(b2.getMinimum());
+            intMax.makeFloor(b2.getMaximum());
+
+            // Check intersection isn't null
+            if (intMin.x < intMax.x &&
+                intMin.y < intMax.y &&
+                intMin.z < intMax.z)
+            {
+                return AxisAlignedBox(intMin, intMax);
+            }
+
+            return AxisAlignedBox();
+		}
+
+		/// Calculate the volume of this box
+		Real volume(void) const
+		{
+			switch (mExtent)
+			{
+			case EXTENT_NULL:
+				return 0.0f;
+
+			case EXTENT_FINITE:
+				{
+					Vector3 diff = mMaximum - mMinimum;
+					return diff.x * diff.y * diff.z;
+				}
+
+			case EXTENT_INFINITE:
+				return Math::POS_INFINITY;
+
+			default: // shut up compiler
+				assert( false && "Never reached" );
+				return 0.0f;
+			}
+		}
+
+		/** Scales the AABB by the vector given. */
+		inline void scale(const Vector3& s)
+		{
+			// Do nothing if current null or infinite
+			if (mExtent != EXTENT_FINITE)
+				return;
+
+			// NB assumes centered on origin
+			Vector3 min = mMinimum * s;
+			Vector3 max = mMaximum * s;
+			setExtents(min, max);
+		}
+
+		/** Tests whether this box intersects a sphere. */
+		bool intersects(const Sphere& s) const
+		{
+			return Math::intersects(s, *this); 
+		}
+		/** Tests whether this box intersects a plane. */
+		bool intersects(const Plane& p) const
+		{
+			return Math::intersects(p, *this);
+		}
+		/** Tests whether the vector point is within this box. */
+		bool intersects(const Vector3& v) const
+		{
+			switch (mExtent)
+			{
+			case EXTENT_NULL:
+				return false;
+
+			case EXTENT_FINITE:
+				return(v.x >= mMinimum.x  &&  v.x <= mMaximum.x  && 
+					v.y >= mMinimum.y  &&  v.y <= mMaximum.y  && 
+					v.z >= mMinimum.z  &&  v.z <= mMaximum.z);
+
+			case EXTENT_INFINITE:
+				return true;
+
+			default: // shut up compiler
+				assert( false && "Never reached" );
+				return false;
+			}
+		}
+		/// Gets the centre of the box
+		Vector3 getCenter(void) const
+		{
+			assert( (mExtent == EXTENT_FINITE) && "Can't get center of a null or infinite AAB" );
+
+			return Vector3(
+				(mMaximum.x + mMinimum.x) * 0.5f,
+				(mMaximum.y + mMinimum.y) * 0.5f,
+				(mMaximum.z + mMinimum.z) * 0.5f);
+		}
+		/// Gets the size of the box
+		Vector3 getSize(void) const
+		{
+			switch (mExtent)
+			{
+			case EXTENT_NULL:
+				return Vector3::ZERO;
+
+			case EXTENT_FINITE:
+				return mMaximum - mMinimum;
+
+			case EXTENT_INFINITE:
+				return Vector3(
+					Math::POS_INFINITY,
+					Math::POS_INFINITY,
+					Math::POS_INFINITY);
+
+			default: // shut up compiler
+				assert( false && "Never reached" );
+				return Vector3::ZERO;
+			}
+		}
+		/// Gets the half-size of the box
+		Vector3 getHalfSize(void) const
+		{
+			switch (mExtent)
+			{
+			case EXTENT_NULL:
+				return Vector3::ZERO;
+
+			case EXTENT_FINITE:
+				return (mMaximum - mMinimum) * 0.5;
+
+			case EXTENT_INFINITE:
+				return Vector3(
+					Math::POS_INFINITY,
+					Math::POS_INFINITY,
+					Math::POS_INFINITY);
+
+			default: // shut up compiler
+				assert( false && "Never reached" );
+				return Vector3::ZERO;
+			}
+		}
+
+        /** Tests whether the given point contained by this box.
+        */
+        bool contains(const Vector3& v) const
+        {
+            if (isNull())
+                return false;
+            if (isInfinite())
+                return true;
+
+            return mMinimum.x <= v.x && v.x <= mMaximum.x &&
+                   mMinimum.y <= v.y && v.y <= mMaximum.y &&
+                   mMinimum.z <= v.z && v.z <= mMaximum.z;
+        }
+
+        /** Tests whether another box contained by this box.
+        */
+        bool contains(const AxisAlignedBox& other) const
+        {
+            if (other.isNull() || this->isInfinite())
+                return true;
+
+            if (this->isNull() || other.isInfinite())
+                return false;
+
+            return this->mMinimum.x <= other.mMinimum.x &&
+                   this->mMinimum.y <= other.mMinimum.y &&
+                   this->mMinimum.z <= other.mMinimum.z &&
+                   other.mMaximum.x <= this->mMaximum.x &&
+                   other.mMaximum.y <= this->mMaximum.y &&
+                   other.mMaximum.z <= this->mMaximum.z;
+        }
+
+        /** Tests 2 boxes for equality.
+        */
+        bool operator== (const AxisAlignedBox& rhs) const
+        {
+            if (this->mExtent != rhs.mExtent)
+                return false;
+
+            if (!this->isFinite())
+                return true;
+
+            return this->mMinimum == rhs.mMinimum &&
+                   this->mMaximum == rhs.mMaximum;
+        }
+
+        /** Tests 2 boxes for inequality.
+        */
+        bool operator!= (const AxisAlignedBox& rhs) const
+        {
+            return !(*this == rhs);
+        }
+
+		// special values
+		static const AxisAlignedBox BOX_NULL;
+		static const AxisAlignedBox BOX_INFINITE;
+
+
+	};
+
+	/** @} */
+	/** @} */
+} // namespace Ogre
+
+#endif

+ 331 - 0
CamelotRenderer/OgreBitwise.h

@@ -0,0 +1,331 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef _Bitwise_H__
+#define _Bitwise_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+
+    /** 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 static_cast<uint16>(s | (m >> 13));
+            }
+            else if (e == 0xff - (127 - 15))
+            {
+                if (m == 0) // Inf
+                {
+                    return static_cast<uint16>(s | 0x7c00);
+                } 
+                else    // NAN
+                {
+                    m >>= 13;
+                    return static_cast<uint16>(s | 0x7c00 | m | (m == 0));
+                }
+            }
+            else
+            {
+                if (e > 30) // Overflow
+                {
+                    return static_cast<uint16>(s | 0x7c00);
+                }
+        
+                return static_cast<uint16>(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

+ 58 - 0
CamelotRenderer/OgreBuildSettings.h

@@ -0,0 +1,58 @@
+#ifndef __Custom_Config_H_
+#define __Custom_Config_H_
+
+// CMake auto-generated configuration options
+
+/* #undef OGRE_STATIC_LIB */
+
+#define OGRE_BUILD_RENDERSYSTEM_D3D9
+/* #undef OGRE_BUILD_RENDERSYSTEM_D3D10 */
+/* #undef OGRE_BUILD_RENDERSYSTEM_D3D11 */
+#define OGRE_BUILD_RENDERSYSTEM_GL
+/* #undef OGRE_BUILD_RENDERSYSTEM_GLES */
+#define OGRE_BUILD_PLUGIN_BSP
+#define OGRE_BUILD_PLUGIN_OCTREE
+#define OGRE_BUILD_PLUGIN_PCZ
+#define OGRE_BUILD_PLUGIN_PFX
+#define OGRE_BUILD_PLUGIN_CG
+
+#define OGRE_CONFIG_LITTLE_ENDIAN
+/* #undef OGRE_CONFIG_BIG_ENDIAN */
+
+#define OGRE_DOUBLE_PRECISION 0
+
+#define OGRE_MEMORY_ALLOCATOR 4
+
+#define OGRE_CONTAINERS_USE_CUSTOM_MEMORY_ALLOCATOR 1
+
+#define OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR 0
+
+#define OGRE_MEMORY_TRACKER_DEBUG_MODE 0
+
+#define OGRE_MEMORY_TRACKER_RELEASE_MODE 0
+
+#define OGRE_THREAD_SUPPORT 0
+
+#define OGRE_THREAD_PROVIDER 0
+
+#define OGRE_NO_FREEIMAGE 0
+
+#define OGRE_NO_DDS_CODEC 0
+
+#define OGRE_NO_PVRTC_CODEC 1
+
+#define OGRE_NO_ZIP_ARCHIVE 0
+
+#define OGRE_NO_VIEWPORT_ORIENTATIONMODE 1
+
+#define OGRE_USE_NEW_COMPILERS 1
+
+#define OGRE_USE_BOOST 1
+
+#define OGRE_PROFILING 0
+
+#define RTSHADER_SYSTEM_BUILD_CORE_SHADERS
+
+#define RTSHADER_SYSTEM_BUILD_EXT_SHADERS
+
+#endif

+ 406 - 0
CamelotRenderer/OgreColourValue.cpp

@@ -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-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "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;
+		}
+
+		
+	}
+
+}
+

+ 334 - 0
CamelotRenderer/OgreColourValue.h

@@ -0,0 +1,334 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef _COLOURVALUE_H__
+#define _COLOURVALUE_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+    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.0f / 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.0f / 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

+ 197 - 0
CamelotRenderer/OgreConfig.h

@@ -0,0 +1,197 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Config_H_
+#define __Config_H_
+
+// Include the CMake-generated build settings.
+// If you get complaints that this file is missing, then you're probably
+// trying to link directly against your source dir. You must then add
+// %BUILD_DIR%/include to your include search path to find OgreBuildSettings.h.
+#include "OgreBuildSettings.h"
+
+/** 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 */
+#ifndef OGRE_PROFILING
+#define OGRE_PROFILING 0
+#endif
+
+/** 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
+#define OGRE_MEMORY_ALLOCATOR_USER 3
+#define OGRE_MEMORY_ALLOCATOR_NEDPOOLING 4
+
+#ifndef OGRE_MEMORY_ALLOCATOR
+#  define OGRE_MEMORY_ALLOCATOR OGRE_MEMORY_ALLOCATOR_NEDPOOLING
+#endif
+
+// Whether to use the custom memory allocator in STL containers
+#ifndef OGRE_CONTAINERS_USE_CUSTOM_MEMORY_ALLOCATOR
+#  define OGRE_CONTAINERS_USE_CUSTOM_MEMORY_ALLOCATOR 1
+#endif
+
+//if you want to make Ogre::String use the custom memory allocator then set:
+//#define OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR 1
+// Doing this will mean Ogre's strings will not be compatible with std::string however
+#ifndef OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR
+#	define OGRE_STRING_USE_CUSTOM_MEMORY_ALLOCATOR 0
+#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 0
+#endif
+
+/** Provider for threading functionality, there are 4 options.
+
+OGRE_THREAD_PROVIDER = 0
+	No support for threading.
+OGRE_THREAD_PROVIDER = 1
+	Boost libraries provide threading functionality.
+OGRE_THREAD_PROVIDER = 2
+	Poco libraries provide threading functionality.
+OGRE_THREAD_PROVIDER = 3
+	TBB library provides threading functionality.
+*/
+#ifndef OGRE_THREAD_PROVIDER
+#define OGRE_THREAD_PROVIDER 0
+#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
+
+/** Disables use of the ZIP archive support.
+WARNING: Disabling this will make the samples unusable.
+*/
+#ifndef OGRE_NO_ZIP_ARCHIVE
+#define OGRE_NO_ZIP_ARCHIVE 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

+ 119 - 0
CamelotRenderer/OgreD3D9Prerequisites.h

@@ -0,0 +1,119 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __D3D9PREREQUISITES_H__
+#define __D3D9PREREQUISITES_H__
+
+#include "OgrePrerequisites.h"
+#ifdef __MINGW32__
+#  include "WIN32/OgreMinGWSupport.h" // extra defines for MinGW to deal with DX SDK
+#endif
+
+#if OGRE_THREAD_SUPPORT
+#define OGRE_LOCK_RECURSIVE_MUTEX(name)   name.lock();
+#define OGRE_UNLOCK_RECURSIVE_MUTEX(name) name.unlock();
+#else
+#define OGRE_LOCK_RECURSIVE_MUTEX(name) 
+#define OGRE_UNLOCK_RECURSIVE_MUTEX(name)
+#endif
+
+
+#if OGRE_THREAD_SUPPORT == 1
+#define D3D9_DEVICE_ACCESS_LOCK				OGRE_LOCK_RECURSIVE_MUTEX(msDeviceAccessMutex);
+#define D3D9_DEVICE_ACCESS_UNLOCK			OGRE_UNLOCK_RECURSIVE_MUTEX(msDeviceAccessMutex);
+#define D3D9_DEVICE_ACCESS_CRITICAL_SECTION	OGRE_LOCK_MUTEX(msDeviceAccessMutex)
+#else
+#define D3D9_DEVICE_ACCESS_LOCK	
+#define D3D9_DEVICE_ACCESS_UNLOCK
+#define D3D9_DEVICE_ACCESS_CRITICAL_SECTION
+#endif
+
+// Define versions for if DirectX is in use (Win32 only)
+#define DIRECT3D_VERSION 0x0900
+
+// some D3D commonly used macros
+#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
+#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
+#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
+
+// enable extended d3d debug 
+#if OGRE_DEBUG_MODE
+#	define D3D_DEBUG_INFO
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#if !defined(NOMINMAX) && defined(_MSC_VER)
+#	define NOMINMAX // required to stop windows.h messing up std::min
+#endif
+#include <d3d9.h>
+#include <d3dx9.h>
+#include <DxErr.h>
+
+
+namespace Ogre
+{
+	// Predefine classes
+	class D3D9RenderSystem;
+	class D3D9RenderWindow;
+	class D3D9Texture;
+	class D3D9TextureManager;
+	class D3D9Driver;
+	class D3D9DriverList;
+	class D3D9VideoMode;
+	class D3D9VideoModeList;
+	class D3D9GpuProgram;
+	class D3D9GpuProgramManager;
+    class D3D9HardwareBufferManager;
+    class D3D9HardwareIndexBuffer;
+    class D3D9HLSLProgramFactory;
+    class D3D9HLSLProgram;
+    class D3D9VertexDeclaration;
+	class D3D9Resource;
+
+// Should we ask D3D to manage vertex/index buffers automatically?
+// Doing so avoids lost devices, but also has a performance impact
+// which is unacceptably bad when using very large buffers
+#define OGRE_D3D_MANAGE_BUFFERS 1
+
+    //-------------------------------------------
+	// Windows setttings
+	//-------------------------------------------
+#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(OGRE_STATIC_LIB)
+#	ifdef OGRED3DENGINEDLL_EXPORTS
+#		define _OgreD3D9Export __declspec(dllexport)
+#	else
+#       if defined( __MINGW32__ )
+#           define _OgreD3D9Export
+#       else
+#    		define _OgreD3D9Export __declspec(dllimport)
+#       endif
+#	endif
+#else
+#	define _OgreD3D9Export
+#endif	// OGRE_WIN32
+}
+#endif

+ 55 - 0
CamelotRenderer/OgreD3D9Resource.cpp

@@ -0,0 +1,55 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreD3D9Resource.h"
+
+namespace Ogre
+{
+	OGRE_STATIC_MUTEX_INSTANCE(D3D9Resource::msDeviceAccessMutex)
+
+	D3D9Resource::D3D9Resource()
+	{				
+		// TODO PORT - Ignored
+		// D3D9RenderSystem::getResourceManager()->_notifyResourceCreated(static_cast<D3D9Resource*>(this));		
+	}
+
+	D3D9Resource::~D3D9Resource()
+	{		
+		// TODO PORT - Ignored
+		//D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+	}
+	
+	void D3D9Resource::lockDeviceAccess()
+	{		
+		D3D9_DEVICE_ACCESS_LOCK;								
+	}
+	
+	void D3D9Resource::unlockDeviceAccess()
+	{		
+		D3D9_DEVICE_ACCESS_UNLOCK;				
+	}
+}

+ 76 - 0
CamelotRenderer/OgreD3D9Resource.h

@@ -0,0 +1,76 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __D3D9Resource_H__
+#define __D3D9Resource_H__
+
+#include "OgreD3D9Prerequisites.h"
+
+namespace Ogre {
+
+	/** Represents a Direct3D rendering resource.
+	Provide unified interface to
+	handle various device states.
+	*/
+	class _OgreD3D9Export D3D9Resource
+	{
+
+	// Interface.
+	public:
+
+		// Called immediately after the Direct3D device has been created.
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) {}
+
+		// Called before the Direct3D device is going to be destroyed.
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) {}
+
+		// Called immediately after the Direct3D device has entered a lost state.
+		// This is the place to release non-managed resources.
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device) {}
+
+		// Called immediately after the Direct3D device has been reset.
+		// This is the place to create non-managed resources.
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device) {}
+
+		// Called when device state is changing. Access to any device should be locked.
+		// Relevant for multi thread application.
+		static void lockDeviceAccess();
+
+		// Called when device state change completed. Access to any device is allowed.
+		// Relevant for multi thread application.
+		static void unlockDeviceAccess();
+
+
+	public:
+		D3D9Resource			();
+		virtual ~D3D9Resource	();
+
+	protected:
+		OGRE_STATIC_MUTEX(msDeviceAccessMutex)		
+	};
+}
+#endif

+ 55 - 0
CamelotRenderer/OgreD3D9VideoMode.cpp

@@ -0,0 +1,55 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreD3D9VideoMode.h"
+
+namespace Ogre 
+{
+	String D3D9VideoMode::getDescription() const
+	{
+		char tmp[128];
+		unsigned int colourDepth = 16;
+		if( mDisplayMode.Format == D3DFMT_X8R8G8B8 ||
+			mDisplayMode.Format == D3DFMT_A8R8G8B8 ||
+			mDisplayMode.Format == D3DFMT_R8G8B8 )
+			colourDepth = 32;
+
+		sprintf( tmp, "%d x %d @ %d-bit colour", mDisplayMode.Width, mDisplayMode.Height, colourDepth );
+		return String(tmp);
+	}
+
+	unsigned int D3D9VideoMode::getColourDepth() const
+	{
+		unsigned int colourDepth = 16;
+		if( mDisplayMode.Format == D3DFMT_X8R8G8B8 ||
+			mDisplayMode.Format == D3DFMT_A8R8G8B8 ||
+			mDisplayMode.Format == D3DFMT_R8G8B8 )
+			colourDepth = 32;
+
+		return colourDepth;
+	}
+}

+ 63 - 0
CamelotRenderer/OgreD3D9VideoMode.h

@@ -0,0 +1,63 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __D3D9VIDEOMODE_H__
+#define __D3D9VIDEOMODE_H__
+
+#include "OgreD3D9Prerequisites.h"
+#include "OgreString.h"
+
+namespace Ogre 
+{
+	static unsigned int modeCount = 0;
+
+	class _OgreD3D9Export D3D9VideoMode
+	{
+	private:
+		D3DDISPLAYMODE mDisplayMode;
+		unsigned int modeNumber;
+
+	public:
+		D3D9VideoMode() { modeNumber = ++modeCount; ZeroMemory( &mDisplayMode, sizeof(D3DDISPLAYMODE) ); }
+		D3D9VideoMode( const D3D9VideoMode &ob ) { modeNumber = ++modeCount; mDisplayMode = ob.mDisplayMode; }
+		D3D9VideoMode( D3DDISPLAYMODE d3ddm ) { modeNumber = ++modeCount; mDisplayMode = d3ddm; }
+		~D3D9VideoMode()
+		{
+			modeCount--;
+		}
+
+		unsigned int getWidth() const { return mDisplayMode.Width; }
+		unsigned int getHeight() const { return mDisplayMode.Height; }
+		D3DFORMAT getFormat() const { return mDisplayMode.Format; }
+		unsigned int getRefreshRate() const { return mDisplayMode.RefreshRate; }
+		unsigned int getColourDepth() const;
+		D3DDISPLAYMODE getDisplayMode() const { return mDisplayMode; }
+		void increaseRefreshRate(unsigned int rr) { mDisplayMode.RefreshRate = rr; } 
+		String getDescription() const;
+	};
+}
+#endif

+ 169 - 0
CamelotRenderer/OgreDefaultHardwareBufferManager.cpp

@@ -0,0 +1,169 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreDefaultHardwareBufferManager.h"
+
+namespace Ogre {
+
+	DefaultHardwareVertexBuffer::DefaultHardwareVertexBuffer(size_t vertexSize, size_t numVertices, 
+															 HardwareBuffer::Usage usage)
+	: HardwareVertexBuffer(0, vertexSize, numVertices, usage, true, false) // always software, never shadowed
+	{
+        // Allocate aligned memory for better SIMD processing friendly.
+        mpData = static_cast<unsigned char*>(OGRE_MALLOC_SIMD(mSizeInBytes, MEMCATEGORY_GEOMETRY));
+	}
+	//-----------------------------------------------------------------------
+	DefaultHardwareVertexBuffer::DefaultHardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize, size_t numVertices, 
+		HardwareBuffer::Usage usage)
+        : HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, true, false) // always software, never shadowed
+	{
+        // Allocate aligned memory for better SIMD processing friendly.
+        mpData = static_cast<unsigned char*>(OGRE_MALLOC_SIMD(mSizeInBytes, MEMCATEGORY_GEOMETRY));
+	}
+	//-----------------------------------------------------------------------
+    DefaultHardwareVertexBuffer::~DefaultHardwareVertexBuffer()
+	{
+		OGRE_FREE_SIMD(mpData, MEMCATEGORY_GEOMETRY);
+	}
+	//-----------------------------------------------------------------------
+    void* DefaultHardwareVertexBuffer::lockImpl(size_t offset, size_t length, LockOptions options)
+	{
+        // Only for use internally, no 'locking' as such
+		return mpData + offset;
+	}
+	//-----------------------------------------------------------------------
+	void DefaultHardwareVertexBuffer::unlockImpl(void)
+	{
+        // Nothing to do
+	}
+	//-----------------------------------------------------------------------
+    void* DefaultHardwareVertexBuffer::lock(size_t offset, size_t length, LockOptions options)
+	{
+        mIsLocked = true;
+		return mpData + offset;
+	}
+	//-----------------------------------------------------------------------
+	void DefaultHardwareVertexBuffer::unlock(void)
+	{
+        mIsLocked = false;
+        // Nothing to do
+	}
+	//-----------------------------------------------------------------------
+    void DefaultHardwareVertexBuffer::readData(size_t offset, size_t length, void* pDest)
+	{
+		assert((offset + length) <= mSizeInBytes);
+		memcpy(pDest, mpData + offset, length);
+	}
+	//-----------------------------------------------------------------------
+    void DefaultHardwareVertexBuffer::writeData(size_t offset, size_t length, const void* pSource,
+			bool discardWholeBuffer)
+	{
+		assert((offset + length) <= mSizeInBytes);
+		// ignore discard, memory is not guaranteed to be zeroised
+		memcpy(mpData + offset, pSource, length);
+
+	}
+	//-----------------------------------------------------------------------
+
+	DefaultHardwareIndexBuffer::DefaultHardwareIndexBuffer(IndexType idxType, 
+		size_t numIndexes, HardwareBuffer::Usage usage) 
+		: HardwareIndexBuffer(0, idxType, numIndexes, usage, true, false) // always software, never shadowed
+	{
+		mpData = OGRE_ALLOC_T(unsigned char, mSizeInBytes, MEMCATEGORY_GEOMETRY);
+	}
+	//-----------------------------------------------------------------------
+    DefaultHardwareIndexBuffer::~DefaultHardwareIndexBuffer()
+	{
+		OGRE_FREE(mpData, MEMCATEGORY_GEOMETRY);
+	}
+	//-----------------------------------------------------------------------
+    void* DefaultHardwareIndexBuffer::lockImpl(size_t offset, size_t length, LockOptions options)
+	{
+        // Only for use internally, no 'locking' as such
+		return mpData + offset;
+	}
+	//-----------------------------------------------------------------------
+	void DefaultHardwareIndexBuffer::unlockImpl(void)
+	{
+        // Nothing to do
+	}
+	//-----------------------------------------------------------------------
+    void* DefaultHardwareIndexBuffer::lock(size_t offset, size_t length, LockOptions options)
+	{
+        mIsLocked = true;
+		return mpData + offset;
+	}
+	//-----------------------------------------------------------------------
+	void DefaultHardwareIndexBuffer::unlock(void)
+	{
+        mIsLocked = false;
+        // Nothing to do
+	}
+	//-----------------------------------------------------------------------
+    void DefaultHardwareIndexBuffer::readData(size_t offset, size_t length, void* pDest)
+	{
+		assert((offset + length) <= mSizeInBytes);
+		memcpy(pDest, mpData + offset, length);
+	}
+	//-----------------------------------------------------------------------
+    void DefaultHardwareIndexBuffer::writeData(size_t offset, size_t length, const void* pSource,
+			bool discardWholeBuffer)
+	{
+		assert((offset + length) <= mSizeInBytes);
+		// ignore discard, memory is not guaranteed to be zeroised
+		memcpy(mpData + offset, pSource, length);
+
+	}
+	//-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+    DefaultHardwareBufferManagerBase::DefaultHardwareBufferManagerBase()
+	{
+	}
+    //-----------------------------------------------------------------------
+    DefaultHardwareBufferManagerBase::~DefaultHardwareBufferManagerBase()
+	{
+        destroyAllDeclarations();
+        destroyAllBindings(); 
+	}
+    //-----------------------------------------------------------------------
+	HardwareVertexBufferSharedPtr 
+        DefaultHardwareBufferManagerBase::createVertexBuffer(size_t vertexSize, 
+		size_t numVerts, HardwareBuffer::Usage usage, bool useShadowBuffer)
+	{
+        DefaultHardwareVertexBuffer* vb = OGRE_NEW DefaultHardwareVertexBuffer(this, vertexSize, numVerts, usage);
+        return HardwareVertexBufferSharedPtr(vb);
+	}
+    //-----------------------------------------------------------------------
+	HardwareIndexBufferSharedPtr 
+        DefaultHardwareBufferManagerBase::createIndexBuffer(HardwareIndexBuffer::IndexType itype, 
+		size_t numIndexes, HardwareBuffer::Usage usage, bool useShadowBuffer)
+	{
+        DefaultHardwareIndexBuffer* ib = OGRE_NEW DefaultHardwareIndexBuffer(itype, numIndexes, usage);
+		return HardwareIndexBufferSharedPtr(ib);
+	}
+}

+ 138 - 0
CamelotRenderer/OgreDefaultHardwareBufferManager.h

@@ -0,0 +1,138 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __DefaultHardwareBufferManager_H__
+#define __DefaultHardwareBufferManager_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+
+    /// Specialisation of HardwareVertexBuffer for emulation
+    class _OgreExport DefaultHardwareVertexBuffer : public HardwareVertexBuffer 
+    {
+	protected:
+		unsigned char* mpData;
+        /** See HardwareBuffer. */
+        void* lockImpl(size_t offset, size_t length, LockOptions options);
+        /** See HardwareBuffer. */
+		void unlockImpl(void);
+    public:
+		DefaultHardwareVertexBuffer(size_t vertexSize, size_t numVertices, HardwareBuffer::Usage usage);
+		DefaultHardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize, size_t numVertices, 
+            HardwareBuffer::Usage usage);
+        ~DefaultHardwareVertexBuffer();
+        /** See HardwareBuffer. */
+        void readData(size_t offset, size_t length, void* pDest);
+        /** See HardwareBuffer. */
+        void writeData(size_t offset, size_t length, const void* pSource,
+				bool discardWholeBuffer = false);
+        /** Override HardwareBuffer to turn off all shadowing. */
+        void* lock(size_t offset, size_t length, LockOptions options);
+        /** Override HardwareBuffer to turn off all shadowing. */
+		void unlock(void);
+
+
+    };
+
+	/// Specialisation of HardwareIndexBuffer for emulation
+    class _OgreExport DefaultHardwareIndexBuffer : public HardwareIndexBuffer
+    {
+	protected:
+		unsigned char* mpData;
+        /** See HardwareBuffer. */
+        void* lockImpl(size_t offset, size_t length, LockOptions options);
+        /** See HardwareBuffer. */
+		void unlockImpl(void);
+    public:
+		DefaultHardwareIndexBuffer(IndexType idxType, size_t numIndexes, HardwareBuffer::Usage usage);
+        ~DefaultHardwareIndexBuffer();
+        /** See HardwareBuffer. */
+        void readData(size_t offset, size_t length, void* pDest);
+        /** See HardwareBuffer. */
+        void writeData(size_t offset, size_t length, const void* pSource,
+				bool discardWholeBuffer = false);
+        /** Override HardwareBuffer to turn off all shadowing. */
+        void* lock(size_t offset, size_t length, LockOptions options);
+        /** Override HardwareBuffer to turn off all shadowing. */
+		void unlock(void);
+
+    };
+
+	/** Specialisation of HardwareBufferManagerBase to emulate hardware buffers.
+	@remarks
+		You might want to instantiate this class if you want to utilise
+		classes like MeshSerializer without having initialised the 
+		rendering system (which is required to create a 'real' hardware
+		buffer manager.
+	*/
+	class _OgreExport DefaultHardwareBufferManagerBase : public HardwareBufferManagerBase
+	{
+    public:
+        DefaultHardwareBufferManagerBase();
+        ~DefaultHardwareBufferManagerBase();
+        /// Creates a vertex buffer
+		HardwareVertexBufferSharedPtr 
+            createVertexBuffer(size_t vertexSize, size_t numVerts, 
+				HardwareBuffer::Usage usage, bool useShadowBuffer = false);
+		/// Create a hardware vertex buffer
+		HardwareIndexBufferSharedPtr 
+            createIndexBuffer(HardwareIndexBuffer::IndexType itype, size_t numIndexes, 
+				HardwareBuffer::Usage usage, bool useShadowBuffer = false);
+    };
+
+	/// DefaultHardwareBufferManager as a Singleton
+	class _OgreExport DefaultHardwareBufferManager : public HardwareBufferManager
+	{
+	public:
+		DefaultHardwareBufferManager()
+			: HardwareBufferManager(OGRE_NEW DefaultHardwareBufferManagerBase()) 
+		{
+
+		}
+		~DefaultHardwareBufferManager()
+		{
+			OGRE_DELETE mImpl;
+		}
+	};
+
+	/** @} */
+	/** @} */
+
+}
+
+#endif

+ 114 - 0
CamelotRenderer/OgreException.cpp

@@ -0,0 +1,114 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreException.h"
+
+#ifdef __BORLANDC__
+    #include <stdio.h>
+#endif
+
+namespace Ogre {
+
+    Exception::Exception(int num, const String& desc, const String& src) :
+        line( 0 ),
+        number( num ),
+        description( desc ),
+        source( src )
+    {
+        // Log this error - not any more, allow catchers to do it
+        //LogManager::getSingleton().logMessage(this->getFullDescription());
+    }
+
+    Exception::Exception(int num, const String& desc, const String& src, 
+		const char* typ, const char* fil, long lin) :
+        line( lin ),
+        number( num ),
+		typeName(typ),
+        description( desc ),
+        source( src ),
+        file( fil )
+    {
+        // Log this error, mask it from debug though since it may be caught and ignored
+		// TODO - PORT - Log IGNORED
+  //      if(LogManager::getSingletonPtr())
+		//{
+  //          LogManager::getSingleton().logMessage(
+		//		this->getFullDescription(), 
+  //              LML_CRITICAL, true);
+		//}
+
+    }
+
+    Exception::Exception(const Exception& rhs)
+        : line( rhs.line ), 
+		number( rhs.number ), 
+		typeName( rhs.typeName ), 
+		description( rhs.description ), 
+		source( rhs.source ), 
+		file( rhs.file )
+    {
+    }
+
+    void Exception::operator = ( const Exception& rhs )
+    {
+        description = rhs.description;
+        number = rhs.number;
+        source = rhs.source;
+        file = rhs.file;
+        line = rhs.line;
+		typeName = rhs.typeName;
+    }
+
+    const String& Exception::getFullDescription(void) const
+    {
+		if (fullDesc.empty())
+		{
+
+			StringUtil::StrStreamType desc;
+
+			desc <<  "OGRE EXCEPTION(" << number << ":" << typeName << "): "
+				<< description 
+				<< " in " << source;
+
+			if( line > 0 )
+			{
+				desc << " at " << file << " (line " << line << ")";
+			}
+
+			fullDesc = desc.str();
+		}
+
+		return fullDesc;
+    }
+
+    int Exception::getNumber(void) const throw()
+    {
+        return number;
+    }
+
+}
+

+ 351 - 0
CamelotRenderer/OgreException.h

@@ -0,0 +1,351 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Exception_H_
+#define __Exception_H_
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreHeaderPrefix.h"
+#include "OgreString.h"
+#include <exception>
+
+// Backwards compatibility with old assert mode definitions
+#if OGRE_RELEASE_ASSERT == 1
+#   define OGRE_ASSERT_MODE 1
+#endif
+
+// Check for OGRE assert mode
+
+// RELEASE_EXCEPTIONS mode
+#if OGRE_ASSERT_MODE == 1
+#   ifdef _DEBUG
+#       define OgreAssert( a, b ) assert( (a) && (b) )
+
+#   else
+#       if OGRE_COMP != OGRE_COMPILER_BORL
+#           define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
+#       else
+#           define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
+#       endif
+
+#   endif
+
+// EXCEPTIONS mode
+#elif OGRE_ASSERT_MODE == 2
+#   if OGRE_COMP != OGRE_COMPILER_BORL
+#       define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
+#   else
+#       define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
+#   endif
+
+// STANDARD mode
+#else
+#   define OgreAssert( a, b ) assert( (a) && (b) )
+
+#endif
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+	/** When thrown, provides information about an error that has occurred inside the engine.
+        @remarks
+            OGRE never uses return values to indicate errors. Instead, if an
+            error occurs, an exception is thrown, and this is the object that
+            encapsulates the detail of the problem. The application using
+            OGRE should always ensure that the exceptions are caught, so all
+            OGRE engine functions should occur within a
+            try{} catch(Ogre::Exception& e) {} block.
+        @par
+            The user application should never create any instances of this
+            object unless it wishes to unify its error handling using the
+            same object.
+    */
+	class _OgreExport Exception : public std::exception
+    {
+    protected:
+        long line;
+        int number;
+		String typeName;
+        String description;
+        String source;
+        String file;
+		mutable String fullDesc;
+    public:
+        /** Static definitions of error codes.
+            @todo
+                Add many more exception codes, since we want the user to be able
+                to catch most of them.
+        */
+        enum ExceptionCodes {
+            ERR_CANNOT_WRITE_TO_FILE,
+            ERR_INVALID_STATE,
+            ERR_INVALIDPARAMS,
+            ERR_RENDERINGAPI_ERROR,
+            ERR_DUPLICATE_ITEM,
+            ERR_ITEM_NOT_FOUND,
+            ERR_FILE_NOT_FOUND,
+            ERR_INTERNAL_ERROR,
+            ERR_RT_ASSERTION_FAILED, 
+			ERR_NOT_IMPLEMENTED
+        };
+
+        /** Default constructor.
+        */
+        Exception( int number, const String& description, const String& source );
+
+        /** Advanced constructor.
+        */
+        Exception( int number, const String& description, const String& source, const char* type, const char* file, long line );
+
+        /** Copy constructor.
+        */
+        Exception(const Exception& rhs);
+
+		/// Needed for  compatibility with std::exception
+		~Exception() throw() {}
+
+        /** Assignment operator.
+        */
+        void operator = (const Exception& rhs);
+
+        /** Returns a string with the full description of this error.
+            @remarks
+                The description contains the error number, the description
+                supplied by the thrower, what routine threw the exception,
+                and will also supply extra platform-specific information
+                where applicable. For example - in the case of a rendering
+                library error, the description of the error will include both
+                the place in which OGRE found the problem, and a text
+                description from the 3D rendering library, if available.
+        */
+        virtual const String& getFullDescription(void) const;
+
+        /** Gets the error code.
+        */
+        virtual int getNumber(void) const throw();
+
+        /** Gets the source function.
+        */
+        virtual const String &getSource() const { return source; }
+
+        /** Gets source file name.
+        */
+        virtual const String &getFile() const { return file; }
+
+        /** Gets line number.
+        */
+        virtual long getLine() const { return line; }
+
+		/** Returns a string with only the 'description' field of this exception. Use 
+			getFullDescriptionto get a full description of the error including line number,
+			error number and what function threw the exception.
+        */
+		virtual const String &getDescription(void) const { return description; }
+
+		/// Override std::exception::what
+		const char* what() const throw() { return getFullDescription().c_str(); }
+        
+    };
+
+
+	/** Template struct which creates a distinct type for each exception code.
+	@note
+	This is useful because it allows us to create an overloaded method
+	for returning different exception types by value without ambiguity. 
+	From 'Modern C++ Design' (Alexandrescu 2001).
+	*/
+	template <int num>
+	struct ExceptionCodeType
+	{
+		enum { number = num };
+	};
+
+	// Specialised exceptions allowing each to be caught specifically
+	// backwards-compatible since exception codes still used
+
+	class _OgreExport UnimplementedException : public Exception 
+	{
+	public:
+		UnimplementedException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "UnimplementedException", inFile, inLine) {}
+	};
+	class _OgreExport FileNotFoundException : public Exception
+	{
+	public:
+		FileNotFoundException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "FileNotFoundException", inFile, inLine) {}
+	};
+	class _OgreExport IOException : public Exception
+	{
+	public:
+		IOException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "IOException", inFile, inLine) {}
+	};
+	class _OgreExport InvalidStateException : public Exception
+	{
+	public:
+		InvalidStateException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "InvalidStateException", inFile, inLine) {}
+	};
+	class _OgreExport InvalidParametersException : public Exception
+	{
+	public:
+		InvalidParametersException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "InvalidParametersException", inFile, inLine) {}
+	};
+	class _OgreExport ItemIdentityException : public Exception
+	{
+	public:
+		ItemIdentityException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "ItemIdentityException", inFile, inLine) {}
+	};
+	class _OgreExport InternalErrorException : public Exception
+	{
+	public:
+		InternalErrorException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "InternalErrorException", inFile, inLine) {}
+	};
+	class _OgreExport RenderingAPIException : public Exception
+	{
+	public:
+		RenderingAPIException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "RenderingAPIException", inFile, inLine) {}
+	};
+	class _OgreExport RuntimeAssertionException : public Exception
+	{
+	public:
+		RuntimeAssertionException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception(inNumber, inDescription, inSource, "RuntimeAssertionException", inFile, inLine) {}
+	};
+
+
+	/** Class implementing dispatch methods in order to construct by-value
+		exceptions of a derived type based just on an exception code.
+	@remarks
+		This nicely handles construction of derived Exceptions by value (needed
+		for throwing) without suffering from ambiguity - each code is turned into
+		a distinct type so that methods can be overloaded. This allows OGRE_EXCEPT
+		to stay small in implementation (desirable since it is embedded) whilst
+		still performing rich code-to-type mapping. 
+	*/
+	class ExceptionFactory
+	{
+	private:
+		/// Private constructor, no construction
+		ExceptionFactory() {}
+	public:
+		static UnimplementedException create(
+			ExceptionCodeType<Exception::ERR_NOT_IMPLEMENTED> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return UnimplementedException(code.number, desc, src, file, line);
+		}
+		static FileNotFoundException create(
+			ExceptionCodeType<Exception::ERR_FILE_NOT_FOUND> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return FileNotFoundException(code.number, desc, src, file, line);
+		}
+		static IOException create(
+			ExceptionCodeType<Exception::ERR_CANNOT_WRITE_TO_FILE> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return IOException(code.number, desc, src, file, line);
+		}
+		static InvalidStateException create(
+			ExceptionCodeType<Exception::ERR_INVALID_STATE> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return InvalidStateException(code.number, desc, src, file, line);
+		}
+		static InvalidParametersException create(
+			ExceptionCodeType<Exception::ERR_INVALIDPARAMS> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return InvalidParametersException(code.number, desc, src, file, line);
+		}
+		static ItemIdentityException create(
+			ExceptionCodeType<Exception::ERR_ITEM_NOT_FOUND> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return ItemIdentityException(code.number, desc, src, file, line);
+		}
+		static ItemIdentityException create(
+			ExceptionCodeType<Exception::ERR_DUPLICATE_ITEM> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return ItemIdentityException(code.number, desc, src, file, line);
+		}
+		static InternalErrorException create(
+			ExceptionCodeType<Exception::ERR_INTERNAL_ERROR> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return InternalErrorException(code.number, desc, src, file, line);
+		}
+		static RenderingAPIException create(
+			ExceptionCodeType<Exception::ERR_RENDERINGAPI_ERROR> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return RenderingAPIException(code.number, desc, src, file, line);
+		}
+		static RuntimeAssertionException create(
+			ExceptionCodeType<Exception::ERR_RT_ASSERTION_FAILED> code, 
+			const String& desc, 
+			const String& src, const char* file, long line)
+		{
+			return RuntimeAssertionException(code.number, desc, src, file, line);
+		}
+
+	};
+	
+
+	
+#ifndef OGRE_EXCEPT
+#define OGRE_EXCEPT(num, desc, src) throw Ogre::ExceptionFactory::create( \
+	Ogre::ExceptionCodeType<num>(), desc, src, __FILE__, __LINE__ );
+#endif
+	/** @} */
+	/** @} */
+
+} // Namespace Ogre
+
+#include "OgreHeaderSuffix.h"
+#endif

+ 1282 - 0
CamelotRenderer/OgreFrustum.cpp

@@ -0,0 +1,1282 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreFrustum.h"
+
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreSphere.h"
+#include "OgreException.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+
+namespace Ogre {
+
+    String Frustum::msMovableType = "Frustum";
+    const Real Frustum::INFINITE_FAR_PLANE_ADJUST = 0.00001;
+    //-----------------------------------------------------------------------
+    Frustum::Frustum(const String& name) : 
+        mProjType(PT_PERSPECTIVE), 
+        mFOVy(Radian(Math::PI/4.0f)), 
+        mFarDist(100000.0f), 
+        mNearDist(100.0f), 
+        mAspect(1.33333333333333f), 
+		mOrthoHeight(1000),
+        mFrustumOffset(Vector2::ZERO),
+        mFocalLength(1.0f),
+        mLastParentOrientation(Quaternion::IDENTITY),
+        mLastParentPosition(Vector3::ZERO),
+        mRecalcFrustum(true), 
+        mRecalcView(true), 
+        mRecalcFrustumPlanes(true),
+        mRecalcWorldSpaceCorners(true),
+        mRecalcVertexData(true),
+		mCustomViewMatrix(false),
+		mCustomProjMatrix(false),
+		mFrustumExtentsManuallySet(false),
+        mOrientationMode(OR_DEGREE_0),
+        mReflect(false), 
+        mLinkedReflectPlane(0),
+        mObliqueDepthProjection(false), 
+        mLinkedObliqueProjPlane(0)
+    {
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        mLastLinkedObliqueProjPlane.normal = Vector3::ZERO;
+
+        updateView();
+        updateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Frustum::~Frustum()
+    {
+        // Do nothing
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFOVy(const Radian& fov)
+    {
+        mFOVy = fov;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const Radian& Frustum::getFOVy(void) const
+    {
+        return mFOVy;
+    }
+
+
+    //-----------------------------------------------------------------------
+    void Frustum::setFarClipDistance(Real farPlane)
+    {
+        mFarDist = farPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getFarClipDistance(void) const
+    {
+        return mFarDist;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setNearClipDistance(Real nearPlane)
+    {
+        if (nearPlane <= 0)
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.",
+                "Frustum::setNearClipDistance");
+        mNearDist = nearPlane;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getNearClipDistance(void) const
+    {
+        return mNearDist;
+    }
+
+    //---------------------------------------------------------------------
+    void Frustum::setFrustumOffset(const Vector2& offset)
+    {
+        mFrustumOffset = offset;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::setFrustumOffset(Real horizontal, Real vertical)
+    {
+        setFrustumOffset(Vector2(horizontal, vertical));
+    }
+    //---------------------------------------------------------------------
+    const Vector2& Frustum::getFrustumOffset() const
+    {
+        return mFrustumOffset;
+    }
+    //---------------------------------------------------------------------
+    void Frustum::setFocalLength(Real focalLength)
+    {
+        if (focalLength <= 0)
+        {
+            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+                "Focal length must be greater than zero.",
+                "Frustum::setFocalLength");
+        }
+
+        mFocalLength = focalLength;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    Real Frustum::getFocalLength() const
+    {
+        return mFocalLength;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrix(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrix;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrixWithRSDepth(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrixRSDepth;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getProjectionMatrixRS(void) const
+    {
+
+        updateFrustum();
+
+        return mProjMatrixRS;
+    }
+    //-----------------------------------------------------------------------
+    const Matrix4& Frustum::getViewMatrix(void) const
+    {
+        updateView();
+
+        return mViewMatrix;
+
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane* Frustum::getFrustumPlanes(void) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        return mFrustumPlanes;
+    }
+
+    //-----------------------------------------------------------------------
+    const Plane& Frustum::getFrustumPlane(unsigned short plane) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        return mFrustumPlanes[plane];
+
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
+    {
+        // Null boxes always invisible
+        if (bound.isNull()) return false;
+
+        // Infinite boxes always visible
+        if (bound.isInfinite()) return true;
+
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        // Get centre of the box
+        Vector3 centre = bound.getCenter();
+        // Get the half-size of the box
+        Vector3 halfSize = bound.getHalfSize();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
+                continue;
+
+            Plane::Side side = mFrustumPlanes[plane].getSide(centre, halfSize);
+            if (side == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        // For each plane, see if all points are on the negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
+                continue;
+
+            if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE)
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    bool Frustum::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const
+    {
+        // Make any pending updates to the calculated frustum planes
+        updateFrustumPlanes();
+
+        // For each plane, see if sphere is on negative side
+        // If so, object is not visible
+        for (int plane = 0; plane < 6; ++plane)
+        {
+            // Skip far plane if infinite view frustum
+            if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
+                continue;
+
+            // If the distance from sphere center to plane is negative, and 'more negative' 
+            // than the radius of the sphere, sphere is outside frustum
+            if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius())
+            {
+                // ALL corners on negative side therefore out of view
+                if (culledBy)
+                    *culledBy = (FrustumPlane)plane;
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const
+    { 
+		if (mCustomProjMatrix)
+		{
+			// Convert clipspace corners to camera space
+			Matrix4 invProj = mProjMatrix.inverse();
+			Vector3 topLeft(-0.5f, 0.5f, 0.0f);
+			Vector3 bottomRight(0.5f, -0.5f, 0.0f);
+
+			topLeft = invProj * topLeft;
+			bottomRight = invProj * bottomRight;
+
+			left = topLeft.x;
+			top = topLeft.y;
+			right = bottomRight.x;
+			bottom = bottomRight.y;
+
+		}
+		else
+		{
+			if (mFrustumExtentsManuallySet)
+			{
+				left = mLeft;
+				right = mRight;
+				top = mTop;
+				bottom = mBottom;
+			}
+			// Calculate general projection parameters
+			else if (mProjType == PT_PERSPECTIVE)
+			{
+				Radian thetaY (mFOVy * 0.5f);
+				Real tanThetaY = Math::Tan(thetaY);
+				Real tanThetaX = tanThetaY * mAspect;
+
+				Real nearFocal = mNearDist / mFocalLength;
+				Real nearOffsetX = mFrustumOffset.x * nearFocal;
+				Real nearOffsetY = mFrustumOffset.y * nearFocal;
+				Real half_w = tanThetaX * mNearDist;
+				Real half_h = tanThetaY * mNearDist;
+
+				left   = - half_w + nearOffsetX;
+				right  = + half_w + nearOffsetX;
+				bottom = - half_h + nearOffsetY;
+				top    = + half_h + nearOffsetY;
+
+				mLeft = left;
+				mRight = right;
+				mTop = top;
+				mBottom = bottom;
+			}
+			else
+			{
+				// Unknown how to apply frustum offset to orthographic camera, just ignore here
+				Real half_w = getOrthoWindowWidth() * 0.5f;
+				Real half_h = getOrthoWindowHeight() * 0.5f;
+
+				left   = - half_w;
+				right  = + half_w;
+				bottom = - half_h;
+				top    = + half_h;
+
+				mLeft = left;
+				mRight = right;
+				mTop = top;
+				mBottom = bottom;
+			}
+
+		}
+    }
+	//-----------------------------------------------------------------------
+	void Frustum::updateFrustumImpl(void) const
+	{
+		// Common calcs
+		Real left, right, bottom, top;
+
+#if OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
+        if (mOrientationMode != OR_PORTRAIT)
+            calcProjectionParameters(bottom, top, left, right);
+        else
+#endif
+            calcProjectionParameters(left, right, bottom, top);
+
+		if (!mCustomProjMatrix)
+		{
+
+			// The code below will dealing with general projection 
+			// parameters, similar glFrustum and glOrtho.
+			// Doesn't optimise manually except division operator, so the 
+			// code more self-explaining.
+
+			Real inv_w = 1 / (right - left);
+			Real inv_h = 1 / (top - bottom);
+			Real inv_d = 1 / (mFarDist - mNearDist);
+
+			// Recalc if frustum params changed
+			if (mProjType == PT_PERSPECTIVE)
+			{
+				// Calc matrix elements
+				Real A = 2 * mNearDist * inv_w;
+				Real B = 2 * mNearDist * inv_h;
+				Real C = (right + left) * inv_w;
+				Real D = (top + bottom) * inv_h;
+				Real q, qn;
+				if (mFarDist == 0)
+				{
+					// Infinite far plane
+					q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+					qn = mNearDist * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
+				}
+				else
+				{
+					q = - (mFarDist + mNearDist) * inv_d;
+					qn = -2 * (mFarDist * mNearDist) * inv_d;
+				}
+
+				// NB: This creates 'uniform' perspective projection matrix,
+				// which depth range [-1,1], right-handed rules
+				//
+				// [ A   0   C   0  ]
+				// [ 0   B   D   0  ]
+				// [ 0   0   q   qn ]
+				// [ 0   0   -1  0  ]
+				//
+				// A = 2 * near / (right - left)
+				// B = 2 * near / (top - bottom)
+				// C = (right + left) / (right - left)
+				// D = (top + bottom) / (top - bottom)
+				// q = - (far + near) / (far - near)
+				// qn = - 2 * (far * near) / (far - near)
+
+				mProjMatrix = Matrix4::ZERO;
+				mProjMatrix[0][0] = A;
+				mProjMatrix[0][2] = C;
+				mProjMatrix[1][1] = B;
+				mProjMatrix[1][2] = D;
+				mProjMatrix[2][2] = q;
+				mProjMatrix[2][3] = qn;
+				mProjMatrix[3][2] = -1;
+
+				if (mObliqueDepthProjection)
+				{
+					// Translate the plane into view space
+
+					// Don't use getViewMatrix here, incase overrided by 
+					// camera and return a cull frustum view matrix
+					updateView();
+					Plane plane = mViewMatrix * mObliqueProjPlane;
+
+					// Thanks to Eric Lenyel for posting this calculation 
+					// at www.terathon.com
+
+					// Calculate the clip-space corner point opposite the 
+					// clipping plane
+					// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
+					// transform it into camera space by multiplying it
+					// by the inverse of the projection matrix
+
+					/* generalised version
+					Vector4 q = matrix.inverse() * 
+					Vector4(Math::Sign(plane.normal.x), 
+					Math::Sign(plane.normal.y), 1.0f, 1.0f);
+					*/
+					Vector4 qVec;
+					qVec.x = (Math::Sign(plane.normal.x) + mProjMatrix[0][2]) / mProjMatrix[0][0];
+					qVec.y = (Math::Sign(plane.normal.y) + mProjMatrix[1][2]) / mProjMatrix[1][1];
+					qVec.z = -1;
+					qVec.w = (1 + mProjMatrix[2][2]) / mProjMatrix[2][3];
+
+					// Calculate the scaled plane vector
+					Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
+					Vector4 c = clipPlane4d * (2 / (clipPlane4d.dotProduct(qVec)));
+
+					// Replace the third row of the projection matrix
+					mProjMatrix[2][0] = c.x;
+					mProjMatrix[2][1] = c.y;
+					mProjMatrix[2][2] = c.z + 1;
+					mProjMatrix[2][3] = c.w; 
+				}
+			} // perspective
+			else if (mProjType == PT_ORTHOGRAPHIC)
+			{
+				Real A = 2 * inv_w;
+				Real B = 2 * inv_h;
+				Real C = - (right + left) * inv_w;
+				Real D = - (top + bottom) * inv_h;
+				Real q, qn;
+				if (mFarDist == 0)
+				{
+					// Can not do infinite far plane here, avoid divided zero only
+					q = - Frustum::INFINITE_FAR_PLANE_ADJUST / mNearDist;
+					qn = - Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
+				}
+				else
+				{
+					q = - 2 * inv_d;
+					qn = - (mFarDist + mNearDist)  * inv_d;
+				}
+
+				// NB: This creates 'uniform' orthographic projection matrix,
+				// which depth range [-1,1], right-handed rules
+				//
+				// [ A   0   0   C  ]
+				// [ 0   B   0   D  ]
+				// [ 0   0   q   qn ]
+				// [ 0   0   0   1  ]
+				//
+				// A = 2 * / (right - left)
+				// B = 2 * / (top - bottom)
+				// C = - (right + left) / (right - left)
+				// D = - (top + bottom) / (top - bottom)
+				// q = - 2 / (far - near)
+				// qn = - (far + near) / (far - near)
+
+				mProjMatrix = Matrix4::ZERO;
+				mProjMatrix[0][0] = A;
+				mProjMatrix[0][3] = C;
+				mProjMatrix[1][1] = B;
+				mProjMatrix[1][3] = D;
+				mProjMatrix[2][2] = q;
+				mProjMatrix[2][3] = qn;
+				mProjMatrix[3][3] = 1;
+			} // ortho            
+		} // !mCustomProjMatrix
+
+#if OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
+        // Deal with orientation mode
+        mProjMatrix = mProjMatrix * Quaternion(Degree(mOrientationMode * 90.f), Vector3::UNIT_Z);
+#endif
+
+		// TODO PORT - IMPORTANT - After I have render system ported make sure to enable this
+		//RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
+		//// API specific
+		//renderSystem->_convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
+		//// API specific for Gpu Programs
+		//renderSystem->_convertProjectionMatrix(mProjMatrix, mProjMatrixRSDepth, true);
+
+
+		// Calculate bounding box (local)
+		// Box is from 0, down -Z, max dimensions as determined from far plane
+		// If infinite view frustum just pick a far value
+		Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+		// Near plane bounds
+		Vector3 min(left, bottom, -farDist);
+		Vector3 max(right, top, 0);
+
+		if (mCustomProjMatrix)
+		{
+			// Some custom projection matrices can have unusual inverted settings
+			// So make sure the AABB is the right way around to start with
+			Vector3 tmp = min;
+			min.makeFloor(max);
+			max.makeCeil(tmp);
+		}
+
+		if (mProjType == PT_PERSPECTIVE)
+		{
+			// Merge with far plane bounds
+			Real radio = farDist / mNearDist;
+			min.makeFloor(Vector3(left * radio, bottom * radio, -farDist));
+			max.makeCeil(Vector3(right * radio, top * radio, 0));
+		}
+		mBoundingBox.setExtents(min, max);
+
+		mRecalcFrustum = false;
+
+		// Signal to update frustum clipping planes
+		mRecalcFrustumPlanes = true;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustum(void) const
+    {
+        if (isFrustumOutOfDate())
+        {
+			updateFrustumImpl();
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::updateVertexData(void) const
+    {
+        if (mRecalcVertexData)
+        {
+            if (mVertexData.vertexBufferBinding->getBufferCount() <= 0)
+            {
+                // Initialise vertex & index data
+                mVertexData.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
+                mVertexData.vertexCount = 32;
+                mVertexData.vertexStart = 0;
+                mVertexData.vertexBufferBinding->setBinding( 0,
+                    HardwareBufferManager::getSingleton().createVertexBuffer(
+                        sizeof(float)*3, 32, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY) );
+            }
+
+            // Note: Even though we can dealing with general projection matrix here,
+            //       but because it's incompatibly with infinite far plane, thus, we
+            //       still need to working with projection parameters.
+
+            // Calc near plane corners
+            Real vpLeft, vpRight, vpBottom, vpTop;
+            calcProjectionParameters(vpLeft, vpRight, vpBottom, vpTop);
+
+            // Treat infinite fardist as some arbitrary far value
+            Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+
+            // Calc far plane corners
+            Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
+            Real farLeft = vpLeft * radio;
+            Real farRight = vpRight * radio;
+            Real farBottom = vpBottom * radio;
+            Real farTop = vpTop * radio;
+
+            // Calculate vertex positions (local)
+            // 0 is the origin
+            // 1, 2, 3, 4 are the points on the near plane, top left first, clockwise
+            // 5, 6, 7, 8 are the points on the far plane, top left first, clockwise
+            HardwareVertexBufferSharedPtr vbuf = mVertexData.vertexBufferBinding->getBuffer(0);
+            float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
+
+            // near plane (remember frustum is going in -Z direction)
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            // far plane (remember frustum is going in -Z direction)
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            // Sides of the pyramid
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            *pFloat++ = 0.0f;    *pFloat++ = 0.0f;   *pFloat++ = 0.0f;
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+
+            // Sides of the box
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpTop;  *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farTop;  *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpTop;    *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farTop;    *pFloat++ = -farDist;
+
+            *pFloat++ = vpRight; *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farRight; *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+            *pFloat++ = vpLeft;  *pFloat++ = vpBottom; *pFloat++ = -mNearDist;
+            *pFloat++ = farLeft;  *pFloat++ = farBottom; *pFloat++ = -farDist;
+
+
+            vbuf->unlock();
+
+            mRecalcVertexData = false;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isViewOutOfDate(void) const
+    {
+        // Attached to node?
+		// TODO PORT - Not attached to node because I'll be handling this differently
+        //if (mParentNode)
+        //{
+        //    if (mRecalcView ||
+        //        mParentNode->_getDerivedOrientation() != mLastParentOrientation ||
+        //        mParentNode->_getDerivedPosition() != mLastParentPosition)
+        //    {
+        //        // Ok, we're out of date with SceneNode we're attached to
+        //        mLastParentOrientation = mParentNode->_getDerivedOrientation();
+        //        mLastParentPosition = mParentNode->_getDerivedPosition();
+        //        mRecalcView = true;
+        //    }
+        //}
+        // Deriving reflection from linked plane?
+        if (mLinkedReflectPlane && 
+            !(mLastLinkedReflectionPlane == *mLinkedReflectPlane))
+        {
+            mReflectPlane = *mLinkedReflectPlane;
+            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+            mLastLinkedReflectionPlane = *mLinkedReflectPlane;
+            mRecalcView = true;
+        }
+
+        return mRecalcView;
+    }
+
+    //-----------------------------------------------------------------------
+    bool Frustum::isFrustumOutOfDate(void) const
+    {
+        // Deriving custom near plane from linked plane?
+        if (mObliqueDepthProjection)
+        {
+            // Out of date when view out of data since plane needs to be in view space
+            if (isViewOutOfDate())
+            {
+                mRecalcFrustum = true;
+            }
+            // Update derived plane
+            if (mLinkedObliqueProjPlane && 
+                !(mLastLinkedObliqueProjPlane == *mLinkedObliqueProjPlane))
+            {
+                mObliqueProjPlane = *mLinkedObliqueProjPlane;
+                mLastLinkedObliqueProjPlane = mObliqueProjPlane;
+                mRecalcFrustum = true;
+            }
+        }
+
+        return mRecalcFrustum;
+    }
+
+    //-----------------------------------------------------------------------
+	void Frustum::updateViewImpl(void) const
+	{
+		// ----------------------
+		// Update the view matrix
+		// ----------------------
+
+		// Get orientation from quaternion
+
+		if (!mCustomViewMatrix)
+		{
+			Matrix3 rot;
+			const Quaternion& orientation = getOrientationForViewUpdate();
+			const Vector3& position = getPositionForViewUpdate();
+
+			mViewMatrix = Math::makeViewMatrix(position, orientation, mReflect? &mReflectMatrix : 0);
+		}
+
+		mRecalcView = false;
+
+		// Signal to update frustum clipping planes
+		mRecalcFrustumPlanes = true;
+		// Signal to update world space corners
+		mRecalcWorldSpaceCorners = true;
+		// Signal to update frustum if oblique plane enabled,
+		// since plane needs to be in view space
+		if (mObliqueDepthProjection)
+		{
+			mRecalcFrustum = true;
+		}
+	}
+	//---------------------------------------------------------------------
+	void Frustum::calcViewMatrixRelative(const Vector3& relPos, Matrix4& matToUpdate) const
+	{
+		Matrix4 matTrans = Matrix4::IDENTITY;
+		matTrans.setTrans(relPos);
+		matToUpdate = getViewMatrix() * matTrans;
+
+	}
+	//-----------------------------------------------------------------------
+    void Frustum::updateView(void) const
+    {
+        if (isViewOutOfDate())
+        {
+			updateViewImpl();
+        }
+    }
+
+	//-----------------------------------------------------------------------
+	void Frustum::updateFrustumPlanesImpl(void) const
+	{
+		// -------------------------
+		// Update the frustum planes
+		// -------------------------
+		Matrix4 combo = mProjMatrix * mViewMatrix;
+
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
+		mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
+		mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
+		mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
+		mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
+		mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
+
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
+		mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
+
+		// Renormalise any normals which were not unit length
+		for(int i=0; i<6; i++ ) 
+		{
+			Real length = mFrustumPlanes[i].normal.normalise();
+			mFrustumPlanes[i].d /= length;
+		}
+
+		mRecalcFrustumPlanes = false;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateFrustumPlanes(void) const
+    {
+        updateView();
+        updateFrustum();
+
+        if (mRecalcFrustumPlanes)
+        {
+			updateFrustumPlanesImpl();
+        }
+    }
+	//-----------------------------------------------------------------------
+	void Frustum::updateWorldSpaceCornersImpl(void) const
+	{
+		Matrix4 eyeToWorld = mViewMatrix.inverseAffine();
+
+		// Note: Even though we can dealing with general projection matrix here,
+		//       but because it's incompatibly with infinite far plane, thus, we
+		//       still need to working with projection parameters.
+
+		// Calc near plane corners
+		Real nearLeft, nearRight, nearBottom, nearTop;
+		calcProjectionParameters(nearLeft, nearRight, nearBottom, nearTop);
+
+		// Treat infinite fardist as some arbitrary far value
+		Real farDist = (mFarDist == 0) ? 100000 : mFarDist;
+
+		// Calc far palne corners
+		Real radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
+		Real farLeft = nearLeft * radio;
+		Real farRight = nearRight * radio;
+		Real farBottom = nearBottom * radio;
+		Real farTop = nearTop * radio;
+
+		// near
+		mWorldSpaceCorners[0] = eyeToWorld.transformAffine(Vector3(nearRight, nearTop,    -mNearDist));
+		mWorldSpaceCorners[1] = eyeToWorld.transformAffine(Vector3(nearLeft,  nearTop,    -mNearDist));
+		mWorldSpaceCorners[2] = eyeToWorld.transformAffine(Vector3(nearLeft,  nearBottom, -mNearDist));
+		mWorldSpaceCorners[3] = eyeToWorld.transformAffine(Vector3(nearRight, nearBottom, -mNearDist));
+		// far
+		mWorldSpaceCorners[4] = eyeToWorld.transformAffine(Vector3(farRight,  farTop,     -farDist));
+		mWorldSpaceCorners[5] = eyeToWorld.transformAffine(Vector3(farLeft,   farTop,     -farDist));
+		mWorldSpaceCorners[6] = eyeToWorld.transformAffine(Vector3(farLeft,   farBottom,  -farDist));
+		mWorldSpaceCorners[7] = eyeToWorld.transformAffine(Vector3(farRight,  farBottom,  -farDist));
+
+
+		mRecalcWorldSpaceCorners = false;
+	}
+    //-----------------------------------------------------------------------
+    void Frustum::updateWorldSpaceCorners(void) const
+    {
+        updateView();
+
+        if (mRecalcWorldSpaceCorners)
+        {
+			updateWorldSpaceCornersImpl();
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    Real Frustum::getAspectRatio(void) const
+    {
+        return mAspect;
+    }
+
+    //-----------------------------------------------------------------------
+    void Frustum::setAspectRatio(Real r)
+    {
+        mAspect = r;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    const AxisAlignedBox& Frustum::getBoundingBox(void) const
+    {
+        return mBoundingBox;
+    }
+    //-----------------------------------------------------------------------
+    const String& Frustum::getMovableType(void) const
+    {
+        return msMovableType;
+    }
+    //-----------------------------------------------------------------------
+	Real Frustum::getBoundingRadius(void) const
+	{
+        return (mFarDist == 0)? 100000 : mFarDist;
+	}
+    // -------------------------------------------------------------------
+    void Frustum::invalidateFrustum() const
+    {
+        mRecalcFrustum = true;
+        mRecalcFrustumPlanes = true;
+        mRecalcWorldSpaceCorners = true;
+        mRecalcVertexData = true;
+    }
+    // -------------------------------------------------------------------
+    void Frustum::invalidateView() const
+    {
+        mRecalcView = true;
+        mRecalcFrustumPlanes = true;
+        mRecalcWorldSpaceCorners = true;
+    }
+    // -------------------------------------------------------------------
+    const Vector3* Frustum::getWorldSpaceCorners(void) const
+    {
+        updateWorldSpaceCorners();
+
+        return mWorldSpaceCorners;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::setProjectionType(ProjectionType pt)
+    {
+        mProjType = pt;
+        invalidateFrustum();
+    }
+
+    //-----------------------------------------------------------------------
+    ProjectionType Frustum::getProjectionType(void) const
+    {
+        return mProjType;
+    }
+    //-----------------------------------------------------------------------
+    const Vector3& Frustum::getPositionForViewUpdate(void) const
+    {
+        return mLastParentPosition;
+    }
+    //-----------------------------------------------------------------------
+    const Quaternion& Frustum::getOrientationForViewUpdate(void) const
+    {
+        return mLastParentOrientation;
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const Plane& p)
+    {
+        mReflect = true;
+        mReflectPlane = p;
+        mLinkedReflectPlane = 0;
+        mReflectMatrix = Math::buildReflectionMatrix(p);
+        invalidateView();
+
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::enableReflection(const Plane* p)
+    {
+        mReflect = true;
+        mLinkedReflectPlane = p;
+        mReflectPlane = *mLinkedReflectPlane;
+        mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
+        mLastLinkedReflectionPlane = *mLinkedReflectPlane;
+        invalidateView();
+    }
+    //-----------------------------------------------------------------------
+    void Frustum::disableReflection(void)
+    {
+        mReflect = false;
+        mLinkedReflectPlane = 0;
+        mLastLinkedReflectionPlane.normal = Vector3::ZERO;
+        invalidateView();
+    }
+    //---------------------------------------------------------------------
+    bool Frustum::projectSphere(const Sphere& sphere, 
+        Real* left, Real* top, Real* right, Real* bottom) const
+    {
+		// See http://www.gamasutra.com/features/20021011/lengyel_06.htm
+        // Transform light position into camera space
+
+        updateView();
+        Vector3 eyeSpacePos = mViewMatrix.transformAffine(sphere.getCenter());
+
+		// initialise
+		*left = *bottom = -1.0f;
+		*right = *top = 1.0f;
+
+        if (eyeSpacePos.z < 0)
+        {
+			updateFrustum();
+			const Matrix4& projMatrix = getProjectionMatrix();
+            Real r = sphere.getRadius();
+			Real rsq = r * r;
+
+            // early-exit
+            if (eyeSpacePos.squaredLength() <= rsq)
+                return false;
+
+			Real Lxz = Math::Sqr(eyeSpacePos.x) + Math::Sqr(eyeSpacePos.z);
+			Real Lyz = Math::Sqr(eyeSpacePos.y) + Math::Sqr(eyeSpacePos.z);
+
+			// Find the tangent planes to the sphere
+			// XZ first
+			// calculate quadratic discriminant: b*b - 4ac
+			// x = Nx
+			// a = Lx^2 + Lz^2
+			// b = -2rLx
+			// c = r^2 - Lz^2
+			Real a = Lxz;
+			Real b = -2.0f * r * eyeSpacePos.x;
+			Real c = rsq - Math::Sqr(eyeSpacePos.z);
+			Real D = b*b - 4.0f*a*c;
+
+			// two roots?
+			if (D > 0)
+			{
+				Real sqrootD = Math::Sqrt(D);
+				// solve the quadratic to get the components of the normal
+				Real Nx0 = (-b + sqrootD) / (2 * a);
+				Real Nx1 = (-b - sqrootD) / (2 * a);
+				
+				// Derive Z from this
+				Real Nz0 = (r - Nx0 * eyeSpacePos.x) / eyeSpacePos.z;
+				Real Nz1 = (r - Nx1 * eyeSpacePos.x) / eyeSpacePos.z;
+
+				// Get the point of tangency
+				// Only consider points of tangency in front of the camera
+				Real Pz0 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz0 / Nx0) * eyeSpacePos.x));
+				if (Pz0 < 0)
+				{
+					// Project point onto near plane in worldspace
+					Real nearx0 = (Nz0 * mNearDist) / Nx0;
+					// now we need to map this to viewport coords
+					// use projection matrix since that will take into account all factors
+					Vector3 relx0 = projMatrix * Vector3(nearx0, 0, -mNearDist);
+
+					// find out whether this is a left side or right side
+					Real Px0 = -(Pz0 * Nz0) / Nx0;
+					if (Px0 > eyeSpacePos.x)
+					{
+						*right = std::min(*right, relx0.x);
+					}
+					else
+					{
+						*left = std::max(*left, relx0.x);
+					}
+				}
+				Real Pz1 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz1 / Nx1) * eyeSpacePos.x));
+				if (Pz1 < 0)
+				{
+					// Project point onto near plane in worldspace
+					Real nearx1 = (Nz1 * mNearDist) / Nx1;
+					// now we need to map this to viewport coords
+					// use projection matrix since that will take into account all factors
+					Vector3 relx1 = projMatrix * Vector3(nearx1, 0, -mNearDist);
+
+					// find out whether this is a left side or right side
+					Real Px1 = -(Pz1 * Nz1) / Nx1;
+					if (Px1 > eyeSpacePos.x)
+					{
+						*right = std::min(*right, relx1.x);
+					}
+					else
+					{
+						*left = std::max(*left, relx1.x);
+					}
+				}
+			}
+
+
+			// Now YZ 
+			// calculate quadratic discriminant: b*b - 4ac
+			// x = Ny
+			// a = Ly^2 + Lz^2
+			// b = -2rLy
+			// c = r^2 - Lz^2
+			a = Lyz;
+			b = -2.0f * r * eyeSpacePos.y;
+			c = rsq - Math::Sqr(eyeSpacePos.z);
+			D = b*b - 4.0f*a*c;
+
+			// two roots?
+			if (D > 0)
+			{
+				Real sqrootD = Math::Sqrt(D);
+				// solve the quadratic to get the components of the normal
+				Real Ny0 = (-b + sqrootD) / (2 * a);
+				Real Ny1 = (-b - sqrootD) / (2 * a);
+
+				// Derive Z from this
+				Real Nz0 = (r - Ny0 * eyeSpacePos.y) / eyeSpacePos.z;
+				Real Nz1 = (r - Ny1 * eyeSpacePos.y) / eyeSpacePos.z;
+
+				// Get the point of tangency
+				// Only consider points of tangency in front of the camera
+				Real Pz0 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz0 / Ny0) * eyeSpacePos.y));
+				if (Pz0 < 0)
+				{
+					// Project point onto near plane in worldspace
+					Real neary0 = (Nz0 * mNearDist) / Ny0;
+					// now we need to map this to viewport coords
+					// use projection matriy since that will take into account all factors
+					Vector3 rely0 = projMatrix * Vector3(0, neary0, -mNearDist);
+
+					// find out whether this is a top side or bottom side
+					Real Py0 = -(Pz0 * Nz0) / Ny0;
+					if (Py0 > eyeSpacePos.y)
+					{
+						*top = std::min(*top, rely0.y);
+					}
+					else
+					{
+						*bottom = std::max(*bottom, rely0.y);
+					}
+				}
+				Real Pz1 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz1 / Ny1) * eyeSpacePos.y));
+				if (Pz1 < 0)
+				{
+					// Project point onto near plane in worldspace
+					Real neary1 = (Nz1 * mNearDist) / Ny1;
+					// now we need to map this to viewport coords
+					// use projection matriy since that will take into account all factors
+					Vector3 rely1 = projMatrix * Vector3(0, neary1, -mNearDist);
+
+					// find out whether this is a top side or bottom side
+					Real Py1 = -(Pz1 * Nz1) / Ny1;
+					if (Py1 > eyeSpacePos.y)
+					{
+						*top = std::min(*top, rely1.y);
+					}
+					else
+					{
+						*bottom = std::max(*bottom, rely1.y);
+					}
+				}
+			}
+        }
+
+        return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f);
+
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const Plane* plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = plane;
+        mObliqueProjPlane = *plane;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::enableCustomNearClipPlane(const Plane& plane)
+    {
+        mObliqueDepthProjection = true;
+        mLinkedObliqueProjPlane = 0;
+        mObliqueProjPlane = plane;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    void Frustum::disableCustomNearClipPlane(void)
+    {
+        mObliqueDepthProjection = false;
+        mLinkedObliqueProjPlane = 0;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+	void Frustum::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
+	{
+		mCustomViewMatrix = enable;
+		if (enable)
+		{
+            assert(viewMatrix.isAffine());
+			mViewMatrix = viewMatrix;
+		}
+		invalidateView();
+	}
+    //---------------------------------------------------------------------
+	void Frustum::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
+	{
+		mCustomProjMatrix = enable;
+		if (enable)
+		{
+			mProjMatrix = projMatrix;
+		}
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	void Frustum::setOrthoWindow(Real w, Real h)
+	{
+		mOrthoHeight = h;
+		mAspect = w / h;
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	void Frustum::setOrthoWindowHeight(Real h)
+	{
+		mOrthoHeight = h;
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	void Frustum::setOrthoWindowWidth(Real w)
+	{
+		mOrthoHeight = w / mAspect;
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	Real Frustum::getOrthoWindowHeight() const
+	{
+		return mOrthoHeight;
+	}
+	//---------------------------------------------------------------------
+	Real Frustum::getOrthoWindowWidth() const
+	{
+		return mOrthoHeight * mAspect;	
+	}
+	//---------------------------------------------------------------------
+	void Frustum::setFrustumExtents(Real left, Real right, Real top, Real bottom)
+	{
+		mFrustumExtentsManuallySet = true;
+		mLeft = left;
+		mRight = right;
+		mTop = top;
+		mBottom = bottom;
+
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	void Frustum::resetFrustumExtents()
+	{
+		mFrustumExtentsManuallySet = false;
+		invalidateFrustum();
+	}
+	//---------------------------------------------------------------------
+	void Frustum::getFrustumExtents(Real& outleft, Real& outright, Real& outtop, Real& outbottom) const
+	{
+		updateFrustum();
+		outleft = mLeft;
+		outright = mRight;
+		outtop = mTop;
+		outbottom = mBottom;
+	}
+    //---------------------------------------------------------------------
+    void Frustum::setOrientationMode(OrientationMode orientationMode)
+    {
+#if OGRE_NO_VIEWPORT_ORIENTATIONMODE != 0
+        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
+                    "Setting Frustrum orientation mode is not supported",
+                    __FUNCTION__);
+#endif
+        mOrientationMode = orientationMode;
+        invalidateFrustum();
+    }
+    //---------------------------------------------------------------------
+    OrientationMode Frustum::getOrientationMode() const
+    {
+#if OGRE_NO_VIEWPORT_ORIENTATIONMODE != 0
+        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
+                    "Getting Frustrum orientation mode is not supported",
+                    __FUNCTION__);
+#endif
+        return mOrientationMode;
+    }
+
+
+} // namespace Ogre

+ 640 - 0
CamelotRenderer/OgreFrustum.h

@@ -0,0 +1,640 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Frustum_H__
+#define __Frustum_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreVector2.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreVertexIndexData.h"
+#include "OgreString.h"
+
+namespace Ogre
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+    /** Specifies orientation mode.
+    */
+    enum OrientationMode
+    {
+        OR_DEGREE_0       = 0,
+        OR_DEGREE_90      = 1,
+        OR_DEGREE_180     = 2,
+        OR_DEGREE_270     = 3,
+
+        OR_PORTRAIT       = OR_DEGREE_0,
+        OR_LANDSCAPERIGHT = OR_DEGREE_90,
+        OR_LANDSCAPELEFT  = OR_DEGREE_270
+    };
+
+	/** Specifies perspective (realistic) or orthographic (architectural) projection.
+    */
+    enum ProjectionType
+    {
+        PT_ORTHOGRAPHIC,
+        PT_PERSPECTIVE
+    };
+
+    /** Worldspace clipping planes.
+    */
+    enum FrustumPlane
+    {
+        FRUSTUM_PLANE_NEAR   = 0,
+        FRUSTUM_PLANE_FAR    = 1,
+        FRUSTUM_PLANE_LEFT   = 2,
+        FRUSTUM_PLANE_RIGHT  = 3,
+        FRUSTUM_PLANE_TOP    = 4,
+        FRUSTUM_PLANE_BOTTOM = 5
+    };
+
+    /** A frustum represents a pyramid, capped at the near and far end which is
+        used to represent either a visible area or a projection area. Can be used
+        for a number of applications.
+    */
+    class _OgreExport Frustum
+    {
+    protected:
+        /// Orthographic or perspective?
+        ProjectionType mProjType;
+
+        /// y-direction field-of-view (default 45)
+        Radian mFOVy;
+        /// Far clip distance - default 10000
+        Real mFarDist;
+        /// Near clip distance - default 100
+        Real mNearDist;
+        /// x/y viewport ratio - default 1.3333
+        Real mAspect;
+		/// Ortho height size (world units)
+		Real mOrthoHeight;
+        /// Off-axis frustum center offset - default (0.0, 0.0)
+        Vector2 mFrustumOffset;
+        /// Focal length of frustum (for stereo rendering, defaults to 1.0)
+        Real mFocalLength;
+
+        /// The 6 main clipping planes
+        mutable Plane mFrustumPlanes[6];
+
+        /// Stored versions of parent orientation / position
+        mutable Quaternion mLastParentOrientation;
+        mutable Vector3 mLastParentPosition;
+
+        /// Pre-calced projection matrix for the specific render system
+        mutable Matrix4 mProjMatrixRS;
+        /// Pre-calced standard projection matrix but with render system depth range
+        mutable Matrix4 mProjMatrixRSDepth;
+        /// Pre-calced standard projection matrix
+        mutable Matrix4 mProjMatrix;
+        /// Pre-calced view matrix
+        mutable Matrix4 mViewMatrix;
+        /// Something's changed in the frustum shape?
+        mutable bool mRecalcFrustum;
+        /// Something re the view pos has changed
+        mutable bool mRecalcView;
+        /// Something re the frustum planes has changed
+        mutable bool mRecalcFrustumPlanes;
+        /// Something re the world space corners has changed
+        mutable bool mRecalcWorldSpaceCorners;
+        /// Something re the vertex data has changed
+        mutable bool mRecalcVertexData;
+		/// Are we using a custom view matrix?
+		bool mCustomViewMatrix;
+		/// Are we using a custom projection matrix?
+		bool mCustomProjMatrix;
+		/// Have the frustum extents been manually set?
+		bool mFrustumExtentsManuallySet;
+		/// Frustum extents
+		mutable Real mLeft, mRight, mTop, mBottom;
+        /// Frustum orientation mode
+        mutable OrientationMode mOrientationMode;
+		
+        // Internal functions for calcs
+        virtual void calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const;
+		/// Update frustum if out of date
+        virtual void updateFrustum(void) const;
+		/// Update view if out of date
+        virtual void updateView(void) const;
+		/// Implementation of updateFrustum (called if out of date)
+		virtual void updateFrustumImpl(void) const;
+		/// Implementation of updateView (called if out of date)
+		virtual void updateViewImpl(void) const;
+        virtual void updateFrustumPlanes(void) const;
+		/// Implementation of updateFrustumPlanes (called if out of date)
+		virtual void updateFrustumPlanesImpl(void) const;
+        virtual void updateWorldSpaceCorners(void) const;
+		/// Implementation of updateWorldSpaceCorners (called if out of date)
+		virtual void updateWorldSpaceCornersImpl(void) const;
+        virtual void updateVertexData(void) const;
+        virtual bool isViewOutOfDate(void) const;
+        virtual bool isFrustumOutOfDate(void) const;
+        /// Signal to update frustum information.
+        virtual void invalidateFrustum(void) const;
+        /// Signal to update view information.
+        virtual void invalidateView(void) const;
+
+        /// Shared class-level name for Movable type
+        static String msMovableType;
+
+        mutable AxisAlignedBox mBoundingBox;
+        mutable VertexData mVertexData;
+
+        mutable Vector3 mWorldSpaceCorners[8];
+
+        /// Is this frustum to act as a reflection of itself?
+        bool mReflect;
+		/// Derived reflection matrix
+        mutable Matrix4 mReflectMatrix;
+        /// Fixed reflection plane
+		mutable Plane mReflectPlane;
+		/// Pointer to a reflection plane (automatically updated)
+		const Plane* mLinkedReflectPlane;
+		/// Record of the last world-space reflection plane info used
+		mutable Plane mLastLinkedReflectionPlane;
+		
+        /// Is this frustum using an oblique depth projection?
+		bool mObliqueDepthProjection;
+		/// Fixed oblique projection plane
+		mutable Plane mObliqueProjPlane;
+		/// Pointer to oblique projection plane (automatically updated)
+		const Plane* mLinkedObliqueProjPlane;
+		/// Record of the last world-space oblique depth projection plane info used
+		mutable Plane mLastLinkedObliqueProjPlane;
+
+    public:
+
+		/// Named constructor
+		Frustum(const String& name = StringUtil::BLANK);
+
+        virtual ~Frustum();
+        /** Sets the Y-dimension Field Of View (FOV) of the frustum.
+            @remarks
+                Field Of View (FOV) is the angle made between the frustum's position, and the edges
+                of the 'screen' onto which the scene is projected. High values (90+ degrees) result in a wide-angle,
+                fish-eye kind of view, low values (30- degrees) in a stretched, telescopic kind of view. Typical values
+                are between 45 and 60 degrees.
+            @par
+                This value represents the VERTICAL field-of-view. The horizontal field of view is calculated from
+                this depending on the dimensions of the viewport (they will only be the same if the viewport is square).
+            @note
+                Setting the FOV overrides the value supplied for frustum::setNearClipPlane.
+         */
+        virtual void setFOVy(const Radian& fovy);
+
+        /** Retrieves the frustums Y-dimension Field Of View (FOV).
+        */
+        virtual const Radian& getFOVy(void) const;
+
+        /** Sets the position of the near clipping plane.
+            @remarks
+                The position of the near clipping plane is the distance from the frustums position to the screen
+                on which the world is projected. The near plane distance, combined with the field-of-view and the
+                aspect ratio, determines the size of the viewport through which the world is viewed (in world
+                co-ordinates). Note that this world viewport is different to a screen viewport, which has it's
+                dimensions expressed in pixels. The frustums viewport should have the same aspect ratio as the
+                screen viewport it renders into to avoid distortion.
+            @param
+                near The distance to the near clipping plane from the frustum in world coordinates.
+         */
+        virtual void setNearClipDistance(Real nearDist);
+
+        /** Sets the position of the near clipping plane.
+        */
+        virtual Real getNearClipDistance(void) const;
+
+        /** Sets the distance to the far clipping plane.
+            @remarks
+                The view frustum is a pyramid created from the frustum position and the edges of the viewport.
+                This method sets the distance for the far end of that pyramid. 
+                Different applications need different values: e.g. a flight sim
+                needs a much further far clipping plane than a first-person 
+                shooter. An important point here is that the larger the ratio 
+                between near and far clipping planes, the lower the accuracy of
+                the Z-buffer used to depth-cue pixels. This is because the
+                Z-range is limited to the size of the Z buffer (16 or 32-bit) 
+                and the max values must be spread over the gap between near and
+                far clip planes. As it happens, you can affect the accuracy far 
+                more by altering the near distance rather than the far distance, 
+                but keep this in mind.
+            @param
+                far The distance to the far clipping plane from the frustum in 
+                world coordinates.If you specify 0, this means an infinite view
+                distance which is useful especially when projecting shadows; but
+                be careful not to use a near distance too close.
+        */
+        virtual void setFarClipDistance(Real farDist);
+
+        /** Retrieves the distance from the frustum to the far clipping plane.
+        */
+        virtual Real getFarClipDistance(void) const;
+
+        /** Sets the aspect ratio for the frustum viewport.
+            @remarks
+                The ratio between the x and y dimensions of the rectangular area visible through the frustum
+                is known as aspect ratio: aspect = width / height .
+            @par
+                The default for most fullscreen windows is 1.3333 - this is also assumed by Ogre unless you
+                use this method to state otherwise.
+        */
+        virtual void setAspectRatio(Real ratio);
+
+        /** Retreives the current aspect ratio.
+        */
+        virtual Real getAspectRatio(void) const;
+
+        /** Sets frustum offsets, used in stereo rendering.
+            @remarks
+                You can set both horizontal and vertical plane offsets of "eye"; in
+                stereo rendering frustum is moved in horizontal plane. To be able to
+                render from two "eyes" you'll need two cameras rendering on two
+                RenderTargets.
+            @par
+                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
+            @param
+                offset The horizontal and vertical plane offsets.
+        */
+        virtual void setFrustumOffset(const Vector2& offset);
+
+        /** Sets frustum offsets, used in stereo rendering.
+            @remarks
+                You can set both horizontal and vertical plane offsets of "eye"; in
+                stereo rendering frustum is moved in horizontal plane. To be able to
+                render from two "eyes" you'll need two cameras rendering on two
+                RenderTargets.
+            @par
+                The frustum offsets is in world coordinates, and default to (0, 0) - no offsets.
+            @param
+                horizontal The horizontal plane offset.
+            @param
+                vertical The vertical plane offset.
+        */
+        virtual void setFrustumOffset(Real horizontal = 0.0, Real vertical = 0.0);
+
+        /** Retrieves the frustum offsets.
+        */
+        virtual const Vector2& getFrustumOffset() const;
+
+        /** Sets frustum focal length (used in stereo rendering).
+            @param
+                focalLength The distance to the focal plane from the frustum in world coordinates.
+        */
+        virtual void setFocalLength(Real focalLength = 1.0);
+
+        /** Returns focal length of frustum.
+        */
+        virtual Real getFocalLength() const;
+
+		/** Manually set the extents of the frustum.
+		@param left, right, top, bottom The position where the side clip planes intersect
+			the near clip plane, in eye space
+		*/
+		virtual void setFrustumExtents(Real left, Real right, Real top, Real bottom);
+		/** Reset the frustum extents to be automatically derived from other params. */
+		virtual void resetFrustumExtents(); 
+		/** Get the extents of the frustum in view space. */
+		virtual void getFrustumExtents(Real& outleft, Real& outright, Real& outtop, Real& outbottom) const;
+
+
+        /** Gets the projection matrix for this frustum adjusted for the current
+			rendersystem specifics (may be right or left-handed, depth range
+			may vary).
+        @remarks
+            This method retrieves the rendering-API dependent version of the projection
+            matrix. If you want a 'typical' projection matrix then use 
+            getProjectionMatrix.
+
+        */
+        virtual const Matrix4& getProjectionMatrixRS(void) const;
+        /** Gets the depth-adjusted projection matrix for the current rendersystem,
+			but one which still conforms to right-hand rules.
+        @remarks
+            This differs from the rendering-API dependent getProjectionMatrix
+            in that it always returns a right-handed projection matrix result 
+            no matter what rendering API is being used - this is required for
+            vertex and fragment programs for example. However, the resulting depth
+            range may still vary between render systems since D3D uses [0,1] and 
+            GL uses [-1,1], and the range must be kept the same between programmable
+            and fixed-function pipelines.
+        */
+        virtual const Matrix4& getProjectionMatrixWithRSDepth(void) const;
+        /** Gets the normal projection matrix for this frustum, ie the 
+        projection matrix which conforms to standard right-handed rules and
+        uses depth range [-1,+1].
+        @remarks
+            This differs from the rendering-API dependent getProjectionMatrixRS
+            in that it always returns a right-handed projection matrix with depth
+            range [-1,+1], result no matter what rendering API is being used - this
+            is required for some uniform algebra for example.
+        */
+        virtual const Matrix4& getProjectionMatrix(void) const;
+
+        /** Gets the view matrix for this frustum. Mainly for use by OGRE internally.
+        */
+        virtual const Matrix4& getViewMatrix(void) const;
+
+		/** Calculate a view matrix for this frustum, relative to a potentially dynamic point. 
+			Mainly for use by OGRE internally when using camera-relative rendering
+			for frustums that are not the centre (e.g. texture projection)
+		*/
+		virtual void calcViewMatrixRelative(const Vector3& relPos, Matrix4& matToUpdate) const;
+
+		/** Set whether to use a custom view matrix on this frustum.
+		@remarks
+			This is an advanced method which allows you to manually set
+			the view matrix on this frustum, rather than having it calculate
+			itself based on it's position and orientation. 
+		@note
+			After enabling a custom view matrix, the frustum will no longer
+			update on its own based on position / orientation changes. You 
+			are completely responsible for keeping the view matrix up to date.
+			The custom matrix will be returned from getViewMatrix.
+		@param enable If true, the custom view matrix passed as the second 
+			parameter will be used in preference to an auto calculated one. If
+			false, the frustum will revert to auto calculating the view matrix.
+		@param viewMatrix The custom view matrix to use, the matrix must be an
+            affine matrix.
+		@see Frustum::setCustomProjectionMatrix, Matrix4::isAffine
+		*/
+		virtual void setCustomViewMatrix(bool enable, 
+			const Matrix4& viewMatrix = Matrix4::IDENTITY);
+		/// Returns whether a custom view matrix is in use
+		virtual bool isCustomViewMatrixEnabled(void) const 
+		{ return mCustomViewMatrix; }
+		
+		/** Set whether to use a custom projection matrix on this frustum.
+		@remarks
+			This is an advanced method which allows you to manually set
+			the projection matrix on this frustum, rather than having it 
+			calculate itself based on it's position and orientation. 
+		@note
+			After enabling a custom projection matrix, the frustum will no 
+			longer update on its own based on field of view and near / far
+			distance changes. You are completely responsible for keeping the 
+			projection matrix up to date if those values change. The custom 
+			matrix will be returned from getProjectionMatrix and derivative
+			functions.
+		@param enable If true, the custom projection matrix passed as the 
+			second parameter will be used in preference to an auto calculated 
+			one. If	false, the frustum will revert to auto calculating the 
+			projection matrix.
+		@param projectionMatrix The custom view matrix to use
+		@see Frustum::setCustomViewMatrix
+		*/
+		virtual void setCustomProjectionMatrix(bool enable, 
+			const Matrix4& projectionMatrix = Matrix4::IDENTITY);
+		/// Returns whether a custom projection matrix is in use
+		virtual bool isCustomProjectionMatrixEnabled(void) const
+		{ return mCustomProjMatrix; }
+
+		/** Retrieves the clipping planes of the frustum (world space).
+        @remarks
+            The clipping planes are ordered as declared in enumerate constants FrustumPlane.
+        */
+        virtual const Plane* getFrustumPlanes(void) const;
+
+        /** Retrieves a specified plane of the frustum (world space).
+            @remarks
+                Gets a reference to one of the planes which make up the frustum frustum, e.g. for clipping purposes.
+        */
+        virtual const Plane& getFrustumPlane( unsigned short plane ) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding box to be checked (world space)
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given container is visible in the Frustum.
+            @param
+                bound Bounding sphere to be checked (world space)
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the sphere was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Sphere& bound, FrustumPlane* culledBy = 0) const;
+
+        /** Tests whether the given vertex is visible in the Frustum.
+            @param
+                vert Vertex to be checked (world space)
+            @param
+                culledBy Optional pointer to an int which will be filled by the plane number which culled
+                the box if the result was false;
+            @returns
+                If the box was visible, true is returned.
+            @par
+                Otherwise, false is returned.
+        */
+        virtual bool isVisible(const Vector3& vert, FrustumPlane* culledBy = 0) const;
+
+        /** Overridden from MovableObject */
+        const AxisAlignedBox& getBoundingBox(void) const;
+
+        /** Overridden from MovableObject */
+		Real getBoundingRadius(void) const;
+
+        /** Overridden from MovableObject */
+        const String& getMovableType(void) const;
+
+        /** Gets the world space corners of the frustum.
+        @remarks
+            The corners are ordered as follows: top-right near, 
+            top-left near, bottom-left near, bottom-right near, 
+            top-right far, top-left far, bottom-left far, bottom-right far.
+        */
+        virtual const Vector3* getWorldSpaceCorners(void) const;
+
+        /** Sets the type of projection to use (orthographic or perspective). Default is perspective.
+        */
+        virtual void setProjectionType(ProjectionType pt);
+
+        /** Retrieves info on the type of projection used (orthographic or perspective).
+        */
+        virtual ProjectionType getProjectionType(void) const;
+
+		/** Sets the orthographic window settings, for use with orthographic rendering only. 
+		@note Calling this method will recalculate the aspect ratio, use 
+			setOrthoWindowHeight or setOrthoWindowWidth alone if you wish to 
+			preserve the aspect ratio but just fit one or other dimension to a 
+			particular size.
+		@param w, h The dimensions of the view window in world units
+		*/
+		virtual void setOrthoWindow(Real w, Real h);
+		/** Sets the orthographic window height, for use with orthographic rendering only. 
+		@note The width of the window will be calculated from the aspect ratio. 
+		@param h The height of the view window in world units
+		*/
+		virtual void setOrthoWindowHeight(Real h);
+		/** Sets the orthographic window width, for use with orthographic rendering only. 
+		@note The height of the window will be calculated from the aspect ratio. 
+		@param w The width of the view window in world units
+		*/
+		virtual void setOrthoWindowWidth(Real w);
+		/** Gets the orthographic window height, for use with orthographic rendering only. 
+		*/
+		virtual Real getOrthoWindowHeight() const;
+		/** Gets the orthographic window width, for use with orthographic rendering only. 
+		@note This is calculated from the orthographic height and the aspect ratio
+		*/
+		virtual Real getOrthoWindowWidth() const;
+
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const Plane& p);
+        /** Modifies this frustum so it always renders from the reflection of itself through the
+        plane specified. Note that this version of the method links to a plane
+		so that changes to it are picked up automatically. It is important that
+		this plane continues to exist whilst this object does; do not destroy
+		the plane before the frustum.
+        @remarks
+        This is obviously useful for performing planar reflections. 
+        */
+        virtual void enableReflection(const Plane* p);
+
+        /** Disables reflection modification previously turned on with enableReflection */
+        virtual void disableReflection(void);
+
+        /// Returns whether this frustum is being reflected
+        virtual bool isReflected(void) const { return mReflect; }
+        /// Returns the reflection matrix of the frustum if appropriate
+        virtual const Matrix4& getReflectionMatrix(void) const { return mReflectMatrix; }
+        /// Returns the reflection plane of the frustum if appropriate
+        virtual const Plane& getReflectionPlane(void) const { return mReflectPlane; }
+
+        /** Project a sphere onto the near plane and get the bounding rectangle. 
+        @param sphere The world-space sphere to project
+        @param radius Radius of the sphere
+        @param left, top, right, bottom Pointers to destination values, these
+            will be completed with the normalised device coordinates (in the 
+            range {-1,1})
+        @returns true if the sphere was projected to a subset of the near plane,
+            false if the entire near plane was contained
+        */
+        virtual bool projectSphere(const Sphere& sphere, 
+            Real* left, Real* top, Real* right, Real* bottom) const;
+
+
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to 
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@par 
+			This version of the method links to a plane, rather than requiring
+			a by-value plane definition, and therefore you can 
+			make changes to the plane (e.g. by moving / rotating the node it is
+			attached to) and they will automatically affect this object.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const Plane* plane);
+		/** Links the frustum to a custom near clip plane, which can be used
+			to clip geometry in a custom manner without using user clip planes.
+		@remarks
+			There are several applications for clipping a scene arbitrarily by
+			a single plane; the most common is when rendering a reflection to  
+			a texture, and you only want to render geometry that is above the 
+			water plane (to do otherwise results in artefacts). Whilst it is
+			possible to use user clip planes, they are not supported on all
+			cards, and sometimes are not hardware accelerated when they are
+			available. Instead, where a single clip plane is involved, this
+			technique uses a 'fudging' of the near clip plane, which is 
+			available and fast on all hardware, to perform as the arbitrary
+			clip plane. This does change the shape of the frustum, leading 
+			to some depth buffer loss of precision, but for many of the uses of
+			this technique that is not an issue.
+		@note This technique only works for perspective projection.
+		@param plane The plane to link to to perform the clipping. This plane
+			must continue to exist while the camera is linked to it; do not
+			destroy it before the frustum. 
+		*/
+		virtual void enableCustomNearClipPlane(const Plane& plane);
+		/** Disables any custom near clip plane. */
+		virtual void disableCustomNearClipPlane(void);
+		/** Is a custom near clip plane in use? */
+		virtual bool isCustomNearClipPlaneEnabled(void) const 
+		{ return mObliqueDepthProjection; }
+
+        /// Small constant used to reduce far plane projection to avoid inaccuracies
+        static const Real INFINITE_FAR_PLANE_ADJUST;
+
+		/** Get the derived position of this frustum. */
+		virtual const Vector3& getPositionForViewUpdate(void) const;
+		/** Get the derived orientation of this frustum. */
+		virtual const Quaternion& getOrientationForViewUpdate(void) const;
+
+        /** Set the orientation mode of the frustum. Default is OR_DEGREE_0
+             @remarks
+                Setting the orientation of a frustum is only supported on
+                iPhone at this time.  An exception is thrown on other platforms.
+        */
+        void setOrientationMode(OrientationMode orientationMode);
+
+        /** Get the orientation mode of the frustum.
+             @remarks
+                Getting the orientation of a frustum is only supported on
+                iPhone at this time.  An exception is thrown on other platforms.
+        */
+        OrientationMode getOrientationMode() const;
+
+    };
+
+	/** @} */
+	/** @} */
+
+}
+
+#endif 

+ 348 - 0
CamelotRenderer/OgreHardwareBuffer.h

@@ -0,0 +1,348 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __HardwareBuffer__
+#define __HardwareBuffer__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** Abstract class defining common features of hardware buffers.
+    @remarks
+ 	    A 'hardware buffer' is any area of memory held outside of core system ram,
+	    and in our case refers mostly to video ram, although in theory this class
+	    could be used with other memory areas such as sound card memory, custom
+	    coprocessor memory etc.
+    @par
+ 	    This reflects the fact that memory held outside of main system RAM must 
+	    be interacted with in a more formal fashion in order to promote
+	    cooperative and optimal usage of the buffers between the various 
+	    processing units which manipulate them.
+    @par
+ 	    This abstract class defines the core interface which is common to all
+	    buffers, whether it be vertex buffers, index buffers, texture memory
+	    or framebuffer memory etc.
+	@par
+		Buffers have the ability to be 'shadowed' in system memory, this is because
+		the kinds of access allowed on hardware buffers is not always as flexible as
+		that allowed for areas of system memory - for example it is often either 
+		impossible, or extremely undesirable from a performance standpoint to read from
+		a hardware buffer; when writing to hardware buffers, you should also write every
+		byte and do it sequentially. In situations where this is too restrictive, 
+		it is possible to create a hardware, write-only buffer (the most efficient kind) 
+		and to back it with a system memory 'shadow' copy which can be read and updated arbitrarily.
+		Ogre handles synchronising this buffer with the real hardware buffer (which should still be
+		created with the HBU_DYNAMIC flag if you intend to update it very frequently). Whilst this
+		approach does have it's own costs, such as increased memory overhead, these costs can 
+		often be outweighed by the performance benefits of using a more hardware efficient buffer.
+		You should look for the 'useShadowBuffer' parameter on the creation methods used to create
+		the buffer of the type you require (see HardwareBufferManager) to enable this feature.
+    */
+	class _OgreExport HardwareBuffer
+    {
+
+	    public:
+		    /// Enums describing buffer usage; not mutually exclusive
+		    enum Usage 
+		    {
+                /** Static buffer which the application rarely modifies once created. Modifying 
+                the contents of this buffer will involve a performance hit.
+                */
+                HBU_STATIC = 1,
+			    /** Indicates the application would like to modify this buffer with the CPU
+			    fairly often. 
+			    Buffers created with this flag will typically end up in AGP memory rather 
+			    than video memory.
+			    */
+			    HBU_DYNAMIC = 2,
+			    /** Indicates the application will never read the contents of the buffer back, 
+			    it will only ever write data. Locking a buffer with this flag will ALWAYS 
+			    return a pointer to new, blank memory rather than the memory associated 
+			    with the contents of the buffer; this avoids DMA stalls because you can 
+			    write to a new memory area while the previous one is being used. 
+			    */
+			    HBU_WRITE_ONLY = 4,
+                /** Indicates that the application will be refilling the contents
+                of the buffer regularly (not just updating, but generating the
+                contents from scratch), and therefore does not mind if the contents 
+                of the buffer are lost somehow and need to be recreated. This
+                allows and additional level of optimisation on the buffer.
+                This option only really makes sense when combined with 
+                HBU_DYNAMIC_WRITE_ONLY.
+                */
+                HBU_DISCARDABLE = 8,
+				/// Combination of HBU_STATIC and HBU_WRITE_ONLY
+				HBU_STATIC_WRITE_ONLY = 5, 
+				/** Combination of HBU_DYNAMIC and HBU_WRITE_ONLY. If you use 
+                this, strongly consider using HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE
+                instead if you update the entire contents of the buffer very 
+                regularly. 
+                */
+				HBU_DYNAMIC_WRITE_ONLY = 6,
+                /// Combination of HBU_DYNAMIC, HBU_WRITE_ONLY and HBU_DISCARDABLE
+                HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE = 14
+
+
+		    };
+		    /// Locking options
+		    enum LockOptions
+		    {
+                /** Normal mode, ie allows read/write and contents are preserved. */
+                HBL_NORMAL,
+			    /** Discards the <em>entire</em> buffer while locking; this allows optimisation to be 
+				performed because synchronisation issues are relaxed. Only allowed on buffers 
+			    created with the HBU_DYNAMIC flag. 
+			    */
+			    HBL_DISCARD,
+			    /** Lock the buffer for reading only. Not allowed in buffers which are created with HBU_WRITE_ONLY. 
+				Mandatory on static buffers, i.e. those created without the HBU_DYNAMIC flag. 
+				*/ 
+			    HBL_READ_ONLY,
+                /** As HBL_NORMAL, except the application guarantees not to overwrite any 
+                region of the buffer which has already been used in this frame, can allow
+                some optimisation on some APIs. */
+                HBL_NO_OVERWRITE
+    			
+		    };
+	    protected:
+		    size_t mSizeInBytes;
+		    Usage mUsage;
+		    bool mIsLocked;
+			size_t mLockStart;
+			size_t mLockSize;
+			bool mSystemMemory;
+            bool mUseShadowBuffer;
+            HardwareBuffer* mpShadowBuffer;
+            bool mShadowUpdated;
+            bool mSuppressHardwareUpdate;
+    		
+            /// Internal implementation of lock()
+		    virtual void* lockImpl(size_t offset, size_t length, LockOptions options) = 0;
+            /// Internal implementation of unlock()
+		    virtual void unlockImpl(void) = 0;
+
+    public:
+		    /// Constructor, to be called by HardwareBufferManager only
+            HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer) 
+				: mUsage(usage), mIsLocked(false), mSystemMemory(systemMemory), 
+                mUseShadowBuffer(useShadowBuffer), mpShadowBuffer(NULL), mShadowUpdated(false), 
+                mSuppressHardwareUpdate(false) 
+            {
+                // If use shadow buffer, upgrade to WRITE_ONLY on hardware side
+                if (useShadowBuffer && usage == HBU_DYNAMIC)
+                {
+                    mUsage = HBU_DYNAMIC_WRITE_ONLY;
+                }
+                else if (useShadowBuffer && usage == HBU_STATIC)
+                {
+                    mUsage = HBU_STATIC_WRITE_ONLY;
+                }
+            }
+            virtual ~HardwareBuffer() {}
+		    /** Lock the buffer for (potentially) reading / writing.
+		    @param offset The byte offset from the start of the buffer to lock
+		    @param length The size of the area to lock, in bytes
+		    @param options Locking options
+		    @returns Pointer to the locked memory
+		    */
+		    virtual void* lock(size_t offset, size_t length, LockOptions options)
+            {
+                assert(!isLocked() && "Cannot lock this buffer, it is already locked!");
+                void* ret;
+				if (mUseShadowBuffer)
+                {
+					if (options != HBL_READ_ONLY)
+					{
+						// we have to assume a read / write lock so we use the shadow buffer
+						// and tag for sync on unlock()
+                        mShadowUpdated = true;
+                    }
+
+                    ret = mpShadowBuffer->lock(offset, length, options);
+                }
+                else
+                {
+					// Lock the real buffer if there is no shadow buffer 
+                    ret = lockImpl(offset, length, options);
+                    mIsLocked = true;
+                }
+				mLockStart = offset;
+				mLockSize = length;
+                return ret;
+            }
+
+            /** Lock the entire buffer for (potentially) reading / writing.
+		    @param options Locking options
+		    @returns Pointer to the locked memory
+            */
+            void* lock(LockOptions options)
+            {
+                return this->lock(0, mSizeInBytes, options);
+            }
+		    /** Releases the lock on this buffer. 
+            @remarks 
+                Locking and unlocking a buffer can, in some rare circumstances such as 
+                switching video modes whilst the buffer is locked, corrupt the 
+                contents of a buffer. This is pretty rare, but if it occurs, 
+                this method will throw an exception, meaning you
+                must re-upload the data.
+            @par
+                Note that using the 'read' and 'write' forms of updating the buffer does not
+                suffer from this problem, so if you want to be 100% sure your
+                data will not be lost, use the 'read' and 'write' forms instead.
+            */
+		    virtual void unlock(void)
+            {
+                assert(isLocked() && "Cannot unlock this buffer, it is not locked!");
+
+				// If we used the shadow buffer this time...
+                if (mUseShadowBuffer && mpShadowBuffer->isLocked())
+                {
+                    mpShadowBuffer->unlock();
+                    // Potentially update the 'real' buffer from the shadow buffer
+                    _updateFromShadow();
+                }
+                else
+                {
+					// Otherwise, unlock the real one
+                    unlockImpl();
+                    mIsLocked = false;
+                }
+
+            }
+
+            /** Reads data from the buffer and places it in the memory pointed to by pDest.
+		    @param offset The byte offset from the start of the buffer to read
+		    @param length The size of the area to read, in bytes
+            @param pDest The area of memory in which to place the data, must be large enough to 
+                accommodate the data!
+            */
+            virtual void readData(size_t offset, size_t length, void* pDest) = 0;
+            /** Writes data to the buffer from an area of system memory; note that you must
+                ensure that your buffer is big enough.
+		    @param offset The byte offset from the start of the buffer to start writing
+		    @param length The size of the data to write to, in bytes
+            @param pSource The source of the data to be written
+			@param discardWholeBuffer If true, this allows the driver to discard the entire buffer when writing,
+				such that DMA stalls can be avoided; use if you can.
+            */
+            virtual void writeData(size_t offset, size_t length, const void* pSource,
+					bool discardWholeBuffer = false) = 0;
+
+			/** Copy data from another buffer into this one.
+			@remarks
+				Note that the source buffer must not be created with the
+                usage HBU_WRITE_ONLY otherwise this will fail. 
+			@param srcBuffer The buffer from which to read the copied data
+			@param srcOffset Offset in the source buffer at which to start reading
+			@param dstOffset Offset in the destination buffer to start writing
+			@param length Length of the data to copy, in bytes.
+			@param discardWholeBuffer If true, will discard the entire contents of this buffer before copying
+			*/
+			virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, 
+				size_t dstOffset, size_t length, bool discardWholeBuffer = false)
+			{
+				const void *srcData = srcBuffer.lock(
+					srcOffset, length, HBL_READ_ONLY);
+				this->writeData(dstOffset, length, srcData, discardWholeBuffer);
+				srcBuffer.unlock();
+			}
+
+			/** Copy all data from another buffer into this one. 
+			@remarks
+				Normally these buffers should be of identical size, but if they're
+				not, the routine will use the smallest of the two sizes.
+			*/
+			virtual void copyData(HardwareBuffer& srcBuffer)
+			{
+				size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes()); 
+				copyData(srcBuffer, 0, 0, sz, true);
+			}
+			
+			/// Updates the real buffer from the shadow buffer, if required
+            virtual void _updateFromShadow(void)
+            {
+                if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
+                {
+                    // Do this manually to avoid locking problems
+                    const void *srcData = mpShadowBuffer->lockImpl(
+    					mLockStart, mLockSize, HBL_READ_ONLY);
+					// Lock with discard if the whole buffer was locked, otherwise normal
+					LockOptions lockOpt;
+					if (mLockStart == 0 && mLockSize == mSizeInBytes)
+						lockOpt = HBL_DISCARD;
+					else
+						lockOpt = HBL_NORMAL;
+					
+                    void *destData = this->lockImpl(
+    					mLockStart, mLockSize, lockOpt);
+					// Copy shadow to real
+                    memcpy(destData, srcData, mLockSize);
+                    this->unlockImpl();
+                    mpShadowBuffer->unlockImpl();
+                    mShadowUpdated = false;
+                }
+            }
+
+            /// Returns the size of this buffer in bytes
+            size_t getSizeInBytes(void) const { return mSizeInBytes; }
+            /// Returns the Usage flags with which this buffer was created
+            Usage getUsage(void) const { return mUsage; }
+			/// Returns whether this buffer is held in system memory
+			bool isSystemMemory(void) const { return mSystemMemory; }
+			/// Returns whether this buffer has a system memory shadow for quicker reading
+			bool hasShadowBuffer(void) const { return mUseShadowBuffer; }
+            /// Returns whether or not this buffer is currently locked.
+            bool isLocked(void) const { 
+                return mIsLocked || (mUseShadowBuffer && mpShadowBuffer->isLocked()); 
+            }
+            /// Pass true to suppress hardware upload of shadow buffer changes
+            void suppressHardwareUpdate(bool suppress) {
+                mSuppressHardwareUpdate = suppress;
+                if (!suppress)
+                    _updateFromShadow();
+            }
+
+
+
+
+    		
+    };
+	/** @} */
+	/** @} */
+}
+#endif
+
+

+ 547 - 0
CamelotRenderer/OgreHardwareBufferManager.cpp

@@ -0,0 +1,547 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreHardwareBufferManager.h"
+#include "OgreVertexIndexData.h"
+
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------
+    template<> HardwareBufferManager* Singleton<HardwareBufferManager>::ms_Singleton = 0;
+    HardwareBufferManager* HardwareBufferManager::getSingletonPtr(void)
+    {
+        return ms_Singleton;
+    }
+    HardwareBufferManager& HardwareBufferManager::getSingleton(void)
+    {  
+        assert( ms_Singleton );  return ( *ms_Singleton );  
+    }
+	//---------------------------------------------------------------------
+	HardwareBufferManager::HardwareBufferManager(HardwareBufferManagerBase* imp)
+		: HardwareBufferManagerBase(), mImpl(imp)
+	{
+
+	}
+	//---------------------------------------------------------------------
+	HardwareBufferManager::~HardwareBufferManager()
+	{
+		// mImpl must be deleted by the creator
+	}
+	//---------------------------------------------------------------------
+	//---------------------------------------------------------------------
+    // Free temporary vertex buffers every 5 minutes on 100fps
+    const size_t HardwareBufferManagerBase::UNDER_USED_FRAME_THRESHOLD = 30000;
+    const size_t HardwareBufferManagerBase::EXPIRED_DELAY_FRAME_THRESHOLD = 5;
+    //-----------------------------------------------------------------------
+    HardwareBufferManagerBase::HardwareBufferManagerBase()
+        : mUnderUsedFrameCount(0)
+    {
+    }
+    //-----------------------------------------------------------------------
+    HardwareBufferManagerBase::~HardwareBufferManagerBase()
+    {
+        // Clear vertex/index buffer list first, avoid destroyed notify do
+        // unnecessary work, and we'll destroy everything here.
+		mVertexBuffers.clear();
+		mIndexBuffers.clear();
+
+        // Destroy everything
+        destroyAllDeclarations();
+        destroyAllBindings();
+        // No need to destroy main buffers - they will be destroyed by removal of bindings
+
+        // No need to destroy temp buffers - they will be destroyed automatically.
+    }
+    //-----------------------------------------------------------------------
+    VertexDeclaration* HardwareBufferManagerBase::createVertexDeclaration(void)
+    {
+        VertexDeclaration* decl = createVertexDeclarationImpl();
+		OGRE_LOCK_MUTEX(mVertexDeclarationsMutex)
+        mVertexDeclarations.insert(decl);
+        return decl;
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::destroyVertexDeclaration(VertexDeclaration* decl)
+    {
+		OGRE_LOCK_MUTEX(mVertexDeclarationsMutex)
+        mVertexDeclarations.erase(decl);
+        destroyVertexDeclarationImpl(decl);
+    }
+    //-----------------------------------------------------------------------
+	VertexBufferBinding* HardwareBufferManagerBase::createVertexBufferBinding(void)
+	{
+		VertexBufferBinding* ret = createVertexBufferBindingImpl();
+		OGRE_LOCK_MUTEX(mVertexBufferBindingsMutex)
+		mVertexBufferBindings.insert(ret);
+		return ret;
+	}
+    //-----------------------------------------------------------------------
+	void HardwareBufferManagerBase::destroyVertexBufferBinding(VertexBufferBinding* binding)
+	{
+		OGRE_LOCK_MUTEX(mVertexBufferBindingsMutex)
+		mVertexBufferBindings.erase(binding);
+		destroyVertexBufferBindingImpl(binding);
+	}
+    //-----------------------------------------------------------------------
+    VertexDeclaration* HardwareBufferManagerBase::createVertexDeclarationImpl(void)
+    {
+        return OGRE_NEW VertexDeclaration();
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::destroyVertexDeclarationImpl(VertexDeclaration* decl)
+    {
+        OGRE_DELETE decl;
+    }
+    //-----------------------------------------------------------------------
+	VertexBufferBinding* HardwareBufferManagerBase::createVertexBufferBindingImpl(void)
+	{
+		return OGRE_NEW VertexBufferBinding();
+	}
+    //-----------------------------------------------------------------------
+	void HardwareBufferManagerBase::destroyVertexBufferBindingImpl(VertexBufferBinding* binding)
+	{
+		OGRE_DELETE binding;
+	}
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::destroyAllDeclarations(void)
+    {
+		OGRE_LOCK_MUTEX(mVertexDeclarationsMutex)
+        VertexDeclarationList::iterator decl;
+        for (decl = mVertexDeclarations.begin(); decl != mVertexDeclarations.end(); ++decl)
+        {
+            destroyVertexDeclarationImpl(*decl);
+        }
+        mVertexDeclarations.clear();
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::destroyAllBindings(void)
+    {
+		OGRE_LOCK_MUTEX(mVertexBufferBindingsMutex)
+        VertexBufferBindingList::iterator bind;
+        for (bind = mVertexBufferBindings.begin(); bind != mVertexBufferBindings.end(); ++bind)
+        {
+            destroyVertexBufferBindingImpl(*bind);
+        }
+        mVertexBufferBindings.clear();
+    }
+	//-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::registerVertexBufferSourceAndCopy(
+			const HardwareVertexBufferSharedPtr& sourceBuffer,
+			const HardwareVertexBufferSharedPtr& copy)
+	{
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+		// Add copy to free temporary vertex buffers
+        mFreeTempVertexBufferMap.insert(
+            FreeTemporaryVertexBufferMap::value_type(sourceBuffer.get(), copy));
+	}
+	//-----------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr 
+    HardwareBufferManagerBase::allocateVertexBufferCopy(
+        const HardwareVertexBufferSharedPtr& sourceBuffer, 
+        BufferLicenseType licenseType, HardwareBufferLicensee* licensee,
+        bool copyData)
+    {
+		// pre-lock the mVertexBuffers mutex, which would usually get locked in
+		//  makeBufferCopy / createVertexBuffer
+		// this prevents a deadlock in _notifyVertexBufferDestroyed
+		// which locks the same mutexes (via other methods) but in reverse order
+		OGRE_LOCK_MUTEX(mVertexBuffersMutex)
+		{
+			OGRE_LOCK_MUTEX(mTempBuffersMutex)
+			HardwareVertexBufferSharedPtr vbuf;
+
+			// Locate existing buffer copy in temporary vertex buffers
+			FreeTemporaryVertexBufferMap::iterator i = 
+				mFreeTempVertexBufferMap.find(sourceBuffer.get());
+			if (i == mFreeTempVertexBufferMap.end())
+			{
+				// copy buffer, use shadow buffer and make dynamic
+				vbuf = makeBufferCopy(
+					sourceBuffer, 
+					HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, 
+					true);
+			}
+			else
+			{
+				// Allocate existing copy
+				vbuf = i->second;
+				mFreeTempVertexBufferMap.erase(i);
+			}
+
+			// Copy data?
+			if (copyData)
+			{
+				vbuf->copyData(*(sourceBuffer.get()), 0, 0, sourceBuffer->getSizeInBytes(), true);
+			}
+
+			// Insert copy into licensee list
+			mTempVertexBufferLicenses.insert(
+				TemporaryVertexBufferLicenseMap::value_type(
+					vbuf.get(),
+					VertexBufferLicense(sourceBuffer.get(), licenseType, EXPIRED_DELAY_FRAME_THRESHOLD, vbuf, licensee)));
+			return vbuf;
+		}
+
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::releaseVertexBufferCopy(
+        const HardwareVertexBufferSharedPtr& bufferCopy)
+    {
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+
+		TemporaryVertexBufferLicenseMap::iterator i =
+            mTempVertexBufferLicenses.find(bufferCopy.get());
+        if (i != mTempVertexBufferLicenses.end())
+        {
+            const VertexBufferLicense& vbl = i->second;
+
+            vbl.licensee->licenseExpired(vbl.buffer.get());
+
+            mFreeTempVertexBufferMap.insert(
+                FreeTemporaryVertexBufferMap::value_type(vbl.originalBufferPtr, vbl.buffer));
+            mTempVertexBufferLicenses.erase(i);
+        }
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::touchVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& bufferCopy)
+    {
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+        TemporaryVertexBufferLicenseMap::iterator i =
+            mTempVertexBufferLicenses.find(bufferCopy.get());
+        if (i != mTempVertexBufferLicenses.end())
+        {
+            VertexBufferLicense& vbl = i->second;
+            assert(vbl.licenseType == BLT_AUTOMATIC_RELEASE);
+
+            vbl.expiredDelay = EXPIRED_DELAY_FRAME_THRESHOLD;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::_freeUnusedBufferCopies(void)
+    {
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+        size_t numFreed = 0;
+
+        // Free unused temporary buffers
+        FreeTemporaryVertexBufferMap::iterator i;
+        i = mFreeTempVertexBufferMap.begin();
+        while (i != mFreeTempVertexBufferMap.end())
+        {
+            FreeTemporaryVertexBufferMap::iterator icur = i++;
+            // Free the temporary buffer that referenced by ourself only.
+            // TODO: Some temporary buffers are bound to vertex buffer bindings
+            // but not checked out, need to sort out method to unbind them.
+            if (icur->second.useCount() <= 1)
+            {
+                ++numFreed;
+                mFreeTempVertexBufferMap.erase(icur);
+            }
+        }
+
+		// TODO PORT - Log ignored
+        //StringUtil::StrStreamType str;
+        //if (numFreed)
+        //{
+        //    str << "HardwareBufferManager: Freed " << numFreed << " unused temporary vertex buffers.";
+        //}
+        //else
+        //{
+        //    str << "HardwareBufferManager: No unused temporary vertex buffers found.";
+        //}
+        //LogManager::getSingleton().logMessage(str.str(), LML_TRIVIAL);
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::_releaseBufferCopies(bool forceFreeUnused)
+    {
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+        size_t numUnused = mFreeTempVertexBufferMap.size();
+        size_t numUsed = mTempVertexBufferLicenses.size();
+
+        // Erase the copies which are automatic licensed out
+        TemporaryVertexBufferLicenseMap::iterator i;
+        i = mTempVertexBufferLicenses.begin(); 
+        while (i != mTempVertexBufferLicenses.end()) 
+        {
+            TemporaryVertexBufferLicenseMap::iterator icur = i++;
+            VertexBufferLicense& vbl = icur->second;
+            if (vbl.licenseType == BLT_AUTOMATIC_RELEASE &&
+                (forceFreeUnused || --vbl.expiredDelay <= 0))
+            {
+				vbl.licensee->licenseExpired(vbl.buffer.get());
+
+                mFreeTempVertexBufferMap.insert(
+                    FreeTemporaryVertexBufferMap::value_type(vbl.originalBufferPtr, vbl.buffer));
+                mTempVertexBufferLicenses.erase(icur);
+            }
+        }
+
+        // Check whether or not free unused temporary vertex buffers.
+        if (forceFreeUnused)
+        {
+            _freeUnusedBufferCopies();
+            mUnderUsedFrameCount = 0;
+        }
+        else
+        {
+            if (numUsed < numUnused)
+            {
+                // Free temporary vertex buffers if too many unused for a long time.
+                // Do overall temporary vertex buffers instead of per source buffer
+                // to avoid overhead.
+                ++mUnderUsedFrameCount;
+                if (mUnderUsedFrameCount >= UNDER_USED_FRAME_THRESHOLD)
+                {
+                    _freeUnusedBufferCopies();
+                    mUnderUsedFrameCount = 0;
+                }
+            }
+            else
+            {
+                mUnderUsedFrameCount = 0;
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::_forceReleaseBufferCopies(
+        const HardwareVertexBufferSharedPtr& sourceBuffer)
+    {
+        _forceReleaseBufferCopies(sourceBuffer.get());
+    }
+    //-----------------------------------------------------------------------
+    void HardwareBufferManagerBase::_forceReleaseBufferCopies(
+        HardwareVertexBuffer* sourceBuffer)
+    {
+		OGRE_LOCK_MUTEX(mTempBuffersMutex)
+        // Erase the copies which are licensed out
+        TemporaryVertexBufferLicenseMap::iterator i;
+        i = mTempVertexBufferLicenses.begin();
+        while (i != mTempVertexBufferLicenses.end()) 
+        {
+            TemporaryVertexBufferLicenseMap::iterator icur = i++;
+            const VertexBufferLicense& vbl = icur->second;
+            if (vbl.originalBufferPtr == sourceBuffer)
+            {
+                // Just tell the owner that this is being released
+                vbl.licensee->licenseExpired(vbl.buffer.get());
+
+                mTempVertexBufferLicenses.erase(icur);
+            }
+        }
+
+        // Erase the free copies
+        //
+        // Why we need this unusual code? It's for resolve reenter problem.
+        //
+        // Using mFreeTempVertexBufferMap.erase(sourceBuffer) directly will
+        // cause reenter into here because vertex buffer destroyed notify.
+        // In most time there are no problem. But when sourceBuffer is the
+        // last item of the mFreeTempVertexBufferMap, some STL multimap
+        // implementation (VC and STLport) will call to clear(), which will
+        // causing intermediate state of mFreeTempVertexBufferMap, in that
+        // time destroyed notify back to here cause illegal accessing in
+        // the end.
+        //
+        // For safely reason, use following code to resolve reenter problem.
+        //
+        typedef FreeTemporaryVertexBufferMap::iterator _Iter;
+        std::pair<_Iter, _Iter> range = mFreeTempVertexBufferMap.equal_range(sourceBuffer);
+        if (range.first != range.second)
+        {
+            list<HardwareVertexBufferSharedPtr>::type holdForDelayDestroy;
+            for (_Iter it = range.first; it != range.second; ++it)
+            {
+                if (it->second.useCount() <= 1)
+                {
+                    holdForDelayDestroy.push_back(it->second);
+                }
+            }
+
+            mFreeTempVertexBufferMap.erase(range.first, range.second);
+
+            // holdForDelayDestroy will destroy auto.
+        }
+    }
+	//-----------------------------------------------------------------------
+	void HardwareBufferManagerBase::_notifyVertexBufferDestroyed(HardwareVertexBuffer* buf)
+	{
+		OGRE_LOCK_MUTEX(mVertexBuffersMutex)
+
+		VertexBufferList::iterator i = mVertexBuffers.find(buf);
+		if (i != mVertexBuffers.end())
+		{
+            // release vertex buffer copies
+			mVertexBuffers.erase(i);
+            _forceReleaseBufferCopies(buf);
+		}
+	}
+	//-----------------------------------------------------------------------
+	void HardwareBufferManagerBase::_notifyIndexBufferDestroyed(HardwareIndexBuffer* buf)
+	{
+		OGRE_LOCK_MUTEX(mIndexBuffersMutex)
+
+		IndexBufferList::iterator i = mIndexBuffers.find(buf);
+		if (i != mIndexBuffers.end())
+		{
+			mIndexBuffers.erase(i);
+		}
+	}
+    //-----------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr 
+    HardwareBufferManagerBase::makeBufferCopy(
+        const HardwareVertexBufferSharedPtr& source,
+        HardwareBuffer::Usage usage, bool useShadowBuffer)
+    {
+        return this->createVertexBuffer(
+            source->getVertexSize(), 
+            source->getNumVertices(),
+            usage, useShadowBuffer);
+    }
+    //-----------------------------------------------------------------------------
+    //-----------------------------------------------------------------------------
+    //-----------------------------------------------------------------------------
+    TempBlendedBufferInfo::~TempBlendedBufferInfo(void)
+    {
+        // check that temp buffers have been released
+        if (!destPositionBuffer.isNull())
+            destPositionBuffer->getManager()->releaseVertexBufferCopy(destPositionBuffer);
+        if (!destNormalBuffer.isNull())
+            destNormalBuffer->getManager()->releaseVertexBufferCopy(destNormalBuffer);
+
+    }
+    //-----------------------------------------------------------------------------
+    void TempBlendedBufferInfo::extractFrom(const VertexData* sourceData)
+    {
+        // Release old buffer copies first
+        if (!destPositionBuffer.isNull())
+        {
+            destPositionBuffer->getManager()->releaseVertexBufferCopy(destPositionBuffer);
+            assert(destPositionBuffer.isNull());
+        }
+        if (!destNormalBuffer.isNull())
+        {
+            destNormalBuffer->getManager()->releaseVertexBufferCopy(destNormalBuffer);
+            assert(destNormalBuffer.isNull());
+        }
+
+        VertexDeclaration* decl = sourceData->vertexDeclaration;
+        VertexBufferBinding* bind = sourceData->vertexBufferBinding;
+        const VertexElement *posElem = decl->findElementBySemantic(VES_POSITION);
+        const VertexElement *normElem = decl->findElementBySemantic(VES_NORMAL);
+
+        assert(posElem && "Positions are required");
+
+        posBindIndex = posElem->getSource();
+        srcPositionBuffer = bind->getBuffer(posBindIndex);
+
+        if (!normElem)
+        {
+            posNormalShareBuffer = false;
+            srcNormalBuffer.setNull();
+        }
+        else
+        {
+            normBindIndex = normElem->getSource();
+            if (normBindIndex == posBindIndex)
+            {
+                posNormalShareBuffer = true;
+                srcNormalBuffer.setNull();
+            }
+            else
+            {
+                posNormalShareBuffer = false;
+                srcNormalBuffer = bind->getBuffer(normBindIndex);
+            }
+        }
+    }
+    //-----------------------------------------------------------------------------
+    void TempBlendedBufferInfo::checkoutTempCopies(bool positions, bool normals)
+    {
+        bindPositions = positions;
+        bindNormals = normals;
+
+        if (positions && destPositionBuffer.isNull())
+        {
+            destPositionBuffer = srcPositionBuffer->getManager()->allocateVertexBufferCopy(srcPositionBuffer, 
+                HardwareBufferManagerBase::BLT_AUTOMATIC_RELEASE, this);
+        }
+        if (normals && !posNormalShareBuffer && !srcNormalBuffer.isNull() && destNormalBuffer.isNull())
+        {
+            destNormalBuffer = srcNormalBuffer->getManager()->allocateVertexBufferCopy(srcNormalBuffer, 
+                HardwareBufferManagerBase::BLT_AUTOMATIC_RELEASE, this);
+        }
+    }
+	//-----------------------------------------------------------------------------
+	bool TempBlendedBufferInfo::buffersCheckedOut(bool positions, bool normals) const
+	{
+        if (positions || (normals && posNormalShareBuffer))
+        {
+            if (destPositionBuffer.isNull())
+                return false;
+
+            destPositionBuffer->getManager()->touchVertexBufferCopy(destPositionBuffer);
+        }
+
+        if (normals && !posNormalShareBuffer)
+        {
+            if (destNormalBuffer.isNull())
+                return false;
+
+            destNormalBuffer->getManager()->touchVertexBufferCopy(destNormalBuffer);
+        }
+
+		return true;
+	}
+    //-----------------------------------------------------------------------------
+    void TempBlendedBufferInfo::bindTempCopies(VertexData* targetData, bool suppressHardwareUpload)
+    {
+        this->destPositionBuffer->suppressHardwareUpdate(suppressHardwareUpload);
+        targetData->vertexBufferBinding->setBinding(
+            this->posBindIndex, this->destPositionBuffer);
+        if (bindNormals && !posNormalShareBuffer && !destNormalBuffer.isNull())
+        {
+            this->destNormalBuffer->suppressHardwareUpdate(suppressHardwareUpload);
+            targetData->vertexBufferBinding->setBinding(
+                this->normBindIndex, this->destNormalBuffer);
+        }
+    }
+    //-----------------------------------------------------------------------------
+    void TempBlendedBufferInfo::licenseExpired(HardwareBuffer* buffer)
+    {
+        assert(buffer == destPositionBuffer.get()
+            || buffer == destNormalBuffer.get());
+
+        if (buffer == destPositionBuffer.get())
+            destPositionBuffer.setNull();
+        if (buffer == destNormalBuffer.get())
+            destNormalBuffer.setNull();
+
+    }
+
+}

+ 529 - 0
CamelotRenderer/OgreHardwareBufferManager.h

@@ -0,0 +1,529 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __HardwareBufferManager__
+#define __HardwareBufferManager__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreSingleton.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+
+// TODO PORT - Removed this include because I don't think it's implemented, nor do I need it for default funcionality
+//#include "OgreRenderToVertexBuffer.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+
+    /** Abstract interface representing a 'licensee' of a hardware buffer copy.
+    remarks
+        Often it's useful to have temporary buffers which are used for working
+        but are not necessarily needed permanently. However, creating and 
+        destroying buffers is expensive, so we need a way to share these 
+        working areas, especially those based on existing fixed buffers. 
+        This class represents a licensee of one of those temporary buffers, 
+        and must be implemented by any user of a temporary buffer if they 
+        wish to be notified when the license is expired. 
+    */
+    class _OgreExport HardwareBufferLicensee
+    {
+    public:
+        virtual ~HardwareBufferLicensee() { }
+        /** This method is called when the buffer license is expired and is about
+        to be returned to the shared pool. */
+        virtual void licenseExpired(HardwareBuffer* buffer) = 0;
+    };
+
+    /** Structure for recording the use of temporary blend buffers */
+    class _OgreExport TempBlendedBufferInfo : public HardwareBufferLicensee
+    {
+    private:
+        // Pre-blended 
+        HardwareVertexBufferSharedPtr srcPositionBuffer;
+        HardwareVertexBufferSharedPtr srcNormalBuffer;
+        // Post-blended 
+        HardwareVertexBufferSharedPtr destPositionBuffer;
+        HardwareVertexBufferSharedPtr destNormalBuffer;
+        /// Both positions and normals are contained in the same buffer
+        bool posNormalShareBuffer;
+        unsigned short posBindIndex;
+        unsigned short normBindIndex;
+        bool bindPositions;
+        bool bindNormals;
+
+    public:
+        ~TempBlendedBufferInfo(void);
+        /// Utility method, extract info from the given VertexData
+        void extractFrom(const VertexData* sourceData);
+        /// Utility method, checks out temporary copies of src into dest
+        void checkoutTempCopies(bool positions = true, bool normals = true);
+        /// Utility method, binds dest copies into a given VertexData struct
+        void bindTempCopies(VertexData* targetData, bool suppressHardwareUpload);
+        /** Overridden member from HardwareBufferLicensee. */
+        void licenseExpired(HardwareBuffer* buffer);
+		/** Detect currently have buffer copies checked out and touch it */
+		bool buffersCheckedOut(bool positions = true, bool normals = true) const;
+    };
+
+
+	/** Base definition of a hardware buffer manager.
+	@remarks
+		This class is deliberately not a Singleton, so that multiple types can 
+		exist at once. The Singleton is wrapped via the Decorator pattern
+		in HardwareBufferManager, below. Each concrete implementation should
+		provide a subclass of HardwareBufferManagerBase, which does the actual
+		work, and also a very simple subclass of HardwareBufferManager which 
+		simply constructs the instance of the HardwareBufferManagerBase subclass 
+		and passes it to the HardwareBufferManager superclass as a delegate. 
+		This subclass must also delete the implementation instance it creates.
+	*/
+	class _OgreExport HardwareBufferManagerBase
+	{
+        friend class HardwareVertexBufferSharedPtr;
+        friend class HardwareIndexBufferSharedPtr;
+    protected:
+        /** WARNING: The following two members should place before all other members.
+            Members destruct order is very important here, because destructing other
+            members will cause notify back to this class, and then will access to this
+            two members.
+        */
+        typedef set<HardwareVertexBuffer*>::type VertexBufferList;
+        typedef set<HardwareIndexBuffer*>::type IndexBufferList;
+        VertexBufferList mVertexBuffers;
+        IndexBufferList mIndexBuffers;
+
+
+        typedef set<VertexDeclaration*>::type VertexDeclarationList;
+		typedef set<VertexBufferBinding*>::type VertexBufferBindingList;
+        VertexDeclarationList mVertexDeclarations;
+		VertexBufferBindingList mVertexBufferBindings;
+
+		// Mutexes
+		OGRE_MUTEX(mVertexBuffersMutex)
+		OGRE_MUTEX(mIndexBuffersMutex)
+		OGRE_MUTEX(mVertexDeclarationsMutex)
+		OGRE_MUTEX(mVertexBufferBindingsMutex)
+
+        /// Internal method for destroys all vertex declarations
+        virtual void destroyAllDeclarations(void);
+        /// Internal method for destroys all vertex buffer bindings
+        virtual void destroyAllBindings(void);
+
+        /// Internal method for creates a new vertex declaration, may be overridden by certain rendering APIs
+        virtual VertexDeclaration* createVertexDeclarationImpl(void);
+        /// Internal method for destroys a vertex declaration, may be overridden by certain rendering APIs
+        virtual void destroyVertexDeclarationImpl(VertexDeclaration* decl);
+
+		/// Internal method for creates a new VertexBufferBinding, may be overridden by certain rendering APIs
+		virtual VertexBufferBinding* createVertexBufferBindingImpl(void);
+		/// Internal method for destroys a VertexBufferBinding, may be overridden by certain rendering APIs
+		virtual void destroyVertexBufferBindingImpl(VertexBufferBinding* binding);
+
+    public:
+
+        enum BufferLicenseType
+        {
+            /// Licensee will only release buffer when it says so
+            BLT_MANUAL_RELEASE,
+            /// Licensee can have license revoked
+            BLT_AUTOMATIC_RELEASE
+        };
+
+    protected:
+        /** Struct holding details of a license to use a temporary shared buffer. */
+        class _OgrePrivate VertexBufferLicense
+        {
+        public:
+            HardwareVertexBuffer* originalBufferPtr;
+            BufferLicenseType licenseType;
+            size_t expiredDelay;
+            HardwareVertexBufferSharedPtr buffer;
+            HardwareBufferLicensee* licensee;
+            VertexBufferLicense(
+                HardwareVertexBuffer* orig,
+                BufferLicenseType ltype, 
+                size_t delay,
+                HardwareVertexBufferSharedPtr buf, 
+                HardwareBufferLicensee* lic) 
+                : originalBufferPtr(orig)
+                , licenseType(ltype)
+                , expiredDelay(delay)
+                , buffer(buf)
+                , licensee(lic)
+            {}
+
+        };
+
+        /// Map from original buffer to temporary buffers
+        typedef multimap<HardwareVertexBuffer*, HardwareVertexBufferSharedPtr>::type FreeTemporaryVertexBufferMap;
+        /// Map of current available temp buffers 
+        FreeTemporaryVertexBufferMap mFreeTempVertexBufferMap;
+        /// Map from temporary buffer to details of a license
+        typedef map<HardwareVertexBuffer*, VertexBufferLicense>::type TemporaryVertexBufferLicenseMap;
+        /// Map of currently licensed temporary buffers
+        TemporaryVertexBufferLicenseMap mTempVertexBufferLicenses;
+        /// Number of frames elapsed since temporary buffers utilization was above half the available
+        size_t mUnderUsedFrameCount;
+        /// Number of frames to wait before free unused temporary buffers
+        static const size_t UNDER_USED_FRAME_THRESHOLD;
+        /// Frame delay for BLT_AUTOMATIC_RELEASE temporary buffers
+        static const size_t EXPIRED_DELAY_FRAME_THRESHOLD;
+		// Mutexes
+		OGRE_MUTEX(mTempBuffersMutex)
+
+
+        /// Creates  a new buffer as a copy of the source, does not copy data
+        virtual HardwareVertexBufferSharedPtr makeBufferCopy(
+            const HardwareVertexBufferSharedPtr& source, 
+            HardwareBuffer::Usage usage, bool useShadowBuffer);
+
+    public:
+        HardwareBufferManagerBase();
+        virtual ~HardwareBufferManagerBase();
+		/** Create a hardware vertex buffer.
+        @remarks
+            This method creates a new vertex buffer; this will act as a source of geometry
+            data for rendering objects. Note that because the meaning of the contents of
+            the vertex buffer depends on the usage, this method does not specify a
+            vertex format; the user of this buffer can actually insert whatever data 
+            they wish, in any format. However, in order to use this with a RenderOperation,
+            the data in this vertex buffer will have to be associated with a semantic element
+            of the rendering pipeline, e.g. a position, or texture coordinates. This is done 
+            using the VertexDeclaration class, which itself contains VertexElement structures
+            referring to the source data.
+        @remarks Note that because vertex buffers can be shared, they are reference
+            counted so you do not need to worry about destroying themm this will be done
+            automatically.
+        @param vertexSize The size in bytes of each vertex in this buffer; you must calculate
+            this based on the kind of data you expect to populate this buffer with.
+        @param numVerts The number of vertices in this buffer.
+        @param usage One or more members of the HardwareBuffer::Usage enumeration; you are
+            strongly advised to use HBU_STATIC_WRITE_ONLY wherever possible, if you need to 
+            update regularly, consider HBU_DYNAMIC_WRITE_ONLY and useShadowBuffer=true.
+		@param useShadowBuffer If set to true, this buffer will be 'shadowed' by one stored in 
+            system memory rather than GPU or AGP memory. You should set this flag if you intend 
+            to read data back from the vertex buffer, because reading data from a buffer
+			in the GPU or AGP memory is very expensive, and is in fact impossible if you
+            specify HBU_WRITE_ONLY for the main buffer. If you use this option, all 
+            reads and writes will be done to the shadow buffer, and the shadow buffer will
+            be synchronised with the real buffer at an appropriate time.
+        */
+		virtual HardwareVertexBufferSharedPtr 
+            createVertexBuffer(size_t vertexSize, size_t numVerts, HardwareBuffer::Usage usage, 
+			bool useShadowBuffer = false) = 0;
+		/** Create a hardware index buffer.
+        @remarks Note that because buffers can be shared, they are reference
+            counted so you do not need to worry about destroying them this will be done
+            automatically.
+		@param itype The type in index, either 16- or 32-bit, depending on how many vertices
+			you need to be able to address
+		@param numIndexes The number of indexes in the buffer
+        @param usage One or more members of the HardwareBuffer::Usage enumeration.
+		@param useShadowBuffer If set to true, this buffer will be 'shadowed' by one stored in 
+            system memory rather than GPU or AGP memory. You should set this flag if you intend 
+            to read data back from the index buffer, because reading data from a buffer
+			in the GPU or AGP memory is very expensive, and is in fact impossible if you
+            specify HBU_WRITE_ONLY for the main buffer. If you use this option, all 
+            reads and writes will be done to the shadow buffer, and the shadow buffer will
+            be synchronised with the real buffer at an appropriate time.
+        */
+		virtual HardwareIndexBufferSharedPtr 
+            createIndexBuffer(HardwareIndexBuffer::IndexType itype, size_t numIndexes, 
+			HardwareBuffer::Usage usage, bool useShadowBuffer = false) = 0;
+
+        /** Creates a new vertex declaration. */
+        virtual VertexDeclaration* createVertexDeclaration(void);
+        /** Destroys a vertex declaration. */
+        virtual void destroyVertexDeclaration(VertexDeclaration* decl);
+
+		/** Creates a new VertexBufferBinding. */
+		virtual VertexBufferBinding* createVertexBufferBinding(void);
+		/** Destroys a VertexBufferBinding. */
+		virtual void destroyVertexBufferBinding(VertexBufferBinding* binding);
+
+		/** Registers a vertex buffer as a copy of another.
+		@remarks
+			This is useful for registering an existing buffer as a temporary buffer
+			which can be allocated just like a copy.
+		*/
+		virtual void registerVertexBufferSourceAndCopy(
+			const HardwareVertexBufferSharedPtr& sourceBuffer,
+			const HardwareVertexBufferSharedPtr& copy);
+
+        /** Allocates a copy of a given vertex buffer.
+        @remarks
+            This method allocates a temporary copy of an existing vertex buffer.
+            This buffer is subsequently stored and can be made available for 
+            other purposes later without incurring the cost of construction / 
+            destruction.
+        @param sourceBuffer The source buffer to use as a copy
+        @param licenseType The type of license required on this buffer - automatic
+            release causes this class to release licenses every frame so that 
+            they can be reallocated anew.
+        @param licensee Pointer back to the class requesting the copy, which must
+            implement HardwareBufferLicense in order to be notified when the license
+            expires.
+        @param copyData If true, the current data is copied as well as the 
+            structure of the buffer
+        */
+        virtual HardwareVertexBufferSharedPtr allocateVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& sourceBuffer, 
+            BufferLicenseType licenseType,
+            HardwareBufferLicensee* licensee,
+            bool copyData = false);
+
+        /** Manually release a vertex buffer copy for others to subsequently use.
+        @remarks
+            Only required if the original call to allocateVertexBufferCopy
+            included a licenseType of BLT_MANUAL_RELEASE. 
+        @param bufferCopy The buffer copy. The caller is expected to delete
+            or at least no longer use this reference, since another user may
+            well begin to modify the contents of the buffer.
+        */
+        virtual void releaseVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& bufferCopy); 
+
+        /** Tell engine that the vertex buffer copy intent to reuse.
+        @remarks
+            Ogre internal keep an expired delay counter of BLT_AUTOMATIC_RELEASE
+            buffers, when the counter count down to zero, it'll release for other
+            purposes later. But you can use this function to reset the counter to
+            the internal configured value, keep the buffer not get released for
+            some frames.
+        @param bufferCopy The buffer copy. The caller is expected to keep this
+            buffer copy for use.
+        */
+        virtual void touchVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& bufferCopy);
+
+        /** Free all unused vertex buffer copies.
+        @remarks
+            This method free all temporary vertex buffers that not in used.
+            In normally, temporary vertex buffers are subsequently stored and can
+            be made available for other purposes later without incurring the cost
+            of construction / destruction. But in some cases you want to free them
+            to save hardware memory (e.g. application was runs in a long time, you
+            might free temporary buffers periodically to avoid memory overload).
+        */
+        virtual void _freeUnusedBufferCopies(void);
+
+        /** Internal method for releasing all temporary buffers which have been 
+           allocated using BLT_AUTOMATIC_RELEASE; is called by OGRE.
+        @param forceFreeUnused If true, free all unused temporary buffers.
+            If false, auto detect and free all unused temporary buffers based on
+            temporary buffers utilization.
+        */
+        virtual void _releaseBufferCopies(bool forceFreeUnused = false);
+
+        /** Internal method that forces the release of copies of a given buffer.
+        @remarks
+            This usually means that the buffer which the copies are based on has
+            been changed in some fundamental way, and the owner of the original 
+            wishes to make that known so that new copies will reflect the
+            changes.
+        @param sourceBuffer the source buffer as a shared pointer.  Any buffer copies created from the source buffer
+            are deleted.
+        */
+        virtual void _forceReleaseBufferCopies(
+            const HardwareVertexBufferSharedPtr& sourceBuffer);
+
+        /** Internal method that forces the release of copies of a given buffer.
+        @remarks
+            This usually means that the buffer which the copies are based on has
+            been changed in some fundamental way, and the owner of the original 
+            wishes to make that known so that new copies will reflect the
+            changes.
+        @param sourceBuffer the source buffer as a pointer.  Any buffer copies created from the source buffer
+            are deleted.
+        */
+        virtual void _forceReleaseBufferCopies(HardwareVertexBuffer* sourceBuffer);
+
+		/// Notification that a hardware vertex buffer has been destroyed
+		void _notifyVertexBufferDestroyed(HardwareVertexBuffer* buf);
+		/// Notification that a hardware index buffer has been destroyed
+		void _notifyIndexBufferDestroyed(HardwareIndexBuffer* buf);
+
+	};
+
+    /** Singleton wrapper for hardware buffer manager. */
+    class _OgreExport HardwareBufferManager : public HardwareBufferManagerBase, public Singleton<HardwareBufferManager>
+    {
+        friend class HardwareVertexBufferSharedPtr;
+        friend class HardwareIndexBufferSharedPtr;
+    protected:
+		HardwareBufferManagerBase* mImpl;
+	public:
+		HardwareBufferManager(HardwareBufferManagerBase* imp);
+		~HardwareBufferManager();
+
+		/** @copydoc HardwareBufferManagerInterface::createVertexBuffer */
+		HardwareVertexBufferSharedPtr 
+            createVertexBuffer(size_t vertexSize, size_t numVerts, HardwareBuffer::Usage usage, 
+			bool useShadowBuffer = false)
+		{
+			return mImpl->createVertexBuffer(vertexSize, numVerts, usage, useShadowBuffer);
+		}
+		/** @copydoc HardwareBufferManagerInterface::createIndexBuffer */
+		HardwareIndexBufferSharedPtr 
+            createIndexBuffer(HardwareIndexBuffer::IndexType itype, size_t numIndexes, 
+			HardwareBuffer::Usage usage, bool useShadowBuffer = false)
+		{
+			return mImpl->createIndexBuffer(itype, numIndexes, usage, useShadowBuffer);
+		}
+
+		/** @copydoc HardwareBufferManagerInterface::createVertexDeclaration */
+		virtual VertexDeclaration* createVertexDeclaration(void)
+		{
+			return mImpl->createVertexDeclaration();
+		}
+		/** @copydoc HardwareBufferManagerInterface::destroyVertexDeclaration */
+        virtual void destroyVertexDeclaration(VertexDeclaration* decl)
+		{
+			mImpl->destroyVertexDeclaration(decl);
+		}
+
+		/** @copydoc HardwareBufferManagerInterface::createVertexBufferBinding */
+		virtual VertexBufferBinding* createVertexBufferBinding(void)
+		{
+			return mImpl->createVertexBufferBinding();
+		}
+		/** @copydoc HardwareBufferManagerInterface::destroyVertexBufferBinding */
+		virtual void destroyVertexBufferBinding(VertexBufferBinding* binding)
+		{
+			mImpl->destroyVertexBufferBinding(binding);
+		}
+		/** @copydoc HardwareBufferManagerInterface::registerVertexBufferSourceAndCopy */
+		virtual void registerVertexBufferSourceAndCopy(
+			const HardwareVertexBufferSharedPtr& sourceBuffer,
+			const HardwareVertexBufferSharedPtr& copy)
+		{
+			mImpl->registerVertexBufferSourceAndCopy(sourceBuffer, copy);
+		}
+		/** @copydoc HardwareBufferManagerInterface::allocateVertexBufferCopy */
+        virtual HardwareVertexBufferSharedPtr allocateVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& sourceBuffer, 
+            BufferLicenseType licenseType,
+            HardwareBufferLicensee* licensee,
+            bool copyData = false)
+		{
+			return mImpl->allocateVertexBufferCopy(sourceBuffer, licenseType, licensee, copyData);
+		}
+		/** @copydoc HardwareBufferManagerInterface::releaseVertexBufferCopy */
+        virtual void releaseVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& bufferCopy)
+		{
+			mImpl->releaseVertexBufferCopy(bufferCopy);
+		}
+
+		/** @copydoc HardwareBufferManagerInterface::touchVertexBufferCopy */
+        virtual void touchVertexBufferCopy(
+            const HardwareVertexBufferSharedPtr& bufferCopy)
+		{
+			mImpl->touchVertexBufferCopy(bufferCopy);
+		}
+
+		/** @copydoc HardwareBufferManagerInterface::_freeUnusedBufferCopies */
+        virtual void _freeUnusedBufferCopies(void)
+		{
+			mImpl->_freeUnusedBufferCopies();
+		}
+		/** @copydoc HardwareBufferManagerInterface::_releaseBufferCopies */
+        virtual void _releaseBufferCopies(bool forceFreeUnused = false)
+		{
+			mImpl->_releaseBufferCopies(forceFreeUnused);
+		}
+		/** @copydoc HardwareBufferManagerInterface::_forceReleaseBufferCopies */
+        virtual void _forceReleaseBufferCopies(
+            const HardwareVertexBufferSharedPtr& sourceBuffer)
+		{
+			mImpl->_forceReleaseBufferCopies(sourceBuffer);
+		}
+		/** @copydoc HardwareBufferManagerInterface::_forceReleaseBufferCopies */
+        virtual void _forceReleaseBufferCopies(HardwareVertexBuffer* sourceBuffer)
+		{
+			mImpl->_forceReleaseBufferCopies(sourceBuffer);
+		}
+		/** @copydoc HardwareBufferManagerInterface::_notifyVertexBufferDestroyed */
+		void _notifyVertexBufferDestroyed(HardwareVertexBuffer* buf)
+		{
+			mImpl->_notifyVertexBufferDestroyed(buf);
+		}
+		/** @copydoc HardwareBufferManagerInterface::_notifyIndexBufferDestroyed */
+		void _notifyIndexBufferDestroyed(HardwareIndexBuffer* buf)
+		{
+			mImpl->_notifyIndexBufferDestroyed(buf);
+		}
+
+
+        /** Override standard Singleton retrieval.
+        @remarks
+        Why do we do this? Well, it's because the Singleton
+        implementation is in a .h file, which means it gets compiled
+        into anybody who includes it. This is needed for the
+        Singleton template to work, but we actually only want it
+        compiled into the implementation of the class based on the
+        Singleton, not all of them. If we don't change this, we get
+        link errors when trying to use the Singleton-based class from
+        an outside dll.
+        @par
+        This method just delegates to the template version anyway,
+        but the implementation stays in this single compilation unit,
+        preventing link errors.
+        */
+        static HardwareBufferManager& getSingleton(void);
+        /** Override standard Singleton retrieval.
+        @remarks
+        Why do we do this? Well, it's because the Singleton
+        implementation is in a .h file, which means it gets compiled
+        into anybody who includes it. This is needed for the
+        Singleton template to work, but we actually only want it
+        compiled into the implementation of the class based on the
+        Singleton, not all of them. If we don't change this, we get
+        link errors when trying to use the Singleton-based class from
+        an outside dll.
+        @par
+        This method just delegates to the template version anyway,
+        but the implementation stays in this single compilation unit,
+        preventing link errors.
+        */
+        static HardwareBufferManager* getSingletonPtr(void);
+            
+    };
+
+	/** @} */
+	/** @} */
+}
+
+#endif
+

+ 87 - 0
CamelotRenderer/OgreHardwareIndexBuffer.cpp

@@ -0,0 +1,87 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreHardwareIndexBuffer.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreDefaultHardwareBufferManager.h"
+
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------------
+    HardwareIndexBuffer::HardwareIndexBuffer(HardwareBufferManagerBase* mgr, IndexType idxType, 
+        size_t numIndexes, HardwareBuffer::Usage usage, 
+        bool useSystemMemory, bool useShadowBuffer) 
+        : HardwareBuffer(usage, useSystemMemory, useShadowBuffer)
+		, mMgr(mgr)
+		, mIndexType(idxType)
+		, mNumIndexes(numIndexes)
+    {
+        // Calculate the size of the indexes
+        switch (mIndexType)
+        {
+        case IT_16BIT:
+            mIndexSize = sizeof(unsigned short);
+            break;
+        case IT_32BIT:
+            mIndexSize = sizeof(unsigned int);
+            break;
+        }
+        mSizeInBytes = mIndexSize * mNumIndexes;
+
+        // Create a shadow buffer if required
+        if (mUseShadowBuffer)
+        {
+            mpShadowBuffer = OGRE_NEW DefaultHardwareIndexBuffer(mIndexType, 
+                mNumIndexes, HardwareBuffer::HBU_DYNAMIC);
+        }
+
+
+    }
+    //-----------------------------------------------------------------------------
+    HardwareIndexBuffer::~HardwareIndexBuffer()
+    {
+		if (mMgr)
+		{
+			mMgr->_notifyIndexBufferDestroyed(this);
+		}
+
+        if (mpShadowBuffer)
+        {
+            OGRE_DELETE mpShadowBuffer;
+        }
+    }
+    //-----------------------------------------------------------------------------
+    HardwareIndexBufferSharedPtr::HardwareIndexBufferSharedPtr(HardwareIndexBuffer* buf)
+        : SharedPtr<HardwareIndexBuffer>(buf)
+    {
+
+    }
+
+}
+

+ 89 - 0
CamelotRenderer/OgreHardwareIndexBuffer.h

@@ -0,0 +1,89 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __HardwareIndexBuffer__
+#define __HardwareIndexBuffer__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreHardwareBuffer.h"
+#include "OgreSharedPtr.h"
+
+namespace Ogre {
+	class HardwareBufferManagerBase;
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** Specialisation of HardwareBuffer for vertex index buffers, still abstract. */
+    class _OgreExport HardwareIndexBuffer : public HardwareBuffer
+    {
+	    public:
+		    enum IndexType {
+			    IT_16BIT,
+			    IT_32BIT
+		    };
+
+	    protected:
+			HardwareBufferManagerBase* mMgr;
+		    IndexType mIndexType;
+		    size_t mNumIndexes;
+            size_t mIndexSize;
+
+	    public:
+		    /// Should be called by HardwareBufferManager
+		    HardwareIndexBuffer(HardwareBufferManagerBase* mgr, IndexType idxType, size_t numIndexes, HardwareBuffer::Usage usage,
+                bool useSystemMemory, bool useShadowBuffer);
+            ~HardwareIndexBuffer();
+			/// Return the manager of this buffer, if any
+			HardwareBufferManagerBase* getManager() const { return mMgr; }
+    		/// Get the type of indexes used in this buffer
+            IndexType getType(void) const { return mIndexType; }
+            /// Get the number of indexes in this buffer
+            size_t getNumIndexes(void) const { return mNumIndexes; }
+            /// Get the size in bytes of each index
+            size_t getIndexSize(void) const { return mIndexSize; }
+
+		    // NB subclasses should override lock, unlock, readData, writeData
+    };
+
+
+    /** Shared pointer implementation used to share index buffers. */
+    class _OgreExport HardwareIndexBufferSharedPtr : public SharedPtr<HardwareIndexBuffer>
+    {
+    public:
+        HardwareIndexBufferSharedPtr() : SharedPtr<HardwareIndexBuffer>() {}
+        explicit HardwareIndexBufferSharedPtr(HardwareIndexBuffer* buf);
+    };
+	/** @} */
+	/** @} */
+}
+#endif
+

+ 686 - 0
CamelotRenderer/OgreHardwareVertexBuffer.cpp

@@ -0,0 +1,686 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreColourValue.h"
+#include "OgreException.h"
+#include "OgreStringConverter.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreDefaultHardwareBufferManager.h"
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------------
+    HardwareVertexBuffer::HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,  
+        size_t numVertices, HardwareBuffer::Usage usage, 
+        bool useSystemMemory, bool useShadowBuffer) 
+        : HardwareBuffer(usage, useSystemMemory, useShadowBuffer), 
+		  mMgr(mgr),
+          mNumVertices(numVertices),
+          mVertexSize(vertexSize)
+    {
+        // Calculate the size of the vertices
+        mSizeInBytes = mVertexSize * numVertices;
+
+        // Create a shadow buffer if required
+        if (mUseShadowBuffer)
+        {
+            mpShadowBuffer = OGRE_NEW DefaultHardwareVertexBuffer(mMgr, mVertexSize, 
+                    mNumVertices, HardwareBuffer::HBU_DYNAMIC);
+        }
+
+    }
+    //-----------------------------------------------------------------------------
+    HardwareVertexBuffer::~HardwareVertexBuffer()
+    {
+		if (mMgr)
+		{
+			mMgr->_notifyVertexBufferDestroyed(this);
+		}
+        if (mpShadowBuffer)
+        {
+            OGRE_DELETE mpShadowBuffer;
+        }
+    }
+    //-----------------------------------------------------------------------------
+    VertexElement::VertexElement(unsigned short source, size_t offset, 
+        VertexElementType theType, VertexElementSemantic semantic, unsigned short index)
+        : mSource(source), mOffset(offset), mType(theType), 
+        mSemantic(semantic), mIndex(index)
+    {
+    }
+    //-----------------------------------------------------------------------------
+	size_t VertexElement::getSize(void) const
+	{
+		return getTypeSize(mType);
+	}
+	//-----------------------------------------------------------------------------
+	size_t VertexElement::getTypeSize(VertexElementType etype)
+	{
+		switch(etype)
+		{
+		case VET_COLOUR:
+		case VET_COLOUR_ABGR:
+		case VET_COLOUR_ARGB:
+			return sizeof(RGBA);
+		case VET_FLOAT1:
+			return sizeof(float);
+		case VET_FLOAT2:
+			return sizeof(float)*2;
+		case VET_FLOAT3:
+			return sizeof(float)*3;
+		case VET_FLOAT4:
+			return sizeof(float)*4;
+		case VET_SHORT1:
+			return sizeof(short);
+		case VET_SHORT2:
+			return sizeof(short)*2;
+		case VET_SHORT3:
+			return sizeof(short)*3;
+		case VET_SHORT4:
+			return sizeof(short)*4;
+        case VET_UBYTE4:
+            return sizeof(unsigned char)*4;
+		}
+		return 0;
+	}
+	//-----------------------------------------------------------------------------
+	unsigned short VertexElement::getTypeCount(VertexElementType etype)
+	{
+		switch (etype)
+		{
+		case VET_COLOUR:
+		case VET_COLOUR_ABGR:
+		case VET_COLOUR_ARGB:
+			return 1;
+		case VET_FLOAT1:
+			return 1;
+		case VET_FLOAT2:
+			return 2;
+		case VET_FLOAT3:
+			return 3;
+		case VET_FLOAT4:
+			return 4;
+		case VET_SHORT1:
+			return 1;
+		case VET_SHORT2:
+			return 2;
+		case VET_SHORT3:
+			return 3;
+		case VET_SHORT4:
+			return 4;
+        case VET_UBYTE4:
+            return 4;
+		}
+		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid type", 
+			"VertexElement::getTypeCount");
+	}
+	//-----------------------------------------------------------------------------
+	VertexElementType VertexElement::multiplyTypeCount(VertexElementType baseType, 
+		unsigned short count)
+	{
+		switch (baseType)
+		{
+		case VET_FLOAT1:
+			switch(count)
+			{
+			case 1:
+				return VET_FLOAT1;
+			case 2:
+				return VET_FLOAT2;
+			case 3:
+				return VET_FLOAT3;
+			case 4:
+				return VET_FLOAT4;
+            default:
+                break;
+			}
+			break;
+		case VET_SHORT1:
+			switch(count)
+			{
+			case 1:
+				return VET_SHORT1;
+			case 2:
+				return VET_SHORT2;
+			case 3:
+				return VET_SHORT3;
+			case 4:
+				return VET_SHORT4;
+            default:
+                break;
+			}
+			break;
+        default:
+            break;
+		}
+		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid base type", 
+			"VertexElement::multiplyTypeCount");
+	}
+	//--------------------------------------------------------------------------
+	VertexElementType VertexElement::getBestColourVertexElementType(void)
+	{
+		// Use the current render system to determine if possible
+		// TODO PORT - Requires singleton to render system and I don't have that yet, but I will once port is complete
+		//if (Root::getSingletonPtr() && Root::getSingletonPtr()->getRenderSystem())
+		//{
+		//	return Root::getSingleton().getRenderSystem()->getColourVertexElementType();
+		//}
+		//else
+		// END PORT
+		{
+			// We can't know the specific type right now, so pick a type
+			// based on platform
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+			return VET_COLOUR_ARGB; // prefer D3D format on windows
+#else
+			return VET_COLOUR_ABGR; // prefer GL format on everything else
+#endif
+
+		}
+	}
+	//--------------------------------------------------------------------------
+	void VertexElement::convertColourValue(VertexElementType srcType, 
+		VertexElementType dstType, uint32* ptr)
+	{
+		if (srcType == dstType)
+			return;
+
+		// Conversion between ARGB and ABGR is always a case of flipping R/B
+		*ptr = 
+		   ((*ptr&0x00FF0000)>>16)|((*ptr&0x000000FF)<<16)|(*ptr&0xFF00FF00);				
+	}
+	//--------------------------------------------------------------------------
+	uint32 VertexElement::convertColourValue(const ColourValue& src, 
+		VertexElementType dst)
+	{
+		switch(dst)
+		{
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+        default:
+#endif
+		case VET_COLOUR_ARGB:
+			return src.getAsARGB();
+#if OGRE_PLATFORM != OGRE_PLATFORM_WIN32
+        default:
+#endif
+		case VET_COLOUR_ABGR: 
+			return src.getAsABGR();
+		};
+
+	}
+	//-----------------------------------------------------------------------------
+	VertexElementType VertexElement::getBaseType(VertexElementType multiType)
+	{
+		switch (multiType)
+		{
+			case VET_FLOAT1:
+			case VET_FLOAT2:
+			case VET_FLOAT3:
+			case VET_FLOAT4:
+				return VET_FLOAT1;
+			case VET_COLOUR:
+				return VET_COLOUR;
+			case VET_COLOUR_ABGR:
+				return VET_COLOUR_ABGR;
+			case VET_COLOUR_ARGB:
+				return VET_COLOUR_ARGB;
+			case VET_SHORT1:
+			case VET_SHORT2:
+			case VET_SHORT3:
+			case VET_SHORT4:
+				return VET_SHORT1;
+			case VET_UBYTE4:
+				return VET_UBYTE4;
+		};
+        // To keep compiler happy
+        return VET_FLOAT1;
+	}
+	//-----------------------------------------------------------------------------
+    VertexDeclaration::VertexDeclaration()
+    {
+    }
+    //-----------------------------------------------------------------------------
+    VertexDeclaration::~VertexDeclaration()
+    {
+    }
+    //-----------------------------------------------------------------------------
+    const VertexDeclaration::VertexElementList& VertexDeclaration::getElements(void) const
+    {
+        return mElementList;
+    }
+    //-----------------------------------------------------------------------------
+    const VertexElement& VertexDeclaration::addElement(unsigned short source, 
+        size_t offset, VertexElementType theType,
+        VertexElementSemantic semantic, unsigned short index)
+    {
+		// Refine colour type to a specific type
+		if (theType == VET_COLOUR)
+		{
+			theType = VertexElement::getBestColourVertexElementType();
+		}
+        mElementList.push_back(
+            VertexElement(source, offset, theType, semantic, index)
+            );
+		return mElementList.back();
+    }
+    //-----------------------------------------------------------------------------
+    const VertexElement& VertexDeclaration::insertElement(unsigned short atPosition,
+        unsigned short source, size_t offset, VertexElementType theType,
+        VertexElementSemantic semantic, unsigned short index)
+    {
+        if (atPosition >= mElementList.size())
+        {
+            return addElement(source, offset, theType, semantic, index);
+        }
+
+        VertexElementList::iterator i = mElementList.begin();
+        for (unsigned short n = 0; n < atPosition; ++n)
+            ++i;
+
+        i = mElementList.insert(i, 
+            VertexElement(source, offset, theType, semantic, index));
+        return *i;
+
+    }
+    //-----------------------------------------------------------------------------
+    const VertexElement* VertexDeclaration::getElement(unsigned short index)
+    {
+        assert(index < mElementList.size() && "Index out of bounds");
+
+        VertexElementList::iterator i = mElementList.begin();
+        for (unsigned short n = 0; n < index; ++n)
+            ++i;
+
+        return &(*i);
+
+    }
+    //-----------------------------------------------------------------------------
+    void VertexDeclaration::removeElement(unsigned short elem_index)
+    {
+        assert(elem_index < mElementList.size() && "Index out of bounds");
+        VertexElementList::iterator i = mElementList.begin();
+        for (unsigned short n = 0; n < elem_index; ++n)
+            ++i;
+        mElementList.erase(i);
+    }
+    //-----------------------------------------------------------------------------
+    void VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index)
+    {
+		VertexElementList::iterator ei, eiend;
+		eiend = mElementList.end();
+		for (ei = mElementList.begin(); ei != eiend; ++ei)
+		{
+			if (ei->getSemantic() == semantic && ei->getIndex() == index)
+			{
+				mElementList.erase(ei);
+                break;
+			}
+		}
+    }
+	//-----------------------------------------------------------------------------
+	void VertexDeclaration::removeAllElements(void)
+	{
+		mElementList.clear();
+	}
+    //-----------------------------------------------------------------------------
+    void VertexDeclaration::modifyElement(unsigned short elem_index, 
+        unsigned short source, size_t offset, VertexElementType theType,
+        VertexElementSemantic semantic, unsigned short index)
+    {
+        assert(elem_index < mElementList.size() && "Index out of bounds");
+        VertexElementList::iterator i = mElementList.begin();
+        std::advance(i, elem_index);
+        (*i) = VertexElement(source, offset, theType, semantic, index);
+    }
+    //-----------------------------------------------------------------------------
+	const VertexElement* VertexDeclaration::findElementBySemantic(
+		VertexElementSemantic sem, unsigned short index)
+	{
+		VertexElementList::const_iterator ei, eiend;
+		eiend = mElementList.end();
+		for (ei = mElementList.begin(); ei != eiend; ++ei)
+		{
+			if (ei->getSemantic() == sem && ei->getIndex() == index)
+			{
+				return &(*ei);
+			}
+		}
+
+		return NULL;
+
+
+	}
+	//-----------------------------------------------------------------------------
+	VertexDeclaration::VertexElementList VertexDeclaration::findElementsBySource(
+		unsigned short source)
+	{
+		VertexElementList retList;
+		VertexElementList::const_iterator ei, eiend;
+		eiend = mElementList.end();
+		for (ei = mElementList.begin(); ei != eiend; ++ei)
+		{
+			if (ei->getSource() == source)
+			{
+				retList.push_back(*ei);
+			}
+		}
+		return retList;
+
+	}
+
+	//-----------------------------------------------------------------------------
+	size_t VertexDeclaration::getVertexSize(unsigned short source)
+	{
+		VertexElementList::const_iterator i, iend;
+		iend = mElementList.end();
+		size_t sz = 0;
+
+		for (i = mElementList.begin(); i != iend; ++i)
+		{
+			if (i->getSource() == source)
+			{
+				sz += i->getSize();
+
+			}
+		}
+		return sz;
+	}
+    //-----------------------------------------------------------------------------
+    VertexDeclaration* VertexDeclaration::clone(HardwareBufferManagerBase* mgr)
+    {
+		HardwareBufferManagerBase* pManager = mgr ? mgr : HardwareBufferManager::getSingletonPtr(); 
+        VertexDeclaration* ret = pManager->createVertexDeclaration();
+
+		VertexElementList::const_iterator i, iend;
+		iend = mElementList.end();
+		for (i = mElementList.begin(); i != iend; ++i)
+		{
+            ret->addElement(i->getSource(), i->getOffset(), i->getType(), i->getSemantic(), i->getIndex());
+        }
+        return ret;
+    }
+    //-----------------------------------------------------------------------------
+    // Sort routine for VertexElement
+    bool VertexDeclaration::vertexElementLess(const VertexElement& e1, const VertexElement& e2)
+    {
+        // Sort by source first
+        if (e1.getSource() < e2.getSource())
+        {
+            return true;
+        }
+        else if (e1.getSource() == e2.getSource())
+        {
+            // Use ordering of semantics to sort
+            if (e1.getSemantic() < e2.getSemantic())
+            {
+                return true;
+            }
+            else if (e1.getSemantic() == e2.getSemantic())
+            {
+                // Use index to sort
+                if (e1.getIndex() < e2.getIndex())
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    void VertexDeclaration::sort(void)
+    {
+        mElementList.sort(VertexDeclaration::vertexElementLess);
+    }
+    //-----------------------------------------------------------------------------
+    void VertexDeclaration::closeGapsInSource(void)
+    {
+        if (mElementList.empty())
+            return;
+
+        // Sort first
+        sort();
+
+        VertexElementList::iterator i, iend;
+        iend = mElementList.end();
+        unsigned short targetIdx = 0;
+        unsigned short lastIdx = getElement(0)->getSource();
+        unsigned short c = 0;
+        for (i = mElementList.begin(); i != iend; ++i, ++c)
+        {
+            VertexElement& elem = *i;
+            if (lastIdx != elem.getSource())
+            {
+                targetIdx++;
+                lastIdx = elem.getSource();
+            }
+            if (targetIdx != elem.getSource())
+            {
+                modifyElement(c, targetIdx, elem.getOffset(), elem.getType(), 
+                    elem.getSemantic(), elem.getIndex());
+            }
+
+        }
+
+    }
+    //-----------------------------------------------------------------------
+    VertexDeclaration* VertexDeclaration::getAutoOrganisedDeclaration(
+		bool skeletalAnimation, bool vertexAnimation)
+    {
+        VertexDeclaration* newDecl = this->clone();
+        // Set all sources to the same buffer (for now)
+        const VertexDeclaration::VertexElementList& elems = newDecl->getElements();
+        VertexDeclaration::VertexElementList::const_iterator i;
+        unsigned short c = 0;
+        for (i = elems.begin(); i != elems.end(); ++i, ++c)
+        {
+            const VertexElement& elem = *i;
+            // Set source & offset to 0 for now, before sort
+            newDecl->modifyElement(c, 0, 0, elem.getType(), elem.getSemantic(), elem.getIndex());
+        }
+        newDecl->sort();
+        // Now sort out proper buffer assignments and offsets
+        size_t offset = 0;
+        c = 0;
+		unsigned short buffer = 0;
+        VertexElementSemantic prevSemantic = VES_POSITION;
+        for (i = elems.begin(); i != elems.end(); ++i, ++c)
+        {
+            const VertexElement& elem = *i;
+
+            bool splitWithPrev = false;
+            bool splitWithNext = false;
+            switch (elem.getSemantic())
+            {
+            case VES_POSITION:
+                // For morph animation, we need positions on their own
+                splitWithPrev = vertexAnimation;
+                splitWithNext = vertexAnimation;
+                break;
+            case VES_NORMAL:
+                // Normals can't sharing with blend weights/indices
+                splitWithPrev = (prevSemantic == VES_BLEND_WEIGHTS || prevSemantic == VES_BLEND_INDICES);
+                // All animated meshes have to split after normal
+                splitWithNext = (skeletalAnimation || vertexAnimation);
+                break;
+            case VES_BLEND_WEIGHTS:
+                // Blend weights/indices can be sharing with their own buffer only
+                splitWithPrev = true;
+                break;
+            case VES_BLEND_INDICES:
+                // Blend weights/indices can be sharing with their own buffer only
+                splitWithNext = true;
+                break;
+            case VES_DIFFUSE:
+            case VES_SPECULAR:
+            case VES_TEXTURE_COORDINATES:
+            case VES_BINORMAL:
+            case VES_TANGENT:
+                break;
+            }
+
+            if (splitWithPrev && offset)
+            {
+                ++buffer;
+                offset = 0;
+            }
+
+            prevSemantic = elem.getSemantic();
+            newDecl->modifyElement(c, buffer, offset,
+                elem.getType(), elem.getSemantic(), elem.getIndex());
+
+            if (splitWithNext)
+            {
+                ++buffer;
+                offset = 0;
+            }
+            else
+            {
+                offset += elem.getSize();
+            }
+        }
+
+        return newDecl;
+
+
+    }
+    //-----------------------------------------------------------------------------
+    unsigned short VertexDeclaration::getMaxSource(void) const
+    {
+        VertexElementList::const_iterator i, iend;
+        iend = mElementList.end();
+        unsigned short ret = 0;
+        for (i = mElementList.begin(); i != iend; ++i)
+        {
+            if (i->getSource() > ret)
+            {
+                ret = i->getSource();
+            }
+
+        }
+        return ret;
+    }
+    //-----------------------------------------------------------------------------
+	VertexBufferBinding::VertexBufferBinding() : mHighIndex(0)
+	{
+	}
+    //-----------------------------------------------------------------------------
+	VertexBufferBinding::~VertexBufferBinding()
+	{
+        unsetAllBindings();
+	}
+    //-----------------------------------------------------------------------------
+	void VertexBufferBinding::setBinding(unsigned short index, const HardwareVertexBufferSharedPtr& buffer)
+	{
+        // NB will replace any existing buffer ptr at this index, and will thus cause
+        // reference count to decrement on that buffer (possibly destroying it)
+		mBindingMap[index] = buffer;
+		mHighIndex = std::max(mHighIndex, (unsigned short)(index+1));
+	}
+    //-----------------------------------------------------------------------------
+	void VertexBufferBinding::unsetBinding(unsigned short index)
+	{
+		VertexBufferBindingMap::iterator i = mBindingMap.find(index);
+		if (i == mBindingMap.end())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+				"Cannot find buffer binding for index " + StringConverter::toString(index),
+				"VertexBufferBinding::unsetBinding");
+		}
+		mBindingMap.erase(i);
+	}
+    //-----------------------------------------------------------------------------
+    void VertexBufferBinding::unsetAllBindings(void)
+    {
+        mBindingMap.clear();
+        mHighIndex = 0;
+    }
+    //-----------------------------------------------------------------------------
+	const VertexBufferBinding::VertexBufferBindingMap& 
+	VertexBufferBinding::getBindings(void) const
+	{
+		return mBindingMap;
+	}
+    //-----------------------------------------------------------------------------
+	const HardwareVertexBufferSharedPtr& VertexBufferBinding::getBuffer(unsigned short index) const
+	{
+		VertexBufferBindingMap::const_iterator i = mBindingMap.find(index);
+		if (i == mBindingMap.end())
+		{
+			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "No buffer is bound to that index.",
+				"VertexBufferBinding::getBuffer");
+		}
+		return i->second;
+	}
+	//-----------------------------------------------------------------------------
+	bool VertexBufferBinding::isBufferBound(unsigned short index) const
+	{
+		return mBindingMap.find(index) != mBindingMap.end();
+	}
+    //-----------------------------------------------------------------------------
+    unsigned short VertexBufferBinding::getLastBoundIndex(void) const
+    {
+        return mBindingMap.empty() ? 0 : mBindingMap.rbegin()->first + 1;
+    }
+    //-----------------------------------------------------------------------------
+    bool VertexBufferBinding::hasGaps(void) const
+    {
+        if (mBindingMap.empty())
+            return false;
+        if (mBindingMap.rbegin()->first + 1 == (int) mBindingMap.size())
+            return false;
+        return true;
+    }
+    //-----------------------------------------------------------------------------
+    void VertexBufferBinding::closeGaps(BindingIndexMap& bindingIndexMap)
+    {
+        bindingIndexMap.clear();
+
+        VertexBufferBindingMap newBindingMap;
+
+        VertexBufferBindingMap::const_iterator it;
+        ushort targetIndex = 0;
+        for (it = mBindingMap.begin(); it != mBindingMap.end(); ++it, ++targetIndex)
+        {
+            bindingIndexMap[it->first] = targetIndex;
+            newBindingMap[targetIndex] = it->second;
+        }
+
+        mBindingMap.swap(newBindingMap);
+        mHighIndex = targetIndex;
+    }
+    //-----------------------------------------------------------------------------
+    HardwareVertexBufferSharedPtr::HardwareVertexBufferSharedPtr(HardwareVertexBuffer* buf)
+        : SharedPtr<HardwareVertexBuffer>(buf)
+    {
+
+    }
+
+
+
+
+}

+ 560 - 0
CamelotRenderer/OgreHardwareVertexBuffer.h

@@ -0,0 +1,560 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __HardwareVertexBuffer__
+#define __HardwareVertexBuffer__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreHardwareBuffer.h"
+#include "OgreSharedPtr.h"
+#include "OgreColourValue.h"
+
+namespace Ogre {
+	class HardwareBufferManagerBase;
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** Specialisation of HardwareBuffer for a vertex buffer. */
+    class _OgreExport HardwareVertexBuffer : public HardwareBuffer
+    {
+	    protected:
+
+			HardwareBufferManagerBase* mMgr;
+		    size_t mNumVertices;
+            size_t mVertexSize;
+
+	    public:
+		    /// Should be called by HardwareBufferManager
+		    HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize, size_t numVertices,
+                HardwareBuffer::Usage usage, bool useSystemMemory, bool useShadowBuffer);
+            ~HardwareVertexBuffer();
+			/// Return the manager of this buffer, if any
+			HardwareBufferManagerBase* getManager() const { return mMgr; }
+            /// Gets the size in bytes of a single vertex in this buffer
+            size_t getVertexSize(void) const { return mVertexSize; }
+            /// Get the number of vertices in this buffer
+            size_t getNumVertices(void) const { return mNumVertices; }
+
+
+
+		    // NB subclasses should override lock, unlock, readData, writeData
+
+    };
+
+    /** Shared pointer implementation used to share index buffers. */
+    class _OgreExport HardwareVertexBufferSharedPtr : public SharedPtr<HardwareVertexBuffer>
+    {
+    public:
+        HardwareVertexBufferSharedPtr() : SharedPtr<HardwareVertexBuffer>() {}
+        explicit HardwareVertexBufferSharedPtr(HardwareVertexBuffer* buf);
+
+
+    };
+
+    /// Vertex element semantics, used to identify the meaning of vertex buffer contents
+	enum VertexElementSemantic {
+		/// Position, 3 reals per vertex
+		VES_POSITION = 1,
+		/// Blending weights
+		VES_BLEND_WEIGHTS = 2,
+        /// Blending indices
+        VES_BLEND_INDICES = 3,
+		/// Normal, 3 reals per vertex
+		VES_NORMAL = 4,
+		/// Diffuse colours
+		VES_DIFFUSE = 5,
+		/// Specular colours
+		VES_SPECULAR = 6,
+		/// Texture coordinates
+		VES_TEXTURE_COORDINATES = 7,
+        /// Binormal (Y axis if normal is Z)
+        VES_BINORMAL = 8,
+        /// Tangent (X axis if normal is Z)
+        VES_TANGENT = 9
+
+	};
+
+    /// Vertex element type, used to identify the base types of the vertex contents
+    enum VertexElementType
+    {
+        VET_FLOAT1 = 0,
+        VET_FLOAT2 = 1,
+        VET_FLOAT3 = 2,
+        VET_FLOAT4 = 3,
+        /// alias to more specific colour type - use the current rendersystem's colour packing
+		VET_COLOUR = 4,
+		VET_SHORT1 = 5,
+		VET_SHORT2 = 6,
+		VET_SHORT3 = 7,
+		VET_SHORT4 = 8,
+        VET_UBYTE4 = 9,
+        /// D3D style compact colour
+        VET_COLOUR_ARGB = 10,
+        /// GL style compact colour
+        VET_COLOUR_ABGR = 11
+    };
+
+    /** This class declares the usage of a single vertex buffer as a component
+        of a complete VertexDeclaration.
+        @remarks
+        Several vertex buffers can be used to supply the input geometry for a
+        rendering operation, and in each case a vertex buffer can be used in
+        different ways for different operations; the buffer itself does not
+        define the semantics (position, normal etc), the VertexElement
+        class does.
+    */
+	class _OgreExport VertexElement
+    {
+    protected:
+        /// The source vertex buffer, as bound to an index using VertexBufferBinding
+        unsigned short mSource;
+        /// The offset in the buffer that this element starts at
+        size_t mOffset;
+        /// The type of element
+        VertexElementType mType;
+        /// The meaning of the element
+        VertexElementSemantic mSemantic;
+        /// Index of the item, only applicable for some elements like texture coords
+        unsigned short mIndex;
+    public:
+		/// Constructor, should not be called directly, only needed because of list
+		VertexElement() {}
+        /// Constructor, should not be called directly, call VertexDeclaration::addElement
+        VertexElement(unsigned short source, size_t offset, VertexElementType theType,
+            VertexElementSemantic semantic, unsigned short index = 0);
+        /// Gets the vertex buffer index from where this element draws it's values
+        unsigned short getSource(void) const { return mSource; }
+        /// Gets the offset into the buffer where this element starts
+        size_t getOffset(void) const { return mOffset; }
+        /// Gets the data format of this element
+        VertexElementType getType(void) const { return mType; }
+        /// Gets the meaning of this element
+        VertexElementSemantic getSemantic(void) const { return mSemantic; }
+        /// Gets the index of this element, only applicable for repeating elements
+        unsigned short getIndex(void) const { return mIndex; }
+		/// Gets the size of this element in bytes
+		size_t getSize(void) const;
+		/// Utility method for helping to calculate offsets
+		static size_t getTypeSize(VertexElementType etype);
+		/// Utility method which returns the count of values in a given type
+		static unsigned short getTypeCount(VertexElementType etype);
+		/** Simple converter function which will turn a single-value type into a
+			multi-value type based on a parameter.
+		*/
+		static VertexElementType multiplyTypeCount(VertexElementType baseType, unsigned short count);
+		/** Simple converter function which will a type into it's single-value
+			equivalent - makes switches on type easier.
+		*/
+		static VertexElementType getBaseType(VertexElementType multiType);
+
+		/** Utility method for converting colour from
+			one packed 32-bit colour type to another.
+		@param srcType The source type
+		@param dstType The destination type
+		@param ptr Read / write value to change
+		*/
+		static void convertColourValue(VertexElementType srcType,
+			VertexElementType dstType, uint32* ptr);
+
+		/** Utility method for converting colour to
+			a packed 32-bit colour type.
+		@param src source colour
+		@param dst The destination type
+		*/
+		static uint32 convertColourValue(const ColourValue& src,
+			VertexElementType dst);
+
+		/** Utility method to get the most appropriate packed colour vertex element format. */
+		static VertexElementType getBestColourVertexElementType(void);
+
+        inline bool operator== (const VertexElement& rhs) const
+        {
+            if (mType != rhs.mType ||
+                mIndex != rhs.mIndex ||
+                mOffset != rhs.mOffset ||
+                mSemantic != rhs.mSemantic ||
+                mSource != rhs.mSource)
+                return false;
+            else
+                return true;
+
+        }
+        /** Adjusts a pointer to the base of a vertex to point at this element.
+        @remarks
+            This variant is for void pointers, passed as a parameter because we can't
+            rely on covariant return types.
+        @param pBase Pointer to the start of a vertex in this buffer.
+        @param pElem Pointer to a pointer which will be set to the start of this element.
+        */
+        inline void baseVertexPointerToElement(void* pBase, void** pElem) const
+        {
+            // The only way we can do this is to cast to char* in order to use byte offset
+            // then cast back to void*.
+            *pElem = static_cast<void*>(
+            	static_cast<unsigned char*>(pBase) + mOffset);
+        }
+        /** Adjusts a pointer to the base of a vertex to point at this element.
+        @remarks
+            This variant is for float pointers, passed as a parameter because we can't
+            rely on covariant return types.
+        @param pBase Pointer to the start of a vertex in this buffer.
+        @param pElem Pointer to a pointer which will be set to the start of this element.
+        */
+        inline void baseVertexPointerToElement(void* pBase, float** pElem) const
+        {
+            // The only way we can do this is to cast to char* in order to use byte offset
+            // then cast back to float*. However we have to go via void* because casting
+            // directly is not allowed
+            *pElem = static_cast<float*>(
+                static_cast<void*>(
+                    static_cast<unsigned char*>(pBase) + mOffset));
+        }
+
+        /** Adjusts a pointer to the base of a vertex to point at this element.
+        @remarks
+            This variant is for RGBA pointers, passed as a parameter because we can't
+            rely on covariant return types.
+        @param pBase Pointer to the start of a vertex in this buffer.
+        @param pElem Pointer to a pointer which will be set to the start of this element.
+        */
+        inline void baseVertexPointerToElement(void* pBase, RGBA** pElem) const
+        {
+            *pElem = static_cast<RGBA*>(
+                static_cast<void*>(
+                    static_cast<unsigned char*>(pBase) + mOffset));
+        }
+        /** Adjusts a pointer to the base of a vertex to point at this element.
+        @remarks
+            This variant is for char pointers, passed as a parameter because we can't
+            rely on covariant return types.
+        @param pBase Pointer to the start of a vertex in this buffer.
+        @param pElem Pointer to a pointer which will be set to the start of this element.
+        */
+        inline void baseVertexPointerToElement(void* pBase, unsigned char** pElem) const
+        {
+            *pElem = static_cast<unsigned char*>(pBase) + mOffset;
+        }
+
+        /** Adjusts a pointer to the base of a vertex to point at this element.
+        @remarks
+        This variant is for ushort pointers, passed as a parameter because we can't
+        rely on covariant return types.
+        @param pBase Pointer to the start of a vertex in this buffer.
+        @param pElem Pointer to a pointer which will be set to the start of this element.
+        */
+        inline void baseVertexPointerToElement(void* pBase, unsigned short** pElem) const
+        {
+			*pElem = static_cast<unsigned short*>(
+				static_cast<void*>(
+					static_cast<unsigned char*>(pBase) + mOffset));
+        }
+
+
+    };
+    /** This class declares the format of a set of vertex inputs, which
+        can be issued to the rendering API through a RenderOperation.
+	@remarks
+	You should be aware that the ordering and structure of the
+	VertexDeclaration can be very important on DirectX with older
+	cards,so if you want to maintain maximum compatibility with
+	all render systems and all cards you should be careful to follow these
+	rules:<ol>
+	<li>VertexElements should be added in the following order, and the order of the
+	elements within a shared buffer should be as follows:
+	position, blending weights, normals, diffuse colours, specular colours,
+            texture coordinates (in order, with no gaps)</li>
+	<li>You must not have unused gaps in your buffers which are not referenced
+	by any VertexElement</li>
+	<li>You must not cause the buffer & offset settings of 2 VertexElements to overlap</li>
+	</ol>
+	Whilst GL and more modern graphics cards in D3D will allow you to defy these rules,
+	sticking to them will ensure that your buffers have the maximum compatibility.
+	@par
+	Like the other classes in this functional area, these declarations should be created and
+	destroyed using the HardwareBufferManager.
+    */
+	class _OgreExport VertexDeclaration
+    {
+    public:
+		/// Defines the list of vertex elements that makes up this declaration
+        typedef list<VertexElement>::type VertexElementList;
+        /// Sort routine for vertex elements
+        static bool vertexElementLess(const VertexElement& e1, const VertexElement& e2);
+    protected:
+        VertexElementList mElementList;
+    public:
+        /// Standard constructor, not you should use HardwareBufferManager::createVertexDeclaration
+        VertexDeclaration();
+        virtual ~VertexDeclaration();
+
+        /** Get the number of elements in the declaration. */
+        size_t getElementCount(void) { return mElementList.size(); }
+        /** Gets read-only access to the list of vertex elements. */
+        const VertexElementList& getElements(void) const;
+        /** Get a single element. */
+        const VertexElement* getElement(unsigned short index);
+
+        /** Sorts the elements in this list to be compatible with the maximum
+            number of rendering APIs / graphics cards.
+        @remarks
+            Older graphics cards require vertex data to be presented in a more
+            rigid way, as defined in the main documentation for this class. As well
+            as the ordering being important, where shared source buffers are used, the
+            declaration must list all the elements for each source in turn.
+        */
+        void sort(void);
+
+        /** Remove any gaps in the source buffer list used by this declaration.
+        @remarks
+            This is useful if you've modified a declaration and want to remove
+            any gaps in the list of buffers being used. Note, however, that if this
+            declaration is already being used with a VertexBufferBinding, you will
+            need to alter that too. This method is mainly useful when reorganising
+            buffers based on an altered declaration.
+        @note
+            This will cause the vertex declaration to be re-sorted.
+        */
+        void closeGapsInSource(void);
+
+        /** Generates a new VertexDeclaration for optimal usage based on the current
+            vertex declaration, which can be used with VertexData::reorganiseBuffers later
+            if you wish, or simply used as a template.
+		@remarks
+			Different buffer organisations and buffer usages will be returned
+            depending on the parameters passed to this method.
+        @param skeletalAnimation Whether this vertex data is going to be
+			skeletally animated
+		@param vertexAnimation Whether this vertex data is going to be vertex animated
+        */
+        VertexDeclaration* getAutoOrganisedDeclaration(bool skeletalAnimation,
+			bool vertexAnimation);
+
+        /** Gets the index of the highest source value referenced by this declaration. */
+        unsigned short getMaxSource(void) const;
+
+
+
+        /** Adds a new VertexElement to this declaration.
+        @remarks
+            This method adds a single element (positions, normals etc) to the end of the
+            vertex declaration. <b>Please read the information in VertexDeclaration about
+	    the importance of ordering and structure for compatibility with older D3D drivers</b>.
+	    @param source The binding index of HardwareVertexBuffer which will provide the source for this element.
+			See VertexBufferBindingState for full information.
+        @param offset The offset in bytes where this element is located in the buffer
+        @param theType The data format of the element (3 floats, a colour etc)
+        @param semantic The meaning of the data (position, normal, diffuse colour etc)
+        @param index Optional index for multi-input elements like texture coordinates
+		@returns A reference to the VertexElement added.
+        */
+        virtual const VertexElement& addElement(unsigned short source, size_t offset, VertexElementType theType,
+            VertexElementSemantic semantic, unsigned short index = 0);
+        /** Inserts a new VertexElement at a given position in this declaration.
+        @remarks
+        This method adds a single element (positions, normals etc) at a given position in this
+        vertex declaration. <b>Please read the information in VertexDeclaration about
+        the importance of ordering and structure for compatibility with older D3D drivers</b>.
+        @param source The binding index of HardwareVertexBuffer which will provide the source for this element.
+        See VertexBufferBindingState for full information.
+        @param offset The offset in bytes where this element is located in the buffer
+        @param theType The data format of the element (3 floats, a colour etc)
+        @param semantic The meaning of the data (position, normal, diffuse colour etc)
+        @param index Optional index for multi-input elements like texture coordinates
+        @returns A reference to the VertexElement added.
+        */
+        virtual const VertexElement& insertElement(unsigned short atPosition,
+            unsigned short source, size_t offset, VertexElementType theType,
+            VertexElementSemantic semantic, unsigned short index = 0);
+
+        /** Remove the element at the given index from this declaration. */
+        virtual void removeElement(unsigned short elem_index);
+
+        /** Remove the element with the given semantic and usage index.
+        @remarks
+            In this case 'index' means the usage index for repeating elements such
+            as texture coordinates. For other elements this will always be 0 and does
+            not refer to the index in the vector.
+        */
+        virtual void removeElement(VertexElementSemantic semantic, unsigned short index = 0);
+
+		/** Remove all elements. */
+		virtual void removeAllElements(void);
+
+        /** Modify an element in-place, params as addElement.
+	   @remarks
+	   <b>Please read the information in VertexDeclaration about
+	    the importance of ordering and structure for compatibility with older D3D drivers</b>.
+	 */
+        virtual void modifyElement(unsigned short elem_index, unsigned short source, size_t offset, VertexElementType theType,
+            VertexElementSemantic semantic, unsigned short index = 0);
+
+		/** Finds a VertexElement with the given semantic, and index if there is more than
+			one element with the same semantic.
+        @remarks
+            If the element is not found, this method returns null.
+		*/
+		virtual const VertexElement* findElementBySemantic(VertexElementSemantic sem, unsigned short index = 0);
+		/** Based on the current elements, gets the size of the vertex for a given buffer source.
+		@param source The buffer binding index for which to get the vertex size.
+		*/
+
+		/** Gets a list of elements which use a given source.
+		@remarks
+			Note that the list of elements is returned by value therefore is separate from
+			the declaration as soon as this method returns.
+		*/
+		virtual VertexElementList findElementsBySource(unsigned short source);
+
+		/** Gets the vertex size defined by this declaration for a given source. */
+        virtual size_t getVertexSize(unsigned short source);
+
+        /** Clones this declaration. 
+		@param mgr Optional HardwareBufferManager to use for creating the clone
+			(if null, use the current default).
+		*/
+        virtual VertexDeclaration* clone(HardwareBufferManagerBase* mgr = 0);
+
+        inline bool operator== (const VertexDeclaration& rhs) const
+        {
+            if (mElementList.size() != rhs.mElementList.size())
+                return false;
+
+            VertexElementList::const_iterator i, iend, rhsi, rhsiend;
+            iend = mElementList.end();
+            rhsiend = rhs.mElementList.end();
+            rhsi = rhs.mElementList.begin();
+            for (i = mElementList.begin(); i != iend && rhsi != rhsiend; ++i, ++rhsi)
+            {
+                if ( !(*i == *rhsi) )
+                    return false;
+            }
+
+            return true;
+        }
+        inline bool operator!= (const VertexDeclaration& rhs) const
+        {
+            return !(*this == rhs);
+        }
+
+    };
+
+	/** Records the state of all the vertex buffer bindings required to provide a vertex declaration
+		with the input data it needs for the vertex elements.
+	@remarks
+		Why do we have this binding list rather than just have VertexElement referring to the
+		vertex buffers direct? Well, in the underlying APIs, binding the vertex buffers to an
+		index (or 'stream') is the way that vertex data is linked, so this structure better
+		reflects the realities of that. In addition, by separating the vertex declaration from
+		the list of vertex buffer bindings, it becomes possible to reuse bindings between declarations
+		and vice versa, giving opportunities to reduce the state changes required to perform rendering.
+	@par
+		Like the other classes in this functional area, these binding maps should be created and
+		destroyed using the HardwareBufferManager.
+	*/
+	class _OgreExport VertexBufferBinding
+	{
+	public:
+		/// Defines the vertex buffer bindings used as source for vertex declarations
+		typedef map<unsigned short, HardwareVertexBufferSharedPtr>::type VertexBufferBindingMap;
+	protected:
+		VertexBufferBindingMap mBindingMap;
+		mutable unsigned short mHighIndex;
+	public:
+		/// Constructor, should not be called direct, use HardwareBufferManager::createVertexBufferBinding
+		VertexBufferBinding();
+		virtual ~VertexBufferBinding();
+		/** Set a binding, associating a vertex buffer with a given index.
+		@remarks
+			If the index is already associated with a vertex buffer,
+            the association will be replaced. This may cause the old buffer
+            to be destroyed if nothing else is referring to it.
+			You should assign bindings from 0 and not leave gaps, although you can
+			bind them in any order.
+		*/
+		virtual void setBinding(unsigned short index, const HardwareVertexBufferSharedPtr& buffer);
+		/** Removes an existing binding. */
+		virtual void unsetBinding(unsigned short index);
+
+        /** Removes all the bindings. */
+        virtual void unsetAllBindings(void);
+
+		/// Gets a read-only version of the buffer bindings
+		virtual const VertexBufferBindingMap& getBindings(void) const;
+
+		/// Gets the buffer bound to the given source index
+		virtual const HardwareVertexBufferSharedPtr& getBuffer(unsigned short index) const;
+		/// Gets whether a buffer is bound to the given source index
+		virtual bool isBufferBound(unsigned short index) const;
+
+        virtual size_t getBufferCount(void) const { return mBindingMap.size(); }
+
+		/** Gets the highest index which has already been set, plus 1.
+		@remarks
+			This is to assist in binding the vertex buffers such that there are
+			not gaps in the list.
+		*/
+		virtual unsigned short getNextIndex(void) const { return mHighIndex++; }
+
+        /** Gets the last bound index.
+        */
+        virtual unsigned short getLastBoundIndex(void) const;
+
+        typedef map<ushort, ushort>::type BindingIndexMap;
+
+        /** Check whether any gaps in the bindings.
+        */
+        virtual bool hasGaps(void) const;
+
+        /** Remove any gaps in the bindings.
+        @remarks
+            This is useful if you've removed vertex buffer from this vertex buffer
+            bindings and want to remove any gaps in the bindings. Note, however,
+            that if this bindings is already being used with a VertexDeclaration,
+            you will need to alter that too. This method is mainly useful when
+            reorganising buffers manually.
+        @param
+            bindingIndexMap To be retrieve the binding index map that used to
+            translation old index to new index; will be cleared by this method
+            before fill-in.
+        */
+        virtual void closeGaps(BindingIndexMap& bindingIndexMap);
+
+
+	};
+	/** @} */
+	/** @} */
+
+
+
+}
+#endif
+

+ 82 - 0
CamelotRenderer/OgreHeaderPrefix.h

@@ -0,0 +1,82 @@
+/*-------------------------------------------------------------------------
+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-2011 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+-------------------------------------------------------------------------*/
+#ifndef __OgreHeaderPrefix_H__
+#define __OgreHeaderPrefix_H__
+
+#include "OgrePrerequisites.h"
+
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+
+// Save warnings state
+#   pragma warning (push)
+// 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: "<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)
+
+// disable: "unreferenced formal parameter"
+// Many versions of VC have bugs which generate this error in cases where they shouldn't
+#   pragma warning (disable : 4100)
+
+#endif
+
+
+#endif
+
+

+ 44 - 0
CamelotRenderer/OgreHeaderSuffix.h

@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+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-2011 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+-------------------------------------------------------------------------*/
+#ifndef __OgreHeaderPrefix_H__
+#define __OgreHeaderPrefix_H__
+
+#include "OgrePrerequisites.h"
+
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+
+// restore previous warnings settings
+#   pragma warning (pop)
+
+
+#endif
+
+
+#endif
+// allow inclusion of prefix again now (this is scoped)
+#undef __OgreHeaderPrefix_H__
+
+

+ 987 - 0
CamelotRenderer/OgreMath.cpp

@@ -0,0 +1,987 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreMath.h"
+#include "asm_math.h"
+#include "OgreVector2.h"
+#include "OgreVector3.h"
+#include "OgreVector4.h"
+#include "OgreRay.h"
+#include "OgreSphere.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgrePlane.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;
+	const Real Math::LOG2 = log(Real(2.0));
+
+    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 = OGRE_ALLOC_T(Real, mTrigTableSize, MEMCATEGORY_GENERAL);
+        mTanTable = OGRE_ALLOC_T(Real, mTrigTableSize, MEMCATEGORY_GENERAL);
+
+        buildTrigTables();
+    }
+
+    //-----------------------------------------------------------------------
+    Math::~Math()
+    {
+        OGRE_FREE(mSinTable, MEMCATEGORY_GENERAL);
+        OGRE_FREE(mTanTable, MEMCATEGORY_GENERAL);
+    }
+
+    //-----------------------------------------------------------------------
+    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;
+    }
+
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, const Plane& plane)
+    {
+
+        Real denom = plane.normal.dotProduct(ray.getDirection());
+        if (Math::Abs(denom) < std::numeric_limits<Real>::epsilon())
+        {
+            // Parallel
+            return std::pair<bool, Real>(false, 0);
+        }
+        else
+        {
+            Real nom = plane.normal.dotProduct(ray.getOrigin()) + plane.d;
+            Real t = -(nom/denom);
+            return std::pair<bool, Real>(t >= 0, t);
+        }
+        
+    }
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, 
+        const vector<Plane>::type& planes, bool normalIsOutside)
+    {
+		list<Plane>::type planesList;
+		for (vector<Plane>::type::const_iterator i = planes.begin(); i != planes.end(); ++i)
+		{
+			planesList.push_back(*i);
+		}
+		return intersects(ray, planesList, normalIsOutside);
+    }
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, 
+        const list<Plane>::type& planes, bool normalIsOutside)
+    {
+		list<Plane>::type::const_iterator planeit, planeitend;
+		planeitend = planes.end();
+		bool allInside = true;
+		std::pair<bool, Real> ret;
+		std::pair<bool, Real> end;
+		ret.first = false;
+		ret.second = 0.0f;
+		end.first = false;
+		end.second = 0;
+
+
+		// derive side
+		// NB we don't pass directly since that would require Plane::Side in 
+		// interface, which results in recursive includes since Math is so fundamental
+		Plane::Side outside = normalIsOutside ? Plane::POSITIVE_SIDE : Plane::NEGATIVE_SIDE;
+
+		for (planeit = planes.begin(); planeit != planeitend; ++planeit)
+		{
+			const Plane& plane = *planeit;
+			// is origin outside?
+			if (plane.getSide(ray.getOrigin()) == outside)
+			{
+				allInside = false;
+				// Test single plane
+				std::pair<bool, Real> planeRes = 
+					ray.intersects(plane);
+				if (planeRes.first)
+				{
+					// Ok, we intersected
+					ret.first = true;
+					// Use the most distant result since convex volume
+					ret.second = std::max(ret.second, planeRes.second);
+				}
+				else
+				{
+					ret.first =false;
+					ret.second=0.0f;
+					return ret;
+				}
+			}
+			else
+			{
+				std::pair<bool, Real> planeRes = 
+					ray.intersects(plane);
+				if (planeRes.first)
+				{
+					if( !end.first )
+					{
+						end.first = true;
+						end.second = planeRes.second;
+					}
+					else
+					{
+						end.second = std::min( planeRes.second, end.second );
+					}
+
+				}
+
+			}
+		}
+
+		if (allInside)
+		{
+			// Intersecting at 0 distance since inside the volume!
+			ret.first = true;
+			ret.second = 0.0f;
+			return ret;
+		}
+
+		if( end.first )
+		{
+			if( end.second < ret.second )
+			{
+				ret.first = false;
+				return ret;
+			}
+		}
+		return ret;
+    }
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, const Sphere& sphere, 
+        bool discardInside)
+    {
+        const Vector3& raydir = ray.getDirection();
+        // Adjust ray origin relative to sphere center
+        const Vector3& rayorig = ray.getOrigin() - sphere.getCenter();
+        Real radius = sphere.getRadius();
+
+        // Check origin inside first
+        if (rayorig.squaredLength() <= radius*radius && discardInside)
+        {
+            return std::pair<bool, Real>(true, 0);
+        }
+
+        // Mmm, quadratics
+        // Build coeffs which can be used with std quadratic solver
+        // ie t = (-b +/- sqrt(b*b + 4ac)) / 2a
+        Real a = raydir.dotProduct(raydir);
+        Real b = 2 * rayorig.dotProduct(raydir);
+        Real c = rayorig.dotProduct(rayorig) - radius*radius;
+
+        // Calc determinant
+        Real d = (b*b) - (4 * a * c);
+        if (d < 0)
+        {
+            // No intersection
+            return std::pair<bool, Real>(false, 0);
+        }
+        else
+        {
+            // BTW, if d=0 there is one intersection, if d > 0 there are 2
+            // But we only want the closest one, so that's ok, just use the 
+            // '-' version of the solver
+            Real t = ( -b - Math::Sqrt(d) ) / (2 * a);
+            if (t < 0)
+                t = ( -b + Math::Sqrt(d) ) / (2 * a);
+            return std::pair<bool, Real>(true, t);
+        }
+
+
+    }
+    //-----------------------------------------------------------------------
+	std::pair<bool, Real> Math::intersects(const Ray& ray, const AxisAlignedBox& box)
+	{
+		if (box.isNull()) return std::pair<bool, Real>(false, 0);
+		if (box.isInfinite()) return std::pair<bool, Real>(true, 0);
+
+		Real lowt = 0.0f;
+		Real t;
+		bool hit = false;
+		Vector3 hitpoint;
+		const Vector3& min = box.getMinimum();
+		const Vector3& max = box.getMaximum();
+		const Vector3& rayorig = ray.getOrigin();
+		const Vector3& raydir = ray.getDirection();
+
+		// Check origin inside first
+		if ( rayorig > min && rayorig < max )
+		{
+			return std::pair<bool, Real>(true, 0);
+		}
+
+		// Check each face in turn, only check closest 3
+		// Min x
+		if (rayorig.x <= min.x && raydir.x > 0)
+		{
+			t = (min.x - rayorig.x) / raydir.x;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max x
+		if (rayorig.x >= max.x && raydir.x < 0)
+		{
+			t = (max.x - rayorig.x) / raydir.x;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Min y
+		if (rayorig.y <= min.y && raydir.y > 0)
+		{
+			t = (min.y - rayorig.y) / raydir.y;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max y
+		if (rayorig.y >= max.y && raydir.y < 0)
+		{
+			t = (max.y - rayorig.y) / raydir.y;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Min z
+		if (rayorig.z <= min.z && raydir.z > 0)
+		{
+			t = (min.z - rayorig.z) / raydir.z;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max z
+		if (rayorig.z >= max.z && raydir.z < 0)
+		{
+			t = (max.z - rayorig.z) / raydir.z;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+
+		return std::pair<bool, Real>(hit, lowt);
+
+	} 
+    //-----------------------------------------------------------------------
+    bool Math::intersects(const Ray& ray, const AxisAlignedBox& box,
+        Real* d1, Real* d2)
+    {
+        if (box.isNull())
+            return false;
+
+        if (box.isInfinite())
+        {
+            if (d1) *d1 = 0;
+            if (d2) *d2 = Math::POS_INFINITY;
+            return true;
+        }
+
+        const Vector3& min = box.getMinimum();
+        const Vector3& max = box.getMaximum();
+        const Vector3& rayorig = ray.getOrigin();
+        const Vector3& raydir = ray.getDirection();
+
+        Vector3 absDir;
+        absDir[0] = Math::Abs(raydir[0]);
+        absDir[1] = Math::Abs(raydir[1]);
+        absDir[2] = Math::Abs(raydir[2]);
+
+        // Sort the axis, ensure check minimise floating error axis first
+        int imax = 0, imid = 1, imin = 2;
+        if (absDir[0] < absDir[2])
+        {
+            imax = 2;
+            imin = 0;
+        }
+        if (absDir[1] < absDir[imin])
+        {
+            imid = imin;
+            imin = 1;
+        }
+        else if (absDir[1] > absDir[imax])
+        {
+            imid = imax;
+            imax = 1;
+        }
+
+        Real start = 0, end = Math::POS_INFINITY;
+
+#define _CALC_AXIS(i)                                       \
+    do {                                                    \
+        Real denom = 1 / raydir[i];                         \
+        Real newstart = (min[i] - rayorig[i]) * denom;      \
+        Real newend = (max[i] - rayorig[i]) * denom;        \
+        if (newstart > newend) std::swap(newstart, newend); \
+        if (newstart > end || newend < start) return false; \
+        if (newstart > start) start = newstart;             \
+        if (newend < end) end = newend;                     \
+    } while(0)
+
+        // Check each axis in turn
+
+        _CALC_AXIS(imax);
+
+        if (absDir[imid] < std::numeric_limits<Real>::epsilon())
+        {
+            // Parallel with middle and minimise axis, check bounds only
+            if (rayorig[imid] < min[imid] || rayorig[imid] > max[imid] ||
+                rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
+                return false;
+        }
+        else
+        {
+            _CALC_AXIS(imid);
+
+            if (absDir[imin] < std::numeric_limits<Real>::epsilon())
+            {
+                // Parallel with minimise axis, check bounds only
+                if (rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
+                    return false;
+            }
+            else
+            {
+                _CALC_AXIS(imin);
+            }
+        }
+#undef _CALC_AXIS
+
+        if (d1) *d1 = start;
+        if (d2) *d2 = end;
+
+        return true;
+    }
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, const Vector3& a,
+        const Vector3& b, const Vector3& c, const Vector3& normal,
+        bool positiveSide, bool negativeSide)
+    {
+        //
+        // Calculate intersection with plane.
+        //
+        Real t;
+        {
+            Real denom = normal.dotProduct(ray.getDirection());
+
+            // Check intersect side
+            if (denom > + std::numeric_limits<Real>::epsilon())
+            {
+                if (!negativeSide)
+                    return std::pair<bool, Real>(false, 0);
+            }
+            else if (denom < - std::numeric_limits<Real>::epsilon())
+            {
+                if (!positiveSide)
+                    return std::pair<bool, Real>(false, 0);
+            }
+            else
+            {
+                // Parallel or triangle area is close to zero when
+                // the plane normal not normalised.
+                return std::pair<bool, Real>(false, 0);
+            }
+
+            t = normal.dotProduct(a - ray.getOrigin()) / denom;
+
+            if (t < 0)
+            {
+                // Intersection is behind origin
+                return std::pair<bool, Real>(false, 0);
+            }
+        }
+
+        //
+        // Calculate the largest area projection plane in X, Y or Z.
+        //
+        size_t i0, i1;
+        {
+            Real n0 = Math::Abs(normal[0]);
+            Real n1 = Math::Abs(normal[1]);
+            Real n2 = Math::Abs(normal[2]);
+
+            i0 = 1; i1 = 2;
+            if (n1 > n2)
+            {
+                if (n1 > n0) i0 = 0;
+            }
+            else
+            {
+                if (n2 > n0) i1 = 0;
+            }
+        }
+
+        //
+        // Check the intersection point is inside the triangle.
+        //
+        {
+            Real u1 = b[i0] - a[i0];
+            Real v1 = b[i1] - a[i1];
+            Real u2 = c[i0] - a[i0];
+            Real v2 = c[i1] - a[i1];
+            Real u0 = t * ray.getDirection()[i0] + ray.getOrigin()[i0] - a[i0];
+            Real v0 = t * ray.getDirection()[i1] + ray.getOrigin()[i1] - a[i1];
+
+            Real alpha = u0 * v2 - u2 * v0;
+            Real beta  = u1 * v0 - u0 * v1;
+            Real area  = u1 * v2 - u2 * v1;
+
+            // epsilon to avoid float precision error
+            const Real EPSILON = 1e-6f;
+
+            Real tolerance = - EPSILON * area;
+
+            if (area > 0)
+            {
+                if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
+                    return std::pair<bool, Real>(false, 0);
+            }
+            else
+            {
+                if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
+                    return std::pair<bool, Real>(false, 0);
+            }
+        }
+
+        return std::pair<bool, Real>(true, t);
+    }
+    //-----------------------------------------------------------------------
+    std::pair<bool, Real> Math::intersects(const Ray& ray, const Vector3& a,
+        const Vector3& b, const Vector3& c,
+        bool positiveSide, bool negativeSide)
+    {
+        Vector3 normal = calculateBasicFaceNormalWithoutNormalize(a, b, c);
+        return intersects(ray, a, b, c, normal, positiveSide, negativeSide);
+    }
+    //-----------------------------------------------------------------------
+    bool Math::intersects(const Sphere& sphere, const AxisAlignedBox& box)
+    {
+        if (box.isNull()) return false;
+        if (box.isInfinite()) return true;
+
+        // Use splitting planes
+        const Vector3& center = sphere.getCenter();
+        Real radius = sphere.getRadius();
+        const Vector3& min = box.getMinimum();
+        const Vector3& max = box.getMaximum();
+
+		// Arvo's algorithm
+		Real s, d = 0;
+		for (int i = 0; i < 3; ++i)
+		{
+			if (center.ptr()[i] < min.ptr()[i])
+			{
+				s = center.ptr()[i] - min.ptr()[i];
+				d += s * s; 
+			}
+			else if(center.ptr()[i] > max.ptr()[i])
+			{
+				s = center.ptr()[i] - max.ptr()[i];
+				d += s * s; 
+			}
+		}
+		return d <= radius * radius;
+
+    }
+    //-----------------------------------------------------------------------
+    bool Math::intersects(const Plane& plane, const AxisAlignedBox& box)
+    {
+        return (plane.getSide(box) == Plane::BOTH_SIDE);
+    }
+    //-----------------------------------------------------------------------
+    bool Math::intersects(const Sphere& sphere, const Plane& plane)
+    {
+        return (
+            Math::Abs(plane.getDistance(sphere.getCenter()))
+            <= sphere.getRadius() );
+    }
+    //-----------------------------------------------------------------------
+    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;
+
+    }
+    //-----------------------------------------------------------------------
+    Matrix4 Math::buildReflectionMatrix(const Plane& p)
+    {
+        return Matrix4(
+            -2 * p.normal.x * p.normal.x + 1,   -2 * p.normal.x * p.normal.y,       -2 * p.normal.x * p.normal.z,       -2 * p.normal.x * p.d, 
+            -2 * p.normal.y * p.normal.x,       -2 * p.normal.y * p.normal.y + 1,   -2 * p.normal.y * p.normal.z,       -2 * p.normal.y * p.d, 
+            -2 * p.normal.z * p.normal.x,       -2 * p.normal.z * p.normal.y,       -2 * p.normal.z * p.normal.z + 1,   -2 * p.normal.z * p.d, 
+            0,                                  0,                                  0,                                  1);
+    }
+    //-----------------------------------------------------------------------
+    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;
+
+	}
+	//---------------------------------------------------------------------
+	Real Math::boundingRadiusFromAABB(const AxisAlignedBox& aabb)
+	{
+		Vector3 max = aabb.getMaximum();
+		Vector3 min = aabb.getMinimum();
+
+		Vector3 magnitude = max;
+		magnitude.makeCeil(-max);
+		magnitude.makeCeil(min);
+		magnitude.makeCeil(-min);
+
+		return magnitude.length();
+	}
+
+}

+ 656 - 0
CamelotRenderer/OgreMath.h

@@ -0,0 +1,656 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Math_H__
+#define __Math_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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; }
+
+		inline _OgreExport friend std::ostream& operator <<
+			( std::ostream& o, const Radian& v )
+		{
+			o << "Radian(" << v.valueRadians() << ")";
+			return o;
+		}
+	};
+
+    /** 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; }
+
+		inline _OgreExport friend std::ostream& operator <<
+			( std::ostream& o, const Degree& v )
+		{
+			o << "Degree(" << v.valueDegrees() << ")";
+			return o;
+		}
+	};
+
+    /** 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)); }
+		static inline bool isNaN(Real f)
+		{
+			// std::isnan() is C99, not supported by all compilers
+			// However NaN always fails this next test, no other number does.
+			return f != f;
+		}
+
+        /** 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)); }
+
+		/// Stored value of log(2) for frequent use
+		static const Real LOG2;
+
+		static inline Real Log2 (Real fValue) { return Real(log(fValue)/LOG2); }
+
+		static inline Real LogN (Real base, Real fValue) { return Real(log(fValue)/log(base)); }
+
+		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);
+        /** Ray / plane intersection, returns boolean result and distance. */
+        static std::pair<bool, Real> intersects(const Ray& ray, const Plane& plane);
+
+        /** Ray / sphere intersection, returns boolean result and distance. */
+        static std::pair<bool, Real> intersects(const Ray& ray, const Sphere& sphere, 
+            bool discardInside = true);
+        
+        /** Ray / box intersection, returns boolean result and distance. */
+        static std::pair<bool, Real> intersects(const Ray& ray, const AxisAlignedBox& box);
+
+        /** Ray / box intersection, returns boolean result and two intersection distance.
+        @param
+            ray The ray.
+        @param
+            box The box.
+        @param
+            d1 A real pointer to retrieve the near intersection distance
+                from the ray origin, maybe <b>null</b> which means don't care
+                about the near intersection distance.
+        @param
+            d2 A real pointer to retrieve the far intersection distance
+                from the ray origin, maybe <b>null</b> which means don't care
+                about the far intersection distance.
+        @returns
+            If the ray is intersects the box, <b>true</b> is returned, and
+            the near intersection distance is return by <i>d1</i>, the
+            far intersection distance is return by <i>d2</i>. Guarantee
+            <b>0</b> <= <i>d1</i> <= <i>d2</i>.
+        @par
+            If the ray isn't intersects the box, <b>false</b> is returned, and
+            <i>d1</i> and <i>d2</i> is unmodified.
+        */
+        static bool intersects(const Ray& ray, const AxisAlignedBox& box,
+            Real* d1, Real* d2);
+
+        /** Ray / triangle intersection, returns boolean result and distance.
+        @param
+            ray The ray.
+        @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), doesn't need
+                normalised since we don't care.
+        @param
+            positiveSide Intersect with "positive side" of the triangle
+        @param
+            negativeSide Intersect with "negative side" of the triangle
+        @returns
+            If the ray is intersects the triangle, a pair of <b>true</b> and the
+            distance between intersection point and ray origin returned.
+        @par
+            If the ray isn't intersects the triangle, a pair of <b>false</b> and
+            <b>0</b> returned.
+        */
+        static std::pair<bool, Real> intersects(const Ray& ray, const Vector3& a,
+            const Vector3& b, const Vector3& c, const Vector3& normal,
+            bool positiveSide = true, bool negativeSide = true);
+
+        /** Ray / triangle intersection, returns boolean result and distance.
+        @param
+            ray The ray.
+        @param
+            a The triangle's first vertex.
+        @param
+            b The triangle's second vertex.
+        @param
+            c The triangle's third vertex.
+        @param
+            positiveSide Intersect with "positive side" of the triangle
+        @param
+            negativeSide Intersect with "negative side" of the triangle
+        @returns
+            If the ray is intersects the triangle, a pair of <b>true</b> and the
+            distance between intersection point and ray origin returned.
+        @par
+            If the ray isn't intersects the triangle, a pair of <b>false</b> and
+            <b>0</b> returned.
+        */
+        static std::pair<bool, Real> intersects(const Ray& ray, const Vector3& a,
+            const Vector3& b, const Vector3& c,
+            bool positiveSide = true, bool negativeSide = true);
+
+        /** Sphere / box intersection test. */
+        static bool intersects(const Sphere& sphere, const AxisAlignedBox& box);
+
+        /** Plane / box intersection test. */
+        static bool intersects(const Plane& plane, const AxisAlignedBox& box);
+
+        /** Ray / convex plane list intersection test. 
+        @param ray The ray to test with
+        @param plaeList List of planes which form a convex volume
+        @param normalIsOutside Does the normal point outside the volume
+        */
+        static std::pair<bool, Real> intersects(
+            const Ray& ray, const vector<Plane>::type& planeList, 
+            bool normalIsOutside);
+        /** Ray / convex plane list intersection test. 
+        @param ray The ray to test with
+        @param plaeList List of planes which form a convex volume
+        @param normalIsOutside Does the normal point outside the volume
+        */
+        static std::pair<bool, Real> intersects(
+            const Ray& ray, const list<Plane>::type& planeList, 
+            bool normalIsOutside);
+
+        /** Sphere / plane intersection test. 
+        @remarks NB just do a plane.getDistance(sphere.getCenter()) for more detail!
+        */
+        static bool intersects(const Sphere& sphere, const Plane& plane);
+
+        /** 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);
+
+        /** Build a reflection matrix for the passed in plane. */
+        static Matrix4 buildReflectionMatrix(const Plane& p);
+        /** 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);
+
+		/** Get a bounding radius value from a bounding box. */
+		static Real boundingRadiusFromAABB(const AxisAlignedBox& aabb);
+
+
+
+        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

+ 1510 - 0
CamelotRenderer/OgreMatrix3.cpp

@@ -0,0 +1,1510 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "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.0f/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.0f ? 1.0f : -1.0f);
+            fT1 = kA[0][0] + fSign*fLength;
+            fInvT1 = 1.0f/fT1;
+            afV[1] = kA[1][0]*fInvT1;
+            afV[2] = kA[2][0]*fInvT1;
+
+            fT2 = -2.0f/(1.0f+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.0f+fT2;
+            kL[0][1] = kL[1][0] = fT2*afV[1];
+            kL[0][2] = kL[2][0] = fT2*afV[2];
+            kL[1][1] = 1.0f+fT2*afV[1]*afV[1];
+            kL[1][2] = kL[2][1] = fT2*afV[1]*afV[2];
+            kL[2][2] = 1.0f+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.0f ? 1.0f : -1.0f);
+            fT1 = kA[0][1] + fSign*fLength;
+            afV[2] = kA[0][2]/fT1;
+
+            fT2 = -2.0f/(1.0f+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.0f+fT2;
+            kR[1][2] = kR[2][1] = fT2*afV[2];
+            kR[2][2] = 1.0f+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.0f ? 1.0f : -1.0f);
+            fT1 = kA[1][1] + fSign*fLength;
+            afV[2] = kA[2][1]/fT1;
+
+            fT2 = -2.0f/(1.0f+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.0f+fT2;
+            Real fB = fT2*afV[2];
+            Real fC = 1.0f+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.0f*fT12*fT12);
+        Real fRoot1 = 0.5f*(fTrace+fDiscr);
+        Real fRoot2 = 0.5f*(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.5f*(fTmp+Math::Sqrt(fTmp*fTmp + 4.0f));
+                    fCos0 = Math::InvSqrt(1.0f+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.0f+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.5f*(-fTmp+Math::Sqrt(fTmp*fTmp + 4.0f));
+                    fCos0 = Math::InvSqrt(1.0f+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.0f+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.0f/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.0f*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.0f+Math::Abs(afCoeff[1]);
+            if ( fTmp > fX )
+                fX = fTmp;
+            fTmp = 1.0f+Math::Abs(afCoeff[2]);
+            if ( fTmp > fX )
+                fX = fTmp;
+        }
+
+        // Newton's method to find root
+        Real fTwoC2 = 2.0f*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.0f*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.0f/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.5f*(fTrace-1.0f);
+        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.5f*Math::Sqrt(m[0][0] -
+                            m[1][1] - m[2][2] + 1.0f);
+                        fHalfInverse = 0.5f/rkAxis.x;
+                        rkAxis.y = fHalfInverse*m[0][1];
+                        rkAxis.z = fHalfInverse*m[0][2];
+                    }
+                    else
+                    {
+                        // r22 is maximum diagonal term
+                        rkAxis.z = 0.5f*Math::Sqrt(m[2][2] -
+                            m[0][0] - m[1][1] + 1.0f);
+                        fHalfInverse = 0.5f/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.5f*Math::Sqrt(m[1][1] -
+                            m[0][0] - m[2][2] + 1.0f);
+                        fHalfInverse  = 0.5f/rkAxis.y;
+                        rkAxis.x = fHalfInverse*m[0][1];
+                        rkAxis.z = fHalfInverse*m[1][2];
+                    }
+                    else
+                    {
+                        // r22 is maximum diagonal term
+                        rkAxis.z = 0.5f*Math::Sqrt(m[2][2] -
+                            m[0][0] - m[1][1] + 1.0f);
+                        fHalfInverse = 0.5f/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.0f-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.0f/fLength;
+            fB *= fInvLength;
+            fC *= fInvLength;
+            Real fQ = 2.0f*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.0f*afSubDiag[i0]);
+                Real fTmp1 = Math::Sqrt(fTmp0*fTmp0+1.0f);
+                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.0f);
+                        afSubDiag[i2+1] = fTmp3*fTmp1;
+                        fSin = 1.0f/fTmp1;
+                        fCos *= fSin;
+                    }
+                    else
+                    {
+                        fSin = fTmp3/fTmp0;
+                        fTmp1 = Math::Sqrt(fSin*fSin+1.0f);
+                        afSubDiag[i2+1] = fTmp0*fTmp1;
+                        fCos = 1.0f/fTmp1;
+                        fSin *= fCos;
+                    }
+                    fTmp0 = afDiag[i2+1]-fTmp2;
+                    fTmp1 = (afDiag[i2]-fTmp0)*fSin+2.0f*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];
+        }
+    }
+    //-----------------------------------------------------------------------
+}

+ 272 - 0
CamelotRenderer/OgreMatrix3.h

@@ -0,0 +1,272 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Matrix3_H__
+#define __Matrix3_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+
+// 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
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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;
+		}
+
+		/** Exchange the contents of this matrix with another. 
+		*/
+		inline void swap(Matrix3& other)
+		{
+			std::swap(m[0][0], other.m[0][0]);
+			std::swap(m[0][1], other.m[0][1]);
+			std::swap(m[0][2], other.m[0][2]);
+			std::swap(m[1][0], other.m[1][0]);
+			std::swap(m[1][1], other.m[1][1]);
+			std::swap(m[1][2], other.m[1][2]);
+			std::swap(m[2][0], other.m[2][0]);
+			std::swap(m[2][1], other.m[2][1]);
+			std::swap(m[2][2], other.m[2][2]);
+		}
+
+        // 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, (Real)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, (Real)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, (Real)1e-04))
+				return true;
+
+			return false;
+		}
+
+		/** Function for writing to a stream.
+		*/
+		inline _OgreExport friend std::ostream& operator <<
+			( std::ostream& o, const Matrix3& mat )
+		{
+			o << "Matrix3(" << mat[0][0] << ", " << mat[0][1] << ", " << mat[0][2] << ", " 
+                            << mat[1][0] << ", " << mat[1][1] << ", " << mat[1][2] << ", " 
+                            << mat[2][0] << ", " << mat[2][1] << ", " << mat[2][2] << ")";
+			return o;
+		}
+
+        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

+ 260 - 0
CamelotRenderer/OgreMatrix4.cpp

@@ -0,0 +1,260 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "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;
+        orientation.ToRotationMatrix(rot3x3);
+
+        // Set up final matrix with scale, rotation and translation
+        m[0][0] = scale.x * rot3x3[0][0]; m[0][1] = scale.y * rot3x3[0][1]; m[0][2] = scale.z * rot3x3[0][2]; m[0][3] = position.x;
+        m[1][0] = scale.x * rot3x3[1][0]; m[1][1] = scale.y * rot3x3[1][1]; m[1][2] = scale.z * rot3x3[1][2]; m[1][3] = position.y;
+        m[2][0] = scale.x * rot3x3[2][0]; m[2][1] = scale.y * rot3x3[2][1]; m[2][2] = scale.z * rot3x3[2][2]; m[2][3] = position.z;
+
+        // 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 = invRot * invTranslate; // rotate
+        invTranslate *= invScale; // scale
+
+        // Next, make a 3x3 rotation matrix
+        Matrix3 rot3x3;
+        invRot.ToRotationMatrix(rot3x3);
+
+        // Set up final matrix with scale, rotation and translation
+        m[0][0] = invScale.x * rot3x3[0][0]; m[0][1] = invScale.x * rot3x3[0][1]; m[0][2] = invScale.x * rot3x3[0][2]; m[0][3] = invTranslate.x;
+        m[1][0] = invScale.y * rot3x3[1][0]; m[1][1] = invScale.y * rot3x3[1][1]; m[1][2] = invScale.y * rot3x3[1][2]; m[1][3] = invTranslate.y;
+        m[2][0] = invScale.z * rot3x3[2][0]; m[2][1] = invScale.z * rot3x3[2][1]; m[2][2] = invScale.z * rot3x3[2][2]; m[2][3] = invTranslate.z;		
+
+        // No projection term
+        m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
+    }
+    //-----------------------------------------------------------------------
+	void Matrix4::decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const
+	{
+		assert(isAffine());
+
+		Matrix3 m3x3;
+		extract3x3Matrix(m3x3);
+
+		Matrix3 matQ;
+		Vector3 vecU;
+		m3x3.QDUDecomposition( matQ, scale, vecU ); 
+
+		orientation = Quaternion( matQ );
+		position = Vector3( m[0][3], m[1][3], m[2][3] );
+	}
+
+}

+ 659 - 0
CamelotRenderer/OgreMatrix4.h

@@ -0,0 +1,659 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Matrix4__
+#define __Matrix4__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+#include "OgreMatrix3.h"
+#include "OgreVector4.h"
+#include "OgrePlane.h"
+namespace Ogre
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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 commutative, 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 is 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);
+        }
+        
+
+		/** Exchange the contents of this matrix with another. 
+		*/
+		inline void swap(Matrix4& other)
+		{
+			std::swap(m[0][0], other.m[0][0]);
+			std::swap(m[0][1], other.m[0][1]);
+			std::swap(m[0][2], other.m[0][2]);
+			std::swap(m[0][3], other.m[0][3]);
+			std::swap(m[1][0], other.m[1][0]);
+			std::swap(m[1][1], other.m[1][1]);
+			std::swap(m[1][2], other.m[1][2]);
+			std::swap(m[1][3], other.m[1][3]);
+			std::swap(m[2][0], other.m[2][0]);
+			std::swap(m[2][1], other.m[2][1]);
+			std::swap(m[2][2], other.m[2][2]);
+			std::swap(m[2][3], other.m[2][3]);
+			std::swap(m[3][0], other.m[3][0]);
+			std::swap(m[3][1], other.m[3][1]);
+			std::swap(m[3][2], other.m[3][2]);
+			std::swap(m[3][3], other.m[3][3]);
+		}
+
+		inline Real* operator [] ( size_t iRow )
+        {
+            assert( iRow < 4 );
+            return m[iRow];
+        }
+
+        inline const Real *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.0f / ( 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
+                );
+        }
+        inline Plane operator * (const Plane& p) const
+        {
+            Plane ret;
+			Matrix4 invTrans = inverse().transpose();
+			Vector4 v4( p.normal.x, p.normal.y, p.normal.z, p.d );
+			v4 = invTrans * v4;
+			ret.normal.x = v4.x; 
+			ret.normal.y = v4.y; 
+			ret.normal.z = v4.z;
+			ret.d = v4.w / ret.normal.normalise();
+
+            return ret;
+        }
+
+
+        /** 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, (Real)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, (Real)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, (Real)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& mat )
+        {
+            o << "Matrix4(";
+			for (size_t i = 0; i < 4; ++i)
+            {
+                o << " row" << (unsigned)i << "{";
+                for(size_t j = 0; j < 4; ++j)
+                {
+                    o << mat[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);
+
+        /** Decompose a Matrix4 to orientation / scale / position.
+        */
+        void decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const;
+
+        /** 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 matrices.
+            @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 an 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 an 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

+ 170 - 0
CamelotRenderer/OgrePlane.cpp

@@ -0,0 +1,170 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgrePlane.h"
+#include "OgreMatrix3.h"
+#include "OgreAxisAlignedBox.h" 
+
+namespace Ogre {
+	//-----------------------------------------------------------------------
+	Plane::Plane ()
+	{
+		normal = Vector3::ZERO;
+		d = 0.0;
+	}
+	//-----------------------------------------------------------------------
+	Plane::Plane (const Plane& rhs)
+	{
+		normal = rhs.normal;
+		d = rhs.d;
+	}
+	//-----------------------------------------------------------------------
+	Plane::Plane (const Vector3& rkNormal, Real fConstant)
+	{
+		normal = rkNormal;
+		d = -fConstant;
+	}
+	//---------------------------------------------------------------------
+	Plane::Plane (Real a, Real b, Real c, Real _d)
+		: normal(a, b, c), d(_d)
+	{
+	}
+	//-----------------------------------------------------------------------
+	Plane::Plane (const Vector3& rkNormal, const Vector3& rkPoint)
+	{
+		redefine(rkNormal, rkPoint);
+	}
+	//-----------------------------------------------------------------------
+	Plane::Plane (const Vector3& rkPoint0, const Vector3& rkPoint1,
+		const Vector3& rkPoint2)
+	{
+		redefine(rkPoint0, rkPoint1, rkPoint2);
+	}
+	//-----------------------------------------------------------------------
+	Real Plane::getDistance (const Vector3& rkPoint) const
+	{
+		return normal.dotProduct(rkPoint) + d;
+	}
+	//-----------------------------------------------------------------------
+	Plane::Side Plane::getSide (const Vector3& rkPoint) const
+	{
+		Real fDistance = getDistance(rkPoint);
+
+		if ( fDistance < 0.0 )
+			return Plane::NEGATIVE_SIDE;
+
+		if ( fDistance > 0.0 )
+			return Plane::POSITIVE_SIDE;
+
+		return Plane::NO_SIDE;
+	}
+
+
+	//-----------------------------------------------------------------------
+	Plane::Side Plane::getSide (const AxisAlignedBox& box) const
+	{
+		if (box.isNull()) 
+			return NO_SIDE;
+		if (box.isInfinite())
+			return BOTH_SIDE;
+
+        return getSide(box.getCenter(), box.getHalfSize());
+	}
+    //-----------------------------------------------------------------------
+    Plane::Side Plane::getSide (const Vector3& centre, const Vector3& halfSize) const
+    {
+        // Calculate the distance between box centre and the plane
+        Real dist = getDistance(centre);
+
+        // Calculate the maximise allows absolute distance for
+        // the distance between box centre and plane
+        Real maxAbsDist = normal.absDotProduct(halfSize);
+
+        if (dist < -maxAbsDist)
+            return Plane::NEGATIVE_SIDE;
+
+        if (dist > +maxAbsDist)
+            return Plane::POSITIVE_SIDE;
+
+        return Plane::BOTH_SIDE;
+    }
+	//-----------------------------------------------------------------------
+	void Plane::redefine(const Vector3& rkPoint0, const Vector3& rkPoint1,
+		const Vector3& rkPoint2)
+	{
+		Vector3 kEdge1 = rkPoint1 - rkPoint0;
+		Vector3 kEdge2 = rkPoint2 - rkPoint0;
+		normal = kEdge1.crossProduct(kEdge2);
+		normal.normalise();
+		d = -normal.dotProduct(rkPoint0);
+	}
+	//-----------------------------------------------------------------------
+	void Plane::redefine(const Vector3& rkNormal, const Vector3& rkPoint)
+	{
+		normal = rkNormal;
+		d = -rkNormal.dotProduct(rkPoint);
+	}
+	//-----------------------------------------------------------------------
+	Vector3 Plane::projectVector(const Vector3& p) const
+	{
+		// We know plane normal is unit length, so use simple method
+		Matrix3 xform;
+		xform[0][0] = 1.0f - normal.x * normal.x;
+		xform[0][1] = -normal.x * normal.y;
+		xform[0][2] = -normal.x * normal.z;
+		xform[1][0] = -normal.y * normal.x;
+		xform[1][1] = 1.0f - normal.y * normal.y;
+		xform[1][2] = -normal.y * normal.z;
+		xform[2][0] = -normal.z * normal.x;
+		xform[2][1] = -normal.z * normal.y;
+		xform[2][2] = 1.0f - normal.z * normal.z;
+		return xform * p;
+
+	}
+	//-----------------------------------------------------------------------
+    Real Plane::normalise(void)
+    {
+        Real fLength = normal.length();
+
+        // Will also work for zero-sized vectors, but will change nothing
+        if (fLength > 1e-08f)
+        {
+            Real fInvLength = 1.0f / fLength;
+            normal *= fInvLength;
+            d *= fInvLength;
+        }
+
+        return fLength;
+    }
+	//-----------------------------------------------------------------------
+	std::ostream& operator<< (std::ostream& o, const Plane& p)
+	{
+		o << "Plane(normal=" << p.normal << ", d=" << p.d << ")";
+		return o;
+	}
+} // namespace Ogre

+ 166 - 0
CamelotRenderer/OgrePlane.h

@@ -0,0 +1,166 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+// This file is based on material originally from:
+// Geometric Tools, LLC
+// Copyright (c) 1998-2010
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+
+
+#ifndef __Plane_H__
+#define __Plane_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** Defines a plane in 3D space.
+        @remarks
+            A plane is defined in 3D space by the equation
+            Ax + By + Cz + D = 0
+        @par
+            This equates to a vector (the normal of the plane, whose x, y
+            and z components equate to the coefficients A, B and C
+            respectively), and a constant (D) which is the distance along
+            the normal you have to go to move the plane back to the origin.
+     */
+    class _OgreExport Plane
+    {
+    public:
+        /** Default constructor - sets everything to 0.
+        */
+        Plane ();
+        Plane (const Plane& rhs);
+        /** Construct a plane through a normal, and a distance to move the plane along the normal.*/
+        Plane (const Vector3& rkNormal, Real fConstant);
+		/** Construct a plane using the 4 constants directly **/
+		Plane (Real a, Real b, Real c, Real d);
+        Plane (const Vector3& rkNormal, const Vector3& rkPoint);
+        Plane (const Vector3& rkPoint0, const Vector3& rkPoint1,
+            const Vector3& rkPoint2);
+
+        /** The "positive side" of the plane is the half space to which the
+            plane normal points. The "negative side" is the other half
+            space. The flag "no side" indicates the plane itself.
+        */
+        enum Side
+        {
+            NO_SIDE,
+            POSITIVE_SIDE,
+            NEGATIVE_SIDE,
+            BOTH_SIDE
+        };
+
+        Side getSide (const Vector3& rkPoint) const;
+
+        /**
+        Returns the side where the alignedBox is. The flag BOTH_SIDE indicates an intersecting box.
+        One corner ON the plane is sufficient to consider the box and the plane intersecting.
+        */
+        Side getSide (const AxisAlignedBox& rkBox) const;
+
+        /** Returns which side of the plane that the given box lies on.
+            The box is defined as centre/half-size pairs for effectively.
+        @param centre The centre of the box.
+        @param halfSize The half-size of the box.
+        @returns
+            POSITIVE_SIDE if the box complete lies on the "positive side" of the plane,
+            NEGATIVE_SIDE if the box complete lies on the "negative side" of the plane,
+            and BOTH_SIDE if the box intersects the plane.
+        */
+        Side getSide (const Vector3& centre, const Vector3& halfSize) const;
+
+        /** This is a pseudodistance. The sign of the return value is
+            positive if the point is on the positive side of the plane,
+            negative if the point is on the negative side, and zero if the
+            point is on the plane.
+            @par
+            The absolute value of the return value is the true distance only
+            when the plane normal is a unit length vector.
+        */
+        Real getDistance (const Vector3& rkPoint) const;
+
+        /** Redefine this plane based on 3 points. */
+        void redefine(const Vector3& rkPoint0, const Vector3& rkPoint1,
+            const Vector3& rkPoint2);
+
+		/** Redefine this plane based on a normal and a point. */
+		void redefine(const Vector3& rkNormal, const Vector3& rkPoint);
+
+		/** Project a vector onto the plane. 
+		@remarks This gives you the element of the input vector that is perpendicular 
+			to the normal of the plane. You can get the element which is parallel
+			to the normal of the plane by subtracting the result of this method
+			from the original vector, since parallel + perpendicular = original.
+		@param v The input vector
+		*/
+		Vector3 projectVector(const Vector3& v) const;
+
+        /** Normalises the plane.
+            @remarks
+                This method normalises the plane's normal and the length scale of d
+                is as well.
+            @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 plane's normal.
+        */
+        Real normalise(void);
+
+		Vector3 normal;
+        Real d;
+
+        /// Comparison operator
+        bool operator==(const Plane& rhs) const
+        {
+            return (rhs.d == d && rhs.normal == normal);
+        }
+        bool operator!=(const Plane& rhs) const
+        {
+            return (rhs.d != d || rhs.normal != normal);
+        }
+
+        _OgreExport friend std::ostream& operator<< (std::ostream& o, const Plane& p);
+    };
+
+    typedef vector<Plane>::type PlaneList;
+	/** @} */
+	/** @} */
+
+} // namespace Ogre
+
+#endif

+ 264 - 0
CamelotRenderer/OgrePlatform.h

@@ -0,0 +1,264 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __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_PLATFORM_SYMBIAN 4
+#define OGRE_PLATFORM_IPHONE 5
+
+#define OGRE_COMPILER_MSVC 1
+#define OGRE_COMPILER_GNUC 2
+#define OGRE_COMPILER_BORL 3
+#define OGRE_COMPILER_WINSCW 4
+#define OGRE_COMPILER_GCCE 5
+
+#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( __GCCE__ )
+#   define OGRE_COMPILER OGRE_COMPILER_GCCE
+#   define OGRE_COMP_VER _MSC_VER
+//#	include <staticlibinit_gcce.h> // This is a GCCE toolchain workaround needed when compiling with GCCE 
+#elif defined( __WINSCW__ )
+#   define OGRE_COMPILER OGRE_COMPILER_WINSCW
+#   define OGRE_COMP_VER _MSC_VER
+#elif 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( __SYMBIAN32__ ) 
+#   define OGRE_PLATFORM OGRE_PLATFORM_SYMBIAN
+#elif defined( __WIN32__ ) || defined( _WIN32 )
+#   define OGRE_PLATFORM OGRE_PLATFORM_WIN32
+#elif defined( __APPLE_CC__)
+    // Device                                                     Simulator
+    // Both requiring OS version 3.0 or greater
+#   if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 30000 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 30000
+#       define OGRE_PLATFORM OGRE_PLATFORM_IPHONE
+#   else
+#       define OGRE_PLATFORM OGRE_PLATFORM_APPLE
+#   endif
+#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.
+// for MinGW, we set DEBUG
+#   if defined(_DEBUG) || defined(DEBUG)
+#       define OGRE_DEBUG_MODE 1
+#   else
+#       define OGRE_DEBUG_MODE 0
+#   endif
+
+// Disable unicode support on MingW for GCC 3, poorly supported in stdlibc++
+// STLPORT fixes this though so allow if found
+// MinGW C++ Toolkit supports unicode and sets the define __MINGW32_TOOLBOX_UNICODE__ in _mingw.h
+// GCC 4 is also fine
+#if defined(__MINGW32__)
+# if OGRE_COMP_VER < 400
+#  if !defined(_STLPORT_VERSION)
+#   include<_mingw.h>
+#   if defined(__MINGW32_TOOLBOX_UNICODE__) || OGRE_COMP_VER > 345
+#    define OGRE_UNICODE_SUPPORT 1
+#   else
+#    define OGRE_UNICODE_SUPPORT 0
+#   endif
+#  else
+#   define OGRE_UNICODE_SUPPORT 1
+#  endif
+# else
+#  define OGRE_UNICODE_SUPPORT 1
+# endif
+#else
+#  define OGRE_UNICODE_SUPPORT 1
+#endif
+
+#endif // OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+
+//----------------------------------------------------------------------------
+// Symbian Settings
+#if OGRE_PLATFORM == OGRE_PLATFORM_SYMBIAN
+#	define OGRE_UNICODE_SUPPORT 1
+#   define OGRE_DEBUG_MODE 0
+#   define _OgreExport
+#   define _OgrePrivate
+#	define CLOCKS_PER_SEC  1000
+// pragma def were found here: http://www.inf.pucrs.br/~eduardob/disciplinas/SistEmbarcados/Mobile/Nokia/Tools/Carbide_vs/WINSCW/Help/PDF/C_Compilers_Reference_3.2.pdf
+#	pragma warn_unusedarg off
+#	pragma warn_emptydecl off
+#	pragma warn_possunwant off
+#endif
+//----------------------------------------------------------------------------
+// Linux/Apple/Symbian Settings
+#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_IPHONE || OGRE_PLATFORM == OGRE_PLATFORM_SYMBIAN
+
+// 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"
+#elif OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
+    #define OGRE_PLATFORM_LIB "OgrePlatform.a"
+#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
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// 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;
+typedef int int32;
+typedef short int16;
+typedef char int8;
+// define uint64 type
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+	typedef unsigned __int64 uint64;
+	typedef __int64 int64;
+#else
+	typedef unsigned long long uint64;
+	typedef long long int64;
+#endif
+
+
+}
+
+#endif

+ 200 - 0
CamelotRenderer/OgrePlatformInformation.h

@@ -0,0 +1,200 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __PlatformInformation_H__
+#define __PlatformInformation_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+//
+// TODO: Puts following macros into OgrePlatform.h?
+//
+
+/* Initial CPU stuff to set.
+*/
+#define OGRE_CPU_UNKNOWN    0
+#define OGRE_CPU_X86        1
+#define OGRE_CPU_PPC        2
+#define OGRE_CPU_ARM        3
+
+/* Find CPU type
+*/
+#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || \
+    (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+#   define OGRE_CPU OGRE_CPU_X86
+
+#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE && defined(__BIG_ENDIAN__)
+#   define OGRE_CPU OGRE_CPU_PPC
+#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+#	define OGRE_CPU OGRE_CPU_X86
+#elif OGRE_PLATFORM == OGRE_PLATFORM_IPHONE && (defined(__i386__) || defined(__x86_64__))
+#	define OGRE_CPU OGRE_CPU_X86
+#elif defined(__arm__)
+#	define OGRE_CPU OGRE_CPU_ARM
+#else
+#   define OGRE_CPU OGRE_CPU_UNKNOWN
+#endif
+
+/* Find how to declare aligned variable.
+*/
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+#   define OGRE_ALIGNED_DECL(type, var, alignment)  __declspec(align(alignment)) type var
+
+#elif OGRE_COMPILER == OGRE_COMPILER_GNUC
+#   define OGRE_ALIGNED_DECL(type, var, alignment)  type var __attribute__((__aligned__(alignment)))
+
+#else
+#   define OGRE_ALIGNED_DECL(type, var, alignment)  type var
+#endif
+
+/** Find perfect alignment (should supports SIMD alignment if SIMD available)
+*/
+#if OGRE_CPU == OGRE_CPU_X86
+#   define OGRE_SIMD_ALIGNMENT  16
+
+#else
+#   define OGRE_SIMD_ALIGNMENT  16
+#endif
+
+/* Declare variable aligned to SIMD alignment.
+*/
+#define OGRE_SIMD_ALIGNED_DECL(type, var)   OGRE_ALIGNED_DECL(type, var, OGRE_SIMD_ALIGNMENT)
+
+/* Define whether or not Ogre compiled with SSE supports.
+*/
+#if OGRE_DOUBLE_PRECISION == 0 && OGRE_CPU == OGRE_CPU_X86 && OGRE_COMPILER == OGRE_COMPILER_MSVC
+#   define __OGRE_HAVE_SSE  1
+#elif OGRE_DOUBLE_PRECISION == 0 && OGRE_CPU == OGRE_CPU_X86 && OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS
+#   define __OGRE_HAVE_SSE  1
+#endif
+
+/* Define whether or not Ogre compiled with VFP supports.
+ */
+#if OGRE_DOUBLE_PRECISION == 0 && OGRE_CPU == OGRE_CPU_ARM && OGRE_COMPILER == OGRE_COMPILER_GNUC && defined(__ARM_ARCH_6K__) && defined(__VFP_FP__)
+#   define __OGRE_HAVE_VFP  1
+#endif
+
+/* Define whether or not Ogre compiled with NEON supports.
+ */
+#if OGRE_DOUBLE_PRECISION == 0 && OGRE_CPU == OGRE_CPU_ARM && OGRE_COMPILER == OGRE_COMPILER_GNUC && defined(__ARM_ARCH_7A__) && defined(__ARM_NEON__)
+#   define __OGRE_HAVE_NEON  1
+#endif
+
+#ifndef __OGRE_HAVE_SSE
+#   define __OGRE_HAVE_SSE  0
+#endif
+
+#ifndef __OGRE_HAVE_VFP
+#   define __OGRE_HAVE_VFP  0
+#endif
+
+#ifndef __OGRE_HAVE_NEON
+#   define __OGRE_HAVE_NEON  0
+#endif
+    
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+
+    /** Class which provides the run-time platform information Ogre runs on.
+        @remarks
+            Ogre is designed to be platform-independent, but some platform
+            and run-time environment specific optimised functions are built-in
+            to maximise performance, and those special optimised routines are
+            need to determine run-time environment for select variant executing
+            path.
+        @par
+            This class manages that provides a couple of functions to determine
+            platform information of the run-time environment.
+        @note
+            This class is supposed to use by advanced user only.
+    */
+    class _OgreExport PlatformInformation
+    {
+    public:
+
+        /// Enum describing the different CPU features we want to check for, platform-dependent
+        enum CpuFeatures
+        {
+#if OGRE_CPU == OGRE_CPU_X86
+            CPU_FEATURE_SSE         = 1 << 0,
+            CPU_FEATURE_SSE2        = 1 << 1,
+            CPU_FEATURE_SSE3        = 1 << 2,
+            CPU_FEATURE_MMX         = 1 << 3,
+            CPU_FEATURE_MMXEXT      = 1 << 4,
+            CPU_FEATURE_3DNOW       = 1 << 5,
+            CPU_FEATURE_3DNOWEXT    = 1 << 6,
+            CPU_FEATURE_CMOV        = 1 << 7,
+            CPU_FEATURE_TSC         = 1 << 8,
+            CPU_FEATURE_FPU         = 1 << 9,
+            CPU_FEATURE_PRO         = 1 << 10,
+            CPU_FEATURE_HTT         = 1 << 11,
+#elif OGRE_CPU == OGRE_CPU_ARM
+            CPU_FEATURE_VFP         = 1 << 12,
+            CPU_FEATURE_NEON        = 1 << 13,
+#endif
+
+            CPU_FEATURE_NONE        = 0
+        };
+
+        /** Gets a string of the CPU identifier.
+        @note
+            Actual detecting are performs in the first time call to this function,
+            and then all future calls with return internal cached value.
+        */
+        static const String& getCpuIdentifier(void);
+
+        /** Gets a or-masked of enum CpuFeatures that are supported by the CPU.
+        @note
+            Actual detecting are performs in the first time call to this function,
+            and then all future calls with return internal cached value.
+        */
+        static uint getCpuFeatures(void);
+
+		/** Gets whether a specific feature is supported by the CPU.
+		@note
+			Actual detecting are performs in the first time call to this function,
+			and then all future calls with return internal cached value.
+		*/
+		static bool hasCpuFeature(CpuFeatures feature);
+
+
+		/** Write the CPU information to the passed in Log */
+		static void log(Log* pLog);
+
+    };
+	/** @} */
+	/** @} */
+
+}
+
+#endif  // __PlatformInformation_H__

+ 77 - 0
CamelotRenderer/OgrePortMemory.h

@@ -0,0 +1,77 @@
+#pragma once
+
+// TODO PORT - I define the memory allocation here because they're often used but I don't have an implementation for them. I should remove calls to the macros altogether but this will do for now
+
+#include <malloc.h>
+#include "OgreAlignedAllocator.h"
+
+#define OGRE_NEW new
+#define OGRE_DELETE delete
+
+#define OGRE_MALLOC(bytes, category) malloc(bytes)
+#define OGRE_ALLOC_T(T, count, category) static_cast<T*>(malloc(sizeof(T)*(count)))
+#define OGRE_FREE(ptr, category) free((void*)ptr)
+
+#define OGRE_NEW_T(T, category) new T
+#define OGRE_NEW_ARRAY_T(T, count, category) new T[count] 
+#define OGRE_DELETE_T(ptr, T, category) if(ptr){delete ptr;}
+#define OGRE_DELETE_ARRAY_T(ptr, T, count, category) if(ptr){delete[] ptr;}
+
+namespace Ogre
+{
+	template<typename T>
+	T* constructN(T* basePtr, size_t count)
+	{
+		for (size_t i = 0; i < count; ++i)
+		{
+			new ((void*)(basePtr+i)) T();
+		}
+		return basePtr;
+	}
+}
+
+#define OGRE_MALLOC_SIMD(bytes, category) ::Ogre::AlignedMemory::allocate(bytes)
+#define OGRE_MALLOC_ALIGN(bytes, category, align) ::Ogre::AlignedMemory::allocate(bytes, align)
+#define OGRE_ALLOC_T_SIMD(T, count, category) static_cast<T*>(::Ogre::AlignedMemory::allocate(sizeof(T)*(count),OGRE_SIMD_ALIGNMENT))
+#define OGRE_ALLOC_T_ALIGN(T, count, category, align) static_cast<T*>(::Ogre::AlignedMemory::allocate(sizeof(T)*(count), align))
+#define OGRE_FREE_SIMD(ptr, category) ::Ogre::AlignedMemory::deallocate(ptr)
+#define OGRE_FREE_ALIGN(ptr, category, align) ::Ogre::AlignedMemory::deallocate(ptr)
+//
+#define OGRE_NEW_T_SIMD(T, category) new (::Ogre::AlignedMemory::allocate(sizeof(T))) T
+#define OGRE_NEW_ARRAY_T_SIMD(T, count, category) ::Ogre::constructN(static_cast<T*>(::Ogre::AlignedMemory::allocate(sizeof(T)*(count))), count) 
+#define OGRE_DELETE_T_SIMD(ptr, T, category) if(ptr){(ptr)->~T(); ::Ogre::AlignedMemory::deallocate(ptr);}
+#define OGRE_DELETE_ARRAY_T_SIMD(ptr, T, count, category) if(ptr){for (size_t b = 0; b < count; ++b) { (ptr)[b].~T();} ::Ogre::AlignedMemory::deallocate(ptr);}
+#define OGRE_NEW_T_ALIGN(T, category, align) new (::Ogre::AlignedMemory::allocate(sizeof(T), align)) T
+#define OGRE_NEW_ARRAY_T_ALIGN(T, count, category, align) ::Ogre::constructN(static_cast<T*>(::Ogre::AlignedMemory::allocate(sizeof(T)*(count), align)), count) 
+#define OGRE_DELETE_T_ALIGN(ptr, T, category, align) if(ptr){(ptr)->~T(); ::Ogre::AlignedMemory::deallocate(ptr);}
+#define OGRE_DELETE_ARRAY_T_ALIGN(ptr, T, count, category, align) if(ptr){for (size_t _b = 0; _b < count; ++_b) { (ptr)[_b].~T();} ::Ogre::AlignedMemory::deallocate(ptr);}
+
+namespace Ogre
+{
+	enum MemoryCategory
+	{
+		/// General purpose
+		MEMCATEGORY_GENERAL = 0,
+		/// Geometry held in main memory
+		MEMCATEGORY_GEOMETRY = 1, 
+		/// Animation data like tracks, bone matrices
+		MEMCATEGORY_ANIMATION = 2, 
+		/// Nodes, control data
+		MEMCATEGORY_SCENE_CONTROL = 3,
+		/// Scene object instances
+		MEMCATEGORY_SCENE_OBJECTS = 4,
+		/// Other resources
+		MEMCATEGORY_RESOURCE = 5,
+		/// Scripting
+		MEMCATEGORY_SCRIPTING = 6,
+		/// Rendersystem structures
+		MEMCATEGORY_RENDERSYS = 7,
+
+		
+		// sentinel value, do not use 
+		MEMCATEGORY_COUNT = 8
+	};
+	/** @} */
+	/** @} */
+
+}

+ 386 - 0
CamelotRenderer/OgrePrerequisites.h

@@ -0,0 +1,386 @@
+/*-------------------------------------------------------------------------
+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-2011 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+-------------------------------------------------------------------------*/
+#ifndef __OgrePrerequisites_H__
+#define __OgrePrerequisites_H__
+
+#include <assert.h>
+
+// Platform-specific stuff
+#include "OgrePlatform.h"
+
+#include "OgrePortMemory.h"
+
+// Needed for OGRE_WCHAR_T_STRINGS below
+#include <string>
+
+
+// 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 7
+    #define OGRE_VERSION_PATCH 4
+	#define OGRE_VERSION_SUFFIX ""
+    #define OGRE_VERSION_NAME "Cthugha"
+
+    #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 >= 1600 // VC++ 10.0
+	#			define HashMap ::std::tr1::unordered_map
+	#           define HashSet ::std::tr1::unordered_set
+	#		elif 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;
+
+
+	// Useful threading defines
+#include "OgreThreadDefines.h"
+
+// 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 DefaultWorkQueue;
+    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 RenderObjectListener;
+    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 StreamSerialiser;
+    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 UserObjectBindings;
+    class Vector2;
+    class Vector3;
+    class Vector4;
+    class Viewport;
+	class VertexAnimationTrack;
+    class VertexBufferBinding;
+    class VertexData;
+    class VertexDeclaration;
+	class VertexMorphKeyFrame;
+    class WireBoundingBox;
+	class WorkQueue;
+    class Compositor;
+    class CompositorManager;
+    class CompositorChain;
+    class CompositorInstance;
+	class CompositorLogic;
+    class CompositionTechnique;
+    class CompositionPass;
+    class CompositionTargetPass;
+	class CustomCompositionPass;
+}
+
+/* Include all the standard header *after* all the configuration
+settings have been made.
+*/
+#include "OgreStdHeaders.h"
+
+namespace Ogre
+{
+	#if OGRE_WCHAR_T_STRINGS
+		typedef std::wstring _StringBase;
+	#else
+		typedef std::string _StringBase;
+	#endif
+
+	#if OGRE_WCHAR_T_STRINGS
+		typedef std::basic_stringstream<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > _StringStreamBase;
+	#else
+		typedef std::basic_stringstream<char,std::char_traits<char>,std::allocator<char> > _StringStreamBase;
+	#endif
+
+	typedef _StringBase String;
+	typedef _StringStreamBase StringStream;
+	typedef StringStream stringstream;
+
+}
+
+//for stl containter
+namespace Ogre
+{ 
+
+
+	template <typename T, typename A = char > 
+	struct deque 
+	{ 
+		typedef typename std::deque<T> type;    
+	}; 
+
+	template <typename T, typename A = char > 
+	struct vector 
+	{ 
+		typedef typename std::vector<T> type;    
+	}; 
+
+	template <typename T, typename A = char > 
+	struct list 
+	{ 
+		typedef typename std::list<T> type;    
+	}; 
+
+	template <typename T, typename P = std::less<T>, typename A = char > 
+	struct set 
+	{ 
+		typedef typename std::set<T, P> type;    
+	}; 
+
+	template <typename K, typename V, typename P = std::less<K>, typename A = char > 
+	struct map 
+	{ 
+		typedef typename std::map<K, V, P> type; 
+	}; 
+
+	template <typename K, typename V, typename P = std::less<K>, typename A = char > 
+	struct multimap 
+	{ 
+		typedef typename std::multimap<K, V, P> type; 
+	}; 
+
+} // Ogre
+
+#endif // __OgrePrerequisites_H__
+
+

+ 608 - 0
CamelotRenderer/OgreQuaternion.cpp

@@ -0,0 +1,608 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+// NOTE THAT THIS FILE IS BASED ON MATERIAL FROM:
+
+// Geometric Tools, LLC
+// Copyright (c) 1998-2010
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+
+#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.0f);  // 2w
+            w = 0.5f*fRoot;
+            fRoot = 0.5f/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.0f);
+            Real* apkQuat[3] = { &x, &y, &z };
+            *apkQuat[i] = 0.5f*fRoot;
+            fRoot = 0.5f/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  = x+x;
+        Real fTy  = y+y;
+        Real fTz  = z+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.0f-(fTyy+fTzz);
+        kRot[0][1] = fTxy-fTwz;
+        kRot[0][2] = fTxz+fTwy;
+        kRot[1][0] = fTxy+fTwz;
+        kRot[1][1] = 1.0f-(fTxx+fTzz);
+        kRot[1][2] = fTyz-fTwx;
+        kRot[2][0] = fTxz-fTwy;
+        kRot[2][1] = fTyz+fTwx;
+        kRot[2][2] = 1.0f-(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.0f*y;
+        Real fTz  = 2.0f*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.0f-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy);
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::yAxis(void) const
+    {
+        Real fTx  = 2.0f*x;
+        Real fTy  = 2.0f*y;
+        Real fTz  = 2.0f*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.0f-(fTxx+fTzz), fTyz+fTwx);
+    }
+    //-----------------------------------------------------------------------
+    Vector3 Quaternion::zAxis(void) const
+    {
+        Real fTx  = 2.0f*x;
+        Real fTy  = 2.0f*y;
+        Real fTz  = 2.0f*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.0f-(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.0f/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.0f/fSin;
+        Real fCoeff0 = Math::Sin((1.0f-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.0f*fT*(1.0f-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.0f*y;
+			Real fTz  = 2.0f*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.0f-(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.0f*x;
+//			Real fTy  = 2.0f*y;
+			Real fTz  = 2.0f*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.0f-(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.0f*x;
+			Real fTy  = 2.0f*y;
+			Real fTz  = 2.0f*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.0f-(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;
+    }
+}

+ 271 - 0
CamelotRenderer/OgreQuaternion.h

@@ -0,0 +1,271 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+// This file is based on material originally from:
+// Geometric Tools, LLC
+// Copyright (c) 1998-2010
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+
+
+#ifndef __Quaternion_H__
+#define __Quaternion_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreMath.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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);
+		}
+
+		/** Exchange the contents of this quaternion with another. 
+		*/
+		inline void swap(Quaternion& other)
+		{
+			std::swap(w, other.w);
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+		}
+
+		/// 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;
+
+		/// Check whether this quaternion contains valid values
+		inline bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
+		}
+
+        /** 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 

+ 111 - 0
CamelotRenderer/OgreRay.h

@@ -0,0 +1,111 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Ray_H_
+#define __Ray_H_
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** Representation of a ray in space, i.e. a line with an origin and direction. */
+    class _OgreExport Ray
+    {
+    protected:
+        Vector3 mOrigin;
+        Vector3 mDirection;
+    public:
+        Ray():mOrigin(Vector3::ZERO), mDirection(Vector3::UNIT_Z) {}
+        Ray(const Vector3& origin, const Vector3& direction)
+            :mOrigin(origin), mDirection(direction) {}
+
+        /** Sets the origin of the ray. */
+        void setOrigin(const Vector3& origin) {mOrigin = origin;} 
+        /** Gets the origin of the ray. */
+        const Vector3& getOrigin(void) const {return mOrigin;} 
+
+        /** Sets the direction of the ray. */
+        void setDirection(const Vector3& dir) {mDirection = dir;} 
+        /** Gets the direction of the ray. */
+        const Vector3& getDirection(void) const {return mDirection;} 
+
+		/** Gets the position of a point t units along the ray. */
+		Vector3 getPoint(Real t) const { 
+			return Vector3(mOrigin + (mDirection * t));
+		}
+		
+		/** Gets the position of a point t units along the ray. */
+		Vector3 operator*(Real t) const { 
+			return getPoint(t);
+		}
+
+		/** Tests whether this ray intersects the given plane. 
+		@returns A pair structure where the first element indicates whether
+			an intersection occurs, and if true, the second element will
+			indicate the distance along the ray at which it intersects. 
+			This can be converted to a point in space by calling getPoint().
+		*/
+		std::pair<bool, Real> intersects(const Plane& p) const
+		{
+			return Math::intersects(*this, p);
+		}
+		/** Tests whether this ray intersects the given sphere. 
+		@returns A pair structure where the first element indicates whether
+			an intersection occurs, and if true, the second element will
+			indicate the distance along the ray at which it intersects. 
+			This can be converted to a point in space by calling getPoint().
+		*/
+		std::pair<bool, Real> intersects(const Sphere& s) const
+		{
+			return Math::intersects(*this, s);
+		}
+		/** Tests whether this ray intersects the given box. 
+		@returns A pair structure where the first element indicates whether
+			an intersection occurs, and if true, the second element will
+			indicate the distance along the ray at which it intersects. 
+			This can be converted to a point in space by calling getPoint().
+		*/
+		std::pair<bool, Real> intersects(const AxisAlignedBox& box) const
+		{
+			return Math::intersects(*this, box);
+		}
+
+    };
+	/** @} */
+	/** @} */
+
+}
+#endif

+ 110 - 0
CamelotRenderer/OgreRenderSystemCapabilities.cpp

@@ -0,0 +1,110 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreRenderSystemCapabilities.h"
+#include "OgreStringConverter.h"
+#include "OgreException.h"
+#include "OgreString.h"
+
+namespace Ogre {
+
+	//-----------------------------------------------------------------------
+	RenderSystemCapabilities::RenderSystemCapabilities()
+		: mVendor(GPU_UNKNOWN)
+		, mNumWorldMatrices(0)
+		, mNumTextureUnits(0)
+		, mStencilBufferBitDepth(0)
+		, mNumVertexBlendMatrices(0)
+		, mNumMultiRenderTargets(1)
+		, mNonPOW2TexturesLimited(false)
+	{
+
+		for(int i = 0; i < CAPS_CATEGORY_COUNT; i++)
+		{
+			mCapabilities[i] = 0;
+		}
+		mCategoryRelevant[CAPS_CATEGORY_COMMON] = true;
+		mCategoryRelevant[CAPS_CATEGORY_COMMON_2] = true;
+		// each rendersystem should enable these
+		mCategoryRelevant[CAPS_CATEGORY_D3D9] = false;
+		mCategoryRelevant[CAPS_CATEGORY_GL] = false;
+
+
+	}
+	//-----------------------------------------------------------------------
+	RenderSystemCapabilities::~RenderSystemCapabilities()
+	{
+	}
+	//---------------------------------------------------------------------
+	StringVector RenderSystemCapabilities::msGPUVendorStrings;
+	//---------------------------------------------------------------------
+	GPUVendor RenderSystemCapabilities::vendorFromString(const String& vendorString)
+	{
+		initVendorStrings();
+		GPUVendor ret = GPU_UNKNOWN;
+		String cmpString = vendorString;
+		StringUtil::toLowerCase(cmpString);
+		for (int i = 0; i < GPU_VENDOR_COUNT; ++i)
+		{
+			// case insensitive (lower case)
+			if (msGPUVendorStrings[i] == cmpString)
+			{
+				ret = static_cast<GPUVendor>(i);
+				break;
+			}
+		}
+
+		return ret;
+		
+	}
+	//---------------------------------------------------------------------
+	String RenderSystemCapabilities::vendorToString(GPUVendor v)
+	{
+		initVendorStrings();
+		return msGPUVendorStrings[v];
+	}
+	//---------------------------------------------------------------------
+	void RenderSystemCapabilities::initVendorStrings()
+	{
+		if (msGPUVendorStrings.empty())
+		{
+			// Always lower case!
+			msGPUVendorStrings.resize(GPU_VENDOR_COUNT);
+			msGPUVendorStrings[GPU_UNKNOWN] = "unknown";
+			msGPUVendorStrings[GPU_NVIDIA] = "nvidia";
+			msGPUVendorStrings[GPU_ATI] = "ati";
+			msGPUVendorStrings[GPU_INTEL] = "intel";
+			msGPUVendorStrings[GPU_3DLABS] = "3dlabs";
+			msGPUVendorStrings[GPU_S3] = "s3";
+			msGPUVendorStrings[GPU_MATROX] = "matrox";
+			msGPUVendorStrings[GPU_SIS] = "sis";
+			msGPUVendorStrings[GPU_IMAGINATION_TECHNOLOGIES] = "imagination technologies";
+			msGPUVendorStrings[GPU_APPLE] = "apple";    // iPhone Simulator
+		}
+	}
+
+}

+ 705 - 0
CamelotRenderer/OgreRenderSystemCapabilities.h

@@ -0,0 +1,705 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __RenderSystemCapabilities__
+#define __RenderSystemCapabilities__ 1
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreString.h"
+#include "OgreStringConverter.h"
+#include "OgreStringVector.h"
+
+// Because there are more than 32 possible Capabilities, more than 1 int is needed to store them all.
+// In fact, an array of integers is used to store capabilities. However all the capabilities are defined in the single
+// enum. The only way to know which capabilities should be stored where in the array is to use some of the 32 bits
+// to record the category of the capability.  These top few bits are used as an index into mCapabilities array
+// The lower bits are used to identify each capability individually by setting 1 bit for each
+
+// Identifies how many bits are reserved for categories
+// NOTE: Although 4 bits (currently) are enough
+#define CAPS_CATEGORY_SIZE 4
+#define OGRE_CAPS_BITSHIFT (32 - CAPS_CATEGORY_SIZE)
+#define CAPS_CATEGORY_MASK (((1 << CAPS_CATEGORY_SIZE) - 1) << OGRE_CAPS_BITSHIFT)
+#define OGRE_CAPS_VALUE(cat, val) ((cat << OGRE_CAPS_BITSHIFT) | (1 << val))
+
+namespace Ogre 
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+
+	/// Enumerates the categories of capabilities
+	enum CapabilitiesCategory
+	{
+		CAPS_CATEGORY_COMMON = 0,
+		CAPS_CATEGORY_COMMON_2 = 1,
+		CAPS_CATEGORY_D3D9 = 2,
+		CAPS_CATEGORY_GL = 3,
+		/// Placeholder for max value
+		CAPS_CATEGORY_COUNT = 4
+	};
+
+	/// Enum describing the different hardware capabilities we want to check for
+	/// OGRE_CAPS_VALUE(a, b) defines each capability
+	// a is the category (which can be from 0 to 15)
+	// b is the value (from 0 to 27)
+	enum Capabilities
+	{
+		/// Supports generating mipmaps in hardware
+		RSC_AUTOMIPMAP              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 0),
+		RSC_BLENDING                = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 1),
+		/// Supports anisotropic texture filtering
+		RSC_ANISOTROPY              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 2),
+		/// Supports fixed-function DOT3 texture blend
+		RSC_DOT3                    = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 3),
+		/// Supports cube mapping
+		RSC_CUBEMAPPING             = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 4),
+		/// Supports hardware stencil buffer
+		RSC_HWSTENCIL               = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 5),
+		/// Supports hardware vertex and index buffers
+		RSC_VBO                     = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 7),
+		/// Supports vertex programs (vertex shaders)
+		RSC_VERTEX_PROGRAM          = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 9),
+		/// Supports fragment programs (pixel shaders)
+		RSC_FRAGMENT_PROGRAM        = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 10),
+		/// Supports performing a scissor test to exclude areas of the screen
+		RSC_SCISSOR_TEST            = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 11),
+		/// Supports separate stencil updates for both front and back faces
+		RSC_TWO_SIDED_STENCIL       = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 12),
+		/// Supports wrapping the stencil value at the range extremeties
+		RSC_STENCIL_WRAP            = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 13),
+		/// Supports hardware occlusion queries
+		RSC_HWOCCLUSION             = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 14),
+		/// Supports user clipping planes
+		RSC_USER_CLIP_PLANES        = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 15),
+		/// Supports the VET_UBYTE4 vertex element type
+		RSC_VERTEX_FORMAT_UBYTE4    = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 16),
+		/// Supports infinite far plane projection
+		RSC_INFINITE_FAR_PLANE      = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 17),
+		/// Supports hardware render-to-texture (bigger than framebuffer)
+		RSC_HWRENDER_TO_TEXTURE     = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 18),
+		/// Supports float textures and render targets
+		RSC_TEXTURE_FLOAT           = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 19),
+		/// Supports non-power of two textures
+		RSC_NON_POWER_OF_2_TEXTURES = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 20),
+		/// Supports 3d (volume) textures
+		RSC_TEXTURE_3D              = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 21),
+		/// Supports basic point sprite rendering
+		RSC_POINT_SPRITES           = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 22),
+		/// Supports extra point parameters (minsize, maxsize, attenuation)
+		RSC_POINT_EXTENDED_PARAMETERS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 23),
+		/// Supports vertex texture fetch
+		RSC_VERTEX_TEXTURE_FETCH = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 24),
+		/// Supports mipmap LOD biasing
+		RSC_MIPMAP_LOD_BIAS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 25),
+		/// Supports hardware geometry programs
+		RSC_GEOMETRY_PROGRAM = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 26),
+		/// Supports rendering to vertex buffers
+		RSC_HWRENDER_TO_VERTEX_BUFFER = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON, 27),
+
+		/// Supports compressed textures
+		RSC_TEXTURE_COMPRESSION = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 0),
+		/// Supports compressed textures in the DXT/ST3C formats
+		RSC_TEXTURE_COMPRESSION_DXT = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 1),
+		/// Supports compressed textures in the VTC format
+		RSC_TEXTURE_COMPRESSION_VTC = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 2),
+		/// Supports compressed textures in the PVRTC format
+		RSC_TEXTURE_COMPRESSION_PVRTC = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 3),
+		/// Supports fixed-function pipeline
+		RSC_FIXED_FUNCTION = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 4),
+		/// Supports MRTs with different bit depths
+		RSC_MRT_DIFFERENT_BIT_DEPTHS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 5),
+		/// Supports Alpha to Coverage (A2C)
+		RSC_ALPHA_TO_COVERAGE = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 6),
+		/// Supports Blending operations other than +
+		RSC_ADVANCED_BLEND_OPERATIONS = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 7),
+
+		// ***** DirectX specific caps *****
+		/// Is DirectX feature "per stage constants" supported
+		RSC_PERSTAGECONSTANT = OGRE_CAPS_VALUE(CAPS_CATEGORY_D3D9, 0),
+
+		// ***** GL Specific Caps *****
+		/// Supports openGL GLEW version 1.5
+		RSC_GL1_5_NOVBO    = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 1),
+		/// Support for Frame Buffer Objects (FBOs)
+		RSC_FBO              = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 2),
+		/// Support for Frame Buffer Objects ARB implementation (regular FBO is higher precedence)
+		RSC_FBO_ARB          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 3),
+		/// Support for Frame Buffer Objects ATI implementation (ARB FBO is higher precedence)
+		RSC_FBO_ATI          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 4),
+		/// Support for PBuffer
+		RSC_PBUFFER          = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 5),
+		/// Support for GL 1.5 but without HW occlusion workaround
+		RSC_GL1_5_NOHWOCCLUSION = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 6),
+		/// Support for point parameters ARB implementation
+		RSC_POINT_EXTENDED_PARAMETERS_ARB = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 7),
+		/// Support for point parameters EXT implementation
+		RSC_POINT_EXTENDED_PARAMETERS_EXT = OGRE_CAPS_VALUE(CAPS_CATEGORY_GL, 8)
+
+
+	};
+
+	/// DriverVersion is used by RenderSystemCapabilities and both GL and D3D9
+	/// to store the version of the current GPU driver
+	struct _OgreExport DriverVersion 
+	{
+		int major;
+		int minor;
+		int release;
+		int build;
+
+		DriverVersion() 
+		{
+			major = minor = release = build = 0;
+		}
+
+		String toString() const 
+		{
+			StringUtil::StrStreamType str;
+			str << major << "." << minor << "." << release << "." << build;
+			return str.str();
+		}
+
+		void fromString(const String& versionString)
+		{
+			StringVector tokens = StringUtil::split(versionString, ".");
+			if(!tokens.empty())
+			{
+				major = StringConverter::parseInt(tokens[0]);
+				if (tokens.size() > 1)
+					minor = StringConverter::parseInt(tokens[1]);
+				if (tokens.size() > 2)
+					release = StringConverter::parseInt(tokens[2]);
+				if (tokens.size() > 3)
+					build = StringConverter::parseInt(tokens[3]);
+			}
+
+		}
+	};
+
+	/** Enumeration of GPU vendors. */
+	enum GPUVendor
+	{
+		GPU_UNKNOWN = 0,
+		GPU_NVIDIA = 1,
+		GPU_ATI = 2, 
+		GPU_INTEL = 3,
+		GPU_S3 = 4,
+		GPU_MATROX = 5,
+		GPU_3DLABS = 6,
+		GPU_SIS = 7,
+        GPU_IMAGINATION_TECHNOLOGIES = 8,
+        GPU_APPLE = 9,  // Apple Software Renderer
+        GPU_NOKIA = 10,
+
+		/// placeholder
+		GPU_VENDOR_COUNT = 11
+	};
+
+	/** singleton class for storing the capabilities of the graphics card. 
+	@remarks
+	This class stores the capabilities of the graphics card.  This
+	information is set by the individual render systems.
+	*/
+	class _OgreExport RenderSystemCapabilities
+	{
+
+	public:
+
+		typedef set<String>::type ShaderProfiles;
+	private:
+		/// This is used to build a database of RSC's
+		/// if a RSC with same name, but newer version is introduced, the older one 
+		/// will be removed
+		DriverVersion mDriverVersion;
+		/// GPU Vendor
+		GPUVendor mVendor;
+
+		static StringVector msGPUVendorStrings;
+		static void initVendorStrings();
+
+		/// The number of world matrices available
+		ushort mNumWorldMatrices;
+		/// The number of texture units available
+		ushort mNumTextureUnits;
+		/// The stencil buffer bit depth
+		ushort mStencilBufferBitDepth;
+		/// The number of matrices available for hardware blending
+		ushort mNumVertexBlendMatrices;
+		/// Stores the capabilities flags.
+		int mCapabilities[CAPS_CATEGORY_COUNT];
+		/// Which categories are relevant
+		bool mCategoryRelevant[CAPS_CATEGORY_COUNT];
+		/// The name of the device as reported by the render system
+		String mDeviceName;
+		/// The identifier associated with the render system for which these capabilities are valid
+		String mRenderSystemName;
+
+		/// The number of floating-point constants vertex programs support
+		ushort mVertexProgramConstantFloatCount;           
+		/// The number of integer constants vertex programs support
+		ushort mVertexProgramConstantIntCount;           
+		/// The number of boolean constants vertex programs support
+		ushort mVertexProgramConstantBoolCount;           
+		/// The number of floating-point constants geometry programs support
+		ushort mGeometryProgramConstantFloatCount;           
+		/// The number of integer constants vertex geometry support
+		ushort mGeometryProgramConstantIntCount;           
+		/// The number of boolean constants vertex geometry support
+		ushort mGeometryProgramConstantBoolCount;           
+		/// The number of floating-point constants fragment programs support
+		ushort mFragmentProgramConstantFloatCount;           
+		/// The number of integer constants fragment programs support
+		ushort mFragmentProgramConstantIntCount;           
+		/// The number of boolean constants fragment programs support
+		ushort mFragmentProgramConstantBoolCount;
+		/// The number of simultaneous render targets supported
+		ushort mNumMultiRenderTargets;
+		/// The maximum point size
+		Real mMaxPointSize;
+		/// Are non-POW2 textures feature-limited?
+		bool mNonPOW2TexturesLimited;
+		/// The number of vertex texture units supported
+		ushort mNumVertexTextureUnits;
+		/// Are vertex texture units shared with fragment processor?
+		bool mVertexTextureUnitsShared;
+		/// The number of vertices a geometry program can emit in a single run
+		int mGeometryProgramNumOutputVertices;
+
+
+		/// The list of supported shader profiles
+		ShaderProfiles mSupportedShaderProfiles;
+
+	public:	
+		RenderSystemCapabilities ();
+		virtual ~RenderSystemCapabilities ();
+
+		virtual size_t calculateSize() const {return 0;}
+
+		/** Set the driver version. */
+		void setDriverVersion(const DriverVersion& version)
+		{
+			mDriverVersion = version;
+		}
+
+		void parseDriverVersionFromString(const String& versionString)
+		{
+			DriverVersion version;
+			version.fromString(versionString);
+			setDriverVersion(version);
+		}
+
+
+		DriverVersion getDriverVersion() const
+		{
+			return mDriverVersion;
+		}
+
+		GPUVendor getVendor() const
+		{
+			return mVendor;
+		}
+
+		void setVendor(GPUVendor v)
+		{
+			mVendor = v;
+		}
+
+		/// Parse and set vendor
+		void parseVendorFromString(const String& vendorString)
+		{
+			setVendor(vendorFromString(vendorString));
+		}
+
+		/// Convert a vendor string to an enum
+		static GPUVendor vendorFromString(const String& vendorString);
+		/// Convert a vendor enum to a string
+		static String vendorToString(GPUVendor v);
+
+		bool isDriverOlderThanVersion(DriverVersion v) const
+		{
+			if (mDriverVersion.major < v.major)
+				return true;
+			else if (mDriverVersion.major == v.major && 
+				mDriverVersion.minor < v.minor)
+				return true;
+			else if (mDriverVersion.major == v.major && 
+				mDriverVersion.minor == v.minor && 
+				mDriverVersion.release < v.release)
+				return true;
+			else if (mDriverVersion.major == v.major && 
+				mDriverVersion.minor == v.minor && 
+				mDriverVersion.release == v.release &&
+				mDriverVersion.build < v.build)
+				return true;
+			return false;
+		}
+
+		void setNumWorldMatrices(ushort num)
+		{
+			mNumWorldMatrices = num;
+		}
+
+		void setNumTextureUnits(ushort num)
+		{
+			mNumTextureUnits = num;
+		}
+
+		void setStencilBufferBitDepth(ushort num)
+		{
+			mStencilBufferBitDepth = num;
+		}
+
+		void setNumVertexBlendMatrices(ushort num)
+		{
+			mNumVertexBlendMatrices = num;
+		}
+
+		/// The number of simultaneous render targets supported
+		void setNumMultiRenderTargets(ushort num)
+		{
+			mNumMultiRenderTargets = num;
+		}
+
+		ushort getNumWorldMatrices(void) const
+		{ 
+			return mNumWorldMatrices;
+		}
+
+		/** Returns the number of texture units the current output hardware
+		supports.
+
+		For use in rendering, this determines how many texture units the
+		are available for multitexturing (i.e. rendering multiple 
+		textures in a single pass). Where a Material has multiple 
+		texture layers, it will try to use multitexturing where 
+		available, and where it is not available, will perform multipass
+		rendering to achieve the same effect. This property only applies
+		to the fixed-function pipeline, the number available to the 
+		programmable pipeline depends on the shader model in use.
+		*/
+		ushort getNumTextureUnits(void) const
+		{
+			return mNumTextureUnits;
+		}
+
+		/** Determines the bit depth of the hardware accelerated stencil 
+		buffer, if supported.
+		@remarks
+		If hardware stencilling is not supported, the software will
+		provide an 8-bit software stencil.
+		*/
+		ushort getStencilBufferBitDepth(void) const
+		{
+			return mStencilBufferBitDepth;
+		}
+
+		/** Returns the number of matrices available to hardware vertex 
+		blending for this rendering system. */
+		ushort getNumVertexBlendMatrices(void) const
+		{
+			return mNumVertexBlendMatrices;
+		}
+
+		/// The number of simultaneous render targets supported
+		ushort getNumMultiRenderTargets(void) const
+		{
+			return mNumMultiRenderTargets;
+		}
+
+		/** Returns true if capability is render system specific
+		*/
+		bool isCapabilityRenderSystemSpecific(const Capabilities c)
+		{
+			int cat = c >> OGRE_CAPS_BITSHIFT;
+			if(cat == CAPS_CATEGORY_GL || cat == CAPS_CATEGORY_D3D9)
+				return true;
+			return false;
+		}
+
+		/** Adds a capability flag
+		*/
+		void setCapability(const Capabilities c) 
+		{ 
+			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			// zero out the index from the stored capability
+			mCapabilities[index] |= (c & ~CAPS_CATEGORY_MASK);
+		}
+
+		/** Remove a capability flag
+		*/
+		void unsetCapability(const Capabilities c) 
+		{ 
+			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			// zero out the index from the stored capability
+			mCapabilities[index] &= (~c | CAPS_CATEGORY_MASK);
+		}
+
+		/** Checks for a capability
+		*/
+		bool hasCapability(const Capabilities c) const
+		{
+			int index = (CAPS_CATEGORY_MASK & c) >> OGRE_CAPS_BITSHIFT;
+			// test against
+			if(mCapabilities[index] & (c & ~CAPS_CATEGORY_MASK))
+			{
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+
+		/** Adds the profile to the list of supported profiles
+		*/
+		void addShaderProfile(const String& profile)
+		{
+			mSupportedShaderProfiles.insert(profile);
+
+		}
+
+		/** Remove a given shader profile, if present.
+		*/
+		void removeShaderProfile(const String& profile)
+		{
+			mSupportedShaderProfiles.erase(profile);
+		}
+
+		/** Returns true if profile is in the list of supported profiles
+		*/
+		bool isShaderProfileSupported(const String& profile) const
+		{
+			return (mSupportedShaderProfiles.end() != mSupportedShaderProfiles.find(profile));
+		}
+
+
+		/** Returns a set of all supported shader profiles
+		* */
+		const ShaderProfiles& getSupportedShaderProfiles() const
+		{
+			return mSupportedShaderProfiles;
+		}
+
+
+		/// The number of floating-point constants vertex programs support
+		ushort getVertexProgramConstantFloatCount(void) const
+		{
+			return mVertexProgramConstantFloatCount;           
+		}
+		/// The number of integer constants vertex programs support
+		ushort getVertexProgramConstantIntCount(void) const
+		{
+			return mVertexProgramConstantIntCount;           
+		}
+		/// The number of boolean constants vertex programs support
+		ushort getVertexProgramConstantBoolCount(void) const
+		{
+			return mVertexProgramConstantBoolCount;           
+		}
+		/// The number of floating-point constants geometry programs support
+		ushort getGeometryProgramConstantFloatCount(void) const
+		{
+			return mGeometryProgramConstantFloatCount;           
+		}
+		/// The number of integer constants geometry programs support
+		ushort getGeometryProgramConstantIntCount(void) const
+		{
+			return mGeometryProgramConstantIntCount;           
+		}
+		/// The number of boolean constants geometry programs support
+		ushort getGeometryProgramConstantBoolCount(void) const
+		{
+			return mGeometryProgramConstantBoolCount;           
+		}
+		/// The number of floating-point constants fragment programs support
+		ushort getFragmentProgramConstantFloatCount(void) const
+		{
+			return mFragmentProgramConstantFloatCount;           
+		}
+		/// The number of integer constants fragment programs support
+		ushort getFragmentProgramConstantIntCount(void) const
+		{
+			return mFragmentProgramConstantIntCount;           
+		}
+		/// The number of boolean constants fragment programs support
+		ushort getFragmentProgramConstantBoolCount(void) const
+		{
+			return mFragmentProgramConstantBoolCount;           
+		}
+
+		/// sets the device name for Render system
+		void setDeviceName(const String& name)
+		{
+			mDeviceName = name;
+		}
+
+		/// gets the device name for render system
+		String getDeviceName() const
+		{
+			return mDeviceName;
+		}
+
+		/// The number of floating-point constants vertex programs support
+		void setVertexProgramConstantFloatCount(ushort c)
+		{
+			mVertexProgramConstantFloatCount = c;           
+		}
+		/// The number of integer constants vertex programs support
+		void setVertexProgramConstantIntCount(ushort c)
+		{
+			mVertexProgramConstantIntCount = c;           
+		}
+		/// The number of boolean constants vertex programs support
+		void setVertexProgramConstantBoolCount(ushort c)
+		{
+			mVertexProgramConstantBoolCount = c;           
+		}
+		/// The number of floating-point constants geometry programs support
+		void setGeometryProgramConstantFloatCount(ushort c)
+		{
+			mGeometryProgramConstantFloatCount = c;           
+		}
+		/// The number of integer constants geometry programs support
+		void setGeometryProgramConstantIntCount(ushort c)
+		{
+			mGeometryProgramConstantIntCount = c;           
+		}
+		/// The number of boolean constants geometry programs support
+		void setGeometryProgramConstantBoolCount(ushort c)
+		{
+			mGeometryProgramConstantBoolCount = c;           
+		}
+		/// The number of floating-point constants fragment programs support
+		void setFragmentProgramConstantFloatCount(ushort c)
+		{
+			mFragmentProgramConstantFloatCount = c;           
+		}
+		/// The number of integer constants fragment programs support
+		void setFragmentProgramConstantIntCount(ushort c)
+		{
+			mFragmentProgramConstantIntCount = c;           
+		}
+		/// The number of boolean constants fragment programs support
+		void setFragmentProgramConstantBoolCount(ushort c)
+		{
+			mFragmentProgramConstantBoolCount = c;           
+		}
+		/// Maximum point screen size in pixels
+		void setMaxPointSize(Real s)
+		{
+			mMaxPointSize = s;
+		}
+		/// Maximum point screen size in pixels
+		Real getMaxPointSize(void) const
+		{
+			return mMaxPointSize;
+		}
+		/// Non-POW2 textures limited
+		void setNonPOW2TexturesLimited(bool l)
+		{
+			mNonPOW2TexturesLimited = l;
+		}
+		/** Are non-power of two textures limited in features?
+		@remarks
+		If the RSC_NON_POWER_OF_2_TEXTURES capability is set, but this
+		method returns true, you can use non power of 2 textures only if:
+		<ul><li>You load them explicitly with no mip maps</li>
+		<li>You don't use DXT texture compression</li>
+		<li>You use clamp texture addressing</li></ul>
+		*/
+		bool getNonPOW2TexturesLimited(void) const
+		{
+			return mNonPOW2TexturesLimited;
+		}
+
+		/// Set the number of vertex texture units supported
+		void setNumVertexTextureUnits(ushort n)
+		{
+			mNumVertexTextureUnits = n;
+		}
+		/// Get the number of vertex texture units supported
+		ushort getNumVertexTextureUnits(void) const
+		{
+			return mNumVertexTextureUnits;
+		}
+		/// Set whether the vertex texture units are shared with the fragment processor
+		void setVertexTextureUnitsShared(bool shared)
+		{
+			mVertexTextureUnitsShared = shared;
+		}
+		/// Get whether the vertex texture units are shared with the fragment processor
+		bool getVertexTextureUnitsShared(void) const
+		{
+			return mVertexTextureUnitsShared;
+		}
+
+		/// Set the number of vertices a single geometry program run can emit
+		void setGeometryProgramNumOutputVertices(int numOutputVertices)
+		{
+			mGeometryProgramNumOutputVertices = numOutputVertices;
+		}
+		/// Get the number of vertices a single geometry program run can emit
+		int getGeometryProgramNumOutputVertices(void) const
+		{
+			return mGeometryProgramNumOutputVertices;
+		}
+
+		/// Get the identifier of the rendersystem from which these capabilities were generated
+		String getRenderSystemName(void) const
+		{
+			return mRenderSystemName;
+		}
+		///  Set the identifier of the rendersystem from which these capabilities were generated
+		void setRenderSystemName(const String& rs)
+		{
+			mRenderSystemName = rs;
+		}
+
+		/// Mark a category as 'relevant' or not, ie will it be reported
+		void setCategoryRelevant(CapabilitiesCategory cat, bool relevant)
+		{
+			mCategoryRelevant[cat] = relevant;
+		}
+
+		/// Return whether a category is 'relevant' or not, ie will it be reported
+		bool isCategoryRelevant(CapabilitiesCategory cat)
+		{
+			return mCategoryRelevant[cat];
+		}
+	};
+
+	/** @} */
+	/** @} */
+} // namespace
+
+#endif // __RenderSystemCapabilities__
+

+ 278 - 0
CamelotRenderer/OgreSharedPtr.h

@@ -0,0 +1,278 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __SharedPtr_H__
+#define __SharedPtr_H__
+
+#include "OgrePrerequisites.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+	/// The method to use to free memory on destruction
+	enum SharedPtrFreeMethod
+	{
+		/// Use OGRE_DELETE to free the memory
+		SPFM_DELETE,
+		/// Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
+		SPFM_DELETE_T,
+		/// Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
+		SPFM_FREE
+	};
+
+	/** Reference-counted shared pointer, used for objects where implicit destruction is 
+        required. 
+    @remarks
+        This is a standard shared pointer implementation which uses a reference 
+        count to work out when to delete the object. 
+	@par
+		If OGRE_THREAD_SUPPORT is defined to be 1, use of this class is thread-safe.
+    */
+	template<class T> class SharedPtr
+	{
+	protected:
+		T* pRep;
+		unsigned int* pUseCount;
+		SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE
+	public:
+		OGRE_AUTO_SHARED_MUTEX // public to allow external locking
+		/** Constructor, does not initialise the SharedPtr.
+			@remarks
+				<b>Dangerous!</b> You have to call bind() before using the SharedPtr.
+		*/
+		SharedPtr() : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
+        {
+            OGRE_SET_AUTO_SHARED_MUTEX_NULL
+        }
+
+		/** Constructor.
+		@param rep The pointer to take ownership of
+		@param freeMode The mechanism to use to free the pointer
+		*/
+        template< class Y>
+		explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) 
+			: pRep(rep)
+			, pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0)
+			, useFreeMethod(inFreeMethod)
+		{
+            OGRE_SET_AUTO_SHARED_MUTEX_NULL
+			if (rep)
+			{
+				OGRE_NEW_AUTO_SHARED_MUTEX
+			}
+		}
+		SharedPtr(const SharedPtr& r)
+            : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
+		{
+			// lock & copy other mutex pointer
+            
+            OGRE_SET_AUTO_SHARED_MUTEX_NULL
+            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
+            {
+			    OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			    OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+			    pRep = r.pRep;
+			    pUseCount = r.pUseCount; 
+				useFreeMethod = r.useFreeMethod;
+			    // Handle zero pointer gracefully to manage STL containers
+			    if(pUseCount)
+			    {
+				    ++(*pUseCount); 
+			    }
+            }
+		}
+		SharedPtr& operator=(const SharedPtr& r) {
+			if (pRep == r.pRep)
+				return *this;
+			// Swap current data into a local copy
+			// this ensures we deal with rhs and this being dependent
+			SharedPtr<T> tmp(r);
+			swap(tmp);
+			return *this;
+		}
+		
+		template< class Y>
+		SharedPtr(const SharedPtr<Y>& r)
+            : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
+		{
+			// lock & copy other mutex pointer
+
+            OGRE_SET_AUTO_SHARED_MUTEX_NULL
+            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
+            {
+			    OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
+			    OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
+			    pRep = r.getPointer();
+			    pUseCount = r.useCountPointer();
+				useFreeMethod = r.freeMethod();
+			    // Handle zero pointer gracefully to manage STL containers
+			    if(pUseCount)
+			    {
+				    ++(*pUseCount);
+			    }
+            }
+		}
+		template< class Y>
+		SharedPtr& operator=(const SharedPtr<Y>& r) {
+			if (pRep == r.getPointer())
+				return *this;
+			// Swap current data into a local copy
+			// this ensures we deal with rhs and this being dependent
+			SharedPtr<T> tmp(r);
+			swap(tmp);
+			return *this;
+		}
+		virtual ~SharedPtr() {
+            release();
+		}
+
+
+		inline T& operator*() const { assert(pRep); return *pRep; }
+		inline T* operator->() const { assert(pRep); return pRep; }
+		inline T* get() const { return pRep; }
+
+		/** Binds rep to the SharedPtr.
+			@remarks
+				Assumes that the SharedPtr is uninitialised!
+		*/
+		void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) {
+			assert(!pRep && !pUseCount);
+            OGRE_NEW_AUTO_SHARED_MUTEX
+			OGRE_LOCK_AUTO_SHARED_MUTEX
+			pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1);
+			pRep = rep;
+			useFreeMethod = inFreeMethod;
+		}
+
+		inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
+		inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
+		inline unsigned int* useCountPointer() const { return pUseCount; }
+
+		inline T* getPointer() const { return pRep; }
+		inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; }
+
+		inline bool isNull(void) const { return pRep == 0; }
+
+        inline void setNull(void) { 
+			if (pRep)
+			{
+				// can't scope lock mutex before release in case deleted
+				release();
+				pRep = 0;
+				pUseCount = 0;
+			}
+        }
+
+    protected:
+
+        inline void release(void)
+        {
+			bool destroyThis = false;
+
+            /* If the mutex is not initialized to a non-zero value, then
+               neither is pUseCount nor pRep.
+             */
+
+            OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
+			{
+				// lock own mutex in limited scope (must unlock before destroy)
+				OGRE_LOCK_AUTO_SHARED_MUTEX
+				if (pUseCount)
+				{
+					if (--(*pUseCount) == 0) 
+					{
+						destroyThis = true;
+	                }
+				}
+            }
+			if (destroyThis)
+				destroy();
+
+            OGRE_SET_AUTO_SHARED_MUTEX_NULL
+        }
+
+        virtual void destroy(void)
+        {
+            // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
+            // BEFORE SHUTTING OGRE DOWN
+            // Use setNull() before shutdown or make sure your pointer goes
+            // out of scope before OGRE shuts down to avoid this.
+			switch(useFreeMethod)
+			{
+			case SPFM_DELETE:
+				OGRE_DELETE pRep;
+				break;
+			case SPFM_DELETE_T:
+				OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL);
+				break;
+			case SPFM_FREE:
+				OGRE_FREE(pRep, MEMCATEGORY_GENERAL);
+				break;
+			};
+			// use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor
+			// we only used OGRE_NEW_T to be able to use constructor
+            OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL);
+			OGRE_DELETE_AUTO_SHARED_MUTEX
+        }
+
+		virtual void swap(SharedPtr<T> &other) 
+		{
+			std::swap(pRep, other.pRep);
+			std::swap(pUseCount, other.pUseCount);
+			std::swap(useFreeMethod, other.useFreeMethod);
+#if OGRE_THREAD_SUPPORT
+			std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
+#endif
+		}
+	};
+
+	template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
+	{
+		return a.get() == b.get();
+	}
+
+	template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
+	{
+		return a.get() != b.get();
+	}
+
+	template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b)
+	{
+		return std::less<const void*>()(a.get(), b.get());
+	}
+	/** @} */
+	/** @} */
+}
+
+
+
+#endif

+ 104 - 0
CamelotRenderer/OgreSingleton.h

@@ -0,0 +1,104 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+/* Original version Copyright (C) Scott Bilas, 2000.
+ * All rights reserved worldwide.
+ *
+ * This software is provided "as is" without express or implied
+ * warranties. You may freely copy and compile this source into
+ * applications you distribute provided that the copyright text
+ * below is included in the resulting source code, for example:
+ * "Portions Copyright (C) Scott Bilas, 2000"
+ */
+#ifndef _SINGLETON_H__
+#define _SINGLETON_H__
+
+// Added by Steve Streeting for Ogre
+#include "OgrePrerequisites.h"
+#include "OgreHeaderPrefix.h"
+
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+// Turn off warnings generated by this singleton implementation
+#   pragma warning (disable : 4311)
+#   pragma warning (disable : 4312)
+#endif
+
+#if defined ( OGRE_GCC_VISIBILITY )
+#   pragma GCC visibility push(default)
+#endif
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+// End SJS additions
+    /** Template class for creating single-instance global classes.
+    */
+    template <typename T> class Singleton
+    {
+	private:
+		/** \brief Explicit private copy constructor. This is a forbidden operation.*/
+		Singleton(const Singleton<T> &);
+
+		/** \brief Private operator= . This is a forbidden operation. */
+		Singleton& operator=(const Singleton<T> &);
+    
+	protected:
+
+        static T* ms_Singleton;
+
+    public:
+        Singleton( void )
+        {
+            assert( !ms_Singleton );
+#if defined( _MSC_VER ) && _MSC_VER < 1200	 
+            int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
+            ms_Singleton = (T*)((int)this + offset);
+#else
+	    ms_Singleton = static_cast< T* >( this );
+#endif
+        }
+        ~Singleton( void )
+            {  assert( ms_Singleton );  ms_Singleton = 0;  }
+        static T& getSingleton( void )
+		{	assert( ms_Singleton );  return ( *ms_Singleton ); }
+        static T* getSingletonPtr( void )
+		{ return ms_Singleton; }
+    };
+	/** @} */
+	/** @} */
+
+}
+#if defined ( OGRE_GCC_VISIBILITY )
+#   pragma GCC visibility pop
+#endif
+
+#include "OgreHeaderSuffix.h"
+#endif

+ 108 - 0
CamelotRenderer/OgreSphere.h

@@ -0,0 +1,108 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Sphere_H_
+#define __Sphere_H_
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+
+#include "OgreVector3.h"
+
+namespace Ogre {
+
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** A sphere primitive, mostly used for bounds checking. 
+    @remarks
+        A sphere in math texts is normally represented by the function
+        x^2 + y^2 + z^2 = r^2 (for sphere's centered on the origin). Ogre stores spheres
+        simply as a center point and a radius.
+    */
+    class _OgreExport Sphere
+    {
+    protected:
+        Real mRadius;
+        Vector3 mCenter;
+    public:
+        /** Standard constructor - creates a unit sphere around the origin.*/
+        Sphere() : mRadius(1.0), mCenter(Vector3::ZERO) {}
+        /** Constructor allowing arbitrary spheres. 
+            @param center The center point of the sphere.
+            @param radius The radius of the sphere.
+        */
+        Sphere(const Vector3& center, Real radius)
+            : mRadius(radius), mCenter(center) {}
+
+        /** Returns the radius of the sphere. */
+        Real getRadius(void) const { return mRadius; }
+
+        /** Sets the radius of the sphere. */
+        void setRadius(Real radius) { mRadius = radius; }
+
+        /** Returns the center point of the sphere. */
+        const Vector3& getCenter(void) const { return mCenter; }
+
+        /** Sets the center point of the sphere. */
+        void setCenter(const Vector3& center) { mCenter = center; }
+
+		/** Returns whether or not this sphere intersects another sphere. */
+		bool intersects(const Sphere& s) const
+		{
+            return (s.mCenter - mCenter).squaredLength() <=
+                Math::Sqr(s.mRadius + mRadius);
+		}
+		/** Returns whether or not this sphere intersects a box. */
+		bool intersects(const AxisAlignedBox& box) const
+		{
+			return Math::intersects(*this, box);
+		}
+		/** Returns whether or not this sphere intersects a plane. */
+		bool intersects(const Plane& plane) const
+		{
+			return Math::intersects(*this, plane);
+		}
+		/** Returns whether or not this sphere intersects a point. */
+		bool intersects(const Vector3& v) const
+		{
+            return ((v - mCenter).squaredLength() <= Math::Sqr(mRadius));
+		}
+        
+
+    };
+	/** @} */
+	/** @} */
+
+}
+
+#endif
+

+ 120 - 0
CamelotRenderer/OgreStdHeaders.h

@@ -0,0 +1,120 @@
+#ifndef __StdHeaders_H__
+#define __StdHeaders_H__
+
+#ifdef __BORLANDC__
+    #define __STD_ALGORITHM
+#endif
+
+#if defined ( OGRE_GCC_VISIBILITY ) && (OGRE_PLATFORM != OGRE_PLATFORM_APPLE && OGRE_PLATFORM != OGRE_PLATFORM_IPHONE)
+/* Until libstdc++ for gcc 4.2 is released, we have to declare all
+ * symbols in libstdc++.so externally visible, otherwise we end up
+ * with them marked as hidden by -fvisible=hidden.
+ *
+ * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20218
+ *
+ * Due to a more strict linker included with Xcode 4, this is disabled on Mac OS X and iOS.
+ * The reason? It changes the visibility of Boost functions.  The mismatch between visibility Boost when used in Ogre (default)
+ * and Boost when compiled (hidden) results in mysterious link errors such as "Bad codegen, pointer diff".
+ */
+#   pragma GCC visibility push(default)
+#endif
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <cstring>
+#include <cstdarg>
+#include <cmath>
+
+// STL containers
+#include <vector>
+#include <map>
+#include <string>
+#include <set>
+#include <list>
+#include <deque>
+#include <queue>
+#include <bitset>
+
+// Note - not in the original STL, but exists in SGI STL and STLport
+// For gcc 4.3 see http://gcc.gnu.org/gcc-4.3/changes.html
+#if (OGRE_COMPILER == OGRE_COMPILER_GNUC) && !defined(STLPORT)
+#   if OGRE_COMP_VER >= 430
+#       include <tr1/unordered_map>
+#       include <tr1/unordered_set> 
+#   else
+#       include <ext/hash_map>
+#       include <ext/hash_set>
+#   endif
+#else
+#   if (OGRE_COMPILER == OGRE_COMPILER_MSVC) && !defined(STLPORT) && OGRE_COMP_VER >= 1600 // VC++ 10.0
+#    	include <unordered_map>
+#    	include <unordered_set>
+#	else
+#   	include <hash_set>
+#   	include <hash_map>
+#	endif
+#endif 
+
+// STL algorithms & functions
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+// C++ Stream stuff
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+#ifdef __BORLANDC__
+namespace Ogre
+{
+    using namespace std;
+}
+#endif
+
+extern "C" {
+
+#   include <sys/types.h>
+#   include <sys/stat.h>
+
+}
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#  undef min
+#  undef max
+#  if defined( __MINGW32__ )
+#    include <unistd.h>
+#  endif
+#endif
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
+extern "C" {
+
+#   include <unistd.h>
+#   include <dlfcn.h>
+
+}
+#endif
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
+extern "C" {
+#   include <unistd.h>
+#   include <sys/param.h>
+#   include <CoreFoundation/CoreFoundation.h>
+}
+#endif
+
+#if OGRE_THREAD_SUPPORT
+#	if !defined(NOMINMAX) && defined(_MSC_VER)
+#		define NOMINMAX // required to stop windows.h messing up std::min
+#	endif
+#   include "Threading/OgreThreadHeaders.h"
+#endif
+
+#if defined ( OGRE_GCC_VISIBILITY ) && (OGRE_PLATFORM != OGRE_PLATFORM_APPLE && OGRE_PLATFORM != OGRE_PLATFORM_IPHONE)
+#   pragma GCC visibility pop
+#endif
+#endif

+ 367 - 0
CamelotRenderer/OgreString.cpp

@@ -0,0 +1,367 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreString.h"
+#include "OgreStringVector.h"
+
+namespace Ogre {
+
+	//-----------------------------------------------------------------------
+	const String StringUtil::BLANK;
+	//-----------------------------------------------------------------------
+    void StringUtil::trim(String& str, bool left, bool right)
+    {
+        /*
+        size_t lspaces, rspaces, len = length(), i;
+
+        lspaces = rspaces = 0;
+
+        if( left )
+        {
+            // Find spaces / tabs on the left
+            for( i = 0;
+                i < len && ( at(i) == ' ' || at(i) == '\t' || at(i) == '\r');
+                ++lspaces, ++i );
+        }
+        
+        if( right && lspaces < len )
+        {
+            // Find spaces / tabs on the right
+            for( i = len - 1;
+                i >= 0 && ( at(i) == ' ' || at(i) == '\t' || at(i) == '\r');
+                rspaces++, i-- );
+        }
+
+        *this = substr(lspaces, len-lspaces-rspaces);
+        */
+        static const String delims = " \t\r";
+        if(right)
+            str.erase(str.find_last_not_of(delims)+1); // trim right
+        if(left)
+            str.erase(0, str.find_first_not_of(delims)); // trim left
+    }
+
+    //-----------------------------------------------------------------------
+    StringVector StringUtil::split( const String& str, const String& delims, unsigned int maxSplits)
+    {
+        StringVector ret;
+        // Pre-allocate some space for performance
+        ret.reserve(maxSplits ? maxSplits+1 : 10);    // 10 is guessed capacity for most case
+
+        unsigned int numSplits = 0;
+
+        // Use STL methods 
+        size_t start, pos;
+        start = 0;
+        do 
+        {
+            pos = str.find_first_of(delims, start);
+            if (pos == start)
+            {
+                // Do nothing
+                start = pos + 1;
+            }
+            else if (pos == String::npos || (maxSplits && numSplits == maxSplits))
+            {
+                // Copy the rest of the string
+                ret.push_back( str.substr(start) );
+                break;
+            }
+            else
+            {
+                // Copy up to delimiter
+                ret.push_back( str.substr(start, pos - start) );
+                start = pos + 1;
+            }
+            // parse up to next real data
+            start = str.find_first_not_of(delims, start);
+            ++numSplits;
+
+        } while (pos != String::npos);
+
+
+
+        return ret;
+    }
+	//-----------------------------------------------------------------------
+	StringVector StringUtil::tokenise( const String& str, const String& singleDelims, const String& doubleDelims, unsigned int maxSplits)
+	{
+        StringVector ret;
+        // Pre-allocate some space for performance
+        ret.reserve(maxSplits ? maxSplits+1 : 10);    // 10 is guessed capacity for most case
+
+        unsigned int numSplits = 0;
+		String delims = singleDelims + doubleDelims;
+
+		// Use STL methods 
+        size_t start, pos;
+		char curDoubleDelim = 0;
+        start = 0;
+        do 
+        {
+			if (curDoubleDelim != 0)
+			{
+				pos = str.find(curDoubleDelim, start);
+			}
+			else
+			{
+				pos = str.find_first_of(delims, start);
+			}
+
+            if (pos == start)
+            {
+				char curDelim = str.at(pos);
+				if (doubleDelims.find_first_of(curDelim) != String::npos)
+				{
+					curDoubleDelim = curDelim;
+				}
+                // Do nothing
+                start = pos + 1;
+            }
+            else if (pos == String::npos || (maxSplits && numSplits == maxSplits))
+            {
+				if (curDoubleDelim != 0)
+				{
+					//Missing closer. Warn or throw exception?
+				}
+                // Copy the rest of the string
+                ret.push_back( str.substr(start) );
+                break;
+            }
+            else
+            {
+				if (curDoubleDelim != 0)
+				{
+					curDoubleDelim = 0;
+				}
+
+				// Copy up to delimiter
+				ret.push_back( str.substr(start, pos - start) );
+				start = pos + 1;
+            }
+			if (curDoubleDelim == 0)
+			{
+				// parse up to next real data
+				start = str.find_first_not_of(singleDelims, start);
+			}
+            
+            ++numSplits;
+
+        } while (pos != String::npos);
+
+        return ret;
+    }
+    //-----------------------------------------------------------------------
+    void StringUtil::toLowerCase(String& str)
+    {
+        std::transform(
+            str.begin(),
+            str.end(),
+            str.begin(),
+			tolower);
+    }
+
+    //-----------------------------------------------------------------------
+    void StringUtil::toUpperCase(String& str) 
+    {
+        std::transform(
+            str.begin(),
+            str.end(),
+            str.begin(),
+			toupper);
+    }
+    //-----------------------------------------------------------------------
+    bool StringUtil::startsWith(const String& str, const String& pattern, bool lowerCase)
+    {
+        size_t thisLen = str.length();
+        size_t patternLen = pattern.length();
+        if (thisLen < patternLen || patternLen == 0)
+            return false;
+
+        String startOfThis = str.substr(0, patternLen);
+        if (lowerCase)
+            StringUtil::toLowerCase(startOfThis);
+
+        return (startOfThis == pattern);
+    }
+    //-----------------------------------------------------------------------
+    bool StringUtil::endsWith(const String& str, const String& pattern, bool lowerCase)
+    {
+        size_t thisLen = str.length();
+        size_t patternLen = pattern.length();
+        if (thisLen < patternLen || patternLen == 0)
+            return false;
+
+        String endOfThis = str.substr(thisLen - patternLen, patternLen);
+        if (lowerCase)
+            StringUtil::toLowerCase(endOfThis);
+
+        return (endOfThis == pattern);
+    }
+    //-----------------------------------------------------------------------
+    String StringUtil::standardisePath(const String& init)
+    {
+        String path = init;
+
+        std::replace( path.begin(), path.end(), '\\', '/' );
+        if( path[path.length() - 1] != '/' )
+            path += '/';
+
+        return path;
+    }
+    //-----------------------------------------------------------------------
+    void StringUtil::splitFilename(const String& qualifiedName, 
+        String& outBasename, String& outPath)
+    {
+        String path = qualifiedName;
+        // Replace \ with / first
+        std::replace( path.begin(), path.end(), '\\', '/' );
+        // split based on final /
+        size_t i = path.find_last_of('/');
+
+        if (i == String::npos)
+        {
+            outPath.clear();
+			outBasename = qualifiedName;
+        }
+        else
+        {
+            outBasename = path.substr(i+1, path.size() - i - 1);
+            outPath = path.substr(0, i+1);
+        }
+
+    }
+	//-----------------------------------------------------------------------
+	void StringUtil::splitBaseFilename(const Ogre::String& fullName, 
+		Ogre::String& outBasename, Ogre::String& outExtention)
+	{
+		size_t i = fullName.find_last_of(".");
+		if (i == Ogre::String::npos)
+		{
+			outExtention.clear();
+			outBasename = fullName;
+		}
+		else
+		{
+			outExtention = fullName.substr(i+1);
+			outBasename = fullName.substr(0, i);
+		}
+	}
+	// ----------------------------------------------------------------------------------------------------------------------------------------------
+	void StringUtil::splitFullFilename(	const Ogre::String& qualifiedName, 
+		Ogre::String& outBasename, Ogre::String& outExtention, Ogre::String& outPath )
+	{
+		Ogre::String fullName;
+		splitFilename( qualifiedName, fullName, outPath );
+		splitBaseFilename( fullName, outBasename, outExtention );
+	}
+    //-----------------------------------------------------------------------
+    bool StringUtil::match(const String& str, const String& pattern, bool caseSensitive)
+    {
+        String tmpStr = str;
+		String tmpPattern = pattern;
+        if (!caseSensitive)
+        {
+            StringUtil::toLowerCase(tmpStr);
+            StringUtil::toLowerCase(tmpPattern);
+        }
+
+        String::const_iterator strIt = tmpStr.begin();
+        String::const_iterator patIt = tmpPattern.begin();
+		String::const_iterator lastWildCardIt = tmpPattern.end();
+        while (strIt != tmpStr.end() && patIt != tmpPattern.end())
+        {
+            if (*patIt == '*')
+            {
+				lastWildCardIt = patIt;
+                // Skip over looking for next character
+                ++patIt;
+                if (patIt == tmpPattern.end())
+				{
+					// Skip right to the end since * matches the entire rest of the string
+					strIt = tmpStr.end();
+				}
+				else
+                {
+					// scan until we find next pattern character
+                    while(strIt != tmpStr.end() && *strIt != *patIt)
+                        ++strIt;
+                }
+            }
+            else
+            {
+                if (*patIt != *strIt)
+                {
+					if (lastWildCardIt != tmpPattern.end())
+					{
+						// The last wildcard can match this incorrect sequence
+						// rewind pattern to wildcard and keep searching
+						patIt = lastWildCardIt;
+						lastWildCardIt = tmpPattern.end();
+					}
+					else
+					{
+						// no wildwards left
+						return false;
+					}
+                }
+                else
+                {
+                    ++patIt;
+                    ++strIt;
+                }
+            }
+
+        }
+		// If we reached the end of both the pattern and the string, we succeeded
+		if (patIt == tmpPattern.end() && strIt == tmpStr.end())
+		{
+        	return true;
+		}
+		else
+		{
+			return false;
+		}
+
+    }
+	//-----------------------------------------------------------------------
+	const String StringUtil::replaceAll(const String& source, const String& replaceWhat, const String& replaceWithWhat)
+	{
+		String result = source;
+        String::size_type pos = 0;
+		while(1)
+		{
+			pos = result.find(replaceWhat,pos);
+			if (pos == String::npos) break;
+			result.replace(pos,replaceWhat.size(),replaceWithWhat);
+            pos += replaceWithWhat.size();
+		}
+		return result;
+	}
+
+}

+ 202 - 0
CamelotRenderer/OgreString.h

@@ -0,0 +1,202 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef _String_H__
+#define _String_H__
+
+#include "OgrePrerequisites.h"
+
+// If we're using the GCC 3.1 C++ Std lib
+#if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 310 && !defined(STLPORT)
+
+// For gcc 4.3 see http://gcc.gnu.org/gcc-4.3/changes.html
+#   if OGRE_COMP_VER >= 430
+#       include <tr1/unordered_map> 
+#   else
+#       include <ext/hash_map>
+namespace __gnu_cxx
+{
+    template <> struct hash< Ogre::_StringBase >
+    {
+        size_t operator()( const Ogre::_StringBase _stringBase ) const
+        {
+            /* This is the PRO-STL way, but it seems to cause problems with VC7.1
+               and in some other cases (although I can't recreate it)
+            hash<const char*> H;
+            return H(_stringBase.c_str());
+            */
+            /** This is our custom way */
+            register size_t ret = 0;
+            for( Ogre::_StringBase::const_iterator it = _stringBase.begin(); it != _stringBase.end(); ++it )
+                ret = 5 * ret + *it;
+
+            return ret;
+        }
+    };
+}
+#   endif
+
+#endif
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+    /** Utility class for manipulating Strings.  */
+    class _OgreExport StringUtil
+    {
+	public:
+		typedef StringStream StrStreamType;
+
+        /** Removes any whitespace characters, be it standard space or
+            TABs and so on.
+            @remarks
+                The user may specify wether they want to trim only the
+                beginning or the end of the String ( the default action is
+                to trim both).
+        */
+        static void trim( String& str, bool left = true, bool right = true );
+
+        /** Returns a StringVector that contains all the substrings delimited
+            by the characters in the passed <code>delims</code> argument.
+            @param
+                delims A list of delimiter characters to split by
+            @param
+                maxSplits The maximum number of splits to perform (0 for unlimited splits). If this
+                parameters is > 0, the splitting process will stop after this many splits, left to right.
+        */
+		static vector<String>::type split( const String& str, const String& delims = "\t\n ", unsigned int maxSplits = 0);
+
+		/** Returns a StringVector that contains all the substrings delimited
+            by the characters in the passed <code>delims</code> argument, 
+			or in the <code>doubleDelims</code> argument, which is used to include (normal) 
+			delimeters in the tokenised string. For example, "strings like this".
+            @param
+                delims A list of delimiter characters to split by
+			@param
+                delims A list of double delimeters characters to tokenise by
+            @param
+                maxSplits The maximum number of splits to perform (0 for unlimited splits). If this
+                parameters is > 0, the splitting process will stop after this many splits, left to right.
+        */
+		static vector<String>::type tokenise( const String& str, const String& delims = "\t\n ", const String& doubleDelims = "\"", unsigned int maxSplits = 0);
+
+		/** Lower-cases all the characters in the string.
+        */
+        static void toLowerCase( String& str );
+
+        /** Upper-cases all the characters in the string.
+        */
+        static void toUpperCase( String& str );
+
+
+        /** Returns whether the string begins with the pattern passed in.
+        @param pattern The pattern to compare with.
+        @param lowerCase If true, the start of the string will be lower cased before
+            comparison, pattern should also be in lower case.
+        */
+        static bool startsWith(const String& str, const String& pattern, bool lowerCase = true);
+
+        /** Returns whether the string ends with the pattern passed in.
+        @param pattern The pattern to compare with.
+        @param lowerCase If true, the end of the string will be lower cased before
+            comparison, pattern should also be in lower case.
+        */
+        static bool endsWith(const String& str, const String& pattern, bool lowerCase = true);
+
+        /** Method for standardising paths - use forward slashes only, end with slash.
+        */
+        static String standardisePath( const String &init);
+
+        /** Method for splitting a fully qualified filename into the base name
+            and path.
+        @remarks
+            Path is standardised as in standardisePath
+        */
+        static void splitFilename(const String& qualifiedName,
+            String& outBasename, String& outPath);
+
+		/** Method for splitting a fully qualified filename into the base name,
+		extension and path.
+		@remarks
+		Path is standardised as in standardisePath
+		*/
+		static void splitFullFilename(const Ogre::String& qualifiedName, 
+			Ogre::String& outBasename, Ogre::String& outExtention, 
+			Ogre::String& outPath);
+
+		/** Method for splitting a filename into the base name
+		and extension.
+		*/
+		static void splitBaseFilename(const Ogre::String& fullName, 
+			Ogre::String& outBasename, Ogre::String& outExtention);
+
+
+        /** Simple pattern-matching routine allowing a wildcard pattern.
+        @param str String to test
+        @param pattern Pattern to match against; can include simple '*' wildcards
+        @param caseSensitive Whether the match is case sensitive or not
+        */
+        static bool match(const String& str, const String& pattern, bool caseSensitive = true);
+
+
+		/** replace all instances of a sub-string with a another sub-string.
+		@param source Source string
+		@param replaceWhat Sub-string to find and replace
+		@param replaceWithWhat Sub-string to replace with (the new sub-string)
+		@returns An updated string with the sub-string replaced
+		*/
+		static const String replaceAll(const String& source, const String& replaceWhat, const String& replaceWithWhat);
+
+        /// Constant blank string, useful for returning by ref where local does not exist
+        static const String BLANK;
+    };
+
+
+#if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 310 && !defined(STLPORT)
+#   if OGRE_COMP_VER < 430
+	typedef ::__gnu_cxx::hash< _StringBase > _StringHash;
+#   else
+	typedef ::std::tr1::hash< _StringBase > _StringHash;
+#   endif
+#elif OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_COMP_VER >= 1600 && !defined(STLPORT) // VC++ 10.0
+	typedef ::std::tr1::hash< _StringBase > _StringHash;
+#elif !defined( _STLP_HASH_FUN_H )
+	typedef stdext::hash_compare< _StringBase, std::less< _StringBase > > _StringHash;
+#else
+	typedef std::hash< _StringBase > _StringHash;
+#endif 
+	/** @} */
+	/** @} */
+
+} // namespace Ogre
+
+#endif // _String_H__

+ 438 - 0
CamelotRenderer/OgreStringConverter.cpp

@@ -0,0 +1,438 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreStringConverter.h"
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(Real val, unsigned short precision, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+        stream.precision(precision);
+        stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(int val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+		stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+#if OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 || OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
+    String StringConverter::toString(unsigned int val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+        stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(size_t val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+        stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+#if OGRE_COMPILER == OGRE_COMPILER_MSVC
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(unsigned long val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+        stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+
+#endif
+    //-----------------------------------------------------------------------
+#else
+    String StringConverter::toString(size_t val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+		stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(unsigned long val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+		stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+#endif
+    String StringConverter::toString(long val, 
+        unsigned short width, char fill, std::ios::fmtflags flags)
+    {
+        stringstream stream;
+		stream.width(width);
+        stream.fill(fill);
+        if (flags)
+            stream.setf(flags);
+        stream << val;
+        return stream.str();
+    }
+	//-----------------------------------------------------------------------
+    String StringConverter::toString(const Vector2& val)
+    {
+        stringstream stream;
+		stream << val.x << " " << val.y;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const Vector3& val)
+    {
+        stringstream stream;
+		stream << val.x << " " << val.y << " " << val.z;
+        return stream.str();
+    }
+	//-----------------------------------------------------------------------
+    String StringConverter::toString(const Vector4& val)
+    {
+        stringstream stream;
+		stream << val.x << " " << val.y << " " << val.z << " " << val.w;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const Matrix3& val)
+    {
+		stringstream stream;
+        stream << val[0][0] << " " 
+            << val[0][1] << " "             
+            << val[0][2] << " "             
+            << val[1][0] << " "             
+            << val[1][1] << " "             
+            << val[1][2] << " "             
+            << val[2][0] << " "             
+            << val[2][1] << " "             
+            << val[2][2];
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(bool val, bool yesNo)
+    {
+        if (val)
+        {
+            if (yesNo)
+            {
+                return "yes";
+            }
+            else
+            {
+                return "true";
+            }
+        }
+        else
+            if (yesNo)
+            {
+                return "no";
+            }
+            else
+            {
+                return "false";
+            }
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const Matrix4& val)
+    {
+		stringstream stream;
+        stream << val[0][0] << " " 
+            << val[0][1] << " "             
+            << val[0][2] << " "             
+            << val[0][3] << " "             
+            << val[1][0] << " "             
+            << val[1][1] << " "             
+            << val[1][2] << " "             
+            << val[1][3] << " "             
+            << val[2][0] << " "             
+            << val[2][1] << " "             
+            << val[2][2] << " "             
+            << val[2][3] << " "             
+            << val[3][0] << " "             
+            << val[3][1] << " "             
+            << val[3][2] << " "             
+            << val[3][3];
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const Quaternion& val)
+    {
+		stringstream stream;
+        stream  << val.w << " " << val.x << " " << val.y << " " << val.z;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const ColourValue& val)
+    {
+		stringstream stream;
+        stream << val.r << " " << val.g << " " << val.b << " " << val.a;
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    String StringConverter::toString(const StringVector& val)
+    {
+		stringstream stream;
+        StringVector::const_iterator i, iend, ibegin;
+        ibegin = val.begin();
+        iend = val.end();
+        for (i = ibegin; i != iend; ++i)
+        {
+            if (i != ibegin)
+                stream << " ";
+
+            stream << *i; 
+        }
+        return stream.str();
+    }
+    //-----------------------------------------------------------------------
+    Real StringConverter::parseReal(const String& val, Real defaultValue)
+    {
+		// Use istringstream for direct correspondence with toString
+		StringStream str(val);
+		Real ret = defaultValue;
+		str >> ret;
+
+        return ret;
+    }
+    //-----------------------------------------------------------------------
+    int StringConverter::parseInt(const String& val, int defaultValue)
+    {
+		// Use istringstream for direct correspondence with toString
+		StringStream str(val);
+		int ret = defaultValue;
+		str >> ret;
+
+        return ret;
+    }
+    //-----------------------------------------------------------------------
+    unsigned int StringConverter::parseUnsignedInt(const String& val, unsigned int defaultValue)
+    {
+		// Use istringstream for direct correspondence with toString
+		StringStream str(val);
+		unsigned int ret = defaultValue;
+		str >> ret;
+
+		return ret;
+    }
+    //-----------------------------------------------------------------------
+    long StringConverter::parseLong(const String& val, long defaultValue)
+    {
+		// Use istringstream for direct correspondence with toString
+		StringStream str(val);
+		long ret = defaultValue;
+		str >> ret;
+
+		return ret;
+    }
+    //-----------------------------------------------------------------------
+    unsigned long StringConverter::parseUnsignedLong(const String& val, unsigned long defaultValue)
+    {
+		// Use istringstream for direct correspondence with toString
+		StringStream str(val);
+		unsigned long ret = defaultValue;
+		str >> ret;
+
+		return ret;
+    }
+    //-----------------------------------------------------------------------
+    bool StringConverter::parseBool(const String& val, bool defaultValue)
+    {
+		if ((StringUtil::startsWith(val, "true") || StringUtil::startsWith(val, "yes")
+			|| StringUtil::startsWith(val, "1")))
+			return true;
+		else if ((StringUtil::startsWith(val, "false") || StringUtil::startsWith(val, "no")
+			|| StringUtil::startsWith(val, "0")))
+			return false;
+		else
+			return defaultValue;
+    }
+    //-----------------------------------------------------------------------
+    Vector2 StringConverter::parseVector2(const String& val, const Vector2& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 2)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Vector2(parseReal(vec[0]),parseReal(vec[1]));
+        }
+    }
+	//-----------------------------------------------------------------------
+    Vector3 StringConverter::parseVector3(const String& val, const Vector3& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 3)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Vector3(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]));
+        }
+    }
+	//-----------------------------------------------------------------------
+    Vector4 StringConverter::parseVector4(const String& val, const Vector4& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 4)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Vector4(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]),parseReal(vec[3]));
+        }
+    }
+    //-----------------------------------------------------------------------
+    Matrix3 StringConverter::parseMatrix3(const String& val, const Matrix3& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 9)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Matrix3(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]),
+                parseReal(vec[3]),parseReal(vec[4]),parseReal(vec[5]),
+                parseReal(vec[6]),parseReal(vec[7]),parseReal(vec[8]));
+        }
+    }
+    //-----------------------------------------------------------------------
+    Matrix4 StringConverter::parseMatrix4(const String& val, const Matrix4& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 16)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Matrix4(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]), parseReal(vec[3]),
+                parseReal(vec[4]),parseReal(vec[5]), parseReal(vec[6]), parseReal(vec[7]),
+                parseReal(vec[8]),parseReal(vec[9]), parseReal(vec[10]), parseReal(vec[11]),
+                parseReal(vec[12]),parseReal(vec[13]), parseReal(vec[14]), parseReal(vec[15]));
+        }
+    }
+    //-----------------------------------------------------------------------
+    Quaternion StringConverter::parseQuaternion(const String& val, const Quaternion& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() != 4)
+        {
+            return defaultValue;
+        }
+        else
+        {
+            return Quaternion(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]), parseReal(vec[3]));
+        }
+    }
+    //-----------------------------------------------------------------------
+    ColourValue StringConverter::parseColourValue(const String& val, const ColourValue& defaultValue)
+    {
+        // Split on space
+        vector<String>::type vec = StringUtil::split(val);
+
+        if (vec.size() == 4)
+        {
+            return ColourValue(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]), parseReal(vec[3]));
+        }
+        else if (vec.size() == 3)
+        {
+            return ColourValue(parseReal(vec[0]),parseReal(vec[1]),parseReal(vec[2]), 1.0f);
+        }
+        else
+        {
+            return defaultValue;
+        }
+    }
+    //-----------------------------------------------------------------------
+    StringVector StringConverter::parseStringVector(const String& val)
+    {
+        return StringUtil::split(val);
+    }
+	//-----------------------------------------------------------------------
+	bool StringConverter::isNumber(const String& val)
+	{
+		StringStream str(val);
+		float tst;
+		str >> tst;
+		return !str.fail() && str.eof();
+	}
+}
+
+

+ 270 - 0
CamelotRenderer/OgreStringConverter.h

@@ -0,0 +1,270 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __StringConverter_H__
+#define __StringConverter_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreStringVector.h"
+#include "OgreColourValue.h"
+#include "OgreMath.h"
+#include "OgreMatrix3.h"
+#include "OgreMatrix4.h"
+#include "OgreQuaternion.h"
+#include "OgreVector2.h"
+#include "OgreVector3.h"
+#include "OgreVector4.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+	/** Class for converting the core Ogre data types to/from Strings.
+    @remarks
+        The code for converting values to and from strings is here as a separate
+        class to avoid coupling String to other datatypes (and vice-versa) which reduces
+        compilation dependency: important given how often the core types are used.
+    @par
+        This class is mainly used for parsing settings in text files. External applications
+        can also use it to interface with classes which use the StringInterface template
+        class.
+    @par
+        The String formats of each of the major types is listed with the methods. The basic types
+        like int and Real just use the underlying C runtime library atof and atoi family methods,
+        however custom types like Vector3, ColourValue and Matrix4 are also supported by this class
+        using custom formats.
+    @author
+        Steve Streeting
+    */
+    class _OgreExport StringConverter
+    {
+    public:
+
+        /** Converts a Real to a String. */
+        static String toString(Real val, unsigned short precision = 6, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+        /** Converts a Radian to a String. */
+        static String toString(Radian val, unsigned short precision = 6, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) )
+        {
+            return toString(val.valueAngleUnits(), precision, width, fill, flags);
+        }
+        /** Converts a Degree to a String. */
+        static String toString(Degree val, unsigned short precision = 6, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) )
+        {
+            return toString(val.valueAngleUnits(), precision, width, fill, flags);
+        }
+        /** Converts an int to a String. */
+        static String toString(int val, unsigned short width = 0, 
+            char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+#if OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 || OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
+        /** Converts an unsigned int to a String. */
+        static String toString(unsigned int val, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+        /** Converts a size_t to a String. */
+        static String toString(size_t val, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+        #if OGRE_COMPILER == OGRE_COMPILER_MSVC
+                /** Converts an unsigned long to a String. */
+                static String toString(unsigned long val, 
+                    unsigned short width = 0, char fill = ' ', 
+                    std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+        #endif
+#else
+        /** Converts a size_t to a String. */
+        static String toString(size_t val, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+        /** Converts an unsigned long to a String. */
+        static String toString(unsigned long val, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+#endif
+        /** Converts a long to a String. */
+        static String toString(long val, 
+            unsigned short width = 0, char fill = ' ', 
+            std::ios::fmtflags flags = std::ios::fmtflags(0) );
+        /** Converts a boolean to a String. 
+        @param yesNo If set to true, result is 'yes' or 'no' instead of 'true' or 'false'
+        */
+        static String toString(bool val, bool yesNo = false);
+		/** Converts a Vector2 to a String. 
+        @remarks
+            Format is "x y" (i.e. 2x Real values, space delimited)
+        */
+        static String toString(const Vector2& val);
+        /** Converts a Vector3 to a String. 
+        @remarks
+            Format is "x y z" (i.e. 3x Real values, space delimited)
+        */
+        static String toString(const Vector3& val);
+		/** Converts a Vector4 to a String. 
+        @remarks
+            Format is "x y z w" (i.e. 4x Real values, space delimited)
+        */
+        static String toString(const Vector4& val);
+        /** Converts a Matrix3 to a String. 
+        @remarks
+            Format is "00 01 02 10 11 12 20 21 22" where '01' means row 0 column 1 etc.
+        */
+        static String toString(const Matrix3& val);
+        /** Converts a Matrix4 to a String. 
+        @remarks
+            Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33" where 
+            '01' means row 0 column 1 etc.
+        */
+        static String toString(const Matrix4& val);
+        /** Converts a Quaternion to a String. 
+        @remarks
+            Format is "w x y z" (i.e. 4x Real values, space delimited)
+        */
+        static String toString(const Quaternion& val);
+        /** Converts a ColourValue to a String. 
+        @remarks
+            Format is "r g b a" (i.e. 4x Real values, space delimited). 
+        */
+        static String toString(const ColourValue& val);
+        /** Converts a StringVector to a string.
+        @remarks
+            Strings must not contain spaces since space is used as a delimiter in
+            the output.
+        */
+        static String toString(const StringVector& val);
+
+        /** Converts a String to a Real. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the Real version of the String.
+        */
+        static Real parseReal(const String& val, Real defaultValue = 0);
+        /** Converts a String to a Angle. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the Angle version of the String.
+        */
+        static inline Radian parseAngle(const String& val, Radian defaultValue = Radian(0)) {
+			return Angle(parseReal(val, defaultValue.valueRadians()));
+		}
+        /** Converts a String to a whole number. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the numeric version of the String.
+        */
+        static int parseInt(const String& val, int defaultValue = 0);
+        /** Converts a String to a whole number. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the numeric version of the String.
+        */
+        static unsigned int parseUnsignedInt(const String& val, unsigned int defaultValue = 0);
+        /** Converts a String to a whole number. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the numeric version of the String.
+        */
+        static long parseLong(const String& val, long defaultValue = 0);
+        /** Converts a String to a whole number. 
+        @returns
+            0.0 if the value could not be parsed, otherwise the numeric version of the String.
+        */
+        static unsigned long parseUnsignedLong(const String& val, unsigned long defaultValue = 0);
+        /** Converts a String to a boolean. 
+        @remarks
+            Returns true if case-insensitive match of the start of the string
+			matches "true", "yes" or "1", false otherwise.
+        */
+        static bool parseBool(const String& val, bool defaultValue = 0);
+		/** Parses a Vector2 out of a String.
+        @remarks
+            Format is "x y" ie. 2 Real components, space delimited. Failure to parse returns
+            Vector2::ZERO.
+        */
+		static Vector2 parseVector2(const String& val, const Vector2& defaultValue = Vector2::ZERO);
+		/** Parses a Vector3 out of a String.
+        @remarks
+            Format is "x y z" ie. 3 Real components, space delimited. Failure to parse returns
+            Vector3::ZERO.
+        */
+        static Vector3 parseVector3(const String& val, const Vector3& defaultValue = Vector3::ZERO);
+        /** Parses a Vector4 out of a String.
+        @remarks
+            Format is "x y z w" ie. 4 Real components, space delimited. Failure to parse returns
+            Vector4::ZERO.
+        */
+        static Vector4 parseVector4(const String& val, const Vector4& defaultValue = Vector4::ZERO);
+        /** Parses a Matrix3 out of a String.
+        @remarks
+            Format is "00 01 02 10 11 12 20 21 22" where '01' means row 0 column 1 etc.
+            Failure to parse returns Matrix3::IDENTITY.
+        */
+        static Matrix3 parseMatrix3(const String& val, const Matrix3& defaultValue = Matrix3::IDENTITY);
+        /** Parses a Matrix4 out of a String.
+        @remarks
+            Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33" where 
+            '01' means row 0 column 1 etc. Failure to parse returns Matrix4::IDENTITY.
+        */
+        static Matrix4 parseMatrix4(const String& val, const Matrix4& defaultValue = Matrix4::IDENTITY);
+        /** Parses a Quaternion out of a String. 
+        @remarks
+            Format is "w x y z" (i.e. 4x Real values, space delimited). 
+            Failure to parse returns Quaternion::IDENTITY.
+        */
+        static Quaternion parseQuaternion(const String& val, const Quaternion& defaultValue = Quaternion::IDENTITY);
+        /** Parses a ColourValue out of a String. 
+        @remarks
+            Format is "r g b a" (i.e. 4x Real values, space delimited), or "r g b" which implies
+            an alpha value of 1.0 (opaque). Failure to parse returns ColourValue::Black.
+        */
+        static ColourValue parseColourValue(const String& val, const ColourValue& defaultValue = ColourValue::Black);
+
+        /** Pareses a StringVector from a string.
+        @remarks
+            Strings must not contain spaces since space is used as a delimiter in
+            the output.
+        */
+        static StringVector parseStringVector(const String& val);
+        /** Checks the String is a valid number value. */
+        static bool isNumber(const String& val);
+    };
+
+	/** @} */
+	/** @} */
+
+}
+
+
+
+#endif
+

+ 53 - 0
CamelotRenderer/OgreStringVector.h

@@ -0,0 +1,53 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef _StringVector_H__
+#define _StringVector_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreString.h"
+#include "OgreSharedPtr.h"
+
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup General
+	*  @{
+	*/
+
+    typedef vector<String>::type StringVector;
+    typedef SharedPtr<StringVector> StringVectorPtr;
+
+	/** @} */
+	/** @} */
+
+}
+
+#endif

+ 61 - 0
CamelotRenderer/OgreThreadDefines.h

@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+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-2011 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+-------------------------------------------------------------------------*/
+#ifndef __OgreThreadDefines_H__
+#define __OgreThreadDefines_H__
+
+#define OGRE_AUTO_MUTEX_NAME mutex
+#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_RW_MUTEX(name)
+#define OGRE_LOCK_RW_MUTEX_READ(name)
+#define OGRE_LOCK_RW_MUTEX_WRITE(name)
+#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_INIT(var) var(0)
+#define OGRE_THREAD_POINTER_VAR(T, var) T* var = 0
+#define OGRE_THREAD_POINTER_SET(var, expr) var = expr
+#define OGRE_THREAD_POINTER_GET(var) var
+#define OGRE_THREAD_POINTER_DELETE(var) { OGRE_DELETE var; var = 0; }
+#define OGRE_THREAD_SLEEP(ms)
+#define OGRE_THREAD_WORKER_INHERIT
+
+#endif
+

+ 42 - 0
CamelotRenderer/OgreVector2.cpp

@@ -0,0 +1,42 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "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);
+
+}

+ 573 - 0
CamelotRenderer/OgreVector2.h

@@ -0,0 +1,573 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector2_H__
+#define __Vector2_H__
+
+
+#include "OgrePrerequisites.h"
+#include "OgreMath.h"
+
+namespace Ogre
+{
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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] )
+        {
+        }
+
+		/** Exchange the contents of this vector with another. 
+		*/
+		inline void swap(Vector2& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+		}
+
+		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.0f / 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.0f / 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;
+        }
+        /** 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 Vector2& 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 Vector2& 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 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.0f / 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.5f,
+                ( y + vec.y ) * 0.5f );
+        }
+
+        /** 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 ) );
+        }
+		/// Check whether this vector contains valid values
+		inline bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y);
+		}
+
+        // 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

+ 42 - 0
CamelotRenderer/OgreVector3.cpp

@@ -0,0 +1,42 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "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);
+}

+ 796 - 0
CamelotRenderer/OgreVector3.h

@@ -0,0 +1,796 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector3_H__
+#define __Vector3_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreMath.h"
+#include "OgreQuaternion.h"
+
+namespace Ogre
+{
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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 )
+        {
+        }
+
+
+		/** Exchange the contents of this vector with another. 
+		*/
+		inline void swap(Vector3& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+		}
+
+		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.0f / 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.0f / 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.0f / 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.5f,
+                ( y + vec.y ) * 0.5f,
+                ( z + vec.z ) * 0.5f );
+        }
+
+        /** 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 = (Real)(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.5f;
+				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();
+
+		}
+
+		/// Check whether this vector contains valid values
+		inline bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
+		}
+
+		// 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

+ 34 - 0
CamelotRenderer/OgreVector4.cpp

@@ -0,0 +1,34 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreVector4.h"
+#include "OgreMath.h"
+
+namespace Ogre
+{
+    const Vector4 Vector4::ZERO( 0, 0, 0, 0 );
+}

+ 414 - 0
CamelotRenderer/OgreVector4.h

@@ -0,0 +1,414 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __Vector4_H__
+#define __Vector4_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreVector3.h"
+
+namespace Ogre
+{
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Math
+	*  @{
+	*/
+	/** 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)
+        {
+        }
+
+		/** Exchange the contents of this vector with another. 
+		*/
+		inline void swap(Vector4& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+			std::swap(w, other.w);
+		}
+	
+		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.0f / 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.0f / 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;
+        }
+		/// Check whether this vector contains valid values
+		inline bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(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
+

+ 976 - 0
CamelotRenderer/OgreVertexIndexData.cpp

@@ -0,0 +1,976 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreVertexIndexData.h"
+#include "OgreHardwareBufferManager.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+#include "OgreVector3.h"
+#include "OgreAxisAlignedBox.h"
+#include "OgreException.h"
+
+namespace Ogre {
+
+    //-----------------------------------------------------------------------
+	VertexData::VertexData(HardwareBufferManagerBase* mgr)
+	{
+		mMgr = mgr ? mgr : HardwareBufferManager::getSingletonPtr();
+		vertexBufferBinding = mMgr->createVertexBufferBinding();
+		vertexDeclaration = mMgr->createVertexDeclaration();
+		mDeleteDclBinding = true;
+		vertexCount = 0;
+		vertexStart = 0;
+		hwAnimDataItemsUsed = 0;
+
+	}
+	//---------------------------------------------------------------------
+	VertexData::VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind)
+	{
+		// this is a fallback rather than actively used
+		mMgr = HardwareBufferManager::getSingletonPtr();
+		vertexDeclaration = dcl;
+		vertexBufferBinding = bind;
+		mDeleteDclBinding = false;
+		vertexCount = 0;
+		vertexStart = 0;
+		hwAnimDataItemsUsed = 0;
+	}
+    //-----------------------------------------------------------------------
+	VertexData::~VertexData()
+	{
+		if (mDeleteDclBinding)
+		{
+			mMgr->destroyVertexBufferBinding(vertexBufferBinding);
+			mMgr->destroyVertexDeclaration(vertexDeclaration);
+		}
+	}
+    //-----------------------------------------------------------------------
+	VertexData* VertexData::clone(bool copyData, HardwareBufferManagerBase* mgr) const
+	{
+		HardwareBufferManagerBase* pManager = mgr ? mgr : mMgr;
+
+		VertexData* dest = OGRE_NEW VertexData(mgr);
+
+		// Copy vertex buffers in turn
+		const VertexBufferBinding::VertexBufferBindingMap& bindings = 
+			this->vertexBufferBinding->getBindings();
+		VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
+		vbend = bindings.end();
+		for (vbi = bindings.begin(); vbi != vbend; ++vbi)
+		{
+			HardwareVertexBufferSharedPtr srcbuf = vbi->second;
+            HardwareVertexBufferSharedPtr dstBuf;
+            if (copyData)
+            {
+			    // create new buffer with the same settings
+			    dstBuf = pManager->createVertexBuffer(
+					    srcbuf->getVertexSize(), srcbuf->getNumVertices(), srcbuf->getUsage(),
+					    srcbuf->hasShadowBuffer());
+
+			    // copy data
+			    dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true);
+            }
+            else
+            {
+                // don't copy, point at existing buffer
+                dstBuf = srcbuf;
+            }
+
+			// Copy binding
+			dest->vertexBufferBinding->setBinding(vbi->first, dstBuf);
+        }
+
+        // Basic vertex info
+        dest->vertexStart = this->vertexStart;
+		dest->vertexCount = this->vertexCount;
+        // Copy elements
+        const VertexDeclaration::VertexElementList elems = 
+            this->vertexDeclaration->getElements();
+        VertexDeclaration::VertexElementList::const_iterator ei, eiend;
+        eiend = elems.end();
+        for (ei = elems.begin(); ei != eiend; ++ei)
+        {
+            dest->vertexDeclaration->addElement(
+                ei->getSource(),
+                ei->getOffset(),
+                ei->getType(),
+                ei->getSemantic(),
+                ei->getIndex() );
+        }
+
+		// Copy reference to hardware shadow buffer, no matter whether copy data or not
+        dest->hardwareShadowVolWBuffer = hardwareShadowVolWBuffer;
+
+		// copy anim data
+		dest->hwAnimationDataList = hwAnimationDataList;
+		dest->hwAnimDataItemsUsed = hwAnimDataItemsUsed;
+
+        
+        return dest;
+	}
+    //-----------------------------------------------------------------------
+    void VertexData::prepareForShadowVolume(void)
+    {
+        /* NOTE
+        I would dearly, dearly love to just use a 4D position buffer in order to 
+        store the extra 'w' value I need to differentiate between extruded and 
+        non-extruded sections of the buffer, so that vertex programs could use that.
+        Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not
+        support 4d position vertices in the fixed-function pipeline. If you use them, 
+        you just see nothing. Since we can't know whether the application is going to use
+        fixed function or vertex programs, we have to stick to 3d position vertices and
+        store the 'w' in a separate 1D texture coordinate buffer, which is only used
+        when rendering the shadow.
+        */
+
+        // Upfront, lets check whether we have vertex program capability
+        bool useVertexPrograms = false;
+		// TODO PORT - Don't have access to render system yet, but will after the port is done. For now assume we always can use vertex programs.
+		//RenderSystem* rend = Root::getSingleton().getRenderSystem();
+        //if (rend && rend->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
+        {
+            useVertexPrograms = true;
+        }
+
+
+        // Look for a position element
+        const VertexElement* posElem = vertexDeclaration->findElementBySemantic(VES_POSITION);
+        if (posElem)
+        {
+            size_t v;
+            unsigned short posOldSource = posElem->getSource();
+
+            HardwareVertexBufferSharedPtr vbuf = vertexBufferBinding->getBuffer(posOldSource);
+            bool wasSharedBuffer = false;
+            // Are there other elements in the buffer except for the position?
+            if (vbuf->getVertexSize() > posElem->getSize())
+            {
+                // We need to create another buffer to contain the remaining elements
+                // Most drivers don't like gaps in the declaration, and in any case it's waste
+                wasSharedBuffer = true;
+            }
+            HardwareVertexBufferSharedPtr newPosBuffer, newRemainderBuffer;
+            if (wasSharedBuffer)
+            {
+                newRemainderBuffer = vbuf->getManager()->createVertexBuffer(
+                    vbuf->getVertexSize() - posElem->getSize(), vbuf->getNumVertices(), vbuf->getUsage(),
+                    vbuf->hasShadowBuffer());
+            }
+            // Allocate new position buffer, will be FLOAT3 and 2x the size
+            size_t oldVertexCount = vbuf->getNumVertices();
+            size_t newVertexCount = oldVertexCount * 2;
+            newPosBuffer = vbuf->getManager()->createVertexBuffer(
+                VertexElement::getTypeSize(VET_FLOAT3), newVertexCount, vbuf->getUsage(), 
+                vbuf->hasShadowBuffer());
+
+            // Iterate over the old buffer, copying the appropriate elements and initialising the rest
+            float* pSrc;
+            unsigned char *pBaseSrc = static_cast<unsigned char*>(
+                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
+            // Point first destination pointer at the start of the new position buffer,
+            // the other one half way along
+            float *pDest = static_cast<float*>(newPosBuffer->lock(HardwareBuffer::HBL_DISCARD));
+            float* pDest2 = pDest + oldVertexCount * 3; 
+
+            // Precalculate any dimensions of vertex areas outside the position
+            size_t prePosVertexSize = 0, postPosVertexSize, postPosVertexOffset;
+            unsigned char *pBaseDestRem = 0;
+            if (wasSharedBuffer)
+            {
+                pBaseDestRem = static_cast<unsigned char*>(
+                    newRemainderBuffer->lock(HardwareBuffer::HBL_DISCARD));
+                prePosVertexSize = posElem->getOffset();
+                postPosVertexOffset = prePosVertexSize + posElem->getSize();
+                postPosVertexSize = vbuf->getVertexSize() - postPosVertexOffset;
+                // the 2 separate bits together should be the same size as the remainder buffer vertex
+                assert (newRemainderBuffer->getVertexSize() == prePosVertexSize + postPosVertexSize);
+
+                // Iterate over the vertices
+                for (v = 0; v < oldVertexCount; ++v)
+                {
+                    // Copy position, into both buffers
+                    posElem->baseVertexPointerToElement(pBaseSrc, &pSrc);
+                    *pDest++ = *pDest2++ = *pSrc++;
+                    *pDest++ = *pDest2++ = *pSrc++;
+                    *pDest++ = *pDest2++ = *pSrc++;
+
+                    // now deal with any other elements 
+                    // Basically we just memcpy the vertex excluding the position
+                    if (prePosVertexSize > 0)
+                        memcpy(pBaseDestRem, pBaseSrc, prePosVertexSize);
+                    if (postPosVertexSize > 0)
+                        memcpy(pBaseDestRem + prePosVertexSize, 
+                            pBaseSrc + postPosVertexOffset, postPosVertexSize);
+                    pBaseDestRem += newRemainderBuffer->getVertexSize();
+
+                    pBaseSrc += vbuf->getVertexSize();
+
+                } // next vertex
+            }
+            else
+            {
+                // Unshared buffer, can block copy the whole thing
+                memcpy(pDest, pBaseSrc, vbuf->getSizeInBytes());
+                memcpy(pDest2, pBaseSrc, vbuf->getSizeInBytes());
+            }
+
+            vbuf->unlock();
+            newPosBuffer->unlock();
+            if (wasSharedBuffer)
+                newRemainderBuffer->unlock();
+
+            // At this stage, he original vertex buffer is going to be destroyed
+            // So we should force the deallocation of any temporary copies
+            vbuf->getManager()->_forceReleaseBufferCopies(vbuf);
+
+            if (useVertexPrograms)
+            {
+                // Now it's time to set up the w buffer
+                hardwareShadowVolWBuffer = vbuf->getManager()->createVertexBuffer(
+                    sizeof(float), newVertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
+                // Fill the first half with 1.0, second half with 0.0
+                pDest = static_cast<float*>(
+                    hardwareShadowVolWBuffer->lock(HardwareBuffer::HBL_DISCARD));
+                for (v = 0; v < oldVertexCount; ++v)
+                {
+                    *pDest++ = 1.0f;
+                }
+                for (v = 0; v < oldVertexCount; ++v)
+                {
+                    *pDest++ = 0.0f;
+                }
+                hardwareShadowVolWBuffer->unlock();
+            }
+
+            unsigned short newPosBufferSource; 
+            if (wasSharedBuffer)
+            {
+                // Get the a new buffer binding index
+                newPosBufferSource= vertexBufferBinding->getNextIndex();
+                // Re-bind the old index to the remainder buffer
+                vertexBufferBinding->setBinding(posOldSource, newRemainderBuffer);
+            }
+            else
+            {
+                // We can just re-use the same source idex for the new position buffer
+                newPosBufferSource = posOldSource;
+            }
+            // Bind the new position buffer
+            vertexBufferBinding->setBinding(newPosBufferSource, newPosBuffer);
+
+            // Now, alter the vertex declaration to change the position source
+            // and the offsets of elements using the same buffer
+            VertexDeclaration::VertexElementList::const_iterator elemi = 
+                vertexDeclaration->getElements().begin();
+            VertexDeclaration::VertexElementList::const_iterator elemiend = 
+                vertexDeclaration->getElements().end();
+            unsigned short idx;
+            for(idx = 0; elemi != elemiend; ++elemi, ++idx) 
+            {
+                if (&(*elemi) == posElem)
+                {
+                    // Modify position to point at new position buffer
+                    vertexDeclaration->modifyElement(
+                        idx, 
+                        newPosBufferSource, // new source buffer
+                        0, // no offset now
+                        VET_FLOAT3, 
+                        VES_POSITION);
+                }
+                else if (wasSharedBuffer &&
+                    elemi->getSource() == posOldSource &&
+                    elemi->getOffset() > prePosVertexSize )
+                {
+                    // This element came after position, remove the position's
+                    // size
+                    vertexDeclaration->modifyElement(
+                        idx, 
+                        posOldSource, // same old source
+                        elemi->getOffset() - posElem->getSize(), // less offset now
+                        elemi->getType(), 
+                        elemi->getSemantic(),
+                        elemi->getIndex());
+
+                }
+
+            }
+
+
+            // Note that we don't change vertexCount, because the other buffer(s) are still the same
+            // size after all
+
+
+        }
+    }
+	//-----------------------------------------------------------------------
+	void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration, 
+		const BufferUsageList& bufferUsages, HardwareBufferManagerBase* mgr)
+	{
+		HardwareBufferManagerBase* pManager = mgr ? mgr : mMgr;
+        // Firstly, close up any gaps in the buffer sources which might have arisen
+        newDeclaration->closeGapsInSource();
+
+		// Build up a list of both old and new elements in each buffer
+		unsigned short buf = 0;
+		vector<void*>::type oldBufferLocks;
+        vector<size_t>::type oldBufferVertexSizes;
+		vector<void*>::type newBufferLocks;
+        vector<size_t>::type newBufferVertexSizes;
+		VertexBufferBinding* newBinding = pManager->createVertexBufferBinding();
+        const VertexBufferBinding::VertexBufferBindingMap& oldBindingMap = vertexBufferBinding->getBindings();
+        VertexBufferBinding::VertexBufferBindingMap::const_iterator itBinding;
+
+        // Pre-allocate old buffer locks
+        if (!oldBindingMap.empty())
+        {
+            size_t count = oldBindingMap.rbegin()->first + 1;
+            oldBufferLocks.resize(count);
+            oldBufferVertexSizes.resize(count);
+        }
+		// Lock all the old buffers for reading
+        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
+        {
+            assert(itBinding->second->getNumVertices() >= vertexCount);
+
+            oldBufferVertexSizes[itBinding->first] =
+                itBinding->second->getVertexSize();
+            oldBufferLocks[itBinding->first] =
+                itBinding->second->lock(
+                    HardwareBuffer::HBL_READ_ONLY);
+        }
+		
+		// Create new buffers and lock all for writing
+		buf = 0;
+		while (!newDeclaration->findElementsBySource(buf).empty())
+		{
+            size_t vertexSize = newDeclaration->getVertexSize(buf);
+
+			HardwareVertexBufferSharedPtr vbuf = 
+				pManager->createVertexBuffer(
+					vertexSize,
+					vertexCount, 
+					bufferUsages[buf]);
+			newBinding->setBinding(buf, vbuf);
+
+            newBufferVertexSizes.push_back(vertexSize);
+			newBufferLocks.push_back(
+				vbuf->lock(HardwareBuffer::HBL_DISCARD));
+			buf++;
+		}
+
+		// Map from new to old elements
+        typedef map<const VertexElement*, const VertexElement*>::type NewToOldElementMap;
+		NewToOldElementMap newToOldElementMap;
+		const VertexDeclaration::VertexElementList& newElemList = newDeclaration->getElements();
+		VertexDeclaration::VertexElementList::const_iterator ei, eiend;
+		eiend = newElemList.end();
+		for (ei = newElemList.begin(); ei != eiend; ++ei)
+		{
+			// Find corresponding old element
+			const VertexElement* oldElem = 
+				vertexDeclaration->findElementBySemantic(
+					(*ei).getSemantic(), (*ei).getIndex());
+			if (!oldElem)
+			{
+				// Error, cannot create new elements with this method
+				OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
+					"Element not found in old vertex declaration", 
+					"VertexData::reorganiseBuffers");
+			}
+			newToOldElementMap[&(*ei)] = oldElem;
+		}
+		// Now iterate over the new buffers, pulling data out of the old ones
+		// For each vertex
+		for (size_t v = 0; v < vertexCount; ++v)
+		{
+			// For each (new) element
+			for (ei = newElemList.begin(); ei != eiend; ++ei)
+			{
+				const VertexElement* newElem = &(*ei);
+                NewToOldElementMap::iterator noi = newToOldElementMap.find(newElem);
+				const VertexElement* oldElem = noi->second;
+				unsigned short oldBufferNo = oldElem->getSource();
+				unsigned short newBufferNo = newElem->getSource();
+				void* pSrcBase = static_cast<void*>(
+					static_cast<unsigned char*>(oldBufferLocks[oldBufferNo])
+					+ v * oldBufferVertexSizes[oldBufferNo]);
+				void* pDstBase = static_cast<void*>(
+					static_cast<unsigned char*>(newBufferLocks[newBufferNo])
+					+ v * newBufferVertexSizes[newBufferNo]);
+				void *pSrc, *pDst;
+				oldElem->baseVertexPointerToElement(pSrcBase, &pSrc);
+				newElem->baseVertexPointerToElement(pDstBase, &pDst);
+				
+				memcpy(pDst, pSrc, newElem->getSize());
+				
+			}
+		}
+
+		// Unlock all buffers
+        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
+        {
+            itBinding->second->unlock();
+        }
+        for (buf = 0; buf < newBinding->getBufferCount(); ++buf)
+        {
+            newBinding->getBuffer(buf)->unlock();
+        }
+
+		// Delete old binding & declaration
+		if (mDeleteDclBinding)
+		{
+			pManager->destroyVertexBufferBinding(vertexBufferBinding);
+			pManager->destroyVertexDeclaration(vertexDeclaration);
+		}
+
+		// Assign new binding and declaration
+		vertexDeclaration = newDeclaration;
+		vertexBufferBinding = newBinding;		
+		// after this is complete, new manager should be used
+		mMgr = pManager;
+		mDeleteDclBinding = true; // because we created these through a manager
+
+	}
+    //-----------------------------------------------------------------------
+    void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration, HardwareBufferManagerBase* mgr)
+    {
+        // Derive the buffer usages from looking at where the source has come
+        // from
+        BufferUsageList usages;
+        for (unsigned short b = 0; b <= newDeclaration->getMaxSource(); ++b)
+        {
+            VertexDeclaration::VertexElementList destElems = newDeclaration->findElementsBySource(b);
+            // Initialise with most restrictive version 
+            // (not really a usable option, but these flags will be removed)
+            HardwareBuffer::Usage final = static_cast<HardwareBuffer::Usage>(
+                HardwareBuffer::HBU_STATIC_WRITE_ONLY | HardwareBuffer::HBU_DISCARDABLE);
+            VertexDeclaration::VertexElementList::iterator v;
+            for (v = destElems.begin(); v != destElems.end(); ++v)
+            {
+                VertexElement& destelem = *v;
+                // get source
+                const VertexElement* srcelem =
+                    vertexDeclaration->findElementBySemantic(
+                        destelem.getSemantic(), destelem.getIndex());
+                // get buffer
+                HardwareVertexBufferSharedPtr srcbuf = 
+                    vertexBufferBinding->getBuffer(srcelem->getSource());
+                // improve flexibility only
+                if (srcbuf->getUsage() & HardwareBuffer::HBU_DYNAMIC)
+                {
+                    // remove static
+                    final = static_cast<HardwareBuffer::Usage>(
+                        final & ~HardwareBuffer::HBU_STATIC);
+                    // add dynamic
+                    final = static_cast<HardwareBuffer::Usage>(
+                        final | HardwareBuffer::HBU_DYNAMIC);
+                }
+                if (!(srcbuf->getUsage() & HardwareBuffer::HBU_WRITE_ONLY))
+                {
+                    // remove write only
+                    final = static_cast<HardwareBuffer::Usage>(
+                        final & ~HardwareBuffer::HBU_WRITE_ONLY);
+                }
+                if (!(srcbuf->getUsage() & HardwareBuffer::HBU_DISCARDABLE))
+                {
+                    // remove discardable
+                    final = static_cast<HardwareBuffer::Usage>(
+                        final & ~HardwareBuffer::HBU_DISCARDABLE);
+                }
+                
+            }
+            usages.push_back(final);
+        }
+        // Call specific method
+        reorganiseBuffers(newDeclaration, usages, mgr);
+
+    }
+    //-----------------------------------------------------------------------
+    void VertexData::closeGapsInBindings(void)
+    {
+        if (!vertexBufferBinding->hasGaps())
+            return;
+
+        // Check for error first
+        const VertexDeclaration::VertexElementList& allelems = 
+            vertexDeclaration->getElements();
+        VertexDeclaration::VertexElementList::const_iterator ai;
+        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
+        {
+            const VertexElement& elem = *ai;
+            if (!vertexBufferBinding->isBufferBound(elem.getSource()))
+            {
+                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
+                    "No buffer is bound to that element source.",
+                    "VertexData::closeGapsInBindings");
+            }
+        }
+
+        // Close gaps in the vertex buffer bindings
+        VertexBufferBinding::BindingIndexMap bindingIndexMap;
+        vertexBufferBinding->closeGaps(bindingIndexMap);
+
+        // Modify vertex elements to reference to new buffer index
+        unsigned short elemIndex = 0;
+        for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
+        {
+            const VertexElement& elem = *ai;
+            VertexBufferBinding::BindingIndexMap::const_iterator it =
+                bindingIndexMap.find(elem.getSource());
+            assert(it != bindingIndexMap.end());
+            ushort targetSource = it->second;
+            if (elem.getSource() != targetSource)
+            {
+                vertexDeclaration->modifyElement(elemIndex, 
+                    targetSource, elem.getOffset(), elem.getType(), 
+                    elem.getSemantic(), elem.getIndex());
+            }
+        }
+    }
+    //-----------------------------------------------------------------------
+    void VertexData::removeUnusedBuffers(void)
+    {
+        set<ushort>::type usedBuffers;
+
+        // Collect used buffers
+        const VertexDeclaration::VertexElementList& allelems = 
+            vertexDeclaration->getElements();
+        VertexDeclaration::VertexElementList::const_iterator ai;
+        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
+        {
+            const VertexElement& elem = *ai;
+            usedBuffers.insert(elem.getSource());
+        }
+
+        // Unset unused buffer bindings
+        ushort count = vertexBufferBinding->getLastBoundIndex();
+        for (ushort index = 0; index < count; ++index)
+        {
+            if (usedBuffers.find(index) == usedBuffers.end() &&
+                vertexBufferBinding->isBufferBound(index))
+            {
+                vertexBufferBinding->unsetBinding(index);
+            }
+        }
+
+        // Close gaps
+        closeGapsInBindings();
+    }
+	//-----------------------------------------------------------------------
+	void VertexData::convertPackedColour(
+		VertexElementType srcType, VertexElementType destType)
+	{
+		if (destType != VET_COLOUR_ABGR && destType != VET_COLOUR_ARGB)
+		{
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+				"Invalid destType parameter", "VertexData::convertPackedColour");
+		}
+		if (srcType != VET_COLOUR_ABGR && srcType != VET_COLOUR_ARGB)
+		{
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+				"Invalid srcType parameter", "VertexData::convertPackedColour");
+		}
+
+		const VertexBufferBinding::VertexBufferBindingMap& bindMap = 
+			vertexBufferBinding->getBindings();
+		VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi;
+		for (bindi = bindMap.begin(); bindi != bindMap.end(); ++bindi)
+		{
+			VertexDeclaration::VertexElementList elems = 
+				vertexDeclaration->findElementsBySource(bindi->first);
+			bool conversionNeeded = false;
+			VertexDeclaration::VertexElementList::iterator elemi;
+			for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
+			{
+				VertexElement& elem = *elemi;
+				if (elem.getType() == VET_COLOUR || 
+					((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
+					&& elem.getType() != destType))
+				{
+					conversionNeeded = true;
+				}
+			}
+
+			if (conversionNeeded)
+			{
+				void* pBase = bindi->second->lock(HardwareBuffer::HBL_NORMAL);
+
+				for (size_t v = 0; v < bindi->second->getNumVertices(); ++v)
+				{
+
+					for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
+					{
+						VertexElement& elem = *elemi;
+						VertexElementType currType = (elem.getType() == VET_COLOUR) ?
+							srcType : elem.getType();
+						if (elem.getType() == VET_COLOUR || 
+							((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
+							&& elem.getType() != destType))
+						{
+							uint32* pRGBA;
+							elem.baseVertexPointerToElement(pBase, &pRGBA);
+							VertexElement::convertColourValue(currType, destType, pRGBA);
+						}
+					}
+					pBase = static_cast<void*>(
+						static_cast<char*>(pBase) + bindi->second->getVertexSize());
+				}
+				bindi->second->unlock();
+
+				// Modify the elements to reflect the changed type
+				const VertexDeclaration::VertexElementList& allelems = 
+					vertexDeclaration->getElements();
+				VertexDeclaration::VertexElementList::const_iterator ai;
+				unsigned short elemIndex = 0;
+				for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
+				{
+					const VertexElement& elem = *ai;
+					if (elem.getType() == VET_COLOUR || 
+						((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
+						&& elem.getType() != destType))
+					{
+						vertexDeclaration->modifyElement(elemIndex, 
+							elem.getSource(), elem.getOffset(), destType, 
+							elem.getSemantic(), elem.getIndex());
+					}
+				}
+
+			}
+
+
+		} // each buffer
+
+
+	}
+	//-----------------------------------------------------------------------
+	void VertexData::allocateHardwareAnimationElements(ushort count)
+	{
+		// Find first free texture coord set
+		unsigned short texCoord = 0;
+		const VertexDeclaration::VertexElementList& vel = vertexDeclaration->getElements();
+		for (VertexDeclaration::VertexElementList::const_iterator i = vel.begin(); 
+			i != vel.end(); ++i)
+		{
+			const VertexElement& el = *i;
+			if (el.getSemantic() == VES_TEXTURE_COORDINATES)
+			{
+				++texCoord;
+			}
+		}
+		assert(texCoord <= OGRE_MAX_TEXTURE_COORD_SETS);
+
+		// Increase to correct size
+		for (size_t c = hwAnimationDataList.size(); c < count; ++c)
+		{
+			// Create a new 3D texture coordinate set
+			HardwareAnimationData data;
+			data.targetVertexElement = &(vertexDeclaration->addElement(
+				vertexBufferBinding->getNextIndex(), 0, VET_FLOAT3, VES_TEXTURE_COORDINATES, texCoord++));
+
+			hwAnimationDataList.push_back(data);
+			// Vertex buffer will not be bound yet, we expect this to be done by the
+			// caller when it becomes appropriate (e.g. through a VertexAnimationTrack)
+		}
+	}
+    //-----------------------------------------------------------------------
+	//-----------------------------------------------------------------------
+	IndexData::IndexData()
+	{
+		indexCount = 0;
+		indexStart = 0;
+		
+	}
+    //-----------------------------------------------------------------------
+	IndexData::~IndexData()
+	{
+	}
+    //-----------------------------------------------------------------------
+	IndexData* IndexData::clone(bool copyData, HardwareBufferManagerBase* mgr) const
+	{
+		HardwareBufferManagerBase* pManager = mgr ? mgr : HardwareBufferManager::getSingletonPtr();
+		IndexData* dest = OGRE_NEW IndexData();
+		if (indexBuffer.get())
+		{
+            if (copyData)
+            {
+			    dest->indexBuffer = pManager->createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(),
+				    indexBuffer->getUsage(), indexBuffer->hasShadowBuffer());
+			    dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true);
+            }
+            else
+            {
+                dest->indexBuffer = indexBuffer;
+            }
+        }
+		dest->indexCount = indexCount;
+		dest->indexStart = indexStart;
+		return dest;
+	}
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+	// Local Utility class for vertex cache optimizer
+	class Triangle
+    {
+    public:
+		enum EdgeMatchType {
+			AB, BC, CA, ANY, NONE
+		};
+
+		uint32 a, b, c;		
+
+		inline Triangle()
+		{
+		}
+
+		inline Triangle( uint32 ta, uint32 tb, uint32 tc ) 
+			: a( ta ), b( tb ), c( tc )
+		{
+		}
+
+		inline Triangle( uint32 t[3] )
+			: a( t[0] ), b( t[1] ), c( t[2] )
+		{
+		}
+
+		inline Triangle( const Triangle& t )
+			: a( t.a ), b( t.b ), c( t.c )
+		{
+		}
+
+		inline bool sharesEdge(const Triangle& t) const
+		{
+			return(	a == t.a && b == t.c ||
+					a == t.b && b == t.a ||
+					a == t.c && b == t.b ||
+					b == t.a && c == t.c ||
+					b == t.b && c == t.a ||
+					b == t.c && c == t.b ||
+					c == t.a && a == t.c ||
+					c == t.b && a == t.a ||
+					c == t.c && a == t.b );
+		}
+
+		inline bool sharesEdge(const uint32 ea, const uint32 eb, const Triangle& t) const
+		{
+			return(	ea == t.a && eb == t.c ||
+					ea == t.b && eb == t.a ||
+					ea == t.c && eb == t.b );	
+		}
+
+		inline bool sharesEdge(const EdgeMatchType edge, const Triangle& t) const
+		{
+			if (edge == AB)
+				return sharesEdge(a, b, t);
+			else if (edge == BC)
+				return sharesEdge(b, c, t);
+			else if (edge == CA)
+				return sharesEdge(c, a, t);
+			else
+				return (edge == ANY) == sharesEdge(t);
+		}
+
+		inline EdgeMatchType endoSharedEdge(const Triangle& t) const
+		{
+			if (sharesEdge(a, b, t)) return AB;
+			if (sharesEdge(b, c, t)) return BC;
+			if (sharesEdge(c, a, t)) return CA;
+			return NONE;
+		}
+
+		inline EdgeMatchType exoSharedEdge(const Triangle& t) const
+		{
+			return t.endoSharedEdge(*this);
+		}
+
+		inline void shiftClockwise()
+		{
+			uint32 t = a;
+			a = c;
+			c = b;
+			b = t;
+		}
+
+		inline void shiftCounterClockwise()
+		{
+			uint32 t = a;
+			a = b;
+			b = c;
+			c = t;
+		}
+	};
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+	void IndexData::optimiseVertexCacheTriList(void)
+	{
+		if (indexBuffer->isLocked()) return;
+
+		void *buffer = indexBuffer->lock(HardwareBuffer::HBL_NORMAL);
+
+		Triangle* triangles;
+		uint32 *dest;
+
+		size_t nIndexes = indexCount;
+		size_t nTriangles = nIndexes / 3;
+		size_t i, j;
+		uint16 *source = 0;
+
+		if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
+		{
+			triangles = OGRE_ALLOC_T(Triangle, nTriangles, MEMCATEGORY_GEOMETRY);
+			source = (uint16 *)buffer;
+			dest = (uint32 *)triangles;
+			for (i = 0; i < nIndexes; ++i) dest[i] = source[i];
+		}
+		else
+			triangles = (Triangle*)buffer;
+
+		// sort triangles based on shared edges
+		uint32 *destlist = OGRE_ALLOC_T(uint32, nTriangles, MEMCATEGORY_GEOMETRY);
+		unsigned char *visited = OGRE_ALLOC_T(unsigned char, nTriangles, MEMCATEGORY_GEOMETRY);
+
+		for (i = 0; i < nTriangles; ++i) visited[i] = 0;
+
+		uint32 start = 0, ti = 0, destcount = 0;
+
+		bool found = false;
+		for (i = 0; i < nTriangles; ++i)
+		{
+			if (found)
+				found = false;
+			else
+			{
+				while (visited[start++]);
+				ti = start - 1;
+			}
+
+			destlist[destcount++] = ti;
+			visited[ti] = 1;
+
+			for (j = start; j < nTriangles; ++j)
+			{
+				if (visited[j]) continue;
+				
+				if (triangles[ti].sharesEdge(triangles[j]))
+				{
+					found = true;
+					ti = static_cast<uint32>(j);
+					break;
+				}
+			}
+		}
+
+		if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
+		{
+			// reorder the indexbuffer
+			j = 0;
+			for (i = 0; i < nTriangles; ++i)
+			{
+				Triangle *t = &triangles[destlist[i]];
+				source[j++] = (uint16)t->a;
+				source[j++] = (uint16)t->b;
+				source[j++] = (uint16)t->c;
+			}
+			OGRE_FREE(triangles, MEMCATEGORY_GEOMETRY);
+		}
+		else
+		{
+			uint32 *reflist = OGRE_ALLOC_T(uint32, nTriangles, MEMCATEGORY_GEOMETRY);
+
+			// fill the referencebuffer
+			for (i = 0; i < nTriangles; ++i)
+				reflist[destlist[i]] = static_cast<uint32>(i);
+			
+			// reorder the indexbuffer
+			for (i = 0; i < nTriangles; ++i)
+			{
+				j = destlist[i];
+				if (i == j) continue; // do not move triangle
+
+				// swap triangles
+
+				Triangle t = triangles[i];
+				triangles[i] = triangles[j];
+				triangles[j] = t;
+
+				// change reference
+				destlist[reflist[i]] = static_cast<uint32>(j);
+				// destlist[i] = i; // not needed, it will not be used
+			}
+
+			OGRE_FREE(reflist, MEMCATEGORY_GEOMETRY);
+		}
+
+		OGRE_FREE(destlist, MEMCATEGORY_GEOMETRY);
+		OGRE_FREE(visited, MEMCATEGORY_GEOMETRY);
+					
+		indexBuffer->unlock();
+	}
+	//-----------------------------------------------------------------------
+	//-----------------------------------------------------------------------
+	void VertexCacheProfiler::profile(const HardwareIndexBufferSharedPtr& indexBuffer)
+    {
+		if (indexBuffer->isLocked()) return;
+
+		uint16 *shortbuffer = (uint16 *)indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
+
+		if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
+			for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
+				inCache(shortbuffer[i]);
+		else
+		{
+			uint32 *buffer = (uint32 *)shortbuffer;
+			for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
+				inCache(buffer[i]);
+		}
+
+		indexBuffer->unlock();
+	}
+
+	//-----------------------------------------------------------------------
+	bool VertexCacheProfiler::inCache(unsigned int index)
+	{
+		for (unsigned int i = 0; i < buffersize; ++i)
+		{
+			if (index == cache[i])
+			{
+				hit++;
+				return true;
+			}
+		}
+
+		miss++;
+		cache[tail++] = index;
+		tail %= size;
+
+		if (buffersize < size) buffersize++;
+
+		return false;
+	}
+	
+
+}

+ 321 - 0
CamelotRenderer/OgreVertexIndexData.h

@@ -0,0 +1,321 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __VertexIndexData_H__
+#define __VertexIndexData_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreHardwareVertexBuffer.h"
+#include "OgreHardwareIndexBuffer.h"
+
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+
+	/// Define a list of usage flags
+	typedef vector<HardwareBuffer::Usage>::type BufferUsageList;
+
+
+	/** Summary class collecting together vertex source information. */
+	class _OgreExport VertexData
+	{
+    private:
+        /// Protected copy constructor, to prevent misuse
+        VertexData(const VertexData& rhs); /* do nothing, should not use */
+        /// Protected operator=, to prevent misuse
+        VertexData& operator=(const VertexData& rhs); /* do not use */
+
+		HardwareBufferManagerBase* mMgr;
+    public:
+		/** Constructor.
+		@note 
+			This constructor creates the VertexDeclaration and VertexBufferBinding
+			automatically, and arranges for their deletion afterwards.
+		@param mgr Optional HardwareBufferManager from which to create resources
+		*/
+        VertexData(HardwareBufferManagerBase* mgr = 0);
+		/** Constructor.
+		@note 
+		This constructor receives the VertexDeclaration and VertexBufferBinding
+		from the caller, and as such does not arrange for their deletion afterwards, 
+		the caller remains responsible for that.
+		@param dcl The VertexDeclaration to use
+		@param bind The VertexBufferBinding to use
+		*/
+		VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind);
+        ~VertexData();
+
+		/** Declaration of the vertex to be used in this operation. 
+		@remarks Note that this is created for you on construction.
+		*/
+		VertexDeclaration* vertexDeclaration;
+		/** The vertex buffer bindings to be used. 
+		@remarks Note that this is created for you on construction.
+		*/
+		VertexBufferBinding* vertexBufferBinding;
+		/// Whether this class should delete the declaration and binding
+		bool mDeleteDclBinding;
+		/// The base vertex index to start from
+		size_t vertexStart;
+		/// The number of vertices used in this operation
+		size_t vertexCount;
+
+
+		/// Struct used to hold hardware morph / pose vertex data information
+		struct HardwareAnimationData
+		{
+			const VertexElement* targetVertexElement;
+			Real parametric;
+		};
+		typedef vector<HardwareAnimationData>::type HardwareAnimationDataList;
+		/// VertexElements used for hardware morph / pose animation
+		HardwareAnimationDataList hwAnimationDataList;
+		/// Number of hardware animation data items used
+		size_t hwAnimDataItemsUsed;
+		
+		/** Clones this vertex data, potentially including replicating any vertex buffers.
+		@param copyData Whether to create new vertex buffers too or just reference the existing ones
+		@param mgr If supplied, the buffer manager through which copies should be made
+		@remarks The caller is expected to delete the returned pointer when ready
+		*/
+		VertexData* clone(bool copyData = true, HardwareBufferManagerBase* mgr = 0) const;
+
+        /** Modifies the vertex data to be suitable for use for rendering shadow geometry.
+        @remarks
+            Preparing vertex data to generate a shadow volume involves firstly ensuring that the 
+            vertex buffer containing the positions is a standalone vertex buffer,
+            with no other components in it. This method will therefore break apart any existing
+            vertex buffers if position is sharing a vertex buffer. 
+            Secondly, it will double the size of this vertex buffer so that there are 2 copies of 
+            the position data for the mesh. The first half is used for the original, and the second 
+            half is used for the 'extruded' version. The vertex count used to render will remain 
+            the same though, so as not to add any overhead to regular rendering of the object.
+            Both copies of the position are required in one buffer because shadow volumes stretch 
+            from the original mesh to the extruded version. 
+        @par
+            It's important to appreciate that this method can fundamentally change the structure of your
+            vertex buffers, although in reality they will be new buffers. As it happens, if other 
+            objects are using the original buffers then they will be unaffected because the reference
+            counting will keep them intact. However, if you have made any assumptions about the 
+            structure of the vertex data in the buffers of this object, you may have to rethink them.
+        */
+        void prepareForShadowVolume(void);
+
+        /** Additional shadow volume vertex buffer storage. 
+        @remarks
+            This additional buffer is only used where we have prepared this VertexData for
+            use in shadow volume construction, and where the current render system supports
+            vertex programs. This buffer contains the 'w' vertex position component which will
+            be used by that program to differentiate between extruded and non-extruded vertices.
+            This 'w' component cannot be included in the original position buffer because
+            DirectX does not allow 4-component positions in the fixed-function pipeline, and the original
+            position buffer must still be usable for fixed-function rendering.
+        @par    
+            Note that we don't store any vertex declaration or vertex buffer binding here because this
+            can be reused in the shadow algorithm.
+        */
+        HardwareVertexBufferSharedPtr hardwareShadowVolWBuffer;
+
+
+		/** Reorganises the data in the vertex buffers according to the 
+			new vertex declaration passed in. Note that new vertex buffers
+			are created and written to, so if the buffers being referenced 
+			by this vertex data object are also used by others, then the 
+			original buffers will not be damaged by this operation.
+			Once this operation has completed, the new declaration 
+			passed in will overwrite the current one.
+		@param newDeclaration The vertex declaration which will be used
+			for the reorganised buffer state. Note that the new declaration
+			must not include any elements which do not already exist in the 
+			current declaration; you can drop elements by 
+			excluding them from the declaration if you wish, however.
+		@param bufferUsages Vector of usage flags which indicate the usage options
+			for each new vertex buffer created. The indexes of the entries must correspond
+			to the buffer binding values referenced in the declaration.
+		@param mgr Optional pointer to the manager to use to create new declarations
+			and buffers etc. If not supplied, the HardwareBufferManager singleton will be used
+		*/
+		void reorganiseBuffers(VertexDeclaration* newDeclaration, const BufferUsageList& bufferUsage, 
+			HardwareBufferManagerBase* mgr = 0);
+
+		/** Reorganises the data in the vertex buffers according to the 
+			new vertex declaration passed in. Note that new vertex buffers
+			are created and written to, so if the buffers being referenced 
+			by this vertex data object are also used by others, then the 
+			original buffers will not be damaged by this operation.
+			Once this operation has completed, the new declaration 
+			passed in will overwrite the current one.
+            This version of the method derives the buffer usages from the existing
+            buffers, by using the 'most flexible' usage from the equivalent sources.
+		@param newDeclaration The vertex declaration which will be used
+			for the reorganised buffer state. Note that the new delcaration
+			must not include any elements which do not already exist in the 
+			current declaration; you can drop elements by 
+			excluding them from the declaration if you wish, however.
+		@param mgr Optional pointer to the manager to use to create new declarations
+			and buffers etc. If not supplied, the HardwareBufferManager singleton will be used
+		*/
+		void reorganiseBuffers(VertexDeclaration* newDeclaration, HardwareBufferManagerBase* mgr = 0);
+
+        /** Remove any gaps in the vertex buffer bindings.
+        @remarks
+            This is useful if you've removed elements and buffers from this vertex
+            data and want to remove any gaps in the vertex buffer bindings. This
+            method is mainly useful when reorganising vertex data manually.
+        @note
+            This will cause binding index of the elements in the vertex declaration
+            to be altered to new binding index.
+        */
+        void closeGapsInBindings(void);
+
+        /** Remove all vertex buffers that never used by the vertex declaration.
+        @remarks
+            This is useful if you've removed elements from the vertex declaration
+            and want to unreference buffers that never used any more. This method
+            is mainly useful when reorganising vertex data manually.
+        @note
+            This also remove any gaps in the vertex buffer bindings.
+        */
+        void removeUnusedBuffers(void);
+
+		/** Convert all packed colour values (VET_COLOUR_*) in buffers used to
+			another type.
+		@param srcType The source colour type to assume if the ambiguous VET_COLOUR
+			is encountered.
+		@param destType The destination colour type, must be VET_COLOUR_ABGR or
+			VET_COLOUR_ARGB.
+		*/
+		void convertPackedColour(VertexElementType srcType, VertexElementType destType);
+
+
+		/** Allocate elements to serve a holder of morph / pose target data 
+			for hardware morphing / pose blending.
+		@remarks
+			This method will allocate the given number of 3D texture coordinate 
+			sets for use as a morph target or target pose offset (3D position).
+			These elements will be saved in hwAnimationDataList.
+			It will also assume that the source of these new elements will be new
+			buffers which are not bound at this time, so will start the sources to 
+			1 higher than the current highest binding source. The caller is
+			expected to bind these new buffers when appropriate. For morph animation
+			the original position buffer will be the 'from' keyframe data, whilst
+			for pose animation it will be the original vertex data.
+		*/
+		void allocateHardwareAnimationElements(ushort count);
+
+
+
+	};
+
+	/** Summary class collecting together index data source information. */
+	class _OgreExport IndexData
+	{
+    protected:
+        /// Protected copy constructor, to prevent misuse
+        IndexData(const IndexData& rhs); /* do nothing, should not use */
+        /// Protected operator=, to prevent misuse
+        IndexData& operator=(const IndexData& rhs); /* do not use */
+    public:
+        IndexData();
+        ~IndexData();
+		/// pointer to the HardwareIndexBuffer to use, must be specified if useIndexes = true
+		HardwareIndexBufferSharedPtr indexBuffer;
+
+		/// index in the buffer to start from for this operation
+		size_t indexStart;
+
+		/// The number of indexes to use from the buffer
+		size_t indexCount;
+
+		/** Clones this index data, potentially including replicating the index buffer.
+		@param copyData Whether to create new buffers too or just reference the existing ones
+		@param mgr If supplied, the buffer manager through which copies should be made
+		@remarks The caller is expected to delete the returned pointer when finished
+		*/
+		IndexData* clone(bool copyData = true, HardwareBufferManagerBase* mgr = 0) const;
+
+		/** Re-order the indexes in this index data structure to be more
+			vertex cache friendly; that is to re-use the same vertices as close
+			together as possible. 
+		@remarks
+			Can only be used for index data which consists of triangle lists.
+			It would in fact be pointless to use it on triangle strips or fans
+			in any case.
+		*/
+		void optimiseVertexCacheTriList(void);
+	
+	};
+
+	/** Vertex cache profiler.
+	@remarks
+		Utility class for evaluating the effectiveness of the use of the vertex
+		cache by a given index buffer.
+	*/
+	class _OgreExport VertexCacheProfiler
+    {
+		public:
+			enum CacheType {
+				FIFO, LRU
+			};
+
+			VertexCacheProfiler(unsigned int cachesize = 16, CacheType cachetype = FIFO )
+				: size ( cachesize ), type ( cachetype ), tail (0), buffersize (0), hit (0), miss (0)
+			{
+				cache = OGRE_ALLOC_T(uint32, size, MEMCATEGORY_GEOMETRY);
+			}
+
+			~VertexCacheProfiler()
+			{
+				OGRE_FREE(cache, MEMCATEGORY_GEOMETRY);
+			}
+
+			void profile(const HardwareIndexBufferSharedPtr& indexBuffer);
+			void reset() { hit = 0; miss = 0; tail = 0; buffersize = 0; }
+			void flush() { tail = 0; buffersize = 0; }
+
+			unsigned int getHits() { return hit; }
+			unsigned int getMisses() { return miss; }
+			unsigned int getSize() { return size; }
+		private:
+			unsigned int size;
+			uint32 *cache;
+			CacheType type;
+
+			unsigned int tail, buffersize;
+			unsigned int hit, miss;
+
+			bool inCache(unsigned int index);
+	};
+	/** @} */
+	/** @} */
+}
+#endif
+

+ 40 - 0
CamelotRenderer/ReadMe.txt

@@ -0,0 +1,40 @@
+========================================================================
+    CONSOLE APPLICATION : CamelotRenderer Project Overview
+========================================================================
+
+AppWizard has created this CamelotRenderer application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your CamelotRenderer application.
+
+
+CamelotRenderer.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+CamelotRenderer.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+CamelotRenderer.cpp
+    This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named CamelotRenderer.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////

+ 376 - 0
CamelotRenderer/asm_math.h

@@ -0,0 +1,376 @@
+#ifndef __asm_math_H__
+#define __asm_math_H__
+
+#include "OgrePrerequisites.h"
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC
+#  pragma warning (push)
+// disable "instruction may be inaccurate on some Pentiums"
+#  pragma warning (disable : 4725)
+#endif
+namespace Ogre
+{
+
+/*=============================================================================
+ ASM math routines posted by davepermen et al on flipcode forums
+=============================================================================*/
+const float pi = 4.0f * atan( 1.0f );
+const float half_pi = 0.5f * 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_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
+
+#if  OGRE_COMPILER == OGRE_COMPILER_MSVC
+#  pragma warning (pop)
+#endif
+
+#endif

+ 8 - 0
CamelotRenderer/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// CamelotRenderer.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file

+ 15 - 0
CamelotRenderer/stdafx.h

@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here

+ 8 - 0
CamelotRenderer/targetver.h

@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>