瀏覽代碼

Reorganized how renderer works (using RenderOperations)
First step towards render sorting

Marko Pintera 12 年之前
父節點
當前提交
1265f65506
共有 54 個文件被更改,包括 853 次插入1065 次删除
  1. 3 0
      BansheeEngine.sln
  2. 4 0
      BansheeEngine/BansheeEngine.vcxproj
  3. 12 0
      BansheeEngine/BansheeEngine.vcxproj.filters
  4. 8 4
      BansheeEngine/Include/BsCamera.h
  5. 1 1
      BansheeEngine/Include/BsDebugDraw.h
  6. 13 0
      BansheeEngine/Include/BsDefaultRendererSort.h
  7. 11 0
      BansheeEngine/Include/BsPrerequisites.h
  8. 18 0
      BansheeEngine/Include/BsRenderOperation.h
  9. 18 4
      BansheeEngine/Include/BsRenderable.h
  10. 29 0
      BansheeEngine/Include/BsRendererSort.h
  11. 2 0
      BansheeEngine/Include/BsSceneManager.h
  12. 5 10
      BansheeEngine/Source/BsCamera.cpp
  13. 2 2
      BansheeEngine/Source/BsDebugDraw.cpp
  14. 30 0
      BansheeEngine/Source/BsDefaultRendererSort.cpp
  15. 1 1
      BansheeEngine/Source/BsGUIManager.cpp
  16. 91 2
      BansheeEngine/Source/BsRenderable.cpp
  17. 3 0
      BansheeForwardRenderer/Include/BsForwardRenderer.h
  18. 35 28
      BansheeForwardRenderer/Source/BsForwardRenderer.cpp
  19. 3 0
      BansheeOctreeSM/Include/BsOctreeSceneManager.h
  20. 26 1
      BansheeOctreeSM/Source/BsOctreeSceneManager.cpp
  21. 1 1
      CamelotClient/CamelotClient.cpp
  22. 1 1
      CamelotCore/CamelotCore.vcxproj
  23. 3 3
      CamelotCore/CamelotCore.vcxproj.filters
  24. 1 1
      CamelotCore/Include/CmCoreThreadAccessor.h
  25. 1 1
      CamelotCore/Include/CmGpuProgram.h
  26. 1 1
      CamelotCore/Include/CmGpuProgramParams.h
  27. 3 0
      CamelotCore/Include/CmMaterial.h
  28. 6 2
      CamelotCore/Include/CmMesh.h
  29. 1 1
      CamelotCore/Include/CmPrerequisites.h
  30. 32 0
      CamelotCore/Include/CmRenderOpMesh.h
  31. 0 85
      CamelotCore/Include/CmRenderOperation.h
  32. 2 2
      CamelotCore/Include/CmRenderSystem.h
  33. 0 6
      CamelotCore/Include/CmRenderer.h
  34. 1 1
      CamelotCore/Source/CmIndexData.cpp
  35. 1 1
      CamelotCore/Source/CmMaterial.cpp
  36. 16 2
      CamelotCore/Source/CmMesh.cpp
  37. 1 1
      CamelotCore/Source/CmRenderSystem.cpp
  38. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h
  39. 2 2
      CamelotUtility/CamelotUtility.vcxproj
  40. 6 6
      CamelotUtility/CamelotUtility.vcxproj.filters
  41. 266 0
      CamelotUtility/Include/CmAABox.cpp
  42. 86 0
      CamelotUtility/Include/CmAABox.h
  43. 0 35
      CamelotUtility/Include/CmAxisAlignedBox.cpp
  44. 0 813
      CamelotUtility/Include/CmAxisAlignedBox.h
  45. 1 1
      CamelotUtility/Include/CmFwdDeclUtil.h
  46. 5 5
      CamelotUtility/Include/CmMath.h
  47. 1 1
      CamelotUtility/Include/CmPlane.h
  48. 1 1
      CamelotUtility/Include/CmRay.h
  49. 1 1
      CamelotUtility/Include/CmSphere.h
  50. 14 30
      CamelotUtility/Source/CmMath.cpp
  51. 2 7
      CamelotUtility/Source/CmPlane.cpp
  52. 21 0
      DrawHelper.txt
  53. 23 0
      PlatformPorting.txt
  54. 37 0
      RenderOperation.txt

+ 3 - 0
BansheeEngine.sln

@@ -40,8 +40,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 	ProjectSection(SolutionItems) = preProject
 	ProjectSection(SolutionItems) = preProject
 		CSharpWrap.txt = CSharpWrap.txt
 		CSharpWrap.txt = CSharpWrap.txt
 		Dependencies.txt = Dependencies.txt
 		Dependencies.txt = Dependencies.txt
+		DrawHelper.txt = DrawHelper.txt
 		EditorWindowDock.txt = EditorWindowDock.txt
 		EditorWindowDock.txt = EditorWindowDock.txt
 		Notes.txt = Notes.txt
 		Notes.txt = Notes.txt
+		PlatformPorting.txt = PlatformPorting.txt
+		RenderOperation.txt = RenderOperation.txt
 		TODO.txt = TODO.txt
 		TODO.txt = TODO.txt
 		TODO_2D_GUI.txt = TODO_2D_GUI.txt
 		TODO_2D_GUI.txt = TODO_2D_GUI.txt
 		TODODoc.txt = TODODoc.txt
 		TODODoc.txt = TODODoc.txt

+ 4 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -228,6 +228,7 @@
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\BsApplication.h" />
     <ClInclude Include="Include\BsApplication.h" />
     <ClInclude Include="Include\BsDebugDraw.h" />
     <ClInclude Include="Include\BsDebugDraw.h" />
+    <ClInclude Include="Include\BsDefaultRendererSort.h" />
     <ClInclude Include="Include\BsDragAndDropManager.h" />
     <ClInclude Include="Include\BsDragAndDropManager.h" />
     <ClInclude Include="Include\BsEngineGUI.h" />
     <ClInclude Include="Include\BsEngineGUI.h" />
     <ClInclude Include="Include\BsGUIArea.h" />
     <ClInclude Include="Include\BsGUIArea.h" />
@@ -264,6 +265,8 @@
     <ClInclude Include="Include\BsGUISkin.h" />
     <ClInclude Include="Include\BsGUISkin.h" />
     <ClInclude Include="Include\BsGUIWidget.h" />
     <ClInclude Include="Include\BsGUIWidget.h" />
     <ClInclude Include="Include\BsImageSprite.h" />
     <ClInclude Include="Include\BsImageSprite.h" />
+    <ClInclude Include="Include\BsRendererSort.h" />
+    <ClInclude Include="Include\BsRenderOperation.h" />
     <ClInclude Include="Include\BsSceneManager.h" />
     <ClInclude Include="Include\BsSceneManager.h" />
     <ClInclude Include="Include\BsGUIScrollArea.h" />
     <ClInclude Include="Include\BsGUIScrollArea.h" />
     <ClInclude Include="Include\BsSprite.h" />
     <ClInclude Include="Include\BsSprite.h" />
@@ -313,6 +316,7 @@
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
     <ClCompile Include="Source\BsGUIWindowMover.cpp" />
     <ClCompile Include="Source\BsGUIWindowMover.cpp" />
     <ClCompile Include="Source\BsImageSprite.cpp" />
     <ClCompile Include="Source\BsImageSprite.cpp" />
+    <ClCompile Include="Source\BsDefaultRendererSort.cpp" />
     <ClCompile Include="Source\BsSceneManager.cpp" />
     <ClCompile Include="Source\BsSceneManager.cpp" />
     <ClCompile Include="Source\BsGUIScrollArea.cpp" />
     <ClCompile Include="Source\BsGUIScrollArea.cpp" />
     <ClCompile Include="Source\BsSprite.cpp" />
     <ClCompile Include="Source\BsSprite.cpp" />

+ 12 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -198,6 +198,15 @@
     <ClInclude Include="Include\BsGUIViewport.h">
     <ClInclude Include="Include\BsGUIViewport.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsRenderOperation.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRendererSort.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDefaultRendererSort.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -341,5 +350,8 @@
     <ClCompile Include="Source\BsGUIViewport.cpp">
     <ClCompile Include="Source\BsGUIViewport.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsDefaultRendererSort.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 8 - 4
BansheeEngine/Include/BsCamera.h

@@ -37,7 +37,7 @@ THE SOFTWARE.
 #include "CmMatrix4.h"
 #include "CmMatrix4.h"
 #include "CmVector3.h"
 #include "CmVector3.h"
 #include "CmVector2.h"
 #include "CmVector2.h"
-#include "CmAxisAlignedBox.h"
+#include "CmAABox.h"
 #include "CmVertexData.h"
 #include "CmVertexData.h"
 #include "CmIndexData.h"
 #include "CmIndexData.h"
 #include "CmPlane.h"
 #include "CmPlane.h"
@@ -342,7 +342,7 @@ namespace BansheeEngine {
             @par
             @par
                 Otherwise, false is returned.
                 Otherwise, false is returned.
         */
         */
-        virtual bool isVisible(const CM::AxisAlignedBox& bound, FrustumPlane* culledBy = 0) const;
+        virtual bool isVisible(const CM::AABox& bound, FrustumPlane* culledBy = 0) const;
 
 
         /** Tests whether the given container is visible in the Frustum.
         /** Tests whether the given container is visible in the Frustum.
             @param
             @param
@@ -371,7 +371,7 @@ namespace BansheeEngine {
         virtual bool isVisible(const CM::Vector3& vert, FrustumPlane* culledBy = 0) const;
         virtual bool isVisible(const CM::Vector3& vert, FrustumPlane* culledBy = 0) const;
 
 
         /** Overridden from MovableObject */
         /** Overridden from MovableObject */
-        const CM::AxisAlignedBox& getBoundingBox(void) const;
+        const CM::AABox& getBoundingBox(void) const;
 
 
         /** Overridden from MovableObject */
         /** Overridden from MovableObject */
 		float getBoundingRadius(void) const;
 		float getBoundingRadius(void) const;
@@ -424,10 +424,14 @@ namespace BansheeEngine {
 		CM::INT32 getPriority() const { return mPriority; }
 		CM::INT32 getPriority() const { return mPriority; }
 		void setPriority(CM::INT32 priority) { mPriority = priority; }
 		void setPriority(CM::INT32 priority) { mPriority = priority; }
 
 
+		CM::UINT64 getLayers() const { return mLayers; }
+		void setLayers(CM::UINT64 layers) { mLayers = layers; }
+
         /// Small constant used to reduce far plane projection to avoid inaccuracies
         /// Small constant used to reduce far plane projection to avoid inaccuracies
         static const float INFINITE_FAR_PLANE_ADJUST;
         static const float INFINITE_FAR_PLANE_ADJUST;
     protected:
     protected:
 		CM::ViewportPtr mViewport;
 		CM::ViewportPtr mViewport;
+		CM::UINT64 mLayers;
 
 
 		/// Orthographic or perspective?
 		/// Orthographic or perspective?
 		ProjectionType mProjType;
 		ProjectionType mProjType;
@@ -498,7 +502,7 @@ namespace BansheeEngine {
 		/// Signal to update frustum information.
 		/// Signal to update frustum information.
 		virtual void invalidateFrustum(void) const;
 		virtual void invalidateFrustum(void) const;
 
 
-		mutable CM::AxisAlignedBox mBoundingBox;
+		mutable CM::AABox mBoundingBox;
 
 
 		mutable CM::Vector3 mWorldSpaceCorners[8];
 		mutable CM::Vector3 mWorldSpaceCorners[8];
 
 

+ 1 - 1
BansheeEngine/Include/BsDebugDraw.h

@@ -3,7 +3,7 @@
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
 #include "CmModule.h"
 #include "CmModule.h"
 #include "CmColor.h"
 #include "CmColor.h"
-#include "CmAxisAlignedBox.h"
+#include "CmAABox.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {

+ 13 - 0
BansheeEngine/Include/BsDefaultRendererSort.h

@@ -0,0 +1,13 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsRendererSort.h"
+
+namespace BansheeEngine 
+{
+	class BS_EXPORT DefaultRendererSort : public RendererSort
+	{
+	public:
+		CM::Vector<SortedRenderOp>::type sort(const HCamera& camera, const CM::Vector<RenderOperation>::type& renderOperations, DepthSortOrder sortOrder, bool allowSortByPass);
+	};
+}

+ 11 - 0
BansheeEngine/Include/BsPrerequisites.h

@@ -68,6 +68,9 @@ namespace BansheeEngine
 	class Renderable;
 	class Renderable;
 	class Camera;
 	class Camera;
 
 
+	struct RenderOperation;
+	class RendererSort;
+
 	typedef std::shared_ptr<TextSprite> TextSpritePtr;
 	typedef std::shared_ptr<TextSprite> TextSpritePtr;
 	typedef std::shared_ptr<SpriteTexture> SpriteTexturePtr;
 	typedef std::shared_ptr<SpriteTexture> SpriteTexturePtr;
 	typedef std::shared_ptr<Overlay> OverlayPtr;
 	typedef std::shared_ptr<Overlay> OverlayPtr;
@@ -83,6 +86,14 @@ namespace BansheeEngine
 		TID_Camera = 30000,
 		TID_Camera = 30000,
 		TID_Renderable = 30001
 		TID_Renderable = 30001
 	};
 	};
+
+	enum class RenderQueue
+	{
+		Skybox = 10000,
+		Opaque = 11000,
+		Transparent = 12000,
+		Overlay = 13000
+	};
 }
 }
 
 
 namespace BS = BansheeEngine;
 namespace BS = BansheeEngine;

+ 18 - 0
BansheeEngine/Include/BsRenderOperation.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "CmRenderOpMesh.h"
+#include "CmVector3.h"
+
+namespace BansheeEngine 
+{
+	struct BS_EXPORT RenderOperation
+	{
+		RenderOperation()
+		{ }
+
+		CM::HMaterial material;
+		CM::RenderOpMesh meshData;
+		CM::Vector3 worldPosition;
+	};
+}

+ 18 - 4
BansheeEngine/Include/BsRenderable.h

@@ -1,7 +1,9 @@
 #pragma once
 #pragma once
 
 
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
+#include "BsRenderOperation.h"
 #include "CmComponent.h"
 #include "CmComponent.h"
+#include "CmAABox.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -9,13 +11,25 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		void setMesh(CM::HMesh mesh) { mMesh = mesh; }
 		void setMesh(CM::HMesh mesh) { mMesh = mesh; }
-		void setMaterial(CM::HMaterial material) { mMaterial = material; }
+		void setNumMaterials(CM::UINT32 numMaterials);
+		void setMaterial(CM::UINT32 idx, CM::HMaterial material);
+		void setLayer(CM::UINT64 layer);
 
 
-		CM::HMesh getMesh() const { return mMesh; }
-		CM::HMaterial getMaterial() const { return mMaterial; }
+		CM::UINT32 getNumRenderOperations() const;
+
+		/**
+		* @note  This method relies on getNumRenderOperations() being called and ensuring that idx doesn't exceed
+		* the number returned by that method
+		*/
+		RenderOperation getRenderOperation(CM::UINT32 idx) const;
+		CM::UINT64 getLayer() const { return mLayer; }
+
+		void updateWorldBounds();
 	private:
 	private:
 		CM::HMesh mMesh;
 		CM::HMesh mMesh;
-		CM::HMaterial mMaterial;
+		CM::Vector<CM::HMaterial>::type mMaterials;
+		CM::UINT64 mLayer;
+		CM::Vector<CM::AABox>::type mWorldBounds;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 							COMPONENT OVERRIDES                    		*/
 		/* 							COMPONENT OVERRIDES                    		*/

+ 29 - 0
BansheeEngine/Include/BsRendererSort.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+
+namespace BansheeEngine 
+{
+	enum class DepthSortOrder
+	{
+		FrontToBack,
+		BackToFront,
+		NoDepthSort
+	};
+
+	struct BS_EXPORT SortedRenderOp
+	{
+		SortedRenderOp(const RenderOperation& op)
+			:baseOperation(op), passIdx(0)
+		{ }
+
+		const RenderOperation& baseOperation;
+		CM::UINT32 passIdx;
+	};
+
+	class BS_EXPORT RendererSort
+	{
+	public:
+		virtual CM::Vector<SortedRenderOp>::type sort(const HCamera& camera, const CM::Vector<RenderOperation>::type& renderOperations, DepthSortOrder sortOrder, bool allowSortByPass) = 0;
+	};
+}

+ 2 - 0
BansheeEngine/Include/BsSceneManager.h

@@ -20,6 +20,8 @@ namespace BansheeEngine
 		 * @brief	Returns all renderables visible to the specified camera.
 		 * @brief	Returns all renderables visible to the specified camera.
 		 */
 		 */
 		virtual CM::Vector<HRenderable>::type getVisibleRenderables(const HCamera& camera) const = 0;
 		virtual CM::Vector<HRenderable>::type getVisibleRenderables(const HCamera& camera) const = 0;
+
+		virtual void updateRenderableBounds() = 0;
 	};
 	};
 
 
 	BS_EXPORT SceneManager& gSceneManager();
 	BS_EXPORT SceneManager& gSceneManager();

+ 5 - 10
BansheeEngine/Source/BsCamera.cpp

@@ -31,7 +31,7 @@ THE SOFTWARE.
 #include "CmMath.h"
 #include "CmMath.h"
 #include "CmMatrix3.h"
 #include "CmMatrix3.h"
 #include "CmVector2.h"
 #include "CmVector2.h"
-#include "CmAxisAlignedBox.h"
+#include "CmAABox.h"
 #include "CmSphere.h"
 #include "CmSphere.h"
 #include "CmHardwareBufferManager.h"
 #include "CmHardwareBufferManager.h"
 #include "CmVertexBuffer.h"
 #include "CmVertexBuffer.h"
@@ -67,7 +67,8 @@ namespace BansheeEngine
 		mCustomProjMatrix(false),
 		mCustomProjMatrix(false),
 		mFrustumExtentsManuallySet(false),
 		mFrustumExtentsManuallySet(false),
 		mIgnoreSceneRenderables(false),
 		mIgnoreSceneRenderables(false),
-		mPriority(0)
+		mPriority(0),
+		mLayers(0xFFFFFFFFFFFFFFFF)
     {
     {
 		updateView();
 		updateView();
 		updateFrustum();
 		updateFrustum();
@@ -223,14 +224,8 @@ namespace BansheeEngine
 	}
 	}
 
 
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
-	bool Camera::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
+	bool Camera::isVisible(const AABox& 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
 		// Make any pending updates to the calculated frustum planes
 		updateFrustumPlanes();
 		updateFrustumPlanes();
 
 
@@ -676,7 +671,7 @@ namespace BansheeEngine
 		invalidateFrustum();
 		invalidateFrustum();
 	}
 	}
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
-	const AxisAlignedBox& Camera::getBoundingBox(void) const
+	const AABox& Camera::getBoundingBox(void) const
 	{
 	{
 		return mBoundingBox;
 		return mBoundingBox;
 	}
 	}

+ 2 - 2
BansheeEngine/Source/BsDebugDraw.cpp

@@ -175,7 +175,7 @@ namespace BansheeEngine
 			PassParametersPtr paramsPtr = mLineMaterial->getPassParameters(i);
 			PassParametersPtr paramsPtr = mLineMaterial->getPassParameters(i);
 			pass->bindParameters(coreAccessor, paramsPtr);
 			pass->bindParameters(coreAccessor, paramsPtr);
 
 
-			coreAccessor.render(mLineMesh->getRenderOperation());
+			coreAccessor.render(mLineMesh->getSubMeshData());
 		}
 		}
 
 
 		for(UINT32 i = 0; i < mTriangleMaterial->getNumPasses(); i++)
 		for(UINT32 i = 0; i < mTriangleMaterial->getNumPasses(); i++)
@@ -186,7 +186,7 @@ namespace BansheeEngine
 			PassParametersPtr paramsPtr = mTriangleMaterial->getPassParameters(i);
 			PassParametersPtr paramsPtr = mTriangleMaterial->getPassParameters(i);
 			pass->bindParameters(coreAccessor, paramsPtr);
 			pass->bindParameters(coreAccessor, paramsPtr);
 
 
-			coreAccessor.render(mTriangleMesh->getRenderOperation());
+			coreAccessor.render(mTriangleMesh->getSubMeshData());
 		}
 		}
 	}
 	}
 
 

+ 30 - 0
BansheeEngine/Source/BsDefaultRendererSort.cpp

@@ -0,0 +1,30 @@
+#include "BsDefaultRendererSort.h"
+#include "BsRenderOperation.h"
+#include "CmMaterial.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	Vector<SortedRenderOp>::type DefaultRendererSort::sort(const HCamera& camera, const Vector<RenderOperation>::type& renderOperations, DepthSortOrder sortOrder, bool allowSortByPass)
+	{
+		Vector<SortedRenderOp>::type sortedOps;
+
+		// Just pass-through for now
+		for(auto& renderOp : renderOperations)
+		{
+			UINT32 numPasses = renderOp.material->getNumPasses();
+			for(UINT32 i = 0; i < numPasses; i++)
+			{
+				sortedOps.push_back(SortedRenderOp(renderOp));
+
+				SortedRenderOp& sortedOp = sortedOps.back();
+				sortedOp.passIdx = i;
+			}
+		}
+
+		// TODO - Actually do some sorting
+
+		return sortedOps;
+	}
+}

+ 1 - 1
BansheeEngine/Source/BsGUIManager.cpp

@@ -243,7 +243,7 @@ namespace BansheeEngine
 			PassParametersPtr paramsPtr = material->getPassParameters(i);
 			PassParametersPtr paramsPtr = material->getPassParameters(i);
 			pass->bindParameters(coreAccessor, paramsPtr);
 			pass->bindParameters(coreAccessor, paramsPtr);
 
 
-			coreAccessor.render(mesh->getRenderOperation());
+			coreAccessor.render(mesh->getSubMeshData());
 		}
 		}
 	}
 	}
 
 

+ 91 - 2
BansheeEngine/Source/BsRenderable.cpp

@@ -1,13 +1,102 @@
 #include "BsRenderable.h"
 #include "BsRenderable.h"
 #include "BsRenderableRTTI.h"
 #include "BsRenderableRTTI.h"
+#include "CmSceneObject.h"
+#include "CmMesh.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	Renderable::Renderable(const HSceneObject& parent)
 	Renderable::Renderable(const HSceneObject& parent)
-		:Component(parent)
-	{ }
+		:Component(parent), mLayer(1)
+	{
+		mMaterials.resize(1);
+	}
+
+	void Renderable::setNumMaterials(CM::UINT32 numMaterials)
+	{
+		mMaterials.resize(numMaterials);
+	}
+
+	void Renderable::setMaterial(CM::UINT32 idx, CM::HMaterial material)
+	{
+		mMaterials[idx] = material;
+	}
+
+	UINT32 Renderable::getNumRenderOperations() const
+	{
+		if(mMesh == nullptr || !mMesh.isLoaded())
+			return 0;
+
+		bool hasAtLeastOneMaterial = false;
+		for(auto& material : mMaterials)
+		{
+			if(material != nullptr)
+			{
+				hasAtLeastOneMaterial = true;
+
+				if(!material.isLoaded()) // We wait until all materials are loaded
+					return 0;
+			}
+		}
+
+		if(hasAtLeastOneMaterial)
+			return mMesh->getNumSubMeshes();
+		else
+			return 0;
+	}
+
+	void Renderable::updateWorldBounds()
+	{
+		if(mMesh == nullptr || !mMesh.isLoaded())
+			return;
+
+		// TODO - This will likely need to be optimized in a more data friendly way
+		// (e.g. store all bounds in a single array, and same with world matrices)
+		mWorldBounds.resize(mMesh->getNumSubMeshes());
+		for(UINT32 i = 0; i < (UINT32)mWorldBounds.size(); i++)
+		{
+			mWorldBounds[i] = mMesh->getBounds(i);
+			mWorldBounds[i].transformAffine(SO()->getWorldTfrm());
+		}
+	}
+
+	RenderOperation Renderable::getRenderOperation(CM::UINT32 idx) const
+	{
+		// TODO - Creating a RenderOperation each call might be excessive considering this will be called a few thousand times a frame
+		RenderOperation ro;
+		
+		if(idx < mMaterials.size() && mMaterials[idx] != nullptr)
+		{
+			ro.material = mMaterials[idx];
+		}
+		else
+		{
+			for(auto& iter = mMaterials.rbegin(); iter != mMaterials.rend(); ++iter)
+			{
+				if((*iter) != nullptr)
+				{
+					ro.material = *iter;
+					break;
+				}
+			}
+		}
+
+		ro.meshData = mMesh->getSubMeshData(idx);
+		ro.worldPosition = mWorldBounds[idx].getCenter();
+
+		return ro;
+	}
+
+	void Renderable::setLayer(UINT64 layer)
+	{
+		bool isPow2 = layer && !( (layer-1) & layer);
+
+		if(!isPow2)
+			CM_EXCEPT(InvalidParametersException, "Invalid layer provided. Only one layer bit may be set.");
+
+		mLayer = layer;
+	}
 
 
 	RTTITypeBase* Renderable::getRTTIStatic()
 	RTTITypeBase* Renderable::getRTTIStatic()
 	{
 	{

+ 3 - 0
BansheeForwardRenderer/Include/BsForwardRenderer.h

@@ -15,5 +15,8 @@ namespace BansheeEngine
 
 
 		virtual void renderAll();
 		virtual void renderAll();
 		virtual void render(const HCamera& camera);
 		virtual void render(const HCamera& camera);
+
+	private:
+		RendererSort* mRenderOpSorter;
 	};
 	};
 }
 }

+ 35 - 28
BansheeForwardRenderer/Source/BsForwardRenderer.cpp

@@ -13,6 +13,7 @@
 #include "CmRenderTarget.h"
 #include "CmRenderTarget.h"
 #include "BsOverlayManager.h"
 #include "BsOverlayManager.h"
 #include "BsGUIManager.h"
 #include "BsGUIManager.h"
+#include "BsDefaultRendererSort.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 
 
@@ -20,10 +21,13 @@ namespace BansheeEngine
 {
 {
 	ForwardRenderer::ForwardRenderer()
 	ForwardRenderer::ForwardRenderer()
 	{
 	{
+		mRenderOpSorter = cm_new<DefaultRendererSort>();
 	}
 	}
 
 
 	ForwardRenderer::~ForwardRenderer()
 	ForwardRenderer::~ForwardRenderer()
-	{ }
+	{
+		cm_delete(mRenderOpSorter);
+	}
 
 
 	const String& ForwardRenderer::getName() const
 	const String& ForwardRenderer::getName() const
 	{
 	{
@@ -33,6 +37,8 @@ namespace BansheeEngine
 
 
 	void ForwardRenderer::renderAll() 
 	void ForwardRenderer::renderAll() 
 	{
 	{
+		gSceneManager().updateRenderableBounds();
+
 		CoreAccessor& coreAccessor = gMainCA();
 		CoreAccessor& coreAccessor = gMainCA();
 		const Vector<HCamera>::type& allCameras = gSceneManager().getAllCameras();
 		const Vector<HCamera>::type& allCameras = gSceneManager().getAllCameras();
 
 
@@ -97,14 +103,7 @@ namespace BansheeEngine
 				if(clearBuffers != 0)
 				if(clearBuffers != 0)
 					coreAccessor.clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
 					coreAccessor.clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
 
 
-				// Render scene
 				render(camera);
 				render(camera);
-
-				// Render overlays
-				OverlayManager::instance().render(camera->getViewport(), coreAccessor);
-
-				// Render GUI elements
-				GUIManager::instance().render(camera->getViewport(), coreAccessor);
 			}
 			}
 
 
 			coreAccessor.endFrame();
 			coreAccessor.endFrame();
@@ -127,37 +126,45 @@ namespace BansheeEngine
 
 
 		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
 		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
 
 
-		// TODO - sort renderables by material/pass/parameters to minimize state changes
+		Vector<RenderOperation>::type renderOperations;
 		for(auto iter = allRenderables.begin(); iter != allRenderables.end(); ++iter)
 		for(auto iter = allRenderables.begin(); iter != allRenderables.end(); ++iter)
 		{
 		{
-			HMaterial material = (*iter)->getMaterial();
-
-			if(material == nullptr || !material.isLoaded())
-				continue;
+			UINT32 numOps = (*iter)->getNumRenderOperations();
 
 
-			HMesh mesh = (*iter)->getMesh();
-
-			if(mesh == nullptr || !mesh.isLoaded())
-				continue;
+			for(UINT32 i = 0; i < numOps; i++)
+				renderOperations.push_back((*iter)->getRenderOperation(i));
+		}
 
 
+		// TODO - Do different things depending on render op settings
+		for(auto& renderOp : renderOperations)
+		{
 			// TODO - Renderer should ensure shader is compatible with it, and it contains all the needed parameters
 			// TODO - Renderer should ensure shader is compatible with it, and it contains all the needed parameters
 			// (probably at an earlier stage). e.g. I want the user to be warned if the shader doesn't contain matViewProjection param
 			// (probably at an earlier stage). e.g. I want the user to be warned if the shader doesn't contain matViewProjection param
 			// (or should we just ignore such missing parameters?)
 			// (or should we just ignore such missing parameters?)
-			material->setMat4("matViewProjection", viewProjMatrix);
+			renderOp.material->setMat4("matViewProjection", viewProjMatrix);
+		}
 
 
-			for(UINT32 i = 0; i < material->getNumPasses(); i++)
-			{
-				PassPtr pass = material->getPass(i);
-				pass->activate(coreAccessor);
+		// TODO - Material queue is completely ignored
+		Vector<SortedRenderOp>::type sortedROps =  mRenderOpSorter->sort(camera, renderOperations, DepthSortOrder::FrontToBack, true);
+
+		for(auto iter = sortedROps.begin(); iter != sortedROps.end(); ++iter)
+		{
+			const RenderOperation& renderOp = iter->baseOperation;
+			HMaterial material = renderOp.material;
 
 
-				PassParametersPtr paramsPtr = material->getPassParameters(i);
-				pass->bindParameters(coreAccessor, paramsPtr);
+			PassPtr pass = material->getPass(iter->passIdx);
+			pass->activate(coreAccessor);
 
 
-				coreAccessor.render(mesh->getRenderOperation());
-			}
+			PassParametersPtr paramsPtr = material->getPassParameters(iter->passIdx);
+			pass->bindParameters(coreAccessor, paramsPtr);
+
+			coreAccessor.render(renderOp.meshData);
 		}
 		}
 
 
-		// TODO - Sort renderables
-		// Render them
+		// Render overlays
+		OverlayManager::instance().render(camera->getViewport(), coreAccessor);
+
+		// Render GUI elements
+		GUIManager::instance().render(camera->getViewport(), coreAccessor);
 	}
 	}
 }
 }

+ 3 - 0
BansheeOctreeSM/Include/BsOctreeSceneManager.h

@@ -14,10 +14,13 @@ namespace BansheeEngine
 		const CM::Vector<HCamera>::type& getAllCameras() const { return mCachedCameras; }
 		const CM::Vector<HCamera>::type& getAllCameras() const { return mCachedCameras; }
 
 
 		CM::Vector<HRenderable>::type getVisibleRenderables(const HCamera& camera) const;
 		CM::Vector<HRenderable>::type getVisibleRenderables(const HCamera& camera) const;
+
+		void updateRenderableBounds();
 	private:
 	private:
 		void notifyComponentAdded(const CM::HComponent& component);
 		void notifyComponentAdded(const CM::HComponent& component);
 		void notifyComponentRemoved(const CM::HComponent& component);
 		void notifyComponentRemoved(const CM::HComponent& component);
 
 
 		CM::Vector<HCamera>::type mCachedCameras;
 		CM::Vector<HCamera>::type mCachedCameras;
+		CM::Vector<HRenderable>::type mRenderables;
 	};
 	};
 }
 }

+ 26 - 1
BansheeOctreeSM/Source/BsOctreeSceneManager.cpp

@@ -25,7 +25,10 @@ namespace BansheeEngine
 
 
 			HRenderable curRenderable = currentGO->getComponent<Renderable>();
 			HRenderable curRenderable = currentGO->getComponent<Renderable>();
 			if(curRenderable != nullptr)
 			if(curRenderable != nullptr)
-				renderables.push_back(curRenderable);
+			{
+				if((curRenderable->getLayer() & camera->getLayers()) != 0)
+					renderables.push_back(curRenderable);
+			}
 
 
 			for(UINT32 i = 0; i < currentGO->getNumChildren(); i++)
 			for(UINT32 i = 0; i < currentGO->getNumChildren(); i++)
 				todo.push(currentGO->getChild(i));
 				todo.push(currentGO->getChild(i));
@@ -34,6 +37,14 @@ namespace BansheeEngine
 		return renderables;
 		return renderables;
 	}
 	}
 
 
+	void OctreeSceneManager::updateRenderableBounds()
+	{
+		for(auto& iter : mRenderables)
+		{
+			iter->updateWorldBounds();
+		}
+	}
+
 	void OctreeSceneManager::notifyComponentAdded(const HComponent& component)
 	void OctreeSceneManager::notifyComponentAdded(const HComponent& component)
 	{
 	{
 		if(component->getTypeId() == TID_Camera)
 		if(component->getTypeId() == TID_Camera)
@@ -48,6 +59,11 @@ namespace BansheeEngine
 
 
 			mCachedCameras.push_back(camera);
 			mCachedCameras.push_back(camera);
 		}
 		}
+		else if(component->getTypeId() == TID_Renderable)
+		{
+			HRenderable renderable = static_object_cast<Renderable>(component);
+			mRenderables.push_back(renderable);
+		}
 	}
 	}
 
 
 	void OctreeSceneManager::notifyComponentRemoved(const HComponent& component)
 	void OctreeSceneManager::notifyComponentRemoved(const HComponent& component)
@@ -64,5 +80,14 @@ namespace BansheeEngine
 
 
 			mCachedCameras.erase(findIter);
 			mCachedCameras.erase(findIter);
 		}
 		}
+		else if(component->getTypeId() == TID_Renderable)
+		{
+			HRenderable renderable = static_object_cast<Renderable>(component);
+
+			// TODO - I should probably use some for of a hash set because searching through possibly thousands of renderables will be slow
+			auto findIter = std::find(mRenderables.begin(), mRenderables.end(), renderable);
+			if(findIter != mRenderables.end())
+				mRenderables.erase(findIter);
+		}
 	}
 	}
 }
 }

+ 1 - 1
CamelotClient/CamelotClient.cpp

@@ -255,7 +255,7 @@ int CALLBACK WinMain(
 	//_ASSERT(_CrtCheckMemory());
 	//_ASSERT(_CrtCheckMemory());
 
 
 	testRenderable->setMesh(dbgMeshRef);
 	testRenderable->setMesh(dbgMeshRef);
-	testRenderable->setMaterial(testMaterial);
+	testRenderable->setMaterial(0, testMaterial);
 
 
 	//// Set the new state for the flag
 	//// Set the new state for the flag
 	//_CrtSetDbgFlag( tmpFlag );
 	//_CrtSetDbgFlag( tmpFlag );

+ 1 - 1
CamelotCore/CamelotCore.vcxproj

@@ -354,7 +354,7 @@
     <ClInclude Include="Include\CmRenderer.h" />
     <ClInclude Include="Include\CmRenderer.h" />
     <ClInclude Include="Include\CmRendererFactory.h" />
     <ClInclude Include="Include\CmRendererFactory.h" />
     <ClInclude Include="Include\CmRendererManager.h" />
     <ClInclude Include="Include\CmRendererManager.h" />
-    <ClInclude Include="Include\CmRenderOperation.h" />
+    <ClInclude Include="Include\CmRenderOpMesh.h" />
     <ClInclude Include="Include\CmRenderStateManager.h" />
     <ClInclude Include="Include\CmRenderStateManager.h" />
     <ClInclude Include="Include\CmRenderSystem.h" />
     <ClInclude Include="Include\CmRenderSystem.h" />
     <ClInclude Include="Include\CmRenderSystemCapabilities.h" />
     <ClInclude Include="Include\CmRenderSystemCapabilities.h" />

+ 3 - 3
CamelotCore/CamelotCore.vcxproj.filters

@@ -255,9 +255,6 @@
     <ClInclude Include="Include\CmSamplerState.h">
     <ClInclude Include="Include\CmSamplerState.h">
       <Filter>Header Files\RenderSystem</Filter>
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\CmRenderOperation.h">
-      <Filter>Header Files\RenderSystem</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmResourceHandle.h">
     <ClInclude Include="Include\CmResourceHandle.h">
       <Filter>Header Files\Resources</Filter>
       <Filter>Header Files\Resources</Filter>
     </ClInclude>
     </ClInclude>
@@ -459,6 +456,9 @@
     <ClInclude Include="Include\CmDeferredCallManager.h">
     <ClInclude Include="Include\CmDeferredCallManager.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmRenderOpMesh.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
     <ClCompile Include="Source\CmApplication.cpp">

+ 1 - 1
CamelotCore/Include/CmCoreThreadAccessor.h

@@ -197,7 +197,7 @@ namespace CamelotFramework
 
 
 
 
 		/** @copydoc RenderSystem::render() */
 		/** @copydoc RenderSystem::render() */
-		void render(const RenderOperation& op)
+		void render(const RenderOpMesh& op)
 		{
 		{
 			mCommandQueue->queue(boost::bind(&RenderSystem::render, RenderSystem::instancePtr(), op));
 			mCommandQueue->queue(boost::bind(&RenderSystem::render, RenderSystem::instancePtr(), op));
 		}
 		}

+ 1 - 1
CamelotCore/Include/CmGpuProgram.h

@@ -30,7 +30,7 @@ THE SOFTWARE.
 
 
 // Precompiler options
 // Precompiler options
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-#include "CmRenderOperation.h"
+#include "CmRenderOpMesh.h"
 #include "CmGpuProgramParams.h"
 #include "CmGpuProgramParams.h"
 #include "CmResource.h"
 #include "CmResource.h"
 #include "CmGpuParamDesc.h"
 #include "CmGpuParamDesc.h"

+ 1 - 1
CamelotCore/Include/CmGpuProgramParams.h

@@ -30,7 +30,7 @@ THE SOFTWARE.
 
 
 // Precompiler options
 // Precompiler options
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-#include "CmRenderOperation.h"
+#include "CmRenderOpMesh.h"
 #include "CmSamplerState.h"
 #include "CmSamplerState.h"
 
 
 namespace CamelotFramework {
 namespace CamelotFramework {

+ 3 - 0
CamelotCore/Include/CmMaterial.h

@@ -77,6 +77,7 @@ namespace CamelotFramework
 		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0);
 		void setMat3(const String& name, const Matrix3& value, UINT32 arrayIdx = 0);
 		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0);
 		void setMat4(const String& name, const Matrix4& value, UINT32 arrayIdx = 0);
 		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0);
 		void setStructData(const String& name, void* value, UINT32 size, UINT32 arrayIdx = 0);
+		void setRenderQueue(INT16 renderQueue) { mRenderQueue = renderQueue; }
 
 
 		//void setParamBlock(const String& name, GpuParamBlockPtr paramBlock);
 		//void setParamBlock(const String& name, GpuParamBlockPtr paramBlock);
 
 
@@ -89,6 +90,7 @@ namespace CamelotFramework
 		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const;
 		Matrix3 getMat3(const String& name, UINT32 arrayIdx = 0) const;
 		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const;
 		Matrix4 getMat4(const String& name, UINT32 arrayIdx = 0) const;
 		const StructData& getStructData(const String& name, UINT32 arrayIdx = 0) const;
 		const StructData& getStructData(const String& name, UINT32 arrayIdx = 0) const;
+		INT16 getRenderQueue() const { return mRenderQueue; }
 
 
 		UINT32 getNumPasses() const;
 		UINT32 getNumPasses() const;
 
 
@@ -106,6 +108,7 @@ namespace CamelotFramework
 
 
 		ShaderPtr mShader;
 		ShaderPtr mShader;
 		TechniquePtr mBestTechnique;
 		TechniquePtr mBestTechnique;
+		INT16 mRenderQueue;
 
 
 		Set<String>::type mValidShareableParamBlocks;
 		Set<String>::type mValidShareableParamBlocks;
 		Map<String, String>::type mValidParams; // Also maps Shader param name -> gpu variable name
 		Map<String, String>::type mValidParams; // Also maps Shader param name -> gpu variable name

+ 6 - 2
CamelotCore/Include/CmMesh.h

@@ -5,7 +5,7 @@
 #include "CmMeshData.h"
 #include "CmMeshData.h"
 #include "CmVertexData.h"
 #include "CmVertexData.h"
 #include "CmIndexData.h"
 #include "CmIndexData.h"
-#include "CmRenderOperation.h"
+#include "CmRenderOpMesh.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
@@ -58,7 +58,11 @@ namespace CamelotFramework
 		 */
 		 */
 		UINT32 mapToSubresourceIdx() const { return 0; }
 		UINT32 mapToSubresourceIdx() const { return 0; }
 
 
-		RenderOperation getRenderOperation(UINT32 subMeshIdx = 0) const;
+		RenderOpMesh getSubMeshData(UINT32 subMeshIdx = 0) const;
+		UINT32 getNumSubMeshes() const { return (UINT32)mSubMeshes.size(); }
+
+		const AABox& getBounds() const;
+		const AABox& getBounds(UINT32 submeshIdx) const;
 
 
 		/**
 		/**
 		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
 		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.

+ 1 - 1
CamelotCore/Include/CmPrerequisites.h

@@ -119,7 +119,7 @@ namespace CamelotFramework {
     class RenderTexture;
     class RenderTexture;
 	class MultiRenderTexture;
 	class MultiRenderTexture;
     class RenderWindow;
     class RenderWindow;
-    class RenderOperation;
+    struct RenderOpMesh;
     class StringInterface;
     class StringInterface;
     class SamplerState;
     class SamplerState;
     class TextureManager;
     class TextureManager;

+ 32 - 0
CamelotCore/Include/CmRenderOpMesh.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmVertexDeclaration.h"
+#include "CmVertexData.h"
+#include "CmIndexData.h"
+
+namespace CamelotFramework 
+{
+	enum DrawOperationType {
+		DOT_POINT_LIST = 1,
+		DOT_LINE_LIST = 2,
+		DOT_LINE_STRIP = 3,
+		DOT_TRIANGLE_LIST = 4,
+		DOT_TRIANGLE_STRIP = 5,
+		DOT_TRIANGLE_FAN = 6
+	};
+
+	struct RenderOpMesh
+	{
+		RenderOpMesh() 
+			:vertexData(nullptr), operationType(DOT_TRIANGLE_LIST), useIndexes(true),
+			indexData(nullptr) 
+		{ }
+
+		VertexData *vertexData;
+		IndexData *indexData;
+
+		DrawOperationType operationType;
+		bool useIndexes;
+	};
+}

+ 0 - 85
CamelotCore/Include/CmRenderOperation.h

@@ -1,85 +0,0 @@
-/*
------------------------------------------------------------------------------
-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.
------------------------------------------------------------------------------
-*/
-#pragma once
-
-#include "CmPrerequisites.h"
-#include "CmVertexDeclaration.h"
-#include "CmVertexData.h"
-#include "CmIndexData.h"
-
-namespace CamelotFramework 
-{
-	/// The rendering operation type to perform
-	enum DrawOperationType {
-		/// A list of points, 1 vertex per point
-		DOT_POINT_LIST = 1,
-		/// A list of lines, 2 vertices per line
-		DOT_LINE_LIST = 2,
-		/// A strip of connected lines, 1 vertex per line plus 1 start vertex
-		DOT_LINE_STRIP = 3,
-		/// A list of triangles, 3 vertices per triangle
-		DOT_TRIANGLE_LIST = 4,
-		/// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that 
-		DOT_TRIANGLE_STRIP = 5,
-		/// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
-		DOT_TRIANGLE_FAN = 6
-	};
-
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup RenderSystem
-	*  @{
-	*/
-	/** Rendering command that is used for rendering of a single object
-	 using a single pass */
-	class RenderOperation
-	{
-	public:
-		/// Vertex source data
-		VertexData *vertexData;
-
-		/// The type of operation to perform
-		DrawOperationType operationType;
-
-		/** Specifies whether to use indexes to determine the vertices to use as input. If false, the vertices are
-		 simply read in sequence to define the primitives. If true, indexes are used instead to identify vertices
-		 anywhere in the buffer, and allowing vertices to be used more than once.
-	   	 If true, then the indexBuffer, indexStart and numIndexes properties must be valid. */
-		bool useIndexes;
-
-		/// Index data - only valid if useIndexes is true
-		IndexData *indexData;
-
-        RenderOperation() :
-            vertexData(0), operationType(DOT_TRIANGLE_LIST), useIndexes(true),
-                indexData(0) {}
-	};
-	/** @} */
-	/** @} */
-}

+ 2 - 2
CamelotCore/Include/CmRenderSystem.h

@@ -39,7 +39,7 @@ THE SOFTWARE.
 #include "CmCommonEnums.h"
 #include "CmCommonEnums.h"
 
 
 #include "CmCommandQueue.h"
 #include "CmCommandQueue.h"
-#include "CmRenderOperation.h"
+#include "CmRenderOpMesh.h"
 #include "CmRenderSystemCapabilities.h"
 #include "CmRenderSystemCapabilities.h"
 #include "CmRenderTarget.h"
 #include "CmRenderTarget.h"
 #include "CmRenderTexture.h"
 #include "CmRenderTexture.h"
@@ -184,7 +184,7 @@ namespace CamelotFramework
 		 * 			It will automatically set up vertex declaration, draw operation, 
 		 * 			It will automatically set up vertex declaration, draw operation, 
 		 * 			vertex and index buffers and draw them.
 		 * 			vertex and index buffers and draw them.
 		 */
 		 */
-		virtual void render(const RenderOperation& op);
+		virtual void render(const RenderOpMesh& op);
 
 
 		/**
 		/**
 		 * @brief	Draw an object based on currently set
 		 * @brief	Draw an object based on currently set

+ 0 - 6
CamelotCore/Include/CmRenderer.h

@@ -14,11 +14,5 @@ namespace CamelotFramework
 		 * @brief	Renders all cameras.
 		 * @brief	Renders all cameras.
 		 */
 		 */
 		virtual void renderAll() = 0;
 		virtual void renderAll() = 0;
-
-		/**
-		 * @brief	 Renders the scene from the perspective of a single camera
-		 * 			 // TODO - Temporarily disabled since I moved Camera out of Camelot
-		 */
-		//virtual void render(const HCamera& camera) = 0;
 	};
 	};
 }
 }

+ 1 - 1
CamelotCore/Source/CmIndexData.cpp

@@ -3,7 +3,7 @@
 #include "CmVertexBuffer.h"
 #include "CmVertexBuffer.h"
 #include "CmIndexBuffer.h"
 #include "CmIndexBuffer.h"
 #include "CmVector3.h"
 #include "CmVector3.h"
-#include "CmAxisAlignedBox.h"
+#include "CmAABox.h"
 #include "CmException.h"
 #include "CmException.h"
 #include "CmRenderSystem.h"
 #include "CmRenderSystem.h"
 
 

+ 1 - 1
CamelotCore/Source/CmMaterial.cpp

@@ -16,7 +16,7 @@
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
 	Material::Material()
 	Material::Material()
-		:Resource(false)
+		:Resource(false), mRenderQueue(0)
 	{
 	{
 
 
 	}
 	}

+ 16 - 2
CamelotCore/Source/CmMesh.cpp

@@ -8,6 +8,7 @@
 #include "CmMeshManager.h"
 #include "CmMeshManager.h"
 #include "CmCoreThread.h"
 #include "CmCoreThread.h"
 #include "CmAsyncOp.h"
 #include "CmAsyncOp.h"
+#include "CmAABox.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
@@ -199,7 +200,7 @@ namespace CamelotFramework
 		return meshData;
 		return meshData;
 	}
 	}
 
 
-	RenderOperation Mesh::getRenderOperation(UINT32 subMeshIdx) const
+	RenderOpMesh Mesh::getSubMeshData(UINT32 subMeshIdx) const
 	{
 	{
 		if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
 		if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
 		{
 		{
@@ -208,7 +209,8 @@ namespace CamelotFramework
 		}
 		}
 
 
 		// TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing
 		// TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing
-		RenderOperation ro;
+		// TODO - Creating a RenderOpMesh each call might be excessive considering this will be called a few thousand times a frame
+		RenderOpMesh ro;
 		ro.indexData = mIndexData;
 		ro.indexData = mIndexData;
 		ro.vertexData = mVertexData;
 		ro.vertexData = mVertexData;
 		ro.useIndexes = true;
 		ro.useIndexes = true;
@@ -217,6 +219,18 @@ namespace CamelotFramework
 		return ro;
 		return ro;
 	}
 	}
 
 
+	const AABox& Mesh::getBounds() const
+	{
+		// TODO - Retrieve bounds for entire mesh (need to calculate them during creation)
+		return AABox::BOX_EMPTY;
+	}
+
+	const AABox& Mesh::getBounds(UINT32 submeshIdx) const
+	{
+		// TODO - Retrieve bounds a specific sub-mesh (need to calculate them during creation)
+		return AABox::BOX_EMPTY;
+	}
+
 	void Mesh::initialize_internal()
 	void Mesh::initialize_internal()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 1 - 1
CamelotCore/Source/CmRenderSystem.cpp

@@ -210,7 +210,7 @@ namespace CamelotFramework {
         return false;
         return false;
 	}
 	}
 
 
-	void RenderSystem::render(const RenderOperation& op)
+	void RenderSystem::render(const RenderOpMesh& op)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h

@@ -8,7 +8,7 @@
 #include "CmVertexData.h"
 #include "CmVertexData.h"
 #include "CmIndexData.h"
 #include "CmIndexData.h"
 #include "CmSamplerState.h"
 #include "CmSamplerState.h"
-#include "CmRenderOperation.h"
+#include "CmRenderOpMesh.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {

+ 2 - 2
CamelotUtility/CamelotUtility.vcxproj

@@ -292,7 +292,7 @@
     <ClInclude Include="Include\CmTimer.h" />
     <ClInclude Include="Include\CmTimer.h" />
     <ClInclude Include="Include\CmTypes.h" />
     <ClInclude Include="Include\CmTypes.h" />
     <ClInclude Include="Include\CmFwdDeclUtil.h" />
     <ClInclude Include="Include\CmFwdDeclUtil.h" />
-    <ClInclude Include="Include\CmAxisAlignedBox.h" />
+    <ClInclude Include="Include\CmAABox.h" />
     <ClInclude Include="Include\CmMath.h" />
     <ClInclude Include="Include\CmMath.h" />
     <ClInclude Include="Include\CmMatrix3.h" />
     <ClInclude Include="Include\CmMatrix3.h" />
     <ClInclude Include="Include\CmMatrix4.h" />
     <ClInclude Include="Include\CmMatrix4.h" />
@@ -320,7 +320,7 @@
     <ClInclude Include="Include\CmTexAtlasGenerator.h" />
     <ClInclude Include="Include\CmTexAtlasGenerator.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="Include\CmAxisAlignedBox.cpp" />
+    <ClCompile Include="Include\CmAABox.cpp" />
     <ClCompile Include="Source\CmColor.cpp" />
     <ClCompile Include="Source\CmColor.cpp" />
     <ClCompile Include="Source\CmDebug.cpp" />
     <ClCompile Include="Source\CmDebug.cpp" />
     <ClCompile Include="Source\CmDynLibManager.cpp" />
     <ClCompile Include="Source\CmDynLibManager.cpp" />

+ 6 - 6
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -69,9 +69,6 @@
     <ClInclude Include="Include\CmMathAsm.h">
     <ClInclude Include="Include\CmMathAsm.h">
       <Filter>Header Files\Math</Filter>
       <Filter>Header Files\Math</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\CmAxisAlignedBox.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmMath.h">
     <ClInclude Include="Include\CmMath.h">
       <Filter>Header Files\Math</Filter>
       <Filter>Header Files\Math</Filter>
     </ClInclude>
     </ClInclude>
@@ -219,11 +216,11 @@
     <ClInclude Include="Include\CmMemStack.h">
     <ClInclude Include="Include\CmMemStack.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmAABox.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="Include\CmAxisAlignedBox.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmMath.cpp">
     <ClCompile Include="Source\CmMath.cpp">
       <Filter>Source Files\Math</Filter>
       <Filter>Source Files\Math</Filter>
     </ClCompile>
     </ClCompile>
@@ -329,5 +326,8 @@
     <ClCompile Include="Source\CmMemStack.cpp">
     <ClCompile Include="Source\CmMemStack.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Include\CmAABox.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 266 - 0
CamelotUtility/Include/CmAABox.cpp

@@ -0,0 +1,266 @@
+#include "CmAABox.h"
+
+namespace CamelotFramework
+{
+	const AABox AABox::BOX_EMPTY;
+
+	AABox::AABox() 
+		:mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
+	{
+		// Default to a null box 
+		setMin(Vector3(-0.5f, -0.5f, -0.5f));
+		setMax(Vector3(0.5f, 0.5f, 0.5f));
+	}
+
+	AABox::AABox(const AABox & rkBox)
+		:mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
+	{
+		setExtents( rkBox.mMinimum, rkBox.mMaximum );
+	}
+
+	AABox::AABox(const Vector3& min, const Vector3& max)
+		:mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
+	{
+		setExtents( min, max );
+	}
+
+	AABox& AABox::operator=(const AABox& rhs)
+	{
+		setExtents(rhs.mMinimum, rhs.mMaximum);
+
+		return *this;
+	}
+
+	void AABox::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" );
+
+		mMinimum = min;
+		mMaximum = max;
+	}
+
+	Vector3 AABox::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();
+		}
+	}
+
+	void AABox::merge( const AABox& rhs )
+	{
+		Vector3 min = mMinimum;
+		Vector3 max = mMaximum;
+		max.makeCeil(rhs.mMaximum);
+		min.makeFloor(rhs.mMinimum);
+
+		setExtents(min, max);
+	}
+
+	void AABox::merge( const Vector3& point )
+	{
+		mMaximum.makeCeil(point);
+		mMinimum.makeFloor(point);
+	}
+
+	void AABox::transform( const Matrix4& matrix )
+	{
+		Vector3 oldMin, oldMax, currentCorner;
+
+		// Getting the old values so that we can use the existing merge method.
+		oldMin = mMinimum;
+		oldMax = mMaximum;
+
+		// 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 ); 
+	}
+
+	void AABox::transformAffine(const Matrix4& m)
+	{
+		assert(m.isAffine());
+
+		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);
+	}
+
+	bool AABox::intersects(const AABox& b2) const
+	{
+		// 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;
+	}
+
+	AABox AABox::intersection(const AABox& b2) const
+	{
+		Vector3 intMin = mMinimum;
+        Vector3 intMax = mMaximum;
+
+        intMin.makeCeil(b2.getMin());
+        intMax.makeFloor(b2.getMax());
+
+        // Check intersection isn't null
+        if (intMin.x < intMax.x &&
+            intMin.y < intMax.y &&
+            intMin.z < intMax.z)
+        {
+            return AABox(intMin, intMax);
+        }
+
+        return AABox();
+	}
+
+	float AABox::volume(void) const
+	{
+		Vector3 diff = mMaximum - mMinimum;
+		return diff.x * diff.y * diff.z;
+	}
+
+	void AABox::scale(const Vector3& s)
+	{
+		// NB assumes centered on origin
+		Vector3 min = mMinimum * s;
+		Vector3 max = mMaximum * s;
+		setExtents(min, max);
+	}
+
+	bool AABox::intersects(const Sphere& s) const
+	{
+		return Math::intersects(s, *this); 
+	}
+
+	bool AABox::intersects(const Plane& p) const
+	{
+		return Math::intersects(p, *this);
+	}
+
+	bool AABox::intersects(const Vector3& v) const
+	{
+		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);
+	}
+
+	Vector3 AABox::getCenter(void) const
+	{
+		return Vector3(
+			(mMaximum.x + mMinimum.x) * 0.5f,
+			(mMaximum.y + mMinimum.y) * 0.5f,
+			(mMaximum.z + mMinimum.z) * 0.5f);
+	}
+
+	Vector3 AABox::getSize(void) const
+	{
+		return mMaximum - mMinimum;
+	}
+
+	Vector3 AABox::getHalfSize(void) const
+	{
+		return (mMaximum - mMinimum) * 0.5;
+	}
+
+    bool AABox::contains(const Vector3& v) const
+    {
+        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;
+    }
+
+    bool AABox::contains(const AABox& other) const
+    {
+        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;
+    }
+
+    bool AABox::operator== (const AABox& rhs) const
+    {
+        return this->mMinimum == rhs.mMinimum &&
+                this->mMaximum == rhs.mMaximum;
+    }
+
+    bool AABox::operator!= (const AABox& rhs) const
+    {
+        return !(*this == rhs);
+    }
+}
+

+ 86 - 0
CamelotUtility/Include/CmAABox.h

@@ -0,0 +1,86 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+
+#include "CmVector3.h"
+#include "CmMatrix4.h"
+
+namespace CamelotFramework 
+{
+	class CM_UTILITY_EXPORT AABox
+	{
+	public:
+		/*
+		   1-----2
+		  /|    /|
+		 / |   / |
+		5-----4  |
+		|  0--|--3
+		| /   | /
+		|/    |/
+		6-----7
+		*/
+		typedef enum CornerEnum {
+			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
+		};
+
+		AABox();
+		AABox(const AABox & rkBox);
+		AABox(const Vector3& min, const Vector3& max);
+
+		AABox& operator=(const AABox& rhs);
+
+		~AABox() { }
+
+		const Vector3& getMin(void) const { return mMinimum; }
+		const Vector3& getMax(void) const { return mMaximum; }
+
+		void setMin(const Vector3& vec) { mMinimum = vec; }
+		void setMax(const Vector3& vec) { mMaximum = vec; }
+
+		void setExtents(const Vector3& min, const Vector3& max);
+
+		Vector3 getCorner(CornerEnum cornerToGet) const;
+
+		void merge(const AABox& rhs);
+		void merge(const Vector3& point);
+
+		void transform(const Matrix4& matrix);
+		void transformAffine(const Matrix4& matrix);
+
+		bool intersects(const AABox& b2) const;
+
+		AABox intersection(const AABox& b2) const;
+
+		float volume() const;
+
+		inline void scale(const Vector3& s);
+
+		bool intersects(const Sphere& s) const;
+		bool intersects(const Plane& p) const;
+		bool intersects(const Vector3& v) const;
+
+		Vector3 getCenter() const;
+		Vector3 getSize() const;
+		Vector3 getHalfSize() const;
+
+        bool contains(const Vector3& v) const;
+        bool contains(const AABox& other) const;
+
+        bool operator== (const AABox& rhs) const;
+        bool operator!= (const AABox& rhs) const;
+
+		static const AABox BOX_EMPTY;
+
+	protected:
+		Vector3 mMinimum;
+		Vector3 mMaximum;
+	};
+}

+ 0 - 35
CamelotUtility/Include/CmAxisAlignedBox.cpp

@@ -1,35 +0,0 @@
-/*
------------------------------------------------------------------------------
-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 "CmAxisAlignedBox.h"
-
-namespace CamelotFramework
-{
-	const AxisAlignedBox AxisAlignedBox::BOX_NULL;
-	const AxisAlignedBox AxisAlignedBox::BOX_INFINITE(AxisAlignedBox::EXTENT_INFINITE);
-}
-

+ 0 - 813
CamelotUtility/Include/CmAxisAlignedBox.h

@@ -1,813 +0,0 @@
-/*
------------------------------------------------------------------------------
-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 "CmPrerequisitesUtil.h"
-
-#include "CmVector3.h"
-#include "CmMatrix4.h"
-
-namespace CamelotFramework {
-	/** \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 CM_UTILITY_EXPORT 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(
-			float mx, float my, float mz,
-			float Mx, float My, float 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)
-				free(mpCorners);
-		}
-
-
-		/** 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( float x, float y, float 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(float x)
-		{
-			mMinimum.x = x;
-		}
-
-		inline void setMinimumY(float y)
-		{
-			mMinimum.y = y;
-		}
-
-		inline void setMinimumZ(float 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( float x, float y, float 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( float x )
-		{
-			mMaximum.x = x;
-		}
-
-		inline void setMaximumY( float y )
-		{
-			mMaximum.y = y;
-		}
-
-		inline void setMaximumZ( float 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(
-			float mx, float my, float mz,
-			float Mx, float My, float 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 Engine 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 = (Vector3*)malloc(sizeof(Vector3) * 8);
-
-			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();
-			}
-		}
-
-		CM_UTILITY_EXPORT 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
-		float 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 CamelotFramework
-
-#endif

+ 1 - 1
CamelotUtility/Include/CmFwdDeclUtil.h

@@ -5,7 +5,7 @@ namespace CamelotFramework {
 	// Allows use of pointers in header files without including individual .h
 	// Allows use of pointers in header files without including individual .h
 	// so decreases dependencies between files
 	// so decreases dependencies between files
 	class Angle;
 	class Angle;
-	class AxisAlignedBox;
+	class AABox;
 	class Degree;
 	class Degree;
 	class Math;
 	class Math;
 	class Matrix3;
 	class Matrix3;

+ 5 - 5
CamelotUtility/Include/CmMath.h

@@ -438,7 +438,7 @@ namespace CamelotFramework
             bool discardInside = true);
             bool discardInside = true);
         
         
         /** Ray / box intersection, returns boolean result and distance. */
         /** Ray / box intersection, returns boolean result and distance. */
-        static std::pair<bool, float> intersects(const Ray& ray, const AxisAlignedBox& box);
+        static std::pair<bool, float> intersects(const Ray& ray, const AABox& box);
 
 
         /** Ray / box intersection, returns boolean result and two intersection distance.
         /** Ray / box intersection, returns boolean result and two intersection distance.
         @param
         @param
@@ -462,7 +462,7 @@ namespace CamelotFramework
             If the ray isn't intersects the box, <b>false</b> is returned, and
             If the ray isn't intersects the box, <b>false</b> is returned, and
             <i>d1</i> and <i>d2</i> is unmodified.
             <i>d1</i> and <i>d2</i> is unmodified.
         */
         */
-        static bool intersects(const Ray& ray, const AxisAlignedBox& box,
+        static bool intersects(const Ray& ray, const AABox& box,
             float* d1, float* d2);
             float* d1, float* d2);
 
 
         /** Ray / triangle intersection, returns boolean result and distance.
         /** Ray / triangle intersection, returns boolean result and distance.
@@ -518,10 +518,10 @@ namespace CamelotFramework
             bool positiveSide = true, bool negativeSide = true);
             bool positiveSide = true, bool negativeSide = true);
 
 
         /** Sphere / box intersection test. */
         /** Sphere / box intersection test. */
-        static bool intersects(const Sphere& sphere, const AxisAlignedBox& box);
+        static bool intersects(const Sphere& sphere, const AABox& box);
 
 
         /** Plane / box intersection test. */
         /** Plane / box intersection test. */
-        static bool intersects(const Plane& plane, const AxisAlignedBox& box);
+        static bool intersects(const Plane& plane, const AABox& box);
 
 
         /** Ray / convex plane list intersection test. 
         /** Ray / convex plane list intersection test. 
         @param ray The ray to test with
         @param ray The ray to test with
@@ -590,7 +590,7 @@ namespace CamelotFramework
 			const Matrix4* reflectMatrix = 0);
 			const Matrix4* reflectMatrix = 0);
 
 
 		/** Get a bounding radius value from a bounding box. */
 		/** Get a bounding radius value from a bounding box. */
-		static float boundingRadiusFromAABB(const AxisAlignedBox& aabb);
+		static float boundingRadiusFromAABB(const AABox& aabb);
 
 
 
 
 
 

+ 1 - 1
CamelotUtility/Include/CmPlane.h

@@ -91,7 +91,7 @@ namespace CamelotFramework {
         Returns the side where the alignedBox is. The flag BOTH_SIDE indicates an intersecting box.
         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.
         One corner ON the plane is sufficient to consider the box and the plane intersecting.
         */
         */
-        Side getSide (const AxisAlignedBox& rkBox) const;
+        Side getSide (const AABox& rkBox) const;
 
 
         /** Returns which side of the plane that the given box lies on.
         /** Returns which side of the plane that the given box lies on.
             The box is defined as centre/half-size pairs for effectively.
             The box is defined as centre/half-size pairs for effectively.

+ 1 - 1
CamelotUtility/Include/CmRay.h

@@ -98,7 +98,7 @@ namespace CamelotFramework {
 			indicate the distance along the ray at which it intersects. 
 			indicate the distance along the ray at which it intersects. 
 			This can be converted to a point in space by calling getPoint().
 			This can be converted to a point in space by calling getPoint().
 		*/
 		*/
-		std::pair<bool, float> intersects(const AxisAlignedBox& box) const
+		std::pair<bool, float> intersects(const AABox& box) const
 		{
 		{
 			return Math::intersects(*this, box);
 			return Math::intersects(*this, box);
 		}
 		}

+ 1 - 1
CamelotUtility/Include/CmSphere.h

@@ -82,7 +82,7 @@ namespace CamelotFramework {
                 Math::Sqr(s.mRadius + mRadius);
                 Math::Sqr(s.mRadius + mRadius);
 		}
 		}
 		/** Returns whether or not this sphere intersects a box. */
 		/** Returns whether or not this sphere intersects a box. */
-		bool intersects(const AxisAlignedBox& box) const
+		bool intersects(const AABox& box) const
 		{
 		{
 			return Math::intersects(*this, box);
 			return Math::intersects(*this, box);
 		}
 		}

+ 14 - 30
CamelotUtility/Source/CmMath.cpp

@@ -32,7 +32,7 @@ THE SOFTWARE.
 #include "CmVector4.h"
 #include "CmVector4.h"
 #include "CmRay.h"
 #include "CmRay.h"
 #include "CmSphere.h"
 #include "CmSphere.h"
-#include "CmAxisAlignedBox.h"
+#include "CmAABox.h"
 #include "CmPlane.h"
 #include "CmPlane.h"
 
 
 
 
@@ -484,17 +484,14 @@ namespace CamelotFramework
 
 
     }
     }
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-	std::pair<bool, float> Math::intersects(const Ray& ray, const AxisAlignedBox& box)
+	std::pair<bool, float> Math::intersects(const Ray& ray, const AABox& box)
 	{
 	{
-		if (box.isNull()) return std::pair<bool, float>(false, 0.0f);
-		if (box.isInfinite()) return std::pair<bool, float>(true, 0.0f);
-
 		float lowt = 0.0f;
 		float lowt = 0.0f;
 		float t;
 		float t;
 		bool hit = false;
 		bool hit = false;
 		Vector3 hitpoint;
 		Vector3 hitpoint;
-		const Vector3& min = box.getMinimum();
-		const Vector3& max = box.getMaximum();
+		const Vector3& min = box.getMin();
+		const Vector3& max = box.getMax();
 		const Vector3& rayorig = ray.getOrigin();
 		const Vector3& rayorig = ray.getOrigin();
 		const Vector3& raydir = ray.getDirection();
 		const Vector3& raydir = ray.getDirection();
 
 
@@ -612,21 +609,11 @@ namespace CamelotFramework
 
 
 	} 
 	} 
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-    bool Math::intersects(const Ray& ray, const AxisAlignedBox& box,
+    bool Math::intersects(const Ray& ray, const AABox& box,
         float* d1, float* d2)
         float* d1, float* 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& min = box.getMin();
+        const Vector3& max = box.getMax();
         const Vector3& rayorig = ray.getOrigin();
         const Vector3& rayorig = ray.getOrigin();
         const Vector3& raydir = ray.getDirection();
         const Vector3& raydir = ray.getDirection();
 
 
@@ -801,16 +788,13 @@ namespace CamelotFramework
         return intersects(ray, a, b, c, normal, positiveSide, negativeSide);
         return intersects(ray, a, b, c, normal, positiveSide, negativeSide);
     }
     }
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-    bool Math::intersects(const Sphere& sphere, const AxisAlignedBox& box)
+    bool Math::intersects(const Sphere& sphere, const AABox& box)
     {
     {
-        if (box.isNull()) return false;
-        if (box.isInfinite()) return true;
-
         // Use splitting planes
         // Use splitting planes
         const Vector3& center = sphere.getCenter();
         const Vector3& center = sphere.getCenter();
         float radius = sphere.getRadius();
         float radius = sphere.getRadius();
-        const Vector3& min = box.getMinimum();
-        const Vector3& max = box.getMaximum();
+        const Vector3& min = box.getMin();
+        const Vector3& max = box.getMax();
 
 
 		// Arvo's algorithm
 		// Arvo's algorithm
 		float s, d = 0;
 		float s, d = 0;
@@ -831,7 +815,7 @@ namespace CamelotFramework
 
 
     }
     }
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-    bool Math::intersects(const Plane& plane, const AxisAlignedBox& box)
+    bool Math::intersects(const Plane& plane, const AABox& box)
     {
     {
         return (plane.getSide(box) == Plane::BOTH_SIDE);
         return (plane.getSide(box) == Plane::BOTH_SIDE);
     }
     }
@@ -966,10 +950,10 @@ namespace CamelotFramework
 
 
 	}
 	}
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
-	float Math::boundingRadiusFromAABB(const AxisAlignedBox& aabb)
+	float Math::boundingRadiusFromAABB(const AABox& aabb)
 	{
 	{
-		Vector3 max = aabb.getMaximum();
-		Vector3 min = aabb.getMinimum();
+		Vector3 max = aabb.getMax();
+		Vector3 min = aabb.getMin();
 
 
 		Vector3 magnitude = max;
 		Vector3 magnitude = max;
 		magnitude.makeCeil(-max);
 		magnitude.makeCeil(-max);

+ 2 - 7
CamelotUtility/Source/CmPlane.cpp

@@ -28,7 +28,7 @@ THE SOFTWARE.
 
 
 #include "CmPlane.h"
 #include "CmPlane.h"
 #include "CmMatrix3.h"
 #include "CmMatrix3.h"
-#include "CmAxisAlignedBox.h" 
+#include "CmAABox.h" 
 
 
 namespace CamelotFramework {
 namespace CamelotFramework {
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
@@ -86,13 +86,8 @@ namespace CamelotFramework {
 
 
 
 
 	//-----------------------------------------------------------------------
 	//-----------------------------------------------------------------------
-	Plane::Side Plane::getSide (const AxisAlignedBox& box) const
+	Plane::Side Plane::getSide (const AABox& box) const
 	{
 	{
-		if (box.isNull()) 
-			return NO_SIDE;
-		if (box.isInfinite())
-			return BOTH_SIDE;
-
         return getSide(box.getCenter(), box.getHalfSize());
         return getSide(box.getCenter(), box.getHalfSize());
 	}
 	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------

+ 21 - 0
DrawHelper.txt

@@ -0,0 +1,21 @@
+Add class DrawHelper:
+ - Line2D_AA - Creates an emulated AA line using triangles. See Recast/imguiRenderGL::drawPolygon for implementation. Line vertices and colors
+      are appended in the specified buffer. No actual drawing is done.
+ - Line2D_Pixel - Creates a simple line using LINE primitive topology. Line vertices and colors are appended in the specified buffer.
+ - Quad2D
+ - QuadBorder2D_AA
+ - QuadBorder2D_Pixel
+ - Polygon2D
+ - PolygonBorder2D_AA
+ - PolygonBorder2D_Pixel
+ - LineList2D_AA
+ - LineList2D_Pixel
+ - RoundedRect2D - Also copy from Recast/imguiRenderGL::drawRoundedRect
+ - Also 3D equivalents
+  - Line, Quad, QuadBorder, Box, BoxBorder
+
+ - Then I also need draw* equivalents of those methods. draw equivalents will also create the buffer and submit the draw call.
+   - draw equivalents accept a time for how long to display the element, if 0 it will only be displayed for one frame
+   - all elements should be grouped into a common vertex/index buffer (as much as possible)
+   - draw methods should combine methods above to make drawing easier. e.g. a transparent box with AA line borders should be easily drawable
+

+ 23 - 0
PlatformPorting.txt

@@ -0,0 +1,23 @@
+Make porting to other platforms easier. Move platform specific files into their own /Platform subfolder.
+Reduce use of CM_PLATFORM where possible
+Split class into different files per-platform where possible
+
+GLRenderer
+ - Win32Window
+ - Win32Prerequisites
+ - Win32Context
+ - Win32GLSupport
+ - GLPRerequisities - different includes are added depending on platform 
+
+Utility
+ - Timer
+ - DynLibManager (currently has everything in one file, need to split it up)
+ - FileSystem - has some OS specific functionality
+
+Core
+ - Cursor - Also move to Utility?
+ - WindowEventUtilities - Rename the class, also split it into separate files per platform
+ - Application::loadPlugin - uses different extensions based on platform. Move platform specific functionality outside?
+
+Search for all occurencess of CM_PLATFORM
+ - Although in all other cases use of CM_PLATFORM can be removed, or is justified

+ 37 - 0
RenderOperation.txt

@@ -0,0 +1,37 @@
+Since DrawHelper needs to queue render commands together with scene objects (in order for transparency to work okay), I will need to implement the RenderOperation approach I thought about earlier.
+ Rename current RenderOperation to SubMeshData
+ Real render operations contains SubMeshData + layer (can be filtered per-camera) + queue (each mesh has a queue and another queue by camera) + Pass
+ (Remove Camera->rendersSceneObjects and replace it with layer)
+ (Make sure to set up preset queues, like opaque, transparent, etc)
+
+ Then I can hook up GUIManager, OverlayManager and DrawHelper with a callback that is used by Renderer to retrieve their operations
+ Attempt to move all sorting (including by render target) out of forward renderer and into an overridable sorter class
+  - Create a hash list with key(containing type, queue, layer, etc.) used for sorting
+
+  Add "materialGroup" to material. It can be used for sorting similar materials together, instead of using some automatic way of determining it.
+
+  Issues with my render operation system:
+ Sorting by depth is impossible because I don't provide any position info with my RenderOperation
+
+ For each frame I will need to calculate world bounds and world position. I cannot do it each time I retrieve a RenderOperation so it should be cached somewhere and reused throughout the frame.
+ - Unity keeps it with Renderable
+   - What happens when the Mesh resource is updated?
+ - How do I do it for non-renerables though?
+
+ ---------------------
+
+ RenderOpSorter:
+ - (Before we send RenderOps to the sorter we first filter them by camera)
+ - Accepts parameters whether to sort back-to-front, front-to-back or ignore depth (depth ignored with skybox and overlay)
+ - Another parameter is whether to sort by pass (transparent ops can't be sorted by pass)
+ - Then we sort:
+  - If back to front
+    - We sort by depth and that's it. We could also sort by material by that only makes sense if two elements have exact same depth which will almost never happen
+  - If front to back
+    - Sort by material first. We call materialSimilarity() method which returns lesser value depending how similar two materials are. We do a pass over all unsorted materials and if similarity is below some threshold we add it to the current bucket. If there are no more similar materials we create a new bucket.
+    - Within bucket we sort by similarity as well (as the elements are added)
+    - Then finally we sort the buckets by depth front to back
+  - No depth
+   - Same as front to back, without the depth sort
+
+ - Sorter should operate directly on provided render op array