Selaa lähdekoodia

Preparing documentation for doxygen generation

BearishSun 10 vuotta sitten
vanhempi
sitoutus
51aa754927
34 muutettua tiedostoa jossa 5771 lisäystä ja 5932 poistoa
  1. 293 293
      BansheeCore/Include/BsInput.h
  2. 3 3
      BansheeUtility/BansheeUtility.vcxproj
  3. 544 502
      BansheeUtility/BansheeUtility.vcxproj.filters
  4. 140 157
      BansheeUtility/Include/BsAABox.h
  5. 39 35
      BansheeUtility/Include/BsBitmapWriter.h
  6. 67 71
      BansheeUtility/Include/BsBounds.h
  7. 41 41
      BansheeUtility/Include/BsCapsule.h
  8. 38 37
      BansheeUtility/Include/BsConvexVolume.h
  9. 36 29
      BansheeUtility/Include/BsDebug.h
  10. 74 64
      BansheeUtility/Include/BsDegree.h
  11. 109 106
      BansheeUtility/Include/BsFwdDeclUtil.h
  12. 38 40
      BansheeUtility/Include/BsLineSegment3.h
  13. 26 32
      BansheeUtility/Include/BsLog.h
  14. 575 594
      BansheeUtility/Include/BsMath.h
  15. 296 322
      BansheeUtility/Include/BsMatrix3.h
  16. 465 494
      BansheeUtility/Include/BsMatrix4.h
  17. 87 85
      BansheeUtility/Include/BsMatrixNxM.h
  18. 92 102
      BansheeUtility/Include/BsPlane.h
  19. 101 73
      BansheeUtility/Include/BsPrerequisitesUtil.h
  20. 62 81
      BansheeUtility/Include/BsQuaternion.h
  21. 614 642
      BansheeUtility/Include/BsRTTIPrerequisites.h
  22. 74 64
      BansheeUtility/Include/BsRadian.h
  23. 80 89
      BansheeUtility/Include/BsRay.h
  24. 61 65
      BansheeUtility/Include/BsRect2.h
  25. 70 77
      BansheeUtility/Include/BsRect2I.h
  26. 71 76
      BansheeUtility/Include/BsRect3.h
  27. 81 101
      BansheeUtility/Include/BsSphere.h
  28. 192 167
      BansheeUtility/Include/BsStdHeaders.h
  29. 30 27
      BansheeUtility/Include/BsTorus.h
  30. 371 407
      BansheeUtility/Include/BsVector2.h
  31. 199 204
      BansheeUtility/Include/BsVector2I.h
  32. 450 499
      BansheeUtility/Include/BsVector3.h
  33. 284 288
      BansheeUtility/Include/BsVector4.h
  34. 68 65
      BansheeUtility/Include/BsVectorNI.h

+ 293 - 293
BansheeCore/Include/BsInput.h

@@ -1,294 +1,294 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsRect2I.h"
-#include "BsOSInputHandler.h"
-#include "BsRawInputHandler.h"
-#include "BsInputFwd.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Primary module used for dealing with input. Allows you to receieve 
-	 *			and query raw or OS input for mouse/keyboard/gamepad.
-	 *
-	 *			All inputs are received through an input handler, which can be overriden to 
-	 *			provide custom input functionality.
-	 */
-	class BS_CORE_EXPORT Input : public Module<Input>
-	{
-		/**
-		 * @brief	Possible button states
-		 */
-		enum class ButtonState
-		{
-			Off, /**< Button is not being pressed. */
-			On, /**< Button is being pressed. */
-			ToggledOn, /**< Button has been pressed this frame. */
-			ToggledOff, /**< Button has been released this frame. */
-			ToggledOnOff, /**< Button has been pressed and released this frame. */
-		};
-
-		/**
-		 * @brief	Contains axis and device data per device
-		 */
-		struct DeviceData
-		{
-			DeviceData();
-
-			Vector<RawAxisState> axes;
-			ButtonState keyStates[BC_Count];
-		};
-
-		/**
-		 * @brief	Different types of possible input event callbacks.
-		 */
-		enum class EventType
-		{
-			ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command
-		};
-
-		/**
-		 * @brief	Stores information about a queued input event that is to be triggered later.
-		 */
-		struct QueuedEvent
-		{
-			QueuedEvent(EventType type, UINT32 idx)
-				:type(type), idx(idx)
-			{ }
-
-			EventType type;
-			UINT32 idx;
-		};
-
-	public:
-		Input();
-		~Input();
-
-		/**
-		 * @brief	Triggered whenever a button is first pressed.
-		 */
-		Event<void(const ButtonEvent&)> onButtonDown;
-
-		/**
-		 * @brief	Triggered whenever a button is first released.
-		 */
-		Event<void(const ButtonEvent&)> onButtonUp;
-
-		/**
-		 * @brief	Triggered whenever user inputs a text character. 
-		 */
-		Event<void(const TextInputEvent&)> onCharInput;
-
-		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) moves.
-		 */
-		Event<void(const PointerEvent&)> onPointerMoved;
-
-		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is pressed.
-		 */
-		Event<void(const PointerEvent&)> onPointerPressed;
-
-		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is released.
-		 */
-		Event<void(const PointerEvent&)> onPointerReleased;
-
-		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is double clicked.
-		 */
-		Event<void(const PointerEvent&)> onPointerDoubleClick;
-
-		// TODO Low priority: Remove this, I can emulate it using virtual input
-		/**
-		 * @brief	Triggers on special input commands.
-		 */
-		Event<void(InputCommandType)> onInputCommand;
-
-		/**
-		 * @brief	Registers a new input handler. Replaces any previous input handler.
-		 *
-		 * @note	Internal method.
-		 */
-		void _registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler);
-
-		/**
-		 * @brief	Called every frame. Detects button state changes and prepares callback events to trigger
-		 *			via a call to "_triggerCallbacks".
-		 *
-		 * @note	Internal method.
-		 */
-		void _update();
-
-		/**
-		 * @brief	Triggers any queued input event callbacks.
-		 */
-		void _triggerCallbacks();
-
-		/**
-		 * @brief	Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside
-		 *			the range for devices with unbound axes (e.g. mouse).
-		 *
-		 * @param	type		Type of axis to query. Usually a type from InputAxis but can be a custom value.
-		 * @param	deviceIdx	Index of the device in case more than one is hooked up (0 - primary).
-		 */
-		float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Query if the provided button is currently being held (this frame or previous frames).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Query if the provided button is currently being released (only true for one frame).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Query if the provided button is currently being pressed (only true for one frame).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Returns position of the pointer (e.g. mouse cursor) relative to the screen.
-		 */
-		Vector2I getPointerPosition() const;
-
-		/**
-		 * @brief	Returns difference between last and current pointer position.
-		 */
-		Vector2I getPointerDelta() const { return mPointerDelta; }
-
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being held (this frame or previous frames).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonHeld(PointerEventButton pointerButton) const;
-
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being released (only true for one frame).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonUp(PointerEventButton pointerButton) const;
-
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being pressed (only true for one frame).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonDown(PointerEventButton pointerButton) const;
-
-		/**
-		 * @brief	Query has the left pointer button has been 
-		 *			double-clicked this frame.
-		 */
-		bool isPointerDoubleClicked() const;
-
-		/**
-		 * @brief	Enables or disables mouse smoothing. Smoothing makes the changes to
-		 *			mouse axes more gradual.
-		 */
-		void setMouseSmoothing(bool enabled);
-
-	private:
-		/**
-		 * @brief	Triggered by input handler when a button is pressed.
-		 */
-		void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
-
-		/**
-		 * @brief	Triggered by input handler when a button is released.
-		 */
-		void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
-
-		/**
-		 * @brief	Triggered by input handler when a single character is input.
-		 */
-		void charInput(UINT32 chr);
-
-		/**
-		 * @brief	Triggered by input handler when a mouse/joystick axis is moved.
-		 */
-		void axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis);
-
-		/**
-		 * @brief	Cursor movement as OS reports it. Used for screen cursor position.
-		 */
-		void cursorMoved(const PointerEvent& event);
-
-		/**
-		 * @brief	Cursor button presses as OS reports it. 
-		 */
-		void cursorPressed(const PointerEvent& event);
-
-		/**
-		 * @brief	Cursor button releases as OS reports it.
-		 */
-		void cursorReleased(const PointerEvent& event);
-		
-		/**
-		 * @brief	Cursor button releases as OS reports it.
-		 */
-		void cursorDoubleClick(const PointerEvent& event);
-
-		/**
-		 * @brief	Input commands as OS reports them.
-		 */
-		void inputCommandEntered(InputCommandType commandType);
-
-		/**
-		 * @brief	Called when window in focus changes, as reported by the OS.
-		 */
-		void inputWindowChanged(RenderWindow& win);
-
-	private:
-		std::shared_ptr<RawInputHandler> mRawInputHandler;
-		std::shared_ptr<OSInputHandler> mOSInputHandler;
-
-		Vector<DeviceData> mDevices;
-		Vector2I mPointerPosition;
-		Vector2I mPointerDelta;
-		ButtonState mPointerButtonStates[3];
-		bool mPointerDoubleClicked;
-		bool mLastPositionSet;
-
-		Vector<QueuedEvent> mQueuedEvents;
-
-		Vector<TextInputEvent> mTextInputEvents;
-		Vector<InputCommandType> mCommandEvents;
-		Vector<PointerEvent> mPointerDoubleClickEvents;
-		Vector<PointerEvent> mPointerReleasedEvents;
-		Vector<PointerEvent> mPointerPressedEvents;
-		Vector<PointerEvent> mPointerMovedEvents;
-
-		Vector<ButtonEvent> mButtonDownEvents;
-		Vector<ButtonEvent> mButtonUpEvents;
-
-		/************************************************************************/
-		/* 								STATICS		                      		*/
-		/************************************************************************/
-		static const int HISTORY_BUFFER_SIZE; // Size of buffer used for input smoothing
-		static const float WEIGHT_MODIFIER;
-	};
-
-	/**
-	 * @copydoc	Input
-	 */
-	BS_CORE_EXPORT Input& gInput();
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsRect2I.h"
+#include "BsOSInputHandler.h"
+#include "BsRawInputHandler.h"
+#include "BsInputFwd.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Primary module used for dealing with input. Allows you to receieve 
+	 *			and query raw or OS input for mouse/keyboard/gamepad.
+	 *
+	 *			All inputs are received through an input handler, which can be overriden to 
+	 *			provide custom input functionality.
+	 */
+	class BS_CORE_EXPORT Input : public Module<Input>
+	{
+		/**
+		 * @brief	Possible button states
+		 */
+		enum class ButtonState
+		{
+			Off, /**< Button is not being pressed. */
+			On, /**< Button is being pressed. */
+			ToggledOn, /**< Button has been pressed this frame. */
+			ToggledOff, /**< Button has been released this frame. */
+			ToggledOnOff, /**< Button has been pressed and released this frame. */
+		};
+
+		/**
+		 * @brief	Contains axis and device data per device
+		 */
+		struct DeviceData
+		{
+			DeviceData();
+
+			Vector<RawAxisState> axes;
+			ButtonState keyStates[BC_Count];
+		};
+
+		/**
+		 * @brief	Different types of possible input event callbacks.
+		 */
+		enum class EventType
+		{
+			ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command
+		};
+
+		/**
+		 * @brief	Stores information about a queued input event that is to be triggered later.
+		 */
+		struct QueuedEvent
+		{
+			QueuedEvent(EventType type, UINT32 idx)
+				:type(type), idx(idx)
+			{ }
+
+			EventType type;
+			UINT32 idx;
+		};
+
+	public:
+		Input();
+		~Input();
+
+		/**
+		 * @brief	Triggered whenever a button is first pressed.
+		 */
+		Event<void(const ButtonEvent&)> onButtonDown;
+
+		/**
+		 * @brief	Triggered whenever a button is first released.
+		 */
+		Event<void(const ButtonEvent&)> onButtonUp;
+
+		/**
+		 * @brief	Triggered whenever user inputs a text character. 
+		 */
+		Event<void(const TextInputEvent&)> onCharInput;
+
+		/**
+		 * @brief	Triggers when some pointing device (mouse cursor, touch) moves.
+		 */
+		Event<void(const PointerEvent&)> onPointerMoved;
+
+		/**
+		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is pressed.
+		 */
+		Event<void(const PointerEvent&)> onPointerPressed;
+
+		/**
+		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is released.
+		 */
+		Event<void(const PointerEvent&)> onPointerReleased;
+
+		/**
+		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is double clicked.
+		 */
+		Event<void(const PointerEvent&)> onPointerDoubleClick;
+
+		// TODO Low priority: Remove this, I can emulate it using virtual input
+		/**
+		 * @brief	Triggers on special input commands.
+		 */
+		Event<void(InputCommandType)> onInputCommand;
+
+		/**
+		 * @brief	Registers a new input handler. Replaces any previous input handler.
+		 *
+		 * @note	Internal method.
+		 */
+		void _registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler);
+
+		/**
+		 * @brief	Called every frame. Detects button state changes and prepares callback events to trigger
+		 *			via a call to _triggerCallbacks().
+		 *
+		 * @note	Internal method.
+		 */
+		void _update();
+
+		/**
+		 * @brief	Triggers any queued input event callbacks.
+		 */
+		void _triggerCallbacks();
+
+		/**
+		 * @brief	Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside
+		 *			the range for devices with unbound axes (e.g. mouse).
+		 *
+		 * @param	type		Type of axis to query. Usually a type from InputAxis but can be a custom value.
+		 * @param	deviceIdx	Index of the device in case more than one is hooked up (0 - primary).
+		 */
+		float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * @brief	Query if the provided button is currently being held (this frame or previous frames).
+		 *
+		 * @param	keyCode		Code of the button to query.
+		 * @param	deviceIdx	Device to query the button on (0 - primary).
+		 */
+		bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * @brief	Query if the provided button is currently being released (only true for one frame).
+		 *
+		 * @param	keyCode		Code of the button to query.
+		 * @param	deviceIdx	Device to query the button on (0 - primary).
+		 */
+		bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * @brief	Query if the provided button is currently being pressed (only true for one frame).
+		 *
+		 * @param	keyCode		Code of the button to query.
+		 * @param	deviceIdx	Device to query the button on (0 - primary).
+		 */
+		bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * @brief	Returns position of the pointer (e.g. mouse cursor) relative to the screen.
+		 */
+		Vector2I getPointerPosition() const;
+
+		/**
+		 * @brief	Returns difference between last and current pointer position.
+		 */
+		Vector2I getPointerDelta() const { return mPointerDelta; }
+
+		/**
+		 * @brief	Query if the provided pointer button is currently 
+		 *			being held (this frame or previous frames).
+		 *
+		 * @param	pointerButton		Code of the button to query.
+		 */
+		bool isPointerButtonHeld(PointerEventButton pointerButton) const;
+
+		/**
+		 * @brief	Query if the provided pointer button is currently 
+		 *			being released (only true for one frame).
+		 *
+		 * @param	pointerButton		Code of the button to query.
+		 */
+		bool isPointerButtonUp(PointerEventButton pointerButton) const;
+
+		/**
+		 * @brief	Query if the provided pointer button is currently 
+		 *			being pressed (only true for one frame).
+		 *
+		 * @param	pointerButton		Code of the button to query.
+		 */
+		bool isPointerButtonDown(PointerEventButton pointerButton) const;
+
+		/**
+		 * @brief	Query has the left pointer button has been 
+		 *			double-clicked this frame.
+		 */
+		bool isPointerDoubleClicked() const;
+
+		/**
+		 * @brief	Enables or disables mouse smoothing. Smoothing makes the changes to
+		 *			mouse axes more gradual.
+		 */
+		void setMouseSmoothing(bool enabled);
+
+	private:
+		/**
+		 * @brief	Triggered by input handler when a button is pressed.
+		 */
+		void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
+
+		/**
+		 * @brief	Triggered by input handler when a button is released.
+		 */
+		void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
+
+		/**
+		 * @brief	Triggered by input handler when a single character is input.
+		 */
+		void charInput(UINT32 chr);
+
+		/**
+		 * @brief	Triggered by input handler when a mouse/joystick axis is moved.
+		 */
+		void axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis);
+
+		/**
+		 * @brief	Cursor movement as OS reports it. Used for screen cursor position.
+		 */
+		void cursorMoved(const PointerEvent& event);
+
+		/**
+		 * @brief	Cursor button presses as OS reports it. 
+		 */
+		void cursorPressed(const PointerEvent& event);
+
+		/**
+		 * @brief	Cursor button releases as OS reports it.
+		 */
+		void cursorReleased(const PointerEvent& event);
+		
+		/**
+		 * @brief	Cursor button releases as OS reports it.
+		 */
+		void cursorDoubleClick(const PointerEvent& event);
+
+		/**
+		 * @brief	Input commands as OS reports them.
+		 */
+		void inputCommandEntered(InputCommandType commandType);
+
+		/**
+		 * @brief	Called when window in focus changes, as reported by the OS.
+		 */
+		void inputWindowChanged(RenderWindow& win);
+
+	private:
+		std::shared_ptr<RawInputHandler> mRawInputHandler;
+		std::shared_ptr<OSInputHandler> mOSInputHandler;
+
+		Vector<DeviceData> mDevices;
+		Vector2I mPointerPosition;
+		Vector2I mPointerDelta;
+		ButtonState mPointerButtonStates[3];
+		bool mPointerDoubleClicked;
+		bool mLastPositionSet;
+
+		Vector<QueuedEvent> mQueuedEvents;
+
+		Vector<TextInputEvent> mTextInputEvents;
+		Vector<InputCommandType> mCommandEvents;
+		Vector<PointerEvent> mPointerDoubleClickEvents;
+		Vector<PointerEvent> mPointerReleasedEvents;
+		Vector<PointerEvent> mPointerPressedEvents;
+		Vector<PointerEvent> mPointerMovedEvents;
+
+		Vector<ButtonEvent> mButtonDownEvents;
+		Vector<ButtonEvent> mButtonUpEvents;
+
+		/************************************************************************/
+		/* 								STATICS		                      		*/
+		/************************************************************************/
+		static const int HISTORY_BUFFER_SIZE; // Size of buffer used for input smoothing
+		static const float WEIGHT_MODIFIER;
+	};
+
+	/**
+	 * @copydoc	Input
+	 */
+	BS_CORE_EXPORT Input& gInput();
 }

+ 3 - 3
BansheeUtility/BansheeUtility.vcxproj

@@ -313,12 +313,15 @@
     <ClCompile Include="Source\Win32\BsWin32Timer.cpp" />
     <ClInclude Include="Include\BsAny.h" />
     <ClInclude Include="Include\BsBinaryCloner.h" />
+    <ClInclude Include="Include\BsBitmapWriter.h" />
     <ClInclude Include="Include\BsBounds.h" />
     <ClInclude Include="Include\BsCapsule.h" />
     <ClInclude Include="Include\BsConvexVolume.h" />
     <ClInclude Include="Include\BsCrashHandler.h" />
+    <ClInclude Include="Include\BsDebug.h" />
     <ClInclude Include="Include\BsEvent.h" />
     <ClInclude Include="Include\BsLineSegment3.h" />
+    <ClInclude Include="Include\BsLog.h" />
     <ClInclude Include="Include\BsMatrixNxM.h" />
     <ClInclude Include="Include\BsMessageHandler.h" />
     <ClInclude Include="Include\BsMessageHandlerFwd.h" />
@@ -338,10 +341,8 @@
     <ClInclude Include="Include\BsThreadPool.h" />
     <ClInclude Include="Include\BsAsyncOp.h" />
     <ClInclude Include="Include\BsBinarySerializer.h" />
-    <ClInclude Include="Include\BsBitmapWriter.h" />
     <ClInclude Include="Include\BsBitwise.h" />
     <ClInclude Include="Include\BsColor.h" />
-    <ClInclude Include="Include\BsDebug.h" />
     <ClInclude Include="Include\BsDegree.h" />
     <ClInclude Include="Include\BsDynLibManager.h" />
     <ClInclude Include="Include\BsException.h" />
@@ -353,7 +354,6 @@
     <ClInclude Include="Include\BsTorus.h" />
     <ClInclude Include="Include\BsVector2I.h" />
     <ClInclude Include="Include\BsIReflectable.h" />
-    <ClInclude Include="Include\BsLog.h" />
     <ClInclude Include="Include\BsManagedDataBlock.h" />
     <ClInclude Include="Include\BsMemoryAllocator.h" />
     <ClInclude Include="Include\BsMemAllocProfiler.h" />

+ 544 - 502
BansheeUtility/BansheeUtility.vcxproj.filters

@@ -1,503 +1,545 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
-    </Filter>
-    <Filter Include="Header Files\Prerequisites">
-      <UniqueIdentifier>{1a68be3e-3394-4b01-9532-2fe9db03afe0}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Math">
-      <UniqueIdentifier>{5423fdfe-e418-4fcd-8eae-9ab4e77856ef}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Math">
-      <UniqueIdentifier>{6f183461-d042-41e0-9c81-aa8bc8462641}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Threading">
-      <UniqueIdentifier>{b65008fc-0109-4b6d-b82b-7c30abdbeacf}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\RTTI">
-      <UniqueIdentifier>{11d535e6-1203-47ca-9062-8548e4d71027}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Serialization">
-      <UniqueIdentifier>{4af02e17-2cf7-4e71-a749-58e0ba71625e}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Serialization">
-      <UniqueIdentifier>{155906c8-9f79-4f86-835a-eb8f5c2f66bf}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Reflection">
-      <UniqueIdentifier>{ceeeab21-95fc-4e22-922c-7c91ecaba0df}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Debug">
-      <UniqueIdentifier>{cdfa7307-cdee-490f-8d31-d8be0d929c70}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Debug">
-      <UniqueIdentifier>{1f4518ad-c827-49dc-8e69-f99a37c82871}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Threading">
-      <UniqueIdentifier>{cb0d2667-8d73-4d4c-9b2b-bc18fbd7fd70}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\ThirdParty">
-      <UniqueIdentifier>{e0b74f43-dbb4-4e2a-8000-6d9f29dda203}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\ThirdParty">
-      <UniqueIdentifier>{8087a3d9-e6ce-4730-9dd6-7550c08cbd3f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\RTTI">
-      <UniqueIdentifier>{57091de5-56e6-4b9a-9b76-8ecaeee60c3f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Win32">
-      <UniqueIdentifier>{e56d4454-f68c-4190-88cf-98a5cc24f6b4}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="Include\BsThreadPool.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTaskScheduler.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsEvent.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSpinLock.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsAny.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsUtil.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTimer.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTime.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTexAtlasGenerator.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsString.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIPrerequisites.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPath.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsModule.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMemStack.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMemoryAllocator.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMemAllocProfiler.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsManagedDataBlock.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsLog.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFrameAlloc.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFileSystem.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsException.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDynLibManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDynLib.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDebug.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDataStream.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsColor.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBitwise.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsThreadDefines.h">
-      <Filter>Header Files\Threading</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsAsyncOp.h">
-      <Filter>Header Files\Threading</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBinarySerializer.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFileSerializer.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMemorySerializer.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsIReflectable.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIField.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIManagedDataBlockField.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIPlainField.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIReflectableField.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIReflectablePtrField.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRTTIType.h">
-      <Filter>Header Files\Reflection</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTypes.h">
-      <Filter>Header Files\Prerequisites</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStdHeaders.h">
-      <Filter>Header Files\Prerequisites</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrerequisitesUtil.h">
-      <Filter>Header Files\Prerequisites</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPlatformDefines.h">
-      <Filter>Header Files\Prerequisites</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFwdDeclUtil.h">
-      <Filter>Header Files\Prerequisites</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsAABox.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDegree.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMath.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMatrix3.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMatrix4.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPlane.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsQuaternion.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRadian.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRay.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSphere.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVector2.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVector2I.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVector3.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVector4.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBitmapWriter.h">
-      <Filter>Header Files\Debug</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBounds.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsConvexVolume.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTestSuite.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTestOutput.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTorus.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsLineSegment3.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRect3.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRect2.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRect2I.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCapsule.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsServiceLocator.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMessageHandler.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMessageHandlerFwd.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStringFormat.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\ThirdParty\md5.h">
-      <Filter>Header Files\ThirdParty</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStringID.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMatrixNxM.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVectorNI.h">
-      <Filter>Header Files\Math</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBinaryDiff.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSerializedObject.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSerializedObjectRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBinaryCloner.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGlobalFrameAlloc.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStaticAlloc.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCrashHandler.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPlatformUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="Source\BsThreadPool.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTaskScheduler.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTime.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTexAtlasGenerator.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsString.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPath.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMemStack.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMemoryAllocator.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsManagedDataBlock.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsLog.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsFrameAlloc.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsException.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDynLibManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDynLib.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDebug.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDataStream.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsColor.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsAsyncOp.cpp">
-      <Filter>Source Files\Threading</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMemorySerializer.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsFileSerializer.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBinarySerializer.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsIReflectable.cpp">
-      <Filter>Source Files\RTTI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRTTIField.cpp">
-      <Filter>Source Files\RTTI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRTTIType.cpp">
-      <Filter>Source Files\RTTI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsAABox.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDegree.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMath.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMatrix3.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMatrix4.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPlane.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsQuaternion.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRadian.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRay.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSphere.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVector2.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVector2I.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVector3.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVector4.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBitmapWriter.cpp">
-      <Filter>Source Files\Debug</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBounds.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsConvexVolume.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTestOutput.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTestSuite.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTorus.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRect3.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRect2.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRect2I.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsLineSegment3.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCapsule.cpp">
-      <Filter>Source Files\Math</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMessageHandler.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\ThirdParty\md5.cpp">
-      <Filter>Source Files\ThirdParty</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsUtil.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsStringID.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBinaryDiff.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSerializedObject.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBinaryCloner.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGlobalFrameAlloc.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32FileSystem.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32CrashHandler.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32Timer.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32PlatformUtility.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32BrowseDialogs.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Header Files\Prerequisites">
+      <UniqueIdentifier>{1a68be3e-3394-4b01-9532-2fe9db03afe0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Math">
+      <UniqueIdentifier>{5423fdfe-e418-4fcd-8eae-9ab4e77856ef}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Math">
+      <UniqueIdentifier>{6f183461-d042-41e0-9c81-aa8bc8462641}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Threading">
+      <UniqueIdentifier>{b65008fc-0109-4b6d-b82b-7c30abdbeacf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\RTTI">
+      <UniqueIdentifier>{11d535e6-1203-47ca-9062-8548e4d71027}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Serialization">
+      <UniqueIdentifier>{4af02e17-2cf7-4e71-a749-58e0ba71625e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Serialization">
+      <UniqueIdentifier>{155906c8-9f79-4f86-835a-eb8f5c2f66bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Reflection">
+      <UniqueIdentifier>{ceeeab21-95fc-4e22-922c-7c91ecaba0df}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Debug">
+      <UniqueIdentifier>{cdfa7307-cdee-490f-8d31-d8be0d929c70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Debug">
+      <UniqueIdentifier>{1f4518ad-c827-49dc-8e69-f99a37c82871}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Threading">
+      <UniqueIdentifier>{cb0d2667-8d73-4d4c-9b2b-bc18fbd7fd70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\ThirdParty">
+      <UniqueIdentifier>{e0b74f43-dbb4-4e2a-8000-6d9f29dda203}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\ThirdParty">
+      <UniqueIdentifier>{8087a3d9-e6ce-4730-9dd6-7550c08cbd3f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\RTTI">
+      <UniqueIdentifier>{57091de5-56e6-4b9a-9b76-8ecaeee60c3f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Win32">
+      <UniqueIdentifier>{e56d4454-f68c-4190-88cf-98a5cc24f6b4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Allocators">
+      <UniqueIdentifier>{15489b83-13bb-41d3-8276-ddb56d5f46d2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Allocators">
+      <UniqueIdentifier>{aa302904-e06f-421b-b4ec-ab94b583750b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Testing">
+      <UniqueIdentifier>{deff13b0-60fc-4600-ad80-50fc7aef9413}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\String">
+      <UniqueIdentifier>{7bc231a5-7777-4b95-b351-0e6c52bab986}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Testing">
+      <UniqueIdentifier>{f4db6226-fcc5-40a3-9eb6-90b1d70f45b6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\String">
+      <UniqueIdentifier>{572f61fe-1690-4434-9268-13ea43546c2a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Error">
+      <UniqueIdentifier>{066ffded-947d-45d1-a6a0-6410c81f96be}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Error">
+      <UniqueIdentifier>{3f227b3f-c844-4e76-a124-8c72abf52f25}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Filesystem">
+      <UniqueIdentifier>{3897653f-09ad-4e97-b79c-d056242992d2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Filesystem">
+      <UniqueIdentifier>{3675d971-ea02-410e-af4f-fb3e9c6e44eb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Graphics">
+      <UniqueIdentifier>{db53bb17-9025-45bd-8fb2-82615f7eb40d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Graphics">
+      <UniqueIdentifier>{dea9161b-d3f5-401f-9005-aceafe004b3d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\General">
+      <UniqueIdentifier>{db663898-59b6-41a1-adf8-1aa06efc57cd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\General">
+      <UniqueIdentifier>{5c5b3495-a9a3-4d91-82a1-3096c7c67d23}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Include\BsThreadDefines.h">
+      <Filter>Header Files\Threading</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsAsyncOp.h">
+      <Filter>Header Files\Threading</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBinarySerializer.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFileSerializer.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMemorySerializer.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsIReflectable.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIField.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIManagedDataBlockField.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIPlainField.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIReflectableField.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIReflectablePtrField.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIType.h">
+      <Filter>Header Files\Reflection</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTypes.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStdHeaders.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrerequisitesUtil.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPlatformDefines.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFwdDeclUtil.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsAABox.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDegree.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMath.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMatrix3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMatrix4.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPlane.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsQuaternion.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRadian.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRay.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSphere.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVector2.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVector2I.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVector3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVector4.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBounds.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsConvexVolume.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTorus.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsLineSegment3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRect3.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRect2.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRect2I.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCapsule.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\ThirdParty\md5.h">
+      <Filter>Header Files\ThirdParty</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMatrixNxM.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVectorNI.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBinaryDiff.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSerializedObject.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSerializedObjectRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBinaryCloner.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFrameAlloc.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGlobalFrameAlloc.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMemAllocProfiler.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMemoryAllocator.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMemStack.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSpinLock.h">
+      <Filter>Header Files\Threading</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsThreadPool.h">
+      <Filter>Header Files\Threading</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStaticAlloc.h">
+      <Filter>Header Files\Allocators</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTaskScheduler.h">
+      <Filter>Header Files\Threading</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsManagedDataBlock.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTestSuite.h">
+      <Filter>Header Files\Testing</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTestOutput.h">
+      <Filter>Header Files\Testing</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsString.h">
+      <Filter>Header Files\String</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStringFormat.h">
+      <Filter>Header Files\String</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStringID.h">
+      <Filter>Header Files\String</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsException.h">
+      <Filter>Header Files\Error</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCrashHandler.h">
+      <Filter>Header Files\Error</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFileSystem.h">
+      <Filter>Header Files\Filesystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDataStream.h">
+      <Filter>Header Files\Filesystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPath.h">
+      <Filter>Header Files\Filesystem</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsColor.h">
+      <Filter>Header Files\Graphics</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTexAtlasGenerator.h">
+      <Filter>Header Files\Graphics</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsAny.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBitwise.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDynLib.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDynLibManager.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsEvent.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMessageHandler.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMessageHandlerFwd.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsModule.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPlatformUtility.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsServiceLocator.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTime.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTimer.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsUtil.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBitmapWriter.h">
+      <Filter>Header Files\Debug</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDebug.h">
+      <Filter>Header Files\Debug</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsLog.h">
+      <Filter>Header Files\Debug</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRTTIPrerequisites.h">
+      <Filter>Header Files\Prerequisites</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Source\BsAsyncOp.cpp">
+      <Filter>Source Files\Threading</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMemorySerializer.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsFileSerializer.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBinarySerializer.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsIReflectable.cpp">
+      <Filter>Source Files\RTTI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRTTIField.cpp">
+      <Filter>Source Files\RTTI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRTTIType.cpp">
+      <Filter>Source Files\RTTI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsAABox.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDegree.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMath.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMatrix3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMatrix4.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPlane.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsQuaternion.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRadian.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRay.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSphere.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVector2.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVector2I.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVector3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVector4.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBitmapWriter.cpp">
+      <Filter>Source Files\Debug</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBounds.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsConvexVolume.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTorus.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRect3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRect2.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRect2I.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsLineSegment3.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCapsule.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\ThirdParty\md5.cpp">
+      <Filter>Source Files\ThirdParty</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBinaryDiff.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSerializedObject.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBinaryCloner.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32FileSystem.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32CrashHandler.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32Timer.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32PlatformUtility.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32BrowseDialogs.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsFrameAlloc.cpp">
+      <Filter>Source Files\Allocators</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGlobalFrameAlloc.cpp">
+      <Filter>Source Files\Allocators</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsManagedDataBlock.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsLog.cpp">
+      <Filter>Source Files\Debug</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDebug.cpp">
+      <Filter>Source Files\Debug</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMemStack.cpp">
+      <Filter>Source Files\Allocators</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMemoryAllocator.cpp">
+      <Filter>Source Files\Allocators</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTaskScheduler.cpp">
+      <Filter>Source Files\Threading</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsThreadPool.cpp">
+      <Filter>Source Files\Threading</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTestSuite.cpp">
+      <Filter>Source Files\Testing</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTestOutput.cpp">
+      <Filter>Source Files\Testing</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsStringID.cpp">
+      <Filter>Source Files\String</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsString.cpp">
+      <Filter>Source Files\String</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsException.cpp">
+      <Filter>Source Files\Error</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDataStream.cpp">
+      <Filter>Source Files\Filesystem</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPath.cpp">
+      <Filter>Source Files\Filesystem</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsColor.cpp">
+      <Filter>Source Files\Graphics</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTexAtlasGenerator.cpp">
+      <Filter>Source Files\Graphics</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDynLib.cpp">
+      <Filter>Source Files\General</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDynLibManager.cpp">
+      <Filter>Source Files\General</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMessageHandler.cpp">
+      <Filter>Source Files\General</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTime.cpp">
+      <Filter>Source Files\General</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsUtil.cpp">
+      <Filter>Source Files\General</Filter>
+    </ClCompile>
+  </ItemGroup>
 </Project>

+ 140 - 157
BansheeUtility/Include/BsAABox.h

@@ -1,18 +1,20 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-#include "BsVector3.h"
-#include "BsMatrix4.h"
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Axis aligned box represented by minimum and maximum point.
-	 */
-	class BS_UTILITY_EXPORT AABox
-	{
-	public:
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+#include "BsMatrix4.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Axis aligned box represented by minimum and maximum point. */
+	class BS_UTILITY_EXPORT AABox
+	{
+	public:
+		/** Different corners of a box. */
 		/*
 		   1-----2
 		  /|    /|
@@ -22,145 +24,126 @@ namespace BansheeEngine
 		| /   | /
 		|/    |/
 		6-----7
-		*/
-		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& copy);
-		AABox(const Vector3& min, const Vector3& max);
-
-		AABox& operator=(const AABox& rhs);
-
-		~AABox() { }
-		
-		/**
-		 * @brief	Gets the corner of the box with minimum values (opposite to maximum corner).
-		 */
-		const Vector3& getMin() const { return mMinimum; }
-
-		/**
-		 * @brief	Gets the corner of the box with maximum values (opposite to minimum corner).
-		 */
-		const Vector3& getMax() const { return mMaximum; }
-
-		/**
-		 * @brief	Sets the corner of the box with minimum values (opposite to maximum corner).
-		 */
-		void setMin(const Vector3& vec) { mMinimum = vec; }
-
-		/**
-		 * @brief	Sets the corner of the box with maximum values (opposite to minimum corner).
-		 */
-		void setMax(const Vector3& vec) { mMaximum = vec; }
-
-		/**
-		 * @brief	Sets the minimum and maximum corners.
-		 */
-		void setExtents(const Vector3& min, const Vector3& max);
-
-		/**
-		 * @brief	Scales the box around the center by multiplying
-		 * 			its extends with the provided scale.
-		 */
-		void scale(const Vector3& s);
-
-		/**
-		 * @brief	Returns the coordinates of a specific corner.
-		 */
-		Vector3 getCorner(CornerEnum cornerToGet) const;
-
-		/**
-		 * @brief	Merges the two boxes, creating a new 
-		 * 			bounding box that encapsulates them both.
-		 */
-		void merge(const AABox& rhs);
-
-		/**
-		 * @brief	Expands the bounding box so it includes
-		 * 			the provided point.
-		 */
-		void merge(const Vector3& point);
-
-		/**
-		 * @brief	Transforms the bounding box by the given matrix.
-		 *
-		 * @note	As the resulting box will no longer be axis aligned, an axis align box 
-		 * 			is instead created by encompassing the transformed oriented bounding box.
-		 * 			Retrieving the value as an actual OBB would provide a tighter fit.
-		 */
-		void transform(const Matrix4& matrix);
-
-		/**
-		 * @brief	Transforms the bounding box by the given matrix.
-		 *
-		 * @note	As the resulting box will no longer be axis aligned, an axis align box 
-		 * 			is instead created by encompassing the transformed oriented bounding box.
-		 * 			Retrieving the value as an actual OBB would provide a tighter fit.
-		 * 			
-		 *			Provided matrix must be affine.
-		 */
-		void transformAffine(const Matrix4& matrix);
-
-		/**
-		 * @brief	Returns true if this and the provided box intersect.
-		 */
-		bool intersects(const AABox& b2) const;
-
-		/**
-		 * @brief	Returns true if the sphere intersects the bounding box.
-		 */
-		bool intersects(const Sphere& s) const;
-
-		/**
-		 * @brief	Returns true if the plane intersects the bounding box.
-		 */
-		bool intersects(const Plane& p) const;
-
-        /**
-         * @brief	Ray / box intersection, returns a boolean result and nearest distance
-         * 			to intersection.
-         */
-        std::pair<bool, float> intersects(const Ray& ray) const;
-
-        /**
-         * @brief	Ray / box intersection, returns boolean result and near and far intersection distance.
-         */
-        bool intersects(const Ray& ray, float& d1, float& d2) const;
-
-		Vector3 getCenter() const;
-		Vector3 getSize() const;
-		Vector3 getHalfSize() const;
-		float getRadius() const;
-		float getVolume() const;
-
-        /**
-         * @brief	Returns true if the provided point is inside the bounding box.
-         */
-        bool contains(const Vector3& v) const;
-
-        /**
-         * @brief	Returns true if the provided bounding box is completely inside the bounding box.
-         */
-        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;
-	};
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(AABox);
-}
+		*/
+		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& copy);
+		AABox(const Vector3& min, const Vector3& max);
+
+		AABox& operator=(const AABox& rhs);
+
+		~AABox() { }
+		
+		/** Gets the corner of the box with minimum values (opposite to maximum corner). */
+		const Vector3& getMin() const { return mMinimum; }
+
+		/** Gets the corner of the box with maximum values (opposite to minimum corner). */
+		const Vector3& getMax() const { return mMaximum; }
+
+		/** Sets the corner of the box with minimum values (opposite to maximum corner). */
+		void setMin(const Vector3& vec) { mMinimum = vec; }
+
+		/** Sets the corner of the box with maximum values (opposite to minimum corner). */
+		void setMax(const Vector3& vec) { mMaximum = vec; }
+
+		/** Sets the minimum and maximum corners. */
+		void setExtents(const Vector3& min, const Vector3& max);
+
+		/** Scales the box around the center by multiplying its extents with the provided scale. */
+		void scale(const Vector3& s);
+
+		/** Returns the coordinates of a specific corner. */
+		Vector3 getCorner(CornerEnum cornerToGet) const;
+
+		/** Merges the two boxes, creating a new bounding box that encapsulates them both. */
+		void merge(const AABox& rhs);
+
+		/** Expands the bounding box so it includes the provided point. */
+		void merge(const Vector3& point);
+
+		/**
+		 * Transforms the bounding box by the given matrix.
+		 *
+		 * @note	
+		 * As the resulting box will no longer be axis aligned, an axis align box 
+		 * is instead created by encompassing the transformed oriented bounding box.
+		 * Retrieving the value as an actual OBB would provide a tighter fit.
+		 */
+		void transform(const Matrix4& matrix);
+
+		/**
+		 * Transforms the bounding box by the given matrix.
+		 *
+		 * @note	
+		 * As the resulting box will no longer be axis aligned, an axis align box 
+		 * is instead created by encompassing the transformed oriented bounding box.
+		 * Retrieving the value as an actual OBB would provide a tighter fit.
+		 *
+		 * @note			
+		 * Provided matrix must be affine.
+		 */
+		void transformAffine(const Matrix4& matrix);
+
+		/** Returns true if this and the provided box intersect. */
+		bool intersects(const AABox& b2) const;
+
+		/** Returns true if the sphere intersects the bounding box. */
+		bool intersects(const Sphere& s) const;
+
+		/** Returns true if the plane intersects the bounding box. */
+		bool intersects(const Plane& p) const;
+
+        /** Ray / box intersection, returns a boolean result and nearest distance to intersection. */
+        std::pair<bool, float> intersects(const Ray& ray) const;
+
+        /** Ray / box intersection, returns boolean result and near and far intersection distance. */
+        bool intersects(const Ray& ray, float& d1, float& d2) const;
+
+		/** Center of the box. */
+		Vector3 getCenter() const;
+
+		/** Size of the box (difference between minimum and maximum corners) */
+		Vector3 getSize() const;
+
+		/** Extents of the box (distance from center to one of the corners) */
+		Vector3 getHalfSize() const;
+
+		/** Radius of a sphere that fully encompasses the box. */
+		float getRadius() const;
+
+		/** Size of the volume in the box. */
+		float getVolume() const;
+
+        /** Returns true if the provided point is inside the bounding box. */
+        bool contains(const Vector3& v) const;
+
+        /** Returns true if the provided bounding box is completely inside the bounding box. */
+        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;
+	};
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(AABox);
+	/** @endcond */
+}

+ 39 - 35
BansheeUtility/Include/BsBitmapWriter.h

@@ -1,36 +1,40 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Utility class from generating BMP images.
-	 */
-	class BS_UTILITY_EXPORT BitmapWriter
-	{
-	public:
-		/**
-		 * @brief	Generates bytes representing the BMP image format, from a set of raw RGB or RGBA pixels.
-		 *
-		 * @param	input		  	The input set of bytes in RGB or RGBA format. Starting byte represents the top left pixel of the image
-		 * 							and following pixels need to be set going from left to right, row after row.
-		 * @param [out]	output	Preallocated buffer where the BMP bytes will be stored. Use "getBMPSize" to retrieve the size needed for this buffer.
-		 * @param	width		  	The width of the image in pixels.
-		 * @param	height		  	The height of the image in pixels.
-		 * @param	bytesPerPixel 	Number of bytes per pixel. 3 for RGB images and 4 for RGBA images. Other values not supported.
-		 */
-		static void rawPixelsToBMP(const UINT8* input, UINT8* output, UINT32 width, UINT32 height, UINT32 bytesPerPixel);
-
-		/**
-		 * @brief	Returns the size of the BMP output buffer that needs to be allocated before calling "rawPixelsToBMP".
-		 *
-		 * @param	width		  	The width of the image in pixels.
-		 * @param	height		  	The height of the image in pixels.
-		 * @param	bytesPerPixel 	Number of bytes per pixel. 3 for RGB images and 4 for RGBA images. Other values not supported.
-		 *
-		 * @return	Size of the BMP output buffer needed to write a BMP of the specified size & bpp.
-		 */
-		static UINT32 getBMPSize(UINT32 width, UINT32 height, UINT32 bytesPerPixel);
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Debug
+	 *  @{
+	 */
+
+	/** Utility class for generating BMP images. */
+	class BS_UTILITY_EXPORT BitmapWriter
+	{
+	public:
+		/**
+		 * Generates bytes representing the BMP image format, from a set of raw RGB or RGBA pixels.
+		 *
+		 * @param[in]	input			The input set of bytes in RGB or RGBA format. Starting byte represents the top left pixel of the image
+		 * 								and following pixels need to be set going from left to right, row after row.
+		 * @param[out]	output			Preallocated buffer where the BMP bytes will be stored. Use getBMPSize() to retrieve the size needed for this buffer.
+		 * @param[in]	width		  	The width of the image in pixels.
+		 * @param[in]	height		  	The height of the image in pixels.
+		 * @param[in]	bytesPerPixel 	Number of bytes per pixel. 3 for RGB images and 4 for RGBA images. Other values not supported.
+		 */
+		static void rawPixelsToBMP(const UINT8* input, UINT8* output, UINT32 width, UINT32 height, UINT32 bytesPerPixel);
+
+		/**
+		 * Returns the size of the BMP output buffer that needs to be allocated before calling rawPixelsToBMP().
+		 *
+		 * @param[in]	width		  	The width of the image in pixels.
+		 * @param[in]	height		  	The height of the image in pixels.
+		 * @param[in]	bytesPerPixel 	Number of bytes per pixel. 3 for RGB images and 4 for RGBA images. Other values not supported.
+		 *
+		 * @return	Size of the BMP output buffer needed to write a BMP of the specified size & bpp.
+		 */
+		static UINT32 getBMPSize(UINT32 width, UINT32 height, UINT32 bytesPerPixel);
+	};
+
+	/** @} */
 }

+ 67 - 71
BansheeUtility/Include/BsBounds.h

@@ -1,71 +1,67 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-#include "BsAABox.h"
-#include "BsSphere.h"
-#include "BsMatrix4.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Bounds represented by an axis aligned box and a sphere.
-	 */
-	class BS_UTILITY_EXPORT Bounds
-	{
-	public:
-		Bounds();
-		Bounds(const AABox& box, const Sphere& sphere);
-		~Bounds() { }
-
-		/**
-		 * @brief	Returns the axis aligned box representing the bounds.
-		 */
-		const AABox& getBox() const { return mBox; }
-
-		/**
-		 * @brief	Returns the sphere representing the bounds.
-		 */
-		const Sphere& getSphere() const { return mSphere; }
-
-		/**
-		 * @brief	Updates the bounds by setting the new bounding box and sphere.
-		 */
-		void setBounds(const AABox& box, const Sphere& sphere);
-
-		/**
-		 * @brief	Merges the two bounds, creating a new bounds that encapsulates 
-		 *			them both.
-		 */
-		void merge(const Bounds& rhs);
-
-		/**
-		* @brief	Expands the bounds so it includes the provided point.
-		*/
-		void merge(const Vector3& point);
-
-		/**
-		 * @brief	Transforms the bounds by the given matrix.
-		 *
-		 * @note	As the resulting box will no longer be axis aligned, an axis align box
-		 * 			is instead created by encompassing the transformed oriented bounding box.
-		 * 			Retrieving the value as an actual OBB would provide a tighter fit.
-		 */
-		void transform(const Matrix4& matrix);
-
-		/**
-		 * @brief	Transforms the bounds by the given matrix.
-		 *
-		 * @note	As the resulting box will no longer be axis aligned, an axis align box
-		 * 			is instead created by encompassing the transformed oriented bounding box.
-		 * 			Retrieving the value as an actual OBB would provide a tighter fit.
-		 *
-		 *			Provided matrix must be affine.
-		 */
-		void transformAffine(const Matrix4& matrix);
-
-	protected:
-		AABox mBox;
-		Sphere mSphere;
-	};
-}
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+#include "BsAABox.h"
+#include "BsSphere.h"
+#include "BsMatrix4.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Bounds represented by an axis aligned box and a sphere. */
+	class BS_UTILITY_EXPORT Bounds
+	{
+	public:
+		Bounds();
+		Bounds(const AABox& box, const Sphere& sphere);
+		~Bounds() { }
+
+		/** Returns the axis aligned box representing the bounds. */
+		const AABox& getBox() const { return mBox; }
+
+		/** Returns the sphere representing the bounds. */
+		const Sphere& getSphere() const { return mSphere; }
+
+		/** Updates the bounds by setting the new bounding box and sphere. */
+		void setBounds(const AABox& box, const Sphere& sphere);
+
+		/** Merges the two bounds, creating a new bounds that encapsulates them both. */
+		void merge(const Bounds& rhs);
+
+		/** Expands the bounds so it includes the provided point. */
+		void merge(const Vector3& point);
+
+		/** 
+		 * Transforms the bounds by the given matrix.
+		 *
+		 * @note	
+		 * As the resulting box will no longer be axis aligned, an axis align box
+		 * is instead created by encompassing the transformed oriented bounding box.
+		 * Retrieving the value as an actual OBB would provide a tighter fit.
+		 */
+		void transform(const Matrix4& matrix);
+
+		/**
+		 * Transforms the bounds by the given matrix.
+		 *
+		 * @note	
+		 * As the resulting box will no longer be axis aligned, an axis align box
+		 * is instead created by encompassing the transformed oriented bounding box.
+		 * Retrieving the value as an actual OBB would provide a tighter fit.
+		 *
+		 * @note
+		 * Provided matrix must be affine.
+		 */
+		void transformAffine(const Matrix4& matrix);
+
+	protected:
+		AABox mBox;
+		Sphere mSphere;
+	};
+
+	/** @} */
+}

+ 41 - 41
BansheeUtility/Include/BsCapsule.h

@@ -1,42 +1,42 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-#include "BsLineSegment3.h"
-
-namespace BansheeEngine
-{
-	/**
-	* @brief	Represents a capsule represented by a line segment and
-	*			a radius.
-	*/
-	class BS_UTILITY_EXPORT Capsule
-	{
-	public:
-		Capsule();
-		Capsule(const LineSegment3& segment, float radius);
-
-		/**
-		 * @brief	Ray/capsule intersection.
-		 *
-		 * @return	Boolean result and distance to the nearest intersection point.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray) const;
-
-		/**
-		 * @brief	Returns the line segment along which the capsule lies.
-		 *			All capsule points are at equal distance from this segment.
-		 */
-		const LineSegment3& getSegment() const { return mSegment; }
-
-		/**
-		 * @brief	Returns the radius of the capsule. It defines the distance
-		 *			of the capsule from its line segment.
-		 */
-		float getRadius() const { return mRadius; }
-
-	private:
-		LineSegment3 mSegment;
-		float mRadius;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+#include "BsLineSegment3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Represents a capsule represented by a line segment and a radius. */
+	class BS_UTILITY_EXPORT Capsule
+	{
+	public:
+		Capsule();
+		Capsule(const LineSegment3& segment, float radius);
+
+		/**
+		 * Ray/capsule intersection.
+		 *
+		 * @return	Boolean result and distance to the nearest intersection point.
+		 */
+		std::pair<bool, float> intersects(const Ray& ray) const;
+
+		/**
+		 * Returns the line segment along which the capsule lies. 
+		 * All capsule points are at equal distance from this segment.
+		 */
+		const LineSegment3& getSegment() const { return mSegment; }
+
+		/** Returns the radius of the capsule. It defines the distance of the capsule from its line segment. */
+		float getRadius() const { return mRadius; }
+
+	private:
+		LineSegment3 mSegment;
+		float mRadius;
+	};
+
+	/** @} */
 }

+ 38 - 37
BansheeUtility/Include/BsConvexVolume.h

@@ -1,38 +1,39 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsPlane.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a convex volume defined by planes representing
-	 *			the volume border.
-	 */
-	class BS_UTILITY_EXPORT ConvexVolume
-	{
-	public:
-		ConvexVolume() {}
-		ConvexVolume(const Vector<Plane>& planes);
-
-		/**
-		 * @brief	Checks does the volume intersects the provided axis aligned box.
-		 *			This will return true if the box is fully inside the volume.
-		 */
-		bool intersects(const AABox& box) const;
-
-		/**
-		 * @brief	Checks does the volume intersects the provided sphere.
-		 *			This will return true if the sphere is fully inside the volume.
-		 */
-		bool intersects(const Sphere& sphere) const;
-
-		/**
-		 * @brief	Returns the internal set of planes that represent the volume.
-		 */
-		const Vector<Plane> getPlanes() const { return mPlanes; }
-
-	private:
-		Vector<Plane> mPlanes;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsPlane.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Represents a convex volume defined by planes representing the volume border. */
+	class BS_UTILITY_EXPORT ConvexVolume
+	{
+	public:
+		ConvexVolume() {}
+		ConvexVolume(const Vector<Plane>& planes);
+
+		/**
+		 * Checks does the volume intersects the provided axis aligned box.
+		 * This will return true if the box is fully inside the volume.
+		 */
+		bool intersects(const AABox& box) const;
+
+		/**
+		 * Checks does the volume intersects the provided sphere.
+		 * This will return true if the sphere is fully inside the volume.
+		 */
+		bool intersects(const Sphere& sphere) const;
+
+		/** Returns the internal set of planes that represent the volume. */
+		Vector<Plane> getPlanes() const { return mPlanes; }
+
+	private:
+		Vector<Plane> mPlanes;
+	};
+
+	/** @} */
 }

+ 36 - 29
BansheeUtility/Include/BsDebug.h

@@ -7,64 +7,49 @@ namespace BansheeEngine
 {
 	class Log;
 
-	/**
-	 * @brief	Available types of channels that debug messages can be logged to.
+	/** @addtogroup Debug
+	 *  @{
 	 */
+
+	/** Available types of channels that debug messages can be logged to. */
 	enum class DebugChannel
 	{
 		Debug, Warning, Error, CompilerWarning, CompilerError
 	};
 
 	/**
-	 * @brief	Utility class providing various debug functionality. Thread safe.
+	 * @brief	Utility class providing various debug functionality.
+	 *
+	 * @note	Thread safe.
 	 */
 	class BS_UTILITY_EXPORT Debug
 	{
 	public:
-		/**
-		 * @brief	Adds a log entry in the "Debug" channel.
-		 */
+		/** Adds a log entry in the "Debug" channel. */
 		void logDebug(const String& msg);
 
-		/**
-		 * @brief	Adds a log entry in the "Warning" channel.
-		 */
+		/** Adds a log entry in the "Warning" channel. */
 		void logWarning(const String& msg);
 
-		/**
-		 * @brief	Adds a log entry in the "Error" channel.
-		 */
+		/** Adds a log entry in the "Error" channel. */
 		void logError(const String& msg);
 
-		/**
-		 * @brief	Adds a log entry in the specified channel. You may specify custom channels as needed.
-		 */
+		/** Adds a log entry in the specified channel. You may specify custom channels as needed. */
 		void log(const String& msg, UINT32 channel);
 
-		/**
-		 * @brief	Retrieves the Log used by the Debug instance.
-		 */
+		/** Retrieves the Log used by the Debug instance. */
 		Log& getLog() { return mLog; }
 
-		/**
-		 * @brief	Converts raw pixels into a BMP image. See "BitmapWriter" for more information.
-		 */
+		/** Converts raw pixels into a BMP image. See BitmapWriter for more information. */
 		void writeAsBMP(UINT8* rawPixels, UINT32 bytesPerPixel, UINT32 width, UINT32 height, const Path& filePath, bool overwrite = true) const;
 
 		/**
-		 * @brief	Saves a log about the current state of the application to the specified location.
+		 * Saves a log about the current state of the application to the specified location.
 		 * 
 		 * @param	path	Absolute path to the log filename.
 		 */
 		void saveLog(const Path& path) const;
 
-		/**
-		 * @brief	Triggers callbacks that notify external code that a log entry was added.
-		 * 			
-		 * @note	Internal method. Sim thread only.
-		 */
-		void _triggerCallbacks();
-
 		/**
 		 * @brief	Triggered when a new entry in the log is added.
 		 * 			
@@ -79,17 +64,39 @@ namespace BansheeEngine
 		 * @note	Sim thread only.
 		 */
 		Event<void()> onLogModified;
+
+		/** @cond INTERNAL */
+
+		/**
+		 * Triggers callbacks that notify external code that a log entry was added.
+		 * 			
+		 * @note	Internal method. Sim thread only.
+		 */
+		void _triggerCallbacks();
+
+		/** @endcond */
 	private:
 		UINT64 mLogHash = 0;
 		Log mLog;
 	};
 
+	/** A simpler way of accessing the Debug module. */
 	BS_UTILITY_EXPORT Debug& gDebug();
 
+/** Shortcut for logging a message in the debug channel. */
 #define LOGDBG(x) BansheeEngine::gDebug().logDebug((x));
+
+/** Shortcut for logging a message in the warning channel. */
 #define LOGWRN(x) BansheeEngine::gDebug().logWarning((x));
+
+/** Shortcut for logging a message in the error channel. */
 #define LOGERR(x) BansheeEngine::gDebug().logError((x));
 
+/** Shortcut for logging a verbose message in the debug channel. Verbose messages can be ignored unlike other log messages. */
 #define LOGDBG_VERBOSE(x)
+
+/** Shortcut for logging a verbose message in the warning channel. Verbose messages can be ignored unlike other log messages. */
 #define LOGWRN_VERBOSE(x)
+
+	/** @} */
 }

+ 74 - 64
BansheeUtility/Include/BsDegree.h

@@ -1,65 +1,75 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsRadian.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Wrapper class which indicates a given angle value is in Degrees.
-	 * 			
-	 *	@note	Degree values are interchangeable with Radian values, and conversions
-	 *			will be done automatically between them.
-	 */
-	class BS_UTILITY_EXPORT Degree
-	{
-		float mDeg;
-
-	public:
-		explicit Degree(float d = 0.0f) : mDeg(d) {}
-		Degree(const Radian& r);
-		Degree& operator= (const float& f) { mDeg = f; return *this; }
-		Degree& operator= (const Degree& d) { mDeg = d.mDeg; return *this; }
-		Degree& operator= (const Radian& r);
-
-		float valueDegrees() const { return mDeg; }
-		float valueRadians() const;
-
-		/**
-		 * @brief  Wraps the angle in [0, 360) range
-		 */
-		Degree wrap();
-
-		const Degree& operator+ () const { return *this; }
-		Degree operator+ (const Degree& d) const { return Degree (mDeg + d.mDeg); }
-		Degree operator+ (const Radian& r) const;
-		Degree& operator+= (const Degree& d) { mDeg += d.mDeg; return *this; }
-		Degree& operator+= (const Radian& r);
-		Degree operator- () const { return Degree(-mDeg); }
-		Degree operator- (const Degree& d) const { return Degree (mDeg - d.mDeg); }
-		Degree operator- (const Radian& r) const;
-		Degree& operator-= (const Degree& d) { mDeg -= d.mDeg; return *this; }
-		Degree& operator-= (const Radian& r);
-		Degree operator* (float f) const { return Degree (mDeg * f); }
-        Degree operator* (const Degree& f) const { return Degree (mDeg * f.mDeg); }
-		Degree& operator*= (float f) { mDeg *= f; return *this; }
-		Degree operator/ (float f) const { return Degree (mDeg / f); }
-		Degree& operator/= (float f) { mDeg /= f; return *this; }
-
-		friend Degree operator* (float lhs, const Degree& rhs) { return Degree(lhs * rhs.mDeg); }
-		friend Degree operator/ (float lhs, const Degree& rhs) { return Degree(lhs / rhs.mDeg); }
-		friend Degree operator+ (Degree& lhs, float rhs) { return Degree(lhs.mDeg + rhs); }
-		friend Degree operator+ (float lhs, const Degree& rhs) { return Degree(lhs + rhs.mDeg); }
-		friend Degree operator- (const Degree& lhs, float rhs) { return Degree(lhs.mDeg - rhs); }
-		friend Degree operator- (const float lhs, const Degree& rhs) { return Degree(lhs - rhs.mDeg); }
-
-		bool operator<  (const Degree& d) const { return mDeg <  d.mDeg; }
-		bool operator<= (const Degree& d) const { return mDeg <= d.mDeg; }
-		bool operator== (const Degree& d) const { return mDeg == d.mDeg; }
-		bool operator!= (const Degree& d) const { return mDeg != d.mDeg; }
-		bool operator>= (const Degree& d) const { return mDeg >= d.mDeg; }
-		bool operator>  (const Degree& d) const { return mDeg >  d.mDeg; }
-	};
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Degree);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRadian.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/**
+	 * Wrapper class which indicates a given angle value is in degrees.
+	 * 			
+	 * @note	
+	 * Degree values are interchangeable with Radian values, and conversions will be done automatically between them.
+	 */
+	class BS_UTILITY_EXPORT Degree
+	{
+	public:
+		explicit Degree(float d = 0.0f) : mDeg(d) {}
+		Degree(const Radian& r);
+		Degree& operator= (const float& f) { mDeg = f; return *this; }
+		Degree& operator= (const Degree& d) { mDeg = d.mDeg; return *this; }
+		Degree& operator= (const Radian& r);
+
+		/** Returns the value of the angle in degrees. */
+		float valueDegrees() const { return mDeg; }
+
+		/** Returns the value of the angle in radians. */
+		float valueRadians() const;
+
+		/** Wraps the angle in [0, 360) range */
+		Degree wrap();
+
+		const Degree& operator+ () const { return *this; }
+		Degree operator+ (const Degree& d) const { return Degree (mDeg + d.mDeg); }
+		Degree operator+ (const Radian& r) const;
+		Degree& operator+= (const Degree& d) { mDeg += d.mDeg; return *this; }
+		Degree& operator+= (const Radian& r);
+		Degree operator- () const { return Degree(-mDeg); }
+		Degree operator- (const Degree& d) const { return Degree (mDeg - d.mDeg); }
+		Degree operator- (const Radian& r) const;
+		Degree& operator-= (const Degree& d) { mDeg -= d.mDeg; return *this; }
+		Degree& operator-= (const Radian& r);
+		Degree operator* (float f) const { return Degree (mDeg * f); }
+        Degree operator* (const Degree& f) const { return Degree (mDeg * f.mDeg); }
+		Degree& operator*= (float f) { mDeg *= f; return *this; }
+		Degree operator/ (float f) const { return Degree (mDeg / f); }
+		Degree& operator/= (float f) { mDeg /= f; return *this; }
+
+		friend Degree operator* (float lhs, const Degree& rhs) { return Degree(lhs * rhs.mDeg); }
+		friend Degree operator/ (float lhs, const Degree& rhs) { return Degree(lhs / rhs.mDeg); }
+		friend Degree operator+ (Degree& lhs, float rhs) { return Degree(lhs.mDeg + rhs); }
+		friend Degree operator+ (float lhs, const Degree& rhs) { return Degree(lhs + rhs.mDeg); }
+		friend Degree operator- (const Degree& lhs, float rhs) { return Degree(lhs.mDeg - rhs); }
+		friend Degree operator- (const float lhs, const Degree& rhs) { return Degree(lhs - rhs.mDeg); }
+
+		bool operator<  (const Degree& d) const { return mDeg <  d.mDeg; }
+		bool operator<= (const Degree& d) const { return mDeg <= d.mDeg; }
+		bool operator== (const Degree& d) const { return mDeg == d.mDeg; }
+		bool operator!= (const Degree& d) const { return mDeg != d.mDeg; }
+		bool operator>= (const Degree& d) const { return mDeg >= d.mDeg; }
+		bool operator>  (const Degree& d) const { return mDeg >  d.mDeg; }
+
+	private:
+		float mDeg;
+	};
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Degree);
+	/** @endcond */
 }

+ 109 - 106
BansheeUtility/Include/BsFwdDeclUtil.h

@@ -1,107 +1,110 @@
-#pragma once
-
-// Contains forward declares used as a convenience
-
-namespace BansheeEngine 
-{
-	/**
-	 * @brief	Values that represent in which order are euler
-	 * 			angles applied when used in transformations.
-	 */
-	enum class EulerAngleOrder
-	{
-		XYZ,
-		XZY,
-		YXZ,
-		YZX,
-		ZXY,
-		ZYX
-	};
-
-	class Angle;
-	class AABox;
-	class Degree;
-	class Math;
-	class Matrix3;
-	class Matrix4;
-	class Plane;
-	class Quaternion;
-	class Radian;
-	class Ray;
-	class Sphere;
-	class Vector2;
-	class Vector3;
-	class Vector4;
-	struct Vector2I;
-	class Rect2I;
-	class Rect2;
-	class Rect3;
-	class Color;
-	class DynLib;
-	class DynLibManager;
-	class DataStream;
-	class MemoryDataStream;
-	class FileDataStream;
-	class MeshData;
-	class FileSystem;
-	class Timer;
-	class Task;
-	class GpuResourceData;
-	class PixelData;
-	class HString;
-	class StringTable;
-	struct LocalizedStringData;
-	class Path;
-	class HThread;
-	class TestSuite;
-	class TestOutput;
-	class AsyncOpSyncData;
-	struct RTTIField;
-	struct RTTIReflectablePtrFieldBase;
-	struct SerializedObject;
-	struct SerializedInstance;
-	class FrameAlloc;
-	class LogEntry;
-	// Reflection
-	class IReflectable;
-	class RTTITypeBase;
-	// Serialization
-	class ISerializable;
-	class SerializableType;
-
-	typedef std::shared_ptr<DataStream> DataStreamPtr;
-	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
-	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
-	typedef std::shared_ptr<MeshData> MeshDataPtr;
-	typedef std::shared_ptr<PixelData> PixelDataPtr;
-	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
-	typedef std::shared_ptr<DataStream> DataStreamPtr;
-	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
-	typedef std::shared_ptr<Task> TaskPtr;
-	typedef std::shared_ptr<TestSuite> TestSuitePtr;
-	typedef std::shared_ptr<AsyncOpSyncData> AsyncOpSyncDataPtr;
-
-	typedef List<DataStreamPtr> DataStreamList;
-	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
-
-	enum TypeID_Utility
-	{
-		TID_Abstract = 50, // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
-		TID_WString = 51,
-		TID_Path = 52,
-		TID_Vector = 53,
-		TID_Map = 54,
-		TID_UnorderedMap = 55,
-		TID_Pair = 56,
-		TID_Set = 57,
-		TID_StringID = 58,
-		TID_SerializedInstance = 59,
-		TID_SerializedField = 60,
-		TID_SerializedObject = 61,
-		TID_SerializedArray = 62,
-		TID_SerializedEntry = 63,
-		TID_SerializedArrayEntry = 64,
-		TID_SerializedSubObject = 65,
-		TID_UnorderedSet = 66,
-	};
+#pragma once
+
+// Contains forward declares used as a convenience
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Values that represent in which order are euler angles applied when used in transformations. */
+	enum class EulerAngleOrder
+	{
+		XYZ,
+		XZY,
+		YXZ,
+		YZX,
+		ZXY,
+		ZYX
+	};
+
+	/** @} */
+
+	class Angle;
+	class AABox;
+	class Degree;
+	class Math;
+	class Matrix3;
+	class Matrix4;
+	class Plane;
+	class Quaternion;
+	class Radian;
+	class Ray;
+	class Sphere;
+	class Vector2;
+	class Vector3;
+	class Vector4;
+	struct Vector2I;
+	class Rect2I;
+	class Rect2;
+	class Rect3;
+	class Color;
+	class DynLib;
+	class DynLibManager;
+	class DataStream;
+	class MemoryDataStream;
+	class FileDataStream;
+	class MeshData;
+	class FileSystem;
+	class Timer;
+	class Task;
+	class GpuResourceData;
+	class PixelData;
+	class HString;
+	class StringTable;
+	struct LocalizedStringData;
+	class Path;
+	class HThread;
+	class TestSuite;
+	class TestOutput;
+	class AsyncOpSyncData;
+	struct RTTIField;
+	struct RTTIReflectablePtrFieldBase;
+	struct SerializedObject;
+	struct SerializedInstance;
+	class FrameAlloc;
+	class LogEntry;
+	// Reflection
+	class IReflectable;
+	class RTTITypeBase;
+	// Serialization
+	class ISerializable;
+	class SerializableType;
+
+	typedef std::shared_ptr<DataStream> DataStreamPtr;
+	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
+	typedef std::shared_ptr<MeshData> MeshDataPtr;
+	typedef std::shared_ptr<PixelData> PixelDataPtr;
+	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
+	typedef std::shared_ptr<DataStream> DataStreamPtr;
+	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+	typedef std::shared_ptr<Task> TaskPtr;
+	typedef std::shared_ptr<TestSuite> TestSuitePtr;
+	typedef std::shared_ptr<AsyncOpSyncData> AsyncOpSyncDataPtr;
+
+	typedef List<DataStreamPtr> DataStreamList;
+	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
+
+	enum TypeID_Utility
+	{
+		TID_Abstract = 50, // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
+		TID_WString = 51,
+		TID_Path = 52,
+		TID_Vector = 53,
+		TID_Map = 54,
+		TID_UnorderedMap = 55,
+		TID_Pair = 56,
+		TID_Set = 57,
+		TID_StringID = 58,
+		TID_SerializedInstance = 59,
+		TID_SerializedField = 60,
+		TID_SerializedObject = 61,
+		TID_SerializedArray = 62,
+		TID_SerializedEntry = 63,
+		TID_SerializedArrayEntry = 64,
+		TID_SerializedSubObject = 65,
+		TID_UnorderedSet = 66,
+	};
 }

+ 38 - 40
BansheeUtility/Include/BsLineSegment3.h

@@ -1,41 +1,39 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a line segment in three dimensional space defined by
-	 *			a start and an end point.
-	 */
-	class BS_UTILITY_EXPORT LineSegment3
-	{
-	public:
-		LineSegment3();
-		LineSegment3(const Vector3& start, const Vector3& end);
-
-		/**
-		 * @brief	Find the nearest point on the line segment and the provided ray.
-		 *
-		 * @return	Set of nearest points and distance from the points. First
-		 *			nearest point is a point along the ray, while the second is along the
-		 *			line segment.
-		 *
-		 * @note	If segment and ray are parallel the set of points at the segment origin are returned.
-		 */
-		std::pair<std::array<Vector3, 2>, float> getNearestPoint(const Ray& ray) const;
-
-		/**
-		 * @brief	Returns the starting point of the line segment.
-		 */
-		const Vector3& getStart() const { return mStart; }
-
-		/**
-		 * @brief	Returns the ending point of the line segment.
-		 */
-		const Vector3& getEnd() const { return mEnd; }
-	private:
-		Vector3 mStart, mEnd;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Represents a line segment in three dimensional space defined by a start and an end point. */
+	class BS_UTILITY_EXPORT LineSegment3
+	{
+	public:
+		LineSegment3();
+		LineSegment3(const Vector3& start, const Vector3& end);
+
+		/**
+		 * Find the nearest point on the line segment and the provided ray.
+		 *
+		 * @return	Set of nearest points and distance from the points. First nearest point is a point along the ray, 
+		 *			while the second is along the line segment.
+		 *
+		 * @note	If segment and ray are parallel the set of points at the segment origin are returned.
+		 */
+		std::pair<std::array<Vector3, 2>, float> getNearestPoint(const Ray& ray) const;
+
+		/** Returns the starting point of the line segment. */
+		const Vector3& getStart() const { return mStart; }
+
+		/** Returns the ending point of the line segment. */
+		const Vector3& getEnd() const { return mEnd; }
+	private:
+		Vector3 mStart, mEnd;
+	};
+
+	/** @} */
 }

+ 26 - 32
BansheeUtility/Include/BsLog.h

@@ -1,21 +1,24 @@
 #pragma once
 
 #include "BsPrerequisitesUtil.h"
-#include "BsEvent.h"
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	A single log entry, containing a message and a channel the message
-	 * 			was recorded on.
+	/** @addtogroup Debug
+	 *  @{
 	 */
+
+	/** A single log entry, containing a message and a channel the message was recorded on. */
 	class BS_UTILITY_EXPORT LogEntry
 	{
 	public:
 		LogEntry() { }
 		LogEntry(const String& msg, UINT32 channel);
 
+		/** Channel the message was recorded on. */
 		UINT32 getChannel() const { return mChannel; }
+
+		/** Text of the message. */
 		const String& getMessage() const { return mMsg; }
 
 	private:
@@ -24,8 +27,8 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Used for logging messages. Can categorize messages according to channels, save the log to a file
-	 * 			and send out callbacks when a new message is added.
+	 * Used for logging messages. Can categorize messages according to channels, save the log to a file
+	 * and send out callbacks when a new message is added.
 	 * 			
 	 * @note	Thread safe.
 	 */
@@ -36,59 +39,48 @@ namespace BansheeEngine
 		~Log();
 
 		/**
-		 * @brief	Logs a new message. 
+		 * Logs a new message. 
 		 *
-		 * @param	message	The message describing the log entry.
-		 * @param	channel Channel in which to store the log entry.
+		 * @param[in]	message	The message describing the log entry.
+		 * @param[in]	channel Channel in which to store the log entry.
 		 */
 		void logMsg(const String& message, UINT32 channel);
 
-		/**
-		 * @brief	Removes all log entries. 
-		 */
+		/** Removes all log entries. */
 		void clear();
 
-		/**
-		 * @brief	Removes all log entries in a specific channel. 
-		 */
+		/** Removes all log entries in a specific channel. */
 		void clear(UINT32 channel);
 
-		/**
-		 * @brief	Returns all existing log entries.
-		 */
+		/** Returns all existing log entries. */
 		Vector<LogEntry> getEntries() const;
 
 		/**
-		 * @brief	Returns the latest unread entry from the log queue, and removes the entry from the unread entries
-		 * 			list.
+		 * Returns the latest unread entry from the log queue, and removes the entry from the unread entries list.
 		 * 			
-		 * @param	entry	Entry that was retrieved, or undefined if no entries exist.
-		 * 					
-		 * @returns	True if an unread entry was retrieved, false otherwise.
+		 * @param[out]	entry	Entry that was retrieved, or undefined if no entries exist.		
+		 * @return				True if an unread entry was retrieved, false otherwise.
 		 */
 		bool getUnreadEntry(LogEntry& entry);
 
 		/**
-		 * @brief	Returns the last available log entry.
-		 *
-		 * @param	entry	Entry that was retrieved, or undefined if no entries exist.
+		 * Returns the last available log entry.
 		 *
-		 * @returns	True if an entry was retrieved, false otherwise.
+		 * @param[out]	entry	Entry that was retrieved, or undefined if no entries exist.
+		 * @return				True if an entry was retrieved, false otherwise.
 		 */
 		bool getLastEntry(LogEntry& entry);
 
 		/**
-		 * @brief	Returns a hash value that is modified whenever entries in the log change. This can be used for
-		 *			checking for changes by external systems.
+		 * Returns a hash value that is modified whenever entries in the log change. This can be used for
+		 * checking for changes by external systems.
 		 */
 		UINT64 getHash() const { return mHash; }
 
 	private:
 		friend class Debug;
 
-		/**
-		 * @brief	Returns all log entries, including those marked as unread.
-		 */
+		/** Returns all log entries, including those marked as unread. */
 		Vector<LogEntry> getAllEntries() const;
 
 		Vector<LogEntry> mEntries;
@@ -96,4 +88,6 @@ namespace BansheeEngine
 		UINT64 mHash;
 		BS_RECURSIVE_MUTEX(mMutex);
 	};
+
+	/** @} */
 }

+ 575 - 594
BansheeUtility/Include/BsMath.h

@@ -1,594 +1,575 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsDegree.h"
-#include "BsRadian.h"
-
-namespace BansheeEngine
-{
-    /**
-     * @brief	Utility class providing common scalar math operations.
-     */
-    class BS_UTILITY_EXPORT Math 
-    {
-    public:
-		static Radian acos(float val);
-		static Radian asin(float val);
-		static Radian atan(float val) { return Radian(std::atan(val)); }
-		static Radian atan2(float y, float x) { return Radian(std::atan2(y,x)); }
-
-        static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
-        static float cos(float val) { return (float)std::cos(val); }
-
-        static float sin(const Radian& val) { return (float)std::sin(val.valueRadians()); }
-        static float sin(float val) { return (float)std::sin(val); }
-
-		static float tan(const Radian& val) { return (float)std::tan(val.valueRadians()); }
-		static float tan(float val) { return (float)std::tan(val); }
-
-		static float sqrt(float val) { return (float)std::sqrt(val); }
-        static Radian sqrt(const Radian& val) { return Radian(std::sqrt(val.valueRadians())); }
-        static Degree sqrt(const Degree& val) { return Degree(std::sqrt(val.valueDegrees())); }
-
-		static float invSqrt(float val);
-		static float sqr(float val) { return val*val; }
-
-		static float pow(float base, float exponent) { return (float)std::pow(base, exponent); }
-		static float exp(float val) { return (float)std::exp(val); }
-
-		static float log(float val) { return (float)std::log(val); }
-		static float log2(float val) { return (float)(std::log(val)/LOG2); }
-		static float logN(float base, float val) { return (float)(std::log(val)/std::log(base)); }
-
-		static float sign(float val);
-		static Radian sign(const Radian& val) { return Radian(sign(val.valueRadians())); }
-		static Degree sign(const Degree& val) { return Degree(sign(val.valueDegrees())); }
-
-		static float abs(float val) { return float(std::fabs(val)); }
-		static Degree abs(const Degree& val) { return Degree(std::fabs(val.valueDegrees())); }
-		static Radian abs(const Radian& val) { return Radian(std::fabs(val.valueRadians())); }
-
-		static float ceil(float val) { return (float)std::ceil(val); }
-		static int ceilToInt(float val) { return (int)std::ceil(val); }
-
-		static float round(float val) { return (float)std::floor(val + 0.5f); }
-		static int roundToInt(float val) { return (int)std::floor(val + 0.5f); }
-
-		static float floor(float val) { return (float)std::floor(val); }
-		static int floorToInt(float val) { return (int)std::floor(val); }
-
-		/**
-		 * @brief	Clamp a value within an inclusive range.
-		 */
-		template <typename T>
-		static T clamp(T val, T minval, T maxval)
-		{
-			assert (minval <= maxval && "Invalid clamp range");
-			return std::max(std::min(val, maxval), minval);
-		}
-
-		/**
-		 * @brief	Clamp a value within an inclusive range [0..1].
-		 */
-		template <typename T>
-		static T clamp01(T val)
-		{
-			return std::max(std::min(val, (T)1), (T)0);
-		}
-
-		/**
-		 * @brief	Checks is the specified value a power of two. Only works on integer values.
-		 */
-		template <typename T>
-		static bool isPow2(T val)
-		{
-			return (val & (val - 1)) == 0;
-		}
-
-		static bool isNaN(float f)
-		{
-			return f != f;
-		}
-
-        /**
-         * @brief	Compare two floats, using tolerance for inaccuracies.
-         */
-        static bool approxEquals(float a, float b, float tolerance = std::numeric_limits<float>::epsilon());
-
-        /**
-         * @brief	Compare two doubles, using tolerance for inaccuracies.
-         */
-		static bool approxEquals(double a, double b, double tolerance = std::numeric_limits<double>::epsilon());
-
-		/**
-         * @brief	Compare two 2D vectors, using tolerance for inaccuracies.
-         */
-		static bool approxEquals(const Vector2& a, const Vector2& b, float tolerance = std::numeric_limits<float>::epsilon());
-
-		/**
-         * @brief	Compare two 3D vectors, using tolerance for inaccuracies.
-         */
-		static bool approxEquals(const Vector3& a, const Vector3& b, float tolerance = std::numeric_limits<float>::epsilon());
-
-		/**
-         * @brief	Compare two 4D vectors, using tolerance for inaccuracies.
-         */
-		static bool approxEquals(const Vector4& a, const Vector4& b, float tolerance = std::numeric_limits<float>::epsilon());
-
-        /**
-         * @brief	Calculates the tangent space vector for a given set of positions / texture coords.
-         */
-        static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
-			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
-
-		/************************************************************************/
-		/* 							TRIG APPROXIMATIONS                      	*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastSin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
-
-		/**
-		 * @brief	Sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastSin0(float val);
-
-		/**
-		 * @brief	Sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastSin0".
-		 */
-		static float fastSin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
-
-		/**
-		 * @brief	Sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastSin0".
-		 */
-		static float fastSin1(float val);
-
-		/**
-		 * @brief	Cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastCos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
-
-		/**
-		 * @brief	Cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastCos0(float val);
-
-		/**
-		 * @brief	Cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastCos0".
-		 */
-		static float fastCos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
-
-		/**
-		 * @brief	Cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastCos0".
-		 */
-		static float fastCos1(float val);
-
-		/**
-		 * @brief	Tangent function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastTan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
-
-		/**
-		 * @brief	Tangent function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastTan0(float val);
-
-		/**
-		 * @brief	Tangent function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastTan0".
-		 */
-		static float fastTan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
-
-		/**
-		 * @brief	Tangent function approximation.
-		 *
-		 * @param	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastTan0".
-		 */
-		static float fastTan1(float val);
-
-		/**
-		 * @brief	Inverse sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastASin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastASin0(float val);
-
-		/**
-		 * @brief	Inverse sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastASin0".
-		 */
-		static float fastASin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse sine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastASin0".
-		 */
-		static float fastASin1(float val);
-
-		/**
-		 * @brief	Inverse cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastACos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastACos0(float val);
-
-		/**
-		 * @brief	Inverse cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastACos0".
-		 */
-		static float fastACos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse cosine function approximation.
-		 *
-		 * @param	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastACos0".
-		 */
-		static float fastACos1(float val);
-
-		/**
-		 * @brief	Inverse tangent function approximation.
-		 *
-		 * @param	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastATan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse tangent function approximation.
-		 *
-		 * @param	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastATan0(float val);
-
-		/**
-		 * @brief	Inverse tangent function approximation.
-		 *
-		 * @param	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastATan0".
-		 */
-		static float fastATan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
-
-		/**
-		 * @brief	Inverse tangent function approximation.
-		 *
-		 * @param	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 * 			Slightly better (and slower) than "fastATan0".
-		 */
-		static float fastATan1(float val);
-
-		/**
-		 * @brief	Interpolates between min and max. Returned value is in
-		 *			[0, 1] range where min = 0, max = 1 and 0.5 is the average
-		 *			of min and max.
-		 */
-		template <typename T>
-		static float lerp01(T val, T min, T max)
-		{
-			return clamp01((val - min) / std::max(max - min, 0.0001F));
-		}
-
-		/**
-		 * @brief	Solves the linear equation with the parameters A, B.
-		 *			Returns number of roots found and the roots themselves will
-		 *			be output in the "roots" array.
-		 *
-		 * @param	roots	Must be at least size of 1.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveLinear(T A, T B, T* roots)
-		{
-			if (!approxEquals(A, (T)0))
-			{
-				roots[0] = -B / A;
-				return 1;
-			}
-
-			roots[0] = 0.0f;
-			return 1;
-		}
-
-		/**
-		 * @brief	Solves the quadratic equation with the parameters A, B, C.
-		 *			Returns number of roots found and the roots themselves will
-		 *			be output in the "roots" array.
-		 *
-		 * @param	roots	Must be at least size of 2.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
-		{
-			if (!approxEquals(A, (T)0))
-			{
-				T p = B / (2 * A);
-				T q = C / A;
-				T D = p * p - q;
-
-				if (!approxEquals(D, (T)0))
-				{
-					if (D < (T)0)
-						return 0;
-					
-					T sqrtD = sqrt(D);
-					roots[0] = sqrtD - p;
-					roots[1] = -sqrtD - p;
-
-					return 2;
-				}
-				else
-				{
-					roots[0] = -p;
-					roots[1] = -p;
-
-					return 1;
-				}
-			}
-			else
-			{
-				return solveLinear(B, C, roots);
-			}
-		}
-
-		/**
-		 * @brief	Solves the cubic equation with the parameters A, B, C, D.
-		 *			Returns number of roots found and the roots themselves will
-		 *			be output in the "roots" array.
-		 *
-		 * @param	roots	Must be at least size of 3.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveCubic(T A, T B, T C, T D, T* roots)
-		{
-			static const T THIRD = (1 / (T)3);
-
-			T invA = 1 / A;
-			A = B * invA;
-			B = C * invA;
-			C = D * invA;
-
-			T sqA = A * A;
-			T p = THIRD * (-THIRD * sqA + B);
-			T q = ((T)0.5) * ((2 / (T)27) * A * sqA - THIRD * A * B + C);
-
-			T cbp = p * p * p;
-			D = q * q + cbp;
-
-			UINT32 numRoots = 0;
-			if (!approxEquals(D, (T)0))
-			{
-				if (D < 0.0)
-				{
-					T phi = THIRD * ::acos(-q / sqrt(-cbp));
-					T t = 2 * sqrt(-p);
-
-					roots[0] = t * cos(phi);
-					roots[1] = -t * cos(phi + PI * THIRD);
-					roots[2] = -t * cos(phi - PI * THIRD);
-
-					numRoots = 3;
-				}
-				else
-				{
-					T sqrtD = sqrt(D);
-					T u = cbrt(sqrtD + fabs(q));
-
-					if (q > (T)0)
-						roots[0] = -u + p / u;
-					else
-						roots[0] = u - p / u;
-
-					numRoots = 1;
-				}
-			}
-			else
-			{
-				if (!approxEquals(q, (T)0))
-				{
-					T u = cbrt(-q);
-					roots[0] = 2 * u;
-					roots[1] = -u;
-
-					numRoots = 2;
-				}
-				else
-				{
-					roots[0] = 0.0f;
-					numRoots = 1;
-				}
-			}
-
-			T sub = THIRD * A;
-			for (UINT32 i = 0; i < numRoots; i++)
-				roots[i] -= sub;
-
-			return numRoots;
-		}
-
-		/**
-		 * @brief	Solves the quartic equation with the parameters A, B, C, D, E.
-		 *			Returns number of roots found and the roots themselves will
-		 *			be output in the "roots" array.
-		 *
-		 * @param	roots	Must be at least size of 4.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
-		{
-			T invA = 1 / A;
-			A = B * invA;
-			B = C * invA;
-			C = D * invA;
-			D = E * invA;
-
-			T sqA = A*A;
-			T p = -(3 / (T)8) * sqA + B;
-			T q = (1 / (T)8) * sqA * A - (T)0.5 * A * B + C;
-			T r = -(3 / (T)256) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
-
-			UINT32 numRoots = 0;
-			if (!approxEquals(r, (T)0))
-			{
-				T cubicA = 1;
-				T cubicB = -(T)0.5 * p ;
-				T cubicC = -r;
-				T cubicD = (T)0.5 * r * p - (1 / (T)8) * q * q;
-
-				solveCubic(cubicA, cubicB, cubicC, cubicD, roots);
-				T z = roots[0];
-
-				T u = z * z - r;
-				T v = 2 * z - p;
-
-				if (approxEquals(u, T(0)))
-					u = 0;
-				else if (u > 0)
-					u = sqrt(u);
-				else
-					return 0;
-
-				if (approxEquals(v, T(0)))
-					v = 0;
-				else if (v > 0)
-					v = sqrt(v);
-				else
-					return 0;
-
-				T quadraticA = 1;
-				T quadraticB = q < 0 ? -v : v;
-				T quadraticC = z - u;
-
-				numRoots = solveQuadratic(quadraticA, quadraticB, quadraticC, roots);
-
-				quadraticA = 1;
-				quadraticB = q < 0 ? v : -v;
-				quadraticC = z + u;
-
-				numRoots += solveQuadratic(quadraticA, quadraticB, quadraticC, roots + numRoots);
-			}
-			else
-			{
-				numRoots = solveCubic(q, p, (T)0, (T)1, roots);
-				roots[numRoots++] = 0;
-			}
-
-			T sub = (1/(T)4) * A;
-			for (UINT32 i = 0; i < numRoots; i++)
-				roots[i] -= sub;
-
-			return numRoots;
-		}
-
-        static const float POS_INFINITY;
-        static const float NEG_INFINITY;
-        static const float PI;
-        static const float TWO_PI;
-        static const float HALF_PI;
-		static const float DEG2RAD;
-		static const float RAD2DEG;
-		static const float LOG2;
-    };
-}
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsDegree.h"
+#include "BsRadian.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** Utility class providing common scalar math operations. */
+    class BS_UTILITY_EXPORT Math 
+    {
+    public:
+		static Radian acos(float val);
+		static Radian asin(float val);
+		static Radian atan(float val) { return Radian(std::atan(val)); }
+		static Radian atan2(float y, float x) { return Radian(std::atan2(y,x)); }
+
+        static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
+        static float cos(float val) { return (float)std::cos(val); }
+
+        static float sin(const Radian& val) { return (float)std::sin(val.valueRadians()); }
+        static float sin(float val) { return (float)std::sin(val); }
+
+		static float tan(const Radian& val) { return (float)std::tan(val.valueRadians()); }
+		static float tan(float val) { return (float)std::tan(val); }
+
+		static float sqrt(float val) { return (float)std::sqrt(val); }
+        static Radian sqrt(const Radian& val) { return Radian(std::sqrt(val.valueRadians())); }
+        static Degree sqrt(const Degree& val) { return Degree(std::sqrt(val.valueDegrees())); }
+
+		static float invSqrt(float val);
+		static float sqr(float val) { return val*val; }
+
+		static float pow(float base, float exponent) { return (float)std::pow(base, exponent); }
+		static float exp(float val) { return (float)std::exp(val); }
+
+		static float log(float val) { return (float)std::log(val); }
+		static float log2(float val) { return (float)(std::log(val)/LOG2); }
+		static float logN(float base, float val) { return (float)(std::log(val)/std::log(base)); }
+
+		static float sign(float val);
+		static Radian sign(const Radian& val) { return Radian(sign(val.valueRadians())); }
+		static Degree sign(const Degree& val) { return Degree(sign(val.valueDegrees())); }
+
+		static float abs(float val) { return float(std::fabs(val)); }
+		static Degree abs(const Degree& val) { return Degree(std::fabs(val.valueDegrees())); }
+		static Radian abs(const Radian& val) { return Radian(std::fabs(val.valueRadians())); }
+
+		static float ceil(float val) { return (float)std::ceil(val); }
+		static int ceilToInt(float val) { return (int)std::ceil(val); }
+
+		static float round(float val) { return (float)std::floor(val + 0.5f); }
+		static int roundToInt(float val) { return (int)std::floor(val + 0.5f); }
+
+		static float floor(float val) { return (float)std::floor(val); }
+		static int floorToInt(float val) { return (int)std::floor(val); }
+
+		/** Clamp a value within an inclusive range. */
+		template <typename T>
+		static T clamp(T val, T minval, T maxval)
+		{
+			assert (minval <= maxval && "Invalid clamp range");
+			return std::max(std::min(val, maxval), minval);
+		}
+
+		/** Clamp a value within an inclusive range [0..1]. */
+		template <typename T>
+		static T clamp01(T val)
+		{
+			return std::max(std::min(val, (T)1), (T)0);
+		}
+
+		/** Checks is the specified value a power of two. Only works on integer values. */
+		template <typename T>
+		static bool isPow2(T val)
+		{
+			return (val & (val - 1)) == 0;
+		}
+
+		static bool isNaN(float f)
+		{
+			return f != f;
+		}
+
+        /** Compare two floats, using tolerance for inaccuracies. */
+        static bool approxEquals(float a, float b, float tolerance = std::numeric_limits<float>::epsilon());
+
+        /** Compare two doubles, using tolerance for inaccuracies. */
+		static bool approxEquals(double a, double b, double tolerance = std::numeric_limits<double>::epsilon());
+
+		/** Compare two 2D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector2& a, const Vector2& b, float tolerance = std::numeric_limits<float>::epsilon());
+
+		/** Compare two 3D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector3& a, const Vector3& b, float tolerance = std::numeric_limits<float>::epsilon());
+
+		/** Compare two 4D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector4& a, const Vector4& b, float tolerance = std::numeric_limits<float>::epsilon());
+
+        /** Calculates the tangent space vector for a given set of positions / texture coords. */
+        static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
+			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
+
+		/************************************************************************/
+		/* 							TRIG APPROXIMATIONS                      	*/
+		/************************************************************************/
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(float val);
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
+		 */
+		static float fastSin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
+		 */
+		static float fastSin1(float val);
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(float val);
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
+		 */
+		static float fastCos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
+		 */
+		static float fastCos1(float val);
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(float val);
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
+		 */
+		static float fastTan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
+		 */
+		static float fastTan1(float val);
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(float val);
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
+		 */
+		static float fastASin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
+		 */
+		static float fastASin1(float val);
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(float val);
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
+		 */
+		static float fastACos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
+		 */
+		static float fastACos1(float val);
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(float val);
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
+		 */
+		static float fastATan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
+		 */
+		static float fastATan1(float val);
+
+		/**
+		 * Interpolates between min and max. Returned value is in [0, 1] range where min = 0, max = 1 and 0.5 is 
+		 * the average of min and max.
+		 */
+		template <typename T>
+		static float lerp01(T val, T min, T max)
+		{
+			return clamp01((val - min) / std::max(max - min, 0.0001F));
+		}
+
+		/**
+		 * Solves the linear equation with the parameters A, B. Returns number of roots found and the roots themselves will
+		 * be output in the @p roots array.
+		 *
+		 * @param[out]	roots	Must be at least size of 1.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveLinear(T A, T B, T* roots)
+		{
+			if (!approxEquals(A, (T)0))
+			{
+				roots[0] = -B / A;
+				return 1;
+			}
+
+			roots[0] = 0.0f;
+			return 1;
+		}
+
+		/**
+		 * Solves the quadratic equation with the parameters A, B, C. Returns number of roots found and the roots themselves
+		 * will be output in the @p roots array.
+		 *
+		 * @param[out]	roots	Must be at least size of 2.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
+		{
+			if (!approxEquals(A, (T)0))
+			{
+				T p = B / (2 * A);
+				T q = C / A;
+				T D = p * p - q;
+
+				if (!approxEquals(D, (T)0))
+				{
+					if (D < (T)0)
+						return 0;
+					
+					T sqrtD = sqrt(D);
+					roots[0] = sqrtD - p;
+					roots[1] = -sqrtD - p;
+
+					return 2;
+				}
+				else
+				{
+					roots[0] = -p;
+					roots[1] = -p;
+
+					return 1;
+				}
+			}
+			else
+			{
+				return solveLinear(B, C, roots);
+			}
+		}
+
+		/**
+		 * Solves the cubic equation with the parameters A, B, C, D. Returns number of roots found and the roots themselves 
+		 * will be output in the @p roots array.
+		 *
+		 * @param[out]	roots	Must be at least size of 3.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveCubic(T A, T B, T C, T D, T* roots)
+		{
+			static const T THIRD = (1 / (T)3);
+
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
+
+			T sqA = A * A;
+			T p = THIRD * (-THIRD * sqA + B);
+			T q = ((T)0.5) * ((2 / (T)27) * A * sqA - THIRD * A * B + C);
+
+			T cbp = p * p * p;
+			D = q * q + cbp;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(D, (T)0))
+			{
+				if (D < 0.0)
+				{
+					T phi = THIRD * ::acos(-q / sqrt(-cbp));
+					T t = 2 * sqrt(-p);
+
+					roots[0] = t * cos(phi);
+					roots[1] = -t * cos(phi + PI * THIRD);
+					roots[2] = -t * cos(phi - PI * THIRD);
+
+					numRoots = 3;
+				}
+				else
+				{
+					T sqrtD = sqrt(D);
+					T u = cbrt(sqrtD + fabs(q));
+
+					if (q > (T)0)
+						roots[0] = -u + p / u;
+					else
+						roots[0] = u - p / u;
+
+					numRoots = 1;
+				}
+			}
+			else
+			{
+				if (!approxEquals(q, (T)0))
+				{
+					T u = cbrt(-q);
+					roots[0] = 2 * u;
+					roots[1] = -u;
+
+					numRoots = 2;
+				}
+				else
+				{
+					roots[0] = 0.0f;
+					numRoots = 1;
+				}
+			}
+
+			T sub = THIRD * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
+		}
+
+		/**
+		 * Solves the quartic equation with the parameters A, B, C, D, E. Returns number of roots found and the roots 
+		 * themselves will be output in the @p roots array.
+		 *
+		 * @param[out]	roots	Must be at least size of 4.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
+		{
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
+			D = E * invA;
+
+			T sqA = A*A;
+			T p = -(3 / (T)8) * sqA + B;
+			T q = (1 / (T)8) * sqA * A - (T)0.5 * A * B + C;
+			T r = -(3 / (T)256) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(r, (T)0))
+			{
+				T cubicA = 1;
+				T cubicB = -(T)0.5 * p ;
+				T cubicC = -r;
+				T cubicD = (T)0.5 * r * p - (1 / (T)8) * q * q;
+
+				solveCubic(cubicA, cubicB, cubicC, cubicD, roots);
+				T z = roots[0];
+
+				T u = z * z - r;
+				T v = 2 * z - p;
+
+				if (approxEquals(u, T(0)))
+					u = 0;
+				else if (u > 0)
+					u = sqrt(u);
+				else
+					return 0;
+
+				if (approxEquals(v, T(0)))
+					v = 0;
+				else if (v > 0)
+					v = sqrt(v);
+				else
+					return 0;
+
+				T quadraticA = 1;
+				T quadraticB = q < 0 ? -v : v;
+				T quadraticC = z - u;
+
+				numRoots = solveQuadratic(quadraticA, quadraticB, quadraticC, roots);
+
+				quadraticA = 1;
+				quadraticB = q < 0 ? v : -v;
+				quadraticC = z + u;
+
+				numRoots += solveQuadratic(quadraticA, quadraticB, quadraticC, roots + numRoots);
+			}
+			else
+			{
+				numRoots = solveCubic(q, p, (T)0, (T)1, roots);
+				roots[numRoots++] = 0;
+			}
+
+			T sub = (1/(T)4) * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
+		}
+
+        static const float POS_INFINITY;
+        static const float NEG_INFINITY;
+        static const float PI;
+        static const float TWO_PI;
+        static const float HALF_PI;
+		static const float DEG2RAD;
+		static const float RAD2DEG;
+		static const float LOG2;
+    };
+
+	/** @} */
+}

+ 296 - 322
BansheeUtility/Include/BsMatrix3.h

@@ -1,323 +1,297 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-    /**
-     * @brief	A 3x3 matrix. Can be used for non-homogenous transformations
-     *          of three dimensional vectors and points.
-     */
-    class BS_UTILITY_EXPORT Matrix3
-    {
-	private:
-		struct EulerAngleOrderData
-		{
-			int a, b, c;
-			float sign;
-		};
-
-    public:
-		Matrix3() {}
-
-        Matrix3(const Matrix3& mat)
-		{
-			memcpy(m, mat.m, 9*sizeof(float));
-		}
-
-        Matrix3(float m00, float m01, float m02,
-                float m10, float m11, float m12,
-                float m20, float m21, float m22)
-		{
-			m[0][0] = m00;
-			m[0][1] = m01;
-			m[0][2] = m02;
-			m[1][0] = m10;
-			m[1][1] = m11;
-			m[1][2] = m12;
-			m[2][0] = m20;
-			m[2][1] = m21;
-			m[2][2] = m22;
-		}
-
-		/**
-         * @brief	Construct a matrix from a quaternion.
-         */
-        explicit Matrix3(const Quaternion& rotation)
-        {
-            fromQuaternion(rotation);
-        }
-
-		/**
-         * @brief	Construct a matrix that performs rotation and scale.
-         */
-        explicit Matrix3(const Quaternion& rotation, const Vector3& scale)
-        {
-            fromQuaternion(rotation);
-			
-			for (int row = 0; row < 3; row++)
-			{
-				for (int col = 0; col < 3; col++)
-					m[row][col] = scale[row]*m[row][col];
-			}
-        }
-
-		/**
-         * @brief	Construct a matrix from an angle/axis pair.
-         */
-        explicit Matrix3(const Vector3& axis, const Radian& angle)
-        {
-            fromAxisAngle(axis, angle);
-        }
-
-        /**
-         * @brief	Construct a matrix from 3 orthonormal local axes.
-         */
-        explicit Matrix3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
-        {
-            fromAxes(xaxis, yaxis, zaxis);
-        }
-
-        /**
-         * @brief	Construct a matrix from euler angles, YXZ ordering.
-         * 			
-		 * @see		Matrix3::fromEulerAngles
-         */
-		explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
-		{
-			fromEulerAngles(xAngle, yAngle, zAngle);
-		}
-
-        /**
-         * @brief	Construct a matrix from euler angles, custom ordering.
-         * 			
-		 * @see		Matrix3::fromEulerAngles
-         */
-		explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
-		{
-			fromEulerAngles(xAngle, yAngle, zAngle, order);
-		}
-
-		/**
-		 * @brief	Swaps the contents of this matrix with another.
-		 */
-		void swap(Matrix3& other)
-		{
-			std::swap(m[0][0], other.m[0][0]);
-			std::swap(m[0][1], other.m[0][1]);
-			std::swap(m[0][2], other.m[0][2]);
-			std::swap(m[1][0], other.m[1][0]);
-			std::swap(m[1][1], other.m[1][1]);
-			std::swap(m[1][2], other.m[1][2]);
-			std::swap(m[2][0], other.m[2][0]);
-			std::swap(m[2][1], other.m[2][1]);
-			std::swap(m[2][2], other.m[2][2]);
-		}
-
-        /**
-         * @brief	Returns a row of the matrix.
-         */
-        inline float* operator[] (UINT32 row) const
-		{
-			assert(row < 3);
-
-			return (float*)m[row];
-		}
-
-        Vector3 getColumn(UINT32 col) const;
-        void setColumn(UINT32 col, const Vector3& vec);
-
-        Matrix3& operator= (const Matrix3& rhs)
-		{
-			memcpy(m, rhs.m, 9*sizeof(float));
-			return *this;
-		}
-        bool operator== (const Matrix3& rhs) const;
-        bool operator!= (const Matrix3& rhs) const;
-
-        Matrix3 operator+ (const Matrix3& rhs) const;
-        Matrix3 operator- (const Matrix3& rhs) const;
-        Matrix3 operator* (const Matrix3& rhs) const;
-        Matrix3 operator- () const;
-		Matrix3 operator* (float rhs) const;
-
-		friend Matrix3 operator* (float lhs, const Matrix3& rhs);
-
-		/**
-		 * @brief	Transforms the given vector by this matrix and returns
-		 * 			the newly transformed vector.
-		 */
-		Vector3 transform(const Vector3& vec) const;
-
-        /**
-         * @brief	Returns a transpose of the matrix (switched columns and rows).
-         */
-        Matrix3 transpose () const;
-
-        /**
-         * @brief	Calculates an inverse of the matrix if it exists.
-         *
-         * @param [out]	mat		Resulting matrix inverse.
-         * @param	fTolerance 	(optional) Tolerance to use when checking
-         * 						if determinant is zero (or near zero in this case).
-         * 						Zero determinant means inverse doesn't exist.
-         *
-         * @return	True if inverse exists, false otherwise.
-         */
-        bool inverse(Matrix3& mat, float fTolerance = 1e-06f) const;
-
-        /**
-         * @brief	Calculates an inverse of the matrix if it exists.
-         *
-		 * @param	fTolerance 	(optional) Tolerance to use when checking
-		 * 						if determinant is zero (or near zero in this case).
-		 * 						Zero determinant means inverse doesn't exist.
-         *
-         * @return	Resulting matrix inverse if it exists, otherwise a zero matrix.
-         */
-        Matrix3 inverse(float fTolerance = 1e-06f) const;
-
-        /**
-         * @brief	Calculates the matrix determinant.
-         */
-        float determinant() const;
-
-        /**
-         * @brief	Decompose a Matrix3 to rotation and scale.
-         *
-         * @note	Matrix must consist only of rotation and uniform scale transformations,
-         * 			otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees
-         * 			rotation portion will not be accurate.
-         */
-        void decomposition(Quaternion& rotation, Vector3& scale) const;
-
-        /**
-         * @brief	Decomposes the matrix into various useful values.
-         *
-         * @param [out]	matL	Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
-         * 						doesn't use non-uniform scaling this matrix will be a conjugate transpose of the rotation part of the matrix.
-         * @param [out]	matS	Singular values of the matrix. If your matrix is affine these will be scaling factors of the matrix.
-		 * @param [out]	matR	Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
-		 * 						doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
-         */
-        void singularValueDecomposition(Matrix3& matL, Vector3& matS, Matrix3& matR) const;
-
-        /**
-         * @brief	Decomposes the matrix into a set of values.
-         *
-         * @param [out]	matQ	Columns form orthonormal bases. If your matrix is affine and
-         * 						doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
-         * @param [out]	vecD	If the matrix is affine these will be scaling factors of the matrix.
-		 * @param [out]	vecU	If the matrix is affine these will be shear factors of the matrix.
-         */
-		void QDUDecomposition(Matrix3& matQ, Vector3& vecD, Vector3& vecU) const;
-
-        /**
-         * @brief	Gram-Schmidt orthonormalization (applied to columns of rotation matrix)
-         */
-        void orthonormalize();
-
-        /**
-         * @brief	Converts an orthonormal matrix to axis angle representation.
-         *
-         * @note	Matrix must be orthonormal.
-         */
-        void toAxisAngle(Vector3& axis, Radian& angle) const;
-
-        /**
-         * @brief	Creates a rotation matrix from an axis angle representation.
-         */
-        void fromAxisAngle(const Vector3& axis, const Radian& angle);
-
-        /**
-         * @brief	Converts an orthonormal matrix to quaternion representation.
-         *
-         * @note	Matrix must be orthonormal.
-         */
-        void toQuaternion(Quaternion& quat) const;
-
-        /**
-         * @brief	Creates a rotation matrix from a quaternion representation.
-         */
-        void fromQuaternion(const Quaternion& quat);
-
-        /**
-         * @brief	Creates a matrix from a three axes.
-         */
-		void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
-
-        /**
-         * @brief	Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
-         *
-         * @param [in,out]	xAngle	Rotation about x axis. (AKA Pitch)
-         * @param [in,out]	yAngle  Rotation about y axis. (AKA Yaw)
-         * @param [in,out]	zAngle 	Rotation about z axis. (AKA Roll)
-         *
-         * @return	True if unique solution was found, false otherwise.
-         * 			
-		 * @note	Matrix must be orthonormal.
-         */
-        bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
-
-        /**
-         * @brief	Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
-         *
-		 * @param	xAngle	Rotation about x axis. (AKA Pitch)
-		 * @param	yAngle	Rotation about y axis. (AKA Yaw)
-		 * @param	zAngle	Rotation about z axis. (AKA Roll)
-         *
-         * @note	Matrix must be orthonormal.
-		 * 			Since different values will be produced depending in which order are the rotations applied, this method assumes
-		 * 			they are applied in YXZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
-         */
-        void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
-
-        /**
-         * @brief	Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
-         *
-		 * @param	xAngle	Rotation about x axis. (AKA Pitch)
-		 * @param	yAngle	Rotation about y axis. (AKA Yaw)
-		 * @param	zAngle	Rotation about z axis. (AKA Roll)
-		 * @param	order 	The order in which rotations will be applied.
-		 * 					Different rotations can be created depending on the order.
-         *
-         * @note	Matrix must be orthonormal.
-         */
-        void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
-
-        /**
-         * @brief	Eigensolver, matrix must be symmetric.
-		 *
-		 * @note	Eigenvectors are vectors which when transformed by the matrix, only change
-		 *			in magnitude, but not in direction. Eigenvalue is that magnitude. In other words
-		 *			you will get the same result whether you multiply the vector by the matrix or by its
-		 *			eigenvalue.
-         */
-        void eigenSolveSymmetric(float eigenValues[3], Vector3 eigenVectors[3]) const;
-
-        static const float EPSILON;
-        static const Matrix3 ZERO;
-        static const Matrix3 IDENTITY;
-
-    protected:
-		friend class Matrix4;
-
-        // Support for eigensolver
-        void tridiagonal (float diag[3], float subDiag[3]);
-        bool QLAlgorithm (float diag[3], float subDiag[3]);
-
-        // Support for singular value decomposition
-        static const float SVD_EPSILON;
-        static const unsigned int SVD_MAX_ITERS;
-        static void bidiagonalize (Matrix3& matA, Matrix3& matL, Matrix3& matR);
-        static void golubKahanStep (Matrix3& matA, Matrix3& matL, Matrix3& matR);
-
-		// Euler angle conversions
-		static const EulerAngleOrderData EA_LOOKUP[6];
-
-        float m[3][3];
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Matrix3);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** A 3x3 matrix. Can be used for non-homogenous transformations of three dimensional vectors and points. */
+    class BS_UTILITY_EXPORT Matrix3
+    {
+	private:
+		struct EulerAngleOrderData
+		{
+			int a, b, c;
+			float sign;
+		};
+
+    public:
+		Matrix3() {}
+
+        Matrix3(const Matrix3& mat)
+		{
+			memcpy(m, mat.m, 9*sizeof(float));
+		}
+
+        Matrix3(float m00, float m01, float m02,
+                float m10, float m11, float m12,
+                float m20, float m21, float m22)
+		{
+			m[0][0] = m00;
+			m[0][1] = m01;
+			m[0][2] = m02;
+			m[1][0] = m10;
+			m[1][1] = m11;
+			m[1][2] = m12;
+			m[2][0] = m20;
+			m[2][1] = m21;
+			m[2][2] = m22;
+		}
+
+		/** Construct a matrix from a quaternion. */
+        explicit Matrix3(const Quaternion& rotation)
+        {
+            fromQuaternion(rotation);
+        }
+
+		/** Construct a matrix that performs rotation and scale. */
+        explicit Matrix3(const Quaternion& rotation, const Vector3& scale)
+        {
+            fromQuaternion(rotation);
+			
+			for (int row = 0; row < 3; row++)
+			{
+				for (int col = 0; col < 3; col++)
+					m[row][col] = scale[row]*m[row][col];
+			}
+        }
+
+		/** Construct a matrix from an angle/axis pair. */
+        explicit Matrix3(const Vector3& axis, const Radian& angle)
+        {
+            fromAxisAngle(axis, angle);
+        }
+
+        /** Construct a matrix from 3 orthonormal local axes. */
+        explicit Matrix3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
+        {
+            fromAxes(xaxis, yaxis, zaxis);
+        }
+
+        /** 
+		 * Construct a matrix from euler angles, YXZ ordering.
+         * 			
+		 * @see		Matrix3::fromEulerAngles
+         */
+		explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
+		{
+			fromEulerAngles(xAngle, yAngle, zAngle);
+		}
+
+        /**
+         * Construct a matrix from euler angles, custom ordering.
+         * 			
+		 * @see		Matrix3::fromEulerAngles
+         */
+		explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
+		{
+			fromEulerAngles(xAngle, yAngle, zAngle, order);
+		}
+
+		/** Swaps the contents of this matrix with another. */
+		void swap(Matrix3& other)
+		{
+			std::swap(m[0][0], other.m[0][0]);
+			std::swap(m[0][1], other.m[0][1]);
+			std::swap(m[0][2], other.m[0][2]);
+			std::swap(m[1][0], other.m[1][0]);
+			std::swap(m[1][1], other.m[1][1]);
+			std::swap(m[1][2], other.m[1][2]);
+			std::swap(m[2][0], other.m[2][0]);
+			std::swap(m[2][1], other.m[2][1]);
+			std::swap(m[2][2], other.m[2][2]);
+		}
+
+        /** Returns a row of the matrix. */
+        float* operator[] (UINT32 row) const
+		{
+			assert(row < 3);
+
+			return (float*)m[row];
+		}
+
+        Vector3 getColumn(UINT32 col) const;
+        void setColumn(UINT32 col, const Vector3& vec);
+
+        Matrix3& operator= (const Matrix3& rhs)
+		{
+			memcpy(m, rhs.m, 9*sizeof(float));
+			return *this;
+		}
+        bool operator== (const Matrix3& rhs) const;
+        bool operator!= (const Matrix3& rhs) const;
+
+        Matrix3 operator+ (const Matrix3& rhs) const;
+        Matrix3 operator- (const Matrix3& rhs) const;
+        Matrix3 operator* (const Matrix3& rhs) const;
+        Matrix3 operator- () const;
+		Matrix3 operator* (float rhs) const;
+
+		friend Matrix3 operator* (float lhs, const Matrix3& rhs);
+
+		/** Transforms the given vector by this matrix and returns the newly transformed vector. */
+		Vector3 transform(const Vector3& vec) const;
+
+        /** Returns a transpose of the matrix (switched columns and rows). */
+        Matrix3 transpose () const;
+
+        /**
+         * Calculates an inverse of the matrix if it exists.
+         *
+         * @param[out]	mat			Resulting matrix inverse.
+         * @param[in]	fTolerance 	(optional) Tolerance to use when checking if determinant is zero (or near zero in this case).
+         * 							Zero determinant means inverse doesn't exist.
+         * @return					True if inverse exists, false otherwise.
+         */
+        bool inverse(Matrix3& mat, float fTolerance = 1e-06f) const;
+
+        /**
+         * Calculates an inverse of the matrix if it exists.
+         *
+		 * @param[in]	fTolerance 	(optional) Tolerance to use when checking if determinant is zero (or near zero in this case).
+		 * 							Zero determinant means inverse doesn't exist.
+         *
+         * @return					Resulting matrix inverse if it exists, otherwise a zero matrix.
+         */
+        Matrix3 inverse(float fTolerance = 1e-06f) const;
+
+        /** Calculates the matrix determinant. */
+        float determinant() const;
+
+        /**
+         * Decompose a Matrix3 to rotation and scale.
+         *
+         * @note	
+		 * Matrix must consist only of rotation and uniform scale transformations, otherwise accurate results are not 
+		 * guaranteed. Applying non-uniform scale guarantees rotation portion will not be accurate.
+         */
+        void decomposition(Quaternion& rotation, Vector3& scale) const;
+
+        /**
+         * Decomposes the matrix into various useful values.
+         *
+         * @param[out]	matL	Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
+         * 						doesn't use non-uniform scaling this matrix will be a conjugate transpose of the rotation part of the matrix.
+         * @param[out]	matS	Singular values of the matrix. If your matrix is affine these will be scaling factors of the matrix.
+		 * @param[out]	matR	Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
+		 * 						doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
+         */
+        void singularValueDecomposition(Matrix3& matL, Vector3& matS, Matrix3& matR) const;
+
+        /**
+         * Decomposes the matrix into a set of values.
+         *
+         * @param[out]	matQ	Columns form orthonormal bases. If your matrix is affine and
+         * 						doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
+         * @param[out]	vecD	If the matrix is affine these will be scaling factors of the matrix.
+		 * @param[out]	vecU	If the matrix is affine these will be shear factors of the matrix.
+         */
+		void QDUDecomposition(Matrix3& matQ, Vector3& vecD, Vector3& vecU) const;
+
+        /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
+        void orthonormalize();
+
+        /**
+         * Converts an orthonormal matrix to axis angle representation.
+         *
+         * @note	Matrix must be orthonormal.
+         */
+        void toAxisAngle(Vector3& axis, Radian& angle) const;
+
+        /** Creates a rotation matrix from an axis angle representation. */
+        void fromAxisAngle(const Vector3& axis, const Radian& angle);
+
+        /**
+         * Converts an orthonormal matrix to quaternion representation.
+         *
+         * @note	Matrix must be orthonormal.
+         */
+        void toQuaternion(Quaternion& quat) const;
+
+        /** Creates a rotation matrix from a quaternion representation. */
+        void fromQuaternion(const Quaternion& quat);
+
+        /** Creates a matrix from a three axes. */
+		void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
+
+        /**
+         * Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
+         *
+         * @param[in,out]	xAngle	Rotation about x axis. (AKA Pitch)
+         * @param[in,out]	yAngle  Rotation about y axis. (AKA Yaw)
+         * @param[in,out]	zAngle 	Rotation about z axis. (AKA Roll)
+         * @return					True if unique solution was found, false otherwise.
+         * 			
+		 * @note	Matrix must be orthonormal.
+         */
+        bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
+
+        /**
+         * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
+         *
+		 * @param[in]	xAngle	Rotation about x axis. (AKA Pitch)
+		 * @param[in]	yAngle	Rotation about y axis. (AKA Yaw)
+		 * @param[in]	zAngle	Rotation about z axis. (AKA Roll)
+         *
+         * @note	Matrix must be orthonormal.
+		 * 			Since different values will be produced depending in which order are the rotations applied, this method assumes
+		 * 			they are applied in YXZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
+         */
+        void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
+
+        /**
+         * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
+         *
+		 * @param[in]	xAngle	Rotation about x axis. (AKA Pitch)
+		 * @param[in]	yAngle	Rotation about y axis. (AKA Yaw)
+		 * @param[in]	zAngle	Rotation about z axis. (AKA Roll)
+		 * @param[in]	order 	The order in which rotations will be applied. 
+		 *						Different rotations can be created depending on the order.
+         *
+         * @note	Matrix must be orthonormal.
+         */
+        void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
+
+        /**
+         * Eigensolver, matrix must be symmetric.
+		 *
+		 * @note	
+		 * Eigenvectors are vectors which when transformed by the matrix, only change in magnitude, but not in direction. 
+		 * Eigenvalue is that magnitude. In other words you will get the same result whether you multiply the vector by the 
+		 * matrix or by its eigenvalue.
+         */
+        void eigenSolveSymmetric(float eigenValues[3], Vector3 eigenVectors[3]) const;
+
+        static const float EPSILON;
+        static const Matrix3 ZERO;
+        static const Matrix3 IDENTITY;
+
+    protected:
+		friend class Matrix4;
+
+        // Support for eigensolver
+        void tridiagonal (float diag[3], float subDiag[3]);
+        bool QLAlgorithm (float diag[3], float subDiag[3]);
+
+        // Support for singular value decomposition
+        static const float SVD_EPSILON;
+        static const unsigned int SVD_MAX_ITERS;
+        static void bidiagonalize (Matrix3& matA, Matrix3& matL, Matrix3& matR);
+        static void golubKahanStep (Matrix3& matA, Matrix3& matL, Matrix3& matR);
+
+		// Euler angle conversions
+		static const EulerAngleOrderData EA_LOOKUP[6];
+
+        float m[3][3];
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Matrix3);
+	/** @endcond */
 }

+ 465 - 494
BansheeUtility/Include/BsMatrix4.h

@@ -1,495 +1,466 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-#include "BsVector3.h"
-#include "BsMatrix3.h"
-#include "BsVector4.h"
-#include "BsPlane.h"
-
-namespace BansheeEngine
-{
-	 /**
-     * @brief	Class representing a 4x4 matrix.
-     */
-    class BS_UTILITY_EXPORT Matrix4
-    {
-    private:
-        union 
-		{
-            float m[4][4];
-            float _m[16];
-        };
-
-    public:
-        Matrix4()
-        { }
-
-        Matrix4(
-            float m00, float m01, float m02, float m03,
-            float m10, float m11, float m12, float m13,
-            float m20, float m21, float m22, float m23,
-            float m30, float m31, float m32, float m33)
-        {
-            m[0][0] = m00;
-            m[0][1] = m01;
-            m[0][2] = m02;
-            m[0][3] = m03;
-            m[1][0] = m10;
-            m[1][1] = m11;
-            m[1][2] = m12;
-            m[1][3] = m13;
-            m[2][0] = m20;
-            m[2][1] = m21;
-            m[2][2] = m22;
-            m[2][3] = m23;
-            m[3][0] = m30;
-            m[3][1] = m31;
-            m[3][2] = m32;
-            m[3][3] = m33;
-        }
-
-		Matrix4(const Matrix4& mat)
-		{
-			memcpy(_m, mat._m, 16*sizeof(float));
-		}
-
-        /**
-         * @brief	Creates a 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
-         */
-        explicit Matrix4(const Matrix3& mat3)
-        {
-			m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2]; m[0][3] = 0.0f;
-			m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2]; m[1][3] = 0.0f;
-			m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2]; m[2][3] = 0.0f;
-			m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
-        }
-
-		/**
-		 * @brief	Swaps the contents of this matrix with another.
-		 */
-		void swap(Matrix4& other)
-		{
-			std::swap(m[0][0], other.m[0][0]);
-			std::swap(m[0][1], other.m[0][1]);
-			std::swap(m[0][2], other.m[0][2]);
-			std::swap(m[0][3], other.m[0][3]);
-			std::swap(m[1][0], other.m[1][0]);
-			std::swap(m[1][1], other.m[1][1]);
-			std::swap(m[1][2], other.m[1][2]);
-			std::swap(m[1][3], other.m[1][3]);
-			std::swap(m[2][0], other.m[2][0]);
-			std::swap(m[2][1], other.m[2][1]);
-			std::swap(m[2][2], other.m[2][2]);
-			std::swap(m[2][3], other.m[2][3]);
-			std::swap(m[3][0], other.m[3][0]);
-			std::swap(m[3][1], other.m[3][1]);
-			std::swap(m[3][2], other.m[3][2]);
-			std::swap(m[3][3], other.m[3][3]);
-		}
-
-		/**
-         * @brief	Returns a row of the matrix.
-         */
-		float* operator[] (UINT32 row)
-        {
-            assert(row < 4);
-
-            return m[row];
-        }
-
-        const float *operator[] (UINT32 row) const
-        {
-            assert(row < 4);
-
-            return m[row];
-        }
-
-        Matrix4 operator* (const Matrix4 &rhs) const
-        {
-			Matrix4 r;
-
-			r.m[0][0] = m[0][0] * rhs.m[0][0] + m[0][1] * rhs.m[1][0] + m[0][2] * rhs.m[2][0] + m[0][3] * rhs.m[3][0];
-			r.m[0][1] = m[0][0] * rhs.m[0][1] + m[0][1] * rhs.m[1][1] + m[0][2] * rhs.m[2][1] + m[0][3] * rhs.m[3][1];
-			r.m[0][2] = m[0][0] * rhs.m[0][2] + m[0][1] * rhs.m[1][2] + m[0][2] * rhs.m[2][2] + m[0][3] * rhs.m[3][2];
-			r.m[0][3] = m[0][0] * rhs.m[0][3] + m[0][1] * rhs.m[1][3] + m[0][2] * rhs.m[2][3] + m[0][3] * rhs.m[3][3];
-
-			r.m[1][0] = m[1][0] * rhs.m[0][0] + m[1][1] * rhs.m[1][0] + m[1][2] * rhs.m[2][0] + m[1][3] * rhs.m[3][0];
-			r.m[1][1] = m[1][0] * rhs.m[0][1] + m[1][1] * rhs.m[1][1] + m[1][2] * rhs.m[2][1] + m[1][3] * rhs.m[3][1];
-			r.m[1][2] = m[1][0] * rhs.m[0][2] + m[1][1] * rhs.m[1][2] + m[1][2] * rhs.m[2][2] + m[1][3] * rhs.m[3][2];
-			r.m[1][3] = m[1][0] * rhs.m[0][3] + m[1][1] * rhs.m[1][3] + m[1][2] * rhs.m[2][3] + m[1][3] * rhs.m[3][3];
-
-			r.m[2][0] = m[2][0] * rhs.m[0][0] + m[2][1] * rhs.m[1][0] + m[2][2] * rhs.m[2][0] + m[2][3] * rhs.m[3][0];
-			r.m[2][1] = m[2][0] * rhs.m[0][1] + m[2][1] * rhs.m[1][1] + m[2][2] * rhs.m[2][1] + m[2][3] * rhs.m[3][1];
-			r.m[2][2] = m[2][0] * rhs.m[0][2] + m[2][1] * rhs.m[1][2] + m[2][2] * rhs.m[2][2] + m[2][3] * rhs.m[3][2];
-			r.m[2][3] = m[2][0] * rhs.m[0][3] + m[2][1] * rhs.m[1][3] + m[2][2] * rhs.m[2][3] + m[2][3] * rhs.m[3][3];
-
-			r.m[3][0] = m[3][0] * rhs.m[0][0] + m[3][1] * rhs.m[1][0] + m[3][2] * rhs.m[2][0] + m[3][3] * rhs.m[3][0];
-			r.m[3][1] = m[3][0] * rhs.m[0][1] + m[3][1] * rhs.m[1][1] + m[3][2] * rhs.m[2][1] + m[3][3] * rhs.m[3][1];
-			r.m[3][2] = m[3][0] * rhs.m[0][2] + m[3][1] * rhs.m[1][2] + m[3][2] * rhs.m[2][2] + m[3][3] * rhs.m[3][2];
-			r.m[3][3] = m[3][0] * rhs.m[0][3] + m[3][1] * rhs.m[1][3] + m[3][2] * rhs.m[2][3] + m[3][3] * rhs.m[3][3];
-
-			return r;
-        }
-
-        Matrix4 operator+ (const Matrix4 &rhs) const
-        {
-            Matrix4 r;
-
-            r.m[0][0] = m[0][0] + rhs.m[0][0];
-            r.m[0][1] = m[0][1] + rhs.m[0][1];
-            r.m[0][2] = m[0][2] + rhs.m[0][2];
-            r.m[0][3] = m[0][3] + rhs.m[0][3];
-
-            r.m[1][0] = m[1][0] + rhs.m[1][0];
-            r.m[1][1] = m[1][1] + rhs.m[1][1];
-            r.m[1][2] = m[1][2] + rhs.m[1][2];
-            r.m[1][3] = m[1][3] + rhs.m[1][3];
-
-            r.m[2][0] = m[2][0] + rhs.m[2][0];
-            r.m[2][1] = m[2][1] + rhs.m[2][1];
-            r.m[2][2] = m[2][2] + rhs.m[2][2];
-            r.m[2][3] = m[2][3] + rhs.m[2][3];
-
-            r.m[3][0] = m[3][0] + rhs.m[3][0];
-            r.m[3][1] = m[3][1] + rhs.m[3][1];
-            r.m[3][2] = m[3][2] + rhs.m[3][2];
-            r.m[3][3] = m[3][3] + rhs.m[3][3];
-
-            return r;
-        }
-
-        Matrix4 operator- (const Matrix4 &rhs) const
-        {
-            Matrix4 r;
-            r.m[0][0] = m[0][0] - rhs.m[0][0];
-            r.m[0][1] = m[0][1] - rhs.m[0][1];
-            r.m[0][2] = m[0][2] - rhs.m[0][2];
-            r.m[0][3] = m[0][3] - rhs.m[0][3];
-
-            r.m[1][0] = m[1][0] - rhs.m[1][0];
-            r.m[1][1] = m[1][1] - rhs.m[1][1];
-            r.m[1][2] = m[1][2] - rhs.m[1][2];
-            r.m[1][3] = m[1][3] - rhs.m[1][3];
-
-            r.m[2][0] = m[2][0] - rhs.m[2][0];
-            r.m[2][1] = m[2][1] - rhs.m[2][1];
-            r.m[2][2] = m[2][2] - rhs.m[2][2];
-            r.m[2][3] = m[2][3] - rhs.m[2][3];
-
-            r.m[3][0] = m[3][0] - rhs.m[3][0];
-            r.m[3][1] = m[3][1] - rhs.m[3][1];
-            r.m[3][2] = m[3][2] - rhs.m[3][2];
-            r.m[3][3] = m[3][3] - rhs.m[3][3];
-
-            return r;
-        }
-
-        inline bool operator== (const Matrix4& rhs ) const
-        {
-            if(m[0][0] != rhs.m[0][0] || m[0][1] != rhs.m[0][1] || m[0][2] != rhs.m[0][2] || m[0][3] != rhs.m[0][3] ||
-               m[1][0] != rhs.m[1][0] || m[1][1] != rhs.m[1][1] || m[1][2] != rhs.m[1][2] || m[1][3] != rhs.m[1][3] ||
-               m[2][0] != rhs.m[2][0] || m[2][1] != rhs.m[2][1] || m[2][2] != rhs.m[2][2] || m[2][3] != rhs.m[2][3] ||
-               m[3][0] != rhs.m[3][0] || m[3][1] != rhs.m[3][1] || m[3][2] != rhs.m[3][2] || m[3][3] != rhs.m[3][3] )
-			{
-                return false;
-			}
-
-            return true;
-        }
-
-        inline bool operator!= (const Matrix4& rhs) const
-        {
-            return !operator==(rhs);
-        }
-
-		Matrix4 operator*(float rhs) const
-		{
-			return Matrix4(rhs*m[0][0], rhs*m[0][1], rhs*m[0][2], rhs*m[0][3],
-						   rhs*m[1][0], rhs*m[1][1], rhs*m[1][2], rhs*m[1][3],
-						   rhs*m[2][0], rhs*m[2][1], rhs*m[2][2], rhs*m[2][3],
-						   rhs*m[3][0], rhs*m[3][1], rhs*m[3][2], rhs*m[3][3]);
-		}
-
-        /**
-         * @brief	Returns a transpose of the matrix (switched columns and rows).
-         */
-        Matrix4 transpose() const
-        {
-            return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
-                           m[0][1], m[1][1], m[2][1], m[3][1],
-                           m[0][2], m[1][2], m[2][2], m[3][2],
-                           m[0][3], m[1][3], m[2][3], m[3][3]);
-        }
-
-		/**
-		 * @brief	Assigns the vector to a column of the matrix
-		 */
-		void setColumn(UINT32 idx, const Vector4& column)
-		{
-			m[0][idx] = column.x;
-			m[1][idx] = column.y;
-			m[2][idx] = column.z;
-			m[3][idx] = column.w;
-		}
-
-		/**
-		 * @brief	Assigns the vector to a row of the matrix
-		 */
-		void setRow(UINT32 idx, const Vector4& column)
-		{
-			m[idx][0] = column.x;
-			m[idx][1] = column.y;
-			m[idx][2] = column.z;
-			m[idx][3] = column.w;
-		}
-
-        /**
-         * @brief	Extracts the rotation/scaling part of the matrix as a 3x3 matrix.
-         */
-        void extract3x3Matrix(Matrix3& m3x3) const
-        {
-            m3x3.m[0][0] = m[0][0];
-            m3x3.m[0][1] = m[0][1];
-            m3x3.m[0][2] = m[0][2];
-            m3x3.m[1][0] = m[1][0];
-            m3x3.m[1][1] = m[1][1];
-            m3x3.m[1][2] = m[1][2];
-            m3x3.m[2][0] = m[2][0];
-            m3x3.m[2][1] = m[2][1];
-            m3x3.m[2][2] = m[2][2];
-        }
-
-		/**
-		 * @brief	Calculates the adjoint of the matrix.
-		 */
-		Matrix4 adjoint() const;
-
-		/**
-		 * @brief	Calculates the determinant of the matrix.
-		 */
-		float determinant() const;
-
-		/**
-		 * @brief	Calculates the determinant of the 3x3 sub-matrix.
-		 */
-		float determinant3x3() const;
-
-		/**
-		 * @brief	Calculates the inverse of the matrix.
-		 */
-		Matrix4 inverse() const;
-        
-        /**
-         * @brief	Creates a matrix from translation, rotation and scale. 
-         * 			
-		 * @note	The transformation are applied in scale->rotation->translation order.
-         */
-        void setTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
-
-        /**
-         * @brief	Creates a matrix from inverse translation, rotation and scale. 
-         * 			
-		 * @note	This is cheaper than "setTRS" and then performing "inverse".
-         */
-        void setInverseTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
-
-        /**
-         * @brief	Decompose a Matrix4 to translation, rotation and scale.
-         *
-         * @note	Matrix must consist only of translation, rotation and uniform scale transformations,
-         * 			otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees
-         * 			results will not be accurate.
-         */
-        void decomposition(Vector3& position, Quaternion& rotation, Vector3& scale) const;
-
-        /**
-		 * @brief	Check whether or not the matrix is affine matrix.
-		 *
-		 * @note	An affine matrix is a 4x4 matrix with row 3 equal to (0, 0, 0, 1),
-		 *			i.e. no projective coefficients.
-         */
-        bool isAffine() const
-        {
-            return m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0 && m[3][3] == 1;
-        }
-
-        /**
-         * @brief	Returns the inverse of the affine matrix.
-         *
-         * @note	Matrix must be affine.
-         */
-        Matrix4 inverseAffine() const;
-
-        /**
-         * @brief	Concatenate two affine matrices.
-         *
-         * @note	Both matrices must be affine.
-         */
-        Matrix4 concatenateAffine(const Matrix4 &other) const
-        {
-            assert(isAffine() && other.isAffine());
-
-            return Matrix4(
-                m[0][0] * other.m[0][0] + m[0][1] * other.m[1][0] + m[0][2] * other.m[2][0],
-                m[0][0] * other.m[0][1] + m[0][1] * other.m[1][1] + m[0][2] * other.m[2][1],
-                m[0][0] * other.m[0][2] + m[0][1] * other.m[1][2] + m[0][2] * other.m[2][2],
-                m[0][0] * other.m[0][3] + m[0][1] * other.m[1][3] + m[0][2] * other.m[2][3] + m[0][3],
-
-                m[1][0] * other.m[0][0] + m[1][1] * other.m[1][0] + m[1][2] * other.m[2][0],
-                m[1][0] * other.m[0][1] + m[1][1] * other.m[1][1] + m[1][2] * other.m[2][1],
-                m[1][0] * other.m[0][2] + m[1][1] * other.m[1][2] + m[1][2] * other.m[2][2],
-                m[1][0] * other.m[0][3] + m[1][1] * other.m[1][3] + m[1][2] * other.m[2][3] + m[1][3],
-
-                m[2][0] * other.m[0][0] + m[2][1] * other.m[1][0] + m[2][2] * other.m[2][0],
-                m[2][0] * other.m[0][1] + m[2][1] * other.m[1][1] + m[2][2] * other.m[2][1],
-                m[2][0] * other.m[0][2] + m[2][1] * other.m[1][2] + m[2][2] * other.m[2][2],
-                m[2][0] * other.m[0][3] + m[2][1] * other.m[1][3] + m[2][2] * other.m[2][3] + m[2][3],
-
-                0, 0, 0, 1);
-        }
-
-        /**
-         * @brief	Transform a plane by this matrix.
-         * 			
-         * @note	Matrix must be affine.
-         */
-        Plane multiplyAffine(const Plane& p) const
-        {
-			Vector4 localNormal(p.normal.x, p.normal.y, p.normal.z, 0.0f);
-			Vector4 localPoint = localNormal * p.d;
-			localPoint.w = 1.0f;
-
-			Matrix4 itMat = inverse().transpose();
-			Vector4 worldNormal = itMat.multiplyAffine(localNormal);
-			Vector4 worldPoint = multiplyAffine(localPoint);
-
-			float d = worldNormal.dot(worldPoint);
-
-			return Plane(worldNormal.x, worldNormal.y, worldNormal.z, d);
-        }
-
-        /**
-         * @brief	Transform a 3D point by this matrix.
-         * 			
-         * @note	Matrix must be affine, if it is not use "multiply" method.
-         */
-        Vector3 multiplyAffine(const Vector3& v) const
-        {
-            return Vector3(
-                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3], 
-                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
-                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
-        }
-
-        /**
-         * @brief	Transform a 4D vector by this matrix.
-         * 			
-         * @note	Matrix must be affine, if it is not use "multiply" method.
-         */
-        Vector4 multiplyAffine(const Vector4& v) const
-        {
-            return Vector4(
-                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
-                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
-                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
-                v.w);
-        }
-
-		/**
-         * @brief	Transform a 3D direction by this matrix.
-         */
-        Vector3 multiplyDirection(const Vector3& v) const
-        {
-            return Vector3(
-                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, 
-                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z,
-                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z);
-        }
-
-        /**
-         * @brief	Transform a 3D point by this matrix.  
-         *
-         * @note	w component of the vector is assumed to be 1. After transformation all components
-         * 			are projected back so that w remains 1.
-         * 			
-		 *			If your matrix doesn't contain projection components use "multiplyAffine" method as it is faster.
-         */
-        Vector3 multiply(const Vector3& v) const
-        {
-            Vector3 r;
-
-            float fInvW = 1.0f / (m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3]);
-
-            r.x = (m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3]) * fInvW;
-            r.y = (m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3]) * fInvW;
-            r.z = (m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]) * fInvW;
-
-            return r;
-        }
-
-        /**
-         * @brief	Transform a 4D vector by this matrix.  
-         *
-         * @note	If your matrix doesn't contain projection components use "multiplyAffine" method as it is faster.
-         */
-        Vector4 multiply(const Vector4& v) const
-        {
-            return Vector4(
-                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
-                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
-                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
-                m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
-                );
-        }
-
-		/**
-		 * @brief	Creates a view matrix and applies optional reflection.
-		 */
-		void makeView(const Vector3& position, const Quaternion& orientation, const Matrix4* reflectMatrix = nullptr);
-
-		/**
-		 * @brief	Creates an ortographic projection matrix.
-		 */
-		void makeProjectionOrtho(float left, float right, float top, float bottom, float near, float far);
-
-		/**
-		 * @brief	Creates a 4x4 transformation matrix that performs translation.
-		 */
-		static Matrix4 translation(const Vector3& translation);
-
-		/**
-		 * @brief	Creates a 4x4 transformation matrix that performs scaling.
-		 */
-		static Matrix4 scaling(const Vector3& scale);
-
-		/**
-		 * @brief	Creates a 4x4 transformation matrix that performs uniform scaling.
-		 */
-		static Matrix4 scaling(float scale);
-
-		/**
-		 * @brief	Creates a 4x4 transformation matrix that performs rotation.
-		 */
-		static Matrix4 rotation(const Quaternion& rotation);
-
-        /**
-         * @brief	Creates a matrix from translation, rotation and scale. 
-         * 			
-		 * @note	The transformation are applied in scale->rotation->translation order.
-         */
-		static Matrix4 TRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
-
-        /**
-         * @brief	Creates a matrix from inverse translation, rotation and scale. 
-         * 			
-		 * @note	This is cheaper than "setTRS" and then performing "inverse".
-         */
-		static Matrix4 inverseTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
-
-		static const Matrix4 ZERO;
-		static const Matrix4 IDENTITY;
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Matrix4);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+#include "BsVector3.h"
+#include "BsMatrix3.h"
+#include "BsVector4.h"
+#include "BsPlane.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	 /** Class representing a 4x4 matrix. */
+    class BS_UTILITY_EXPORT Matrix4
+    {
+    private:
+        union 
+		{
+            float m[4][4];
+            float _m[16];
+        };
+
+    public:
+        Matrix4()
+        { }
+
+        Matrix4(
+            float m00, float m01, float m02, float m03,
+            float m10, float m11, float m12, float m13,
+            float m20, float m21, float m22, float m23,
+            float m30, float m31, float m32, float m33)
+        {
+            m[0][0] = m00;
+            m[0][1] = m01;
+            m[0][2] = m02;
+            m[0][3] = m03;
+            m[1][0] = m10;
+            m[1][1] = m11;
+            m[1][2] = m12;
+            m[1][3] = m13;
+            m[2][0] = m20;
+            m[2][1] = m21;
+            m[2][2] = m22;
+            m[2][3] = m23;
+            m[3][0] = m30;
+            m[3][1] = m31;
+            m[3][2] = m32;
+            m[3][3] = m33;
+        }
+
+		Matrix4(const Matrix4& mat)
+		{
+			memcpy(_m, mat._m, 16*sizeof(float));
+		}
+
+        /** Creates a 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix. */
+        explicit Matrix4(const Matrix3& mat3)
+        {
+			m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2]; m[0][3] = 0.0f;
+			m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2]; m[1][3] = 0.0f;
+			m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2]; m[2][3] = 0.0f;
+			m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
+        }
+
+		/** Swaps the contents of this matrix with another. */
+		void swap(Matrix4& other)
+		{
+			std::swap(m[0][0], other.m[0][0]);
+			std::swap(m[0][1], other.m[0][1]);
+			std::swap(m[0][2], other.m[0][2]);
+			std::swap(m[0][3], other.m[0][3]);
+			std::swap(m[1][0], other.m[1][0]);
+			std::swap(m[1][1], other.m[1][1]);
+			std::swap(m[1][2], other.m[1][2]);
+			std::swap(m[1][3], other.m[1][3]);
+			std::swap(m[2][0], other.m[2][0]);
+			std::swap(m[2][1], other.m[2][1]);
+			std::swap(m[2][2], other.m[2][2]);
+			std::swap(m[2][3], other.m[2][3]);
+			std::swap(m[3][0], other.m[3][0]);
+			std::swap(m[3][1], other.m[3][1]);
+			std::swap(m[3][2], other.m[3][2]);
+			std::swap(m[3][3], other.m[3][3]);
+		}
+
+		/** Returns a row of the matrix. */
+		float* operator[] (UINT32 row)
+        {
+            assert(row < 4);
+
+            return m[row];
+        }
+
+        const float *operator[] (UINT32 row) const
+        {
+            assert(row < 4);
+
+            return m[row];
+        }
+
+        Matrix4 operator* (const Matrix4 &rhs) const
+        {
+			Matrix4 r;
+
+			r.m[0][0] = m[0][0] * rhs.m[0][0] + m[0][1] * rhs.m[1][0] + m[0][2] * rhs.m[2][0] + m[0][3] * rhs.m[3][0];
+			r.m[0][1] = m[0][0] * rhs.m[0][1] + m[0][1] * rhs.m[1][1] + m[0][2] * rhs.m[2][1] + m[0][3] * rhs.m[3][1];
+			r.m[0][2] = m[0][0] * rhs.m[0][2] + m[0][1] * rhs.m[1][2] + m[0][2] * rhs.m[2][2] + m[0][3] * rhs.m[3][2];
+			r.m[0][3] = m[0][0] * rhs.m[0][3] + m[0][1] * rhs.m[1][3] + m[0][2] * rhs.m[2][3] + m[0][3] * rhs.m[3][3];
+
+			r.m[1][0] = m[1][0] * rhs.m[0][0] + m[1][1] * rhs.m[1][0] + m[1][2] * rhs.m[2][0] + m[1][3] * rhs.m[3][0];
+			r.m[1][1] = m[1][0] * rhs.m[0][1] + m[1][1] * rhs.m[1][1] + m[1][2] * rhs.m[2][1] + m[1][3] * rhs.m[3][1];
+			r.m[1][2] = m[1][0] * rhs.m[0][2] + m[1][1] * rhs.m[1][2] + m[1][2] * rhs.m[2][2] + m[1][3] * rhs.m[3][2];
+			r.m[1][3] = m[1][0] * rhs.m[0][3] + m[1][1] * rhs.m[1][3] + m[1][2] * rhs.m[2][3] + m[1][3] * rhs.m[3][3];
+
+			r.m[2][0] = m[2][0] * rhs.m[0][0] + m[2][1] * rhs.m[1][0] + m[2][2] * rhs.m[2][0] + m[2][3] * rhs.m[3][0];
+			r.m[2][1] = m[2][0] * rhs.m[0][1] + m[2][1] * rhs.m[1][1] + m[2][2] * rhs.m[2][1] + m[2][3] * rhs.m[3][1];
+			r.m[2][2] = m[2][0] * rhs.m[0][2] + m[2][1] * rhs.m[1][2] + m[2][2] * rhs.m[2][2] + m[2][3] * rhs.m[3][2];
+			r.m[2][3] = m[2][0] * rhs.m[0][3] + m[2][1] * rhs.m[1][3] + m[2][2] * rhs.m[2][3] + m[2][3] * rhs.m[3][3];
+
+			r.m[3][0] = m[3][0] * rhs.m[0][0] + m[3][1] * rhs.m[1][0] + m[3][2] * rhs.m[2][0] + m[3][3] * rhs.m[3][0];
+			r.m[3][1] = m[3][0] * rhs.m[0][1] + m[3][1] * rhs.m[1][1] + m[3][2] * rhs.m[2][1] + m[3][3] * rhs.m[3][1];
+			r.m[3][2] = m[3][0] * rhs.m[0][2] + m[3][1] * rhs.m[1][2] + m[3][2] * rhs.m[2][2] + m[3][3] * rhs.m[3][2];
+			r.m[3][3] = m[3][0] * rhs.m[0][3] + m[3][1] * rhs.m[1][3] + m[3][2] * rhs.m[2][3] + m[3][3] * rhs.m[3][3];
+
+			return r;
+        }
+
+        Matrix4 operator+ (const Matrix4 &rhs) const
+        {
+            Matrix4 r;
+
+            r.m[0][0] = m[0][0] + rhs.m[0][0];
+            r.m[0][1] = m[0][1] + rhs.m[0][1];
+            r.m[0][2] = m[0][2] + rhs.m[0][2];
+            r.m[0][3] = m[0][3] + rhs.m[0][3];
+
+            r.m[1][0] = m[1][0] + rhs.m[1][0];
+            r.m[1][1] = m[1][1] + rhs.m[1][1];
+            r.m[1][2] = m[1][2] + rhs.m[1][2];
+            r.m[1][3] = m[1][3] + rhs.m[1][3];
+
+            r.m[2][0] = m[2][0] + rhs.m[2][0];
+            r.m[2][1] = m[2][1] + rhs.m[2][1];
+            r.m[2][2] = m[2][2] + rhs.m[2][2];
+            r.m[2][3] = m[2][3] + rhs.m[2][3];
+
+            r.m[3][0] = m[3][0] + rhs.m[3][0];
+            r.m[3][1] = m[3][1] + rhs.m[3][1];
+            r.m[3][2] = m[3][2] + rhs.m[3][2];
+            r.m[3][3] = m[3][3] + rhs.m[3][3];
+
+            return r;
+        }
+
+        Matrix4 operator- (const Matrix4 &rhs) const
+        {
+            Matrix4 r;
+            r.m[0][0] = m[0][0] - rhs.m[0][0];
+            r.m[0][1] = m[0][1] - rhs.m[0][1];
+            r.m[0][2] = m[0][2] - rhs.m[0][2];
+            r.m[0][3] = m[0][3] - rhs.m[0][3];
+
+            r.m[1][0] = m[1][0] - rhs.m[1][0];
+            r.m[1][1] = m[1][1] - rhs.m[1][1];
+            r.m[1][2] = m[1][2] - rhs.m[1][2];
+            r.m[1][3] = m[1][3] - rhs.m[1][3];
+
+            r.m[2][0] = m[2][0] - rhs.m[2][0];
+            r.m[2][1] = m[2][1] - rhs.m[2][1];
+            r.m[2][2] = m[2][2] - rhs.m[2][2];
+            r.m[2][3] = m[2][3] - rhs.m[2][3];
+
+            r.m[3][0] = m[3][0] - rhs.m[3][0];
+            r.m[3][1] = m[3][1] - rhs.m[3][1];
+            r.m[3][2] = m[3][2] - rhs.m[3][2];
+            r.m[3][3] = m[3][3] - rhs.m[3][3];
+
+            return r;
+        }
+
+        inline bool operator== (const Matrix4& rhs ) const
+        {
+            if(m[0][0] != rhs.m[0][0] || m[0][1] != rhs.m[0][1] || m[0][2] != rhs.m[0][2] || m[0][3] != rhs.m[0][3] ||
+               m[1][0] != rhs.m[1][0] || m[1][1] != rhs.m[1][1] || m[1][2] != rhs.m[1][2] || m[1][3] != rhs.m[1][3] ||
+               m[2][0] != rhs.m[2][0] || m[2][1] != rhs.m[2][1] || m[2][2] != rhs.m[2][2] || m[2][3] != rhs.m[2][3] ||
+               m[3][0] != rhs.m[3][0] || m[3][1] != rhs.m[3][1] || m[3][2] != rhs.m[3][2] || m[3][3] != rhs.m[3][3] )
+			{
+                return false;
+			}
+
+            return true;
+        }
+
+        inline bool operator!= (const Matrix4& rhs) const
+        {
+            return !operator==(rhs);
+        }
+
+		Matrix4 operator*(float rhs) const
+		{
+			return Matrix4(rhs*m[0][0], rhs*m[0][1], rhs*m[0][2], rhs*m[0][3],
+						   rhs*m[1][0], rhs*m[1][1], rhs*m[1][2], rhs*m[1][3],
+						   rhs*m[2][0], rhs*m[2][1], rhs*m[2][2], rhs*m[2][3],
+						   rhs*m[3][0], rhs*m[3][1], rhs*m[3][2], rhs*m[3][3]);
+		}
+
+        /** Returns a transpose of the matrix (switched columns and rows). */
+        Matrix4 transpose() const
+        {
+            return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
+                           m[0][1], m[1][1], m[2][1], m[3][1],
+                           m[0][2], m[1][2], m[2][2], m[3][2],
+                           m[0][3], m[1][3], m[2][3], m[3][3]);
+        }
+
+		/** Assigns the vector to a column of the matrix. */
+		void setColumn(UINT32 idx, const Vector4& column)
+		{
+			m[0][idx] = column.x;
+			m[1][idx] = column.y;
+			m[2][idx] = column.z;
+			m[3][idx] = column.w;
+		}
+
+		/** Assigns the vector to a row of the matrix. */
+		void setRow(UINT32 idx, const Vector4& column)
+		{
+			m[idx][0] = column.x;
+			m[idx][1] = column.y;
+			m[idx][2] = column.z;
+			m[idx][3] = column.w;
+		}
+
+        /** Extracts the rotation/scaling part of the matrix as a 3x3 matrix. */
+        void extract3x3Matrix(Matrix3& m3x3) const
+        {
+            m3x3.m[0][0] = m[0][0];
+            m3x3.m[0][1] = m[0][1];
+            m3x3.m[0][2] = m[0][2];
+            m3x3.m[1][0] = m[1][0];
+            m3x3.m[1][1] = m[1][1];
+            m3x3.m[1][2] = m[1][2];
+            m3x3.m[2][0] = m[2][0];
+            m3x3.m[2][1] = m[2][1];
+            m3x3.m[2][2] = m[2][2];
+        }
+
+		/** Calculates the adjoint of the matrix. */
+		Matrix4 adjoint() const;
+
+		/** Calculates the determinant of the matrix. */
+		float determinant() const;
+
+		/** Calculates the determinant of the 3x3 sub-matrix. */
+		float determinant3x3() const;
+
+		/** Calculates the inverse of the matrix. */
+		Matrix4 inverse() const;
+        
+        /**
+         * Creates a matrix from translation, rotation and scale. 
+         * 			
+		 * @note	The transformation are applied in scale->rotation->translation order.
+         */
+        void setTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
+
+        /**
+         * Creates a matrix from inverse translation, rotation and scale. 
+         * 			
+		 * @note	This is cheaper than setTRS() and then performing inverse().
+         */
+        void setInverseTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
+
+        /**
+         * Decompose a Matrix4 to translation, rotation and scale.
+         *
+         * @note	
+		 * Matrix must consist only of translation, rotation and uniform scale transformations,
+         * otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees
+         * results will not be accurate.
+         */
+        void decomposition(Vector3& position, Quaternion& rotation, Vector3& scale) const;
+
+        /**
+		 * Check whether or not the matrix is affine matrix.
+		 *
+		 * @note	An affine matrix is a 4x4 matrix with row 3 equal to (0, 0, 0, 1), i.e. no projective coefficients.
+         */
+        bool isAffine() const
+        {
+            return m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0 && m[3][3] == 1;
+        }
+
+        /**
+         * Returns the inverse of the affine matrix.
+         *
+         * @note	Matrix must be affine.
+         */
+        Matrix4 inverseAffine() const;
+
+        /**
+         * Concatenate two affine matrices.
+         *
+         * @note	Both matrices must be affine.
+         */
+        Matrix4 concatenateAffine(const Matrix4 &other) const
+        {
+            assert(isAffine() && other.isAffine());
+
+            return Matrix4(
+                m[0][0] * other.m[0][0] + m[0][1] * other.m[1][0] + m[0][2] * other.m[2][0],
+                m[0][0] * other.m[0][1] + m[0][1] * other.m[1][1] + m[0][2] * other.m[2][1],
+                m[0][0] * other.m[0][2] + m[0][1] * other.m[1][2] + m[0][2] * other.m[2][2],
+                m[0][0] * other.m[0][3] + m[0][1] * other.m[1][3] + m[0][2] * other.m[2][3] + m[0][3],
+
+                m[1][0] * other.m[0][0] + m[1][1] * other.m[1][0] + m[1][2] * other.m[2][0],
+                m[1][0] * other.m[0][1] + m[1][1] * other.m[1][1] + m[1][2] * other.m[2][1],
+                m[1][0] * other.m[0][2] + m[1][1] * other.m[1][2] + m[1][2] * other.m[2][2],
+                m[1][0] * other.m[0][3] + m[1][1] * other.m[1][3] + m[1][2] * other.m[2][3] + m[1][3],
+
+                m[2][0] * other.m[0][0] + m[2][1] * other.m[1][0] + m[2][2] * other.m[2][0],
+                m[2][0] * other.m[0][1] + m[2][1] * other.m[1][1] + m[2][2] * other.m[2][1],
+                m[2][0] * other.m[0][2] + m[2][1] * other.m[1][2] + m[2][2] * other.m[2][2],
+                m[2][0] * other.m[0][3] + m[2][1] * other.m[1][3] + m[2][2] * other.m[2][3] + m[2][3],
+
+                0, 0, 0, 1);
+        }
+
+        /**
+         * Transform a plane by this matrix.
+         * 			
+         * @note	Matrix must be affine.
+         */
+        Plane multiplyAffine(const Plane& p) const
+        {
+			Vector4 localNormal(p.normal.x, p.normal.y, p.normal.z, 0.0f);
+			Vector4 localPoint = localNormal * p.d;
+			localPoint.w = 1.0f;
+
+			Matrix4 itMat = inverse().transpose();
+			Vector4 worldNormal = itMat.multiplyAffine(localNormal);
+			Vector4 worldPoint = multiplyAffine(localPoint);
+
+			float d = worldNormal.dot(worldPoint);
+
+			return Plane(worldNormal.x, worldNormal.y, worldNormal.z, d);
+        }
+
+        /**
+         * Transform a 3D point by this matrix.
+         * 			
+         * @note	Matrix must be affine, if it is not use multiply() method.
+         */
+        Vector3 multiplyAffine(const Vector3& v) const
+        {
+            return Vector3(
+                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3], 
+                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
+                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
+        }
+
+        /**
+         * Transform a 4D vector by this matrix.
+         * 			
+         * @note	Matrix must be affine, if it is not use multiply() method.
+         */
+        Vector4 multiplyAffine(const Vector4& v) const
+        {
+            return Vector4(
+                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
+                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
+                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
+                v.w);
+        }
+
+		/** Transform a 3D direction by this matrix. */
+        Vector3 multiplyDirection(const Vector3& v) const
+        {
+            return Vector3(
+                    m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, 
+                    m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z,
+                    m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z);
+        }
+
+        /**
+         * Transform a 3D point by this matrix.  
+         *
+         * @note	
+		 * w component of the vector is assumed to be 1. After transformation all components
+         * are projected back so that w remains 1.
+         * @note
+		 * If your matrix doesn't contain projection components use multiplyAffine() method as it is faster.
+         */
+        Vector3 multiply(const Vector3& v) const
+        {
+            Vector3 r;
+
+            float fInvW = 1.0f / (m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3]);
+
+            r.x = (m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3]) * fInvW;
+            r.y = (m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3]) * fInvW;
+            r.z = (m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]) * fInvW;
+
+            return r;
+        }
+
+        /**
+         * Transform a 4D vector by this matrix.  
+         *
+         * @note	If your matrix doesn't contain projection components use multiplyAffine() method as it is faster.
+         */
+        Vector4 multiply(const Vector4& v) const
+        {
+            return Vector4(
+                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, 
+                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
+                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
+                m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
+                );
+        }
+
+		/** Creates a view matrix and applies optional reflection. */
+		void makeView(const Vector3& position, const Quaternion& orientation, const Matrix4* reflectMatrix = nullptr);
+
+		/** Creates an ortographic projection matrix. */
+		void makeProjectionOrtho(float left, float right, float top, float bottom, float near, float far);
+
+		/** Creates a 4x4 transformation matrix that performs translation. */
+		static Matrix4 translation(const Vector3& translation);
+
+		/** Creates a 4x4 transformation matrix that performs scaling. */
+		static Matrix4 scaling(const Vector3& scale);
+
+		/** Creates a 4x4 transformation matrix that performs uniform scaling. */
+		static Matrix4 scaling(float scale);
+
+		/** Creates a 4x4 transformation matrix that performs rotation. */
+		static Matrix4 rotation(const Quaternion& rotation);
+
+        /**
+         * Creates a matrix from translation, rotation and scale. 
+         * 			
+		 * @note	The transformation are applied in scale->rotation->translation order.
+         */
+		static Matrix4 TRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
+
+        /**
+         * Creates a matrix from inverse translation, rotation and scale. 
+         * 			
+		 * @note	This is cheaper than setTRS() and then performing inverse().
+         */
+		static Matrix4 inverseTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
+
+		static const Matrix4 ZERO;
+		static const Matrix4 IDENTITY;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Matrix4);
+	/** @endcond */
 }

+ 87 - 85
BansheeUtility/Include/BsMatrixNxM.h

@@ -1,86 +1,88 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Class representing a NxM matrix.
-	 *
-	 * @note	If you need to use matrices for more than just data storage then
-	 *			it is suggested you use specialized Matrix3 or Matrix4 classes
-	 *			as they provide a wide range of functionality.
-	 */
-	template<int N, int M>
-	class MatrixNxM
-	{
-	public:
-		MatrixNxM() {}
-
-		MatrixNxM(float data[N*M])
-		{
-			memcpy(m, data, N*M * sizeof(float));
-		}
-
-		/**
-		 * @brief	Returns a transpose of the matrix (switched columns and rows).
-		 */
-		MatrixNxM<N, M> transpose() const
-		{
-			MatrixNxM<N, M> matTranspose;
-			for (UINT32 row = 0; row < N; row++)
-			{
-				for (UINT32 col = 0; col < M; col++)
-					matTranspose[row][col] = m[col][row];
-			}
-
-			return matTranspose;
-		}
-
-		/**
-         * @brief	Returns a row of the matrix.
-         */
-        inline float* operator[] (UINT32 row) const
-		{
-			assert(row < N);
-
-			return (float*)m[row];
-		}
-
-		MatrixNxM<N, M>& operator= (const MatrixNxM<N, M>& rhs)
-		{
-			memcpy(m, rhs.m, (N*M)*sizeof(float));
-			return *this;
-		}
-
-		bool operator== (const MatrixNxM<N, M>& rhs) const
-		{
-			for (UINT32 row = 0; row < N; row++)
-			{
-				for (UINT32 col = 0; col < M; col++)
-				{
-					if (m[row][col] != rhs.m[row][col])
-						return false;
-				}
-			}
-
-			return true;
-		}
-
-		bool operator!= (const MatrixNxM<N, M>& rhs) const
-		{
-			return !operator==(rhs);
-		}
-
-		float m[N][M];
-	};
-
-	typedef MatrixNxM<2, 2> Matrix2;
-	typedef MatrixNxM<2, 3> Matrix2x3;
-	typedef MatrixNxM<2, 4> Matrix2x4;
-	typedef MatrixNxM<3, 2> Matrix3x2;
-	typedef MatrixNxM<3, 4> Matrix3x4;
-	typedef MatrixNxM<4, 2> Matrix4x2;
-	typedef MatrixNxM<4, 3> Matrix4x3;
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/**
+	 * Class representing a NxM matrix.
+	 *
+	 * @note	If you need to use matrices for more than just data storage then
+	 *			it is suggested you use specialized Matrix3 or Matrix4 classes
+	 *			as they provide a wide range of functionality.
+	 */
+	template<int N, int M>
+	class MatrixNxM
+	{
+	public:
+		MatrixNxM() {}
+
+		MatrixNxM(float data[N*M])
+		{
+			memcpy(m, data, N*M * sizeof(float));
+		}
+
+		/** Returns a transpose of the matrix (switched columns and rows). */
+		MatrixNxM<N, M> transpose() const
+		{
+			MatrixNxM<N, M> matTranspose;
+			for (UINT32 row = 0; row < N; row++)
+			{
+				for (UINT32 col = 0; col < M; col++)
+					matTranspose[row][col] = m[col][row];
+			}
+
+			return matTranspose;
+		}
+
+		/** Returns a row of the matrix. */
+        float* operator[] (UINT32 row) const
+		{
+			assert(row < N);
+
+			return (float*)m[row];
+		}
+
+		MatrixNxM<N, M>& operator= (const MatrixNxM<N, M>& rhs)
+		{
+			memcpy(m, rhs.m, (N*M)*sizeof(float));
+			return *this;
+		}
+
+		bool operator== (const MatrixNxM<N, M>& rhs) const
+		{
+			for (UINT32 row = 0; row < N; row++)
+			{
+				for (UINT32 col = 0; col < M; col++)
+				{
+					if (m[row][col] != rhs.m[row][col])
+						return false;
+				}
+			}
+
+			return true;
+		}
+
+		bool operator!= (const MatrixNxM<N, M>& rhs) const
+		{
+			return !operator==(rhs);
+		}
+
+		float m[N][M];
+	};
+
+	typedef MatrixNxM<2, 2> Matrix2;
+	typedef MatrixNxM<2, 3> Matrix2x3;
+	typedef MatrixNxM<2, 4> Matrix2x4;
+	typedef MatrixNxM<3, 2> Matrix3x2;
+	typedef MatrixNxM<3, 4> Matrix3x4;
+	typedef MatrixNxM<4, 2> Matrix4x2;
+	typedef MatrixNxM<4, 3> Matrix4x3;
+
+	/** @} */
 }

+ 92 - 102
BansheeUtility/Include/BsPlane.h

@@ -1,103 +1,93 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine 
-{
-    /**
-     * @brief	A plane represented by a normal and a distance.
-     */
-    class BS_UTILITY_EXPORT Plane
-    {
-	public:
-		/**
-		 * @brief	The "positive side" of the plane is the half space to which the
-		 *			plane normal points. The "negative side" is the other half
-		 *			space. The flag "no side" indicates the plane itself.
-         */
-        enum Side
-        {
-            NO_SIDE,
-            POSITIVE_SIDE,
-            NEGATIVE_SIDE,
-            BOTH_SIDE
-        };
-
-    public:
-        Plane();
-        Plane(const Plane& copy);
-        Plane(const Vector3& normal, float d);
-		Plane(float a, float b, float c, float d);
-        Plane(const Vector3& normal, const Vector3& point);
-        Plane(const Vector3& point0, const Vector3& point1, const Vector3& point2);
-
-        /**
-         * @brief	Returns the side of the plane where the point is located on.
-         * 			
-		 * @note	NO_SIDE signifies the point is on the plane.
-         */
-        Side getSide(const Vector3& point) const;
-
-        /**
-		 * @brief	Returns the side where the alignedBox is. The flag BOTH_SIDE indicates an intersecting box.
-		 *			One corner ON the plane is sufficient to consider the box and the plane intersecting.
-         */
-        Side getSide(const AABox& box) const;
-
-        /**
-		 * @brief	Returns the side where the sphere is. The flag BOTH_SIDE indicates an intersecting sphere.
-         */
-		Side getSide(const Sphere& sphere) const;
-
-        /**
-         * @brief	Returns a distance from point to plane.
-         *
-		 * @note	The sign of the return value is positive if the point is on the 
-		 * 			positive side of the plane, negative if the point is on the negative 
-		 * 			side, and zero if the point is on the plane.
-         */
-        float getDistance(const Vector3& point) const;
-
-		/**
-		 * @brief	Project a vector onto the plane.
-		 */
-		Vector3 projectVector(const Vector3& v) const;
-
-        /**
-		 * @brief	Normalizes the plane's normal and the length scale of d
-		 *			is as well.
-         */
-        float normalize();
-
-		/**
-		 * @brief	Box/plane intersection.
-		 */
-		bool intersects(const AABox& box) const;
-
-		/**
-		 * @brief	Sphere/plane intersection.
-		 */
-		bool intersects(const Sphere& sphere) const;
-
-		/**
-		 * @brief	Ray/plane intersection, returns boolean result and distance to intersection point.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray) const;
-
-        bool operator==(const Plane& rhs) const
-        {
-            return (rhs.d == d && rhs.normal == normal);
-        }
-        bool operator!=(const Plane& rhs) const
-        {
-            return (rhs.d != d || rhs.normal != normal);
-        }
-
-	public:
-		Vector3 normal;
-		float d;
-    };
-
-    typedef Vector<Plane> PlaneList;
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** A plane represented by a normal and a distance. */
+    class BS_UTILITY_EXPORT Plane
+    {
+	public:
+		/**
+		 * The "positive side" of the plane is the half space to which the plane normal points. The "negative side" is the 
+		 * other half space. The flag "no side" indicates the plane itself.
+         */
+        enum Side
+        {
+            NO_SIDE,
+            POSITIVE_SIDE,
+            NEGATIVE_SIDE,
+            BOTH_SIDE
+        };
+
+    public:
+        Plane();
+        Plane(const Plane& copy);
+        Plane(const Vector3& normal, float d);
+		Plane(float a, float b, float c, float d);
+        Plane(const Vector3& normal, const Vector3& point);
+        Plane(const Vector3& point0, const Vector3& point1, const Vector3& point2);
+
+        /**
+         * Returns the side of the plane where the point is located on.
+         * 			
+		 * @note	NO_SIDE signifies the point is on the plane.
+         */
+        Side getSide(const Vector3& point) const;
+
+        /**
+		 * Returns the side where the alignedBox is. The flag BOTH_SIDE indicates an intersecting box.
+		 * One corner ON the plane is sufficient to consider the box and the plane intersecting.
+         */
+        Side getSide(const AABox& box) const;
+
+        /** Returns the side where the sphere is. The flag BOTH_SIDE indicates an intersecting sphere. */
+		Side getSide(const Sphere& sphere) const;
+
+        /**
+         * Returns a distance from point to plane.
+         *
+		 * @note	The sign of the return value is positive if the point is on the 
+		 * 			positive side of the plane, negative if the point is on the negative 
+		 * 			side, and zero if the point is on the plane.
+         */
+        float getDistance(const Vector3& point) const;
+
+		/** Project a vector onto the plane. */
+		Vector3 projectVector(const Vector3& v) const;
+
+        /** Normalizes the plane's normal and the length scale of d. */
+        float normalize();
+
+		/** Box/plane intersection. */
+		bool intersects(const AABox& box) const;
+
+		/** Sphere/plane intersection. */
+		bool intersects(const Sphere& sphere) const;
+
+		/** Ray/plane intersection, returns boolean result and distance to intersection point. */
+		std::pair<bool, float> intersects(const Ray& ray) const;
+
+        bool operator==(const Plane& rhs) const
+        {
+            return (rhs.d == d && rhs.normal == normal);
+        }
+        bool operator!=(const Plane& rhs) const
+        {
+            return (rhs.d != d || rhs.normal != normal);
+        }
+
+	public:
+		Vector3 normal;
+		float d;
+    };
+
+    typedef Vector<Plane> PlaneList;
+
+	/** @} */
 }

+ 101 - 73
BansheeUtility/Include/BsPrerequisitesUtil.h

@@ -1,74 +1,102 @@
-#pragma once
-
-#include <assert.h>
-
-// 0 - No thread support
-// 1 - Render system is thread safe (TODO: NOT WORKING and will probably be removed)
-// 2 - Thread support but render system can only be accessed from main thread
-#define BS_THREAD_SUPPORT 2
-
-#define BS_PROFILING_ENABLED 1
-
-// Versions
-
-#define BS_VER_DEV 1
-#define BS_VER_PREVIEW 2
-
-#define BS_VER BS_VER_DEV
-
-// Platform-specific stuff
-#include "BsPlatformDefines.h"
-
-#if BS_COMPILER == BS_COMPILER_MSVC
-
-// TODO - This is not deactivated anywhere, therefore it applies to any file that includes this header.
-//      - Right now I don't have an easier way to apply these warnings globally so I'm keeping it this way.
-
-// Secure versions aren't multiplatform, so we won't be using them
-#define _CRT_SECURE_NO_WARNINGS
-
-// disable: "<type> needs to have dll-interface to be used by clients'
-// Happens on STL member variables which are not public therefore is ok
-#   pragma warning (disable: 4251)
-
-// disable: 'X' Function call with parameters that may be unsafe
-#	pragma warning(disable: 4996) 
-
-// disable: decorated name length exceeded, name was truncated
-// Happens with really long type names. Even fairly standard use
-// of std::unordered_map with custom parameters, meaning I can't
-// really do much to avoid it. It shouldn't effect execution
-// but might cause problems if you compile library
-// with one compiler and use it in another.
-#	pragma warning(disable: 4503)
-
-// disable: C++ exception handler used, but unwind semantics are not enabled
-// We don't care about this as any exception is meant to crash the program.
-#	pragma warning(disable: 4530)
-
-#endif
-
-// Short-hand names for various built-in types
-#include "BsTypes.h"
-
-#include "BsMemoryAllocator.h"
-
-// Useful threading defines
-#include "BsThreadDefines.h"
-
-// Commonly used standard headers
-#include "BsStdHeaders.h"
-
-// Forward declarations
-#include "BsFwdDeclUtil.h"
-
-#include "BsRTTIPrerequisites.h"
-
-#include "BsString.h"
-#include "BsMessageHandlerFwd.h"
-#include "BsUtil.h"
-#include "BsPath.h"
-#include "BsStringID.h"
-#include "BsEvent.h"
-#include "BsPlatformUtility.h"
+#pragma once
+
+#include <assert.h>
+
+/** @defgroup Utility Utility
+ *	Lowest layer of the engine containing a collection of very decoupled and separate systems that are 
+ *  likely to be used throughout all of the higher layers.
+ *  @{
+ */
+
+/** @defgroup Math Math
+ *	Math utility library containing a variety of general purpose math functionality.
+ */
+
+/** @defgroup RTTI RTTI
+ *  A set of systems for defining and using run-time type information.
+ */
+
+/** @defgroup Memory Memory
+ *  A set of methods and classes meant to manipulate memory.
+ */
+
+/** @defgroup Containers Containers
+ *  Contains a set of templated commonly used containers.
+ */
+
+/** @defgroup Debug Debug
+ *  Contains various functionality used to help with debugging.
+ */
+
+/** @} */
+
+// 0 - No thread support
+// 1 - Render system is thread safe (TODO: NOT WORKING and will probably be removed)
+// 2 - Thread support but render system can only be accessed from main thread
+#define BS_THREAD_SUPPORT 2
+
+#define BS_PROFILING_ENABLED 1
+
+// Versions
+
+#define BS_VER_DEV 1
+#define BS_VER_PREVIEW 2
+
+#define BS_VER BS_VER_DEV
+
+// Platform-specific stuff
+#include "BsPlatformDefines.h"
+
+#if BS_COMPILER == BS_COMPILER_MSVC
+
+// TODO - This is not deactivated anywhere, therefore it applies to any file that includes this header.
+//      - Right now I don't have an easier way to apply these warnings globally so I'm keeping it this way.
+
+// Secure versions aren't multiplatform, so we won't be using them
+#define _CRT_SECURE_NO_WARNINGS
+
+// disable: "<type> needs to have dll-interface to be used by clients'
+// Happens on STL member variables which are not public therefore is ok
+#   pragma warning (disable: 4251)
+
+// disable: 'X' Function call with parameters that may be unsafe
+#	pragma warning(disable: 4996) 
+
+// disable: decorated name length exceeded, name was truncated
+// Happens with really long type names. Even fairly standard use
+// of std::unordered_map with custom parameters, meaning I can't
+// really do much to avoid it. It shouldn't effect execution
+// but might cause problems if you compile library
+// with one compiler and use it in another.
+#	pragma warning(disable: 4503)
+
+// disable: C++ exception handler used, but unwind semantics are not enabled
+// We don't care about this as any exception is meant to crash the program.
+#	pragma warning(disable: 4530)
+
+#endif
+
+// Short-hand names for various built-in types
+#include "BsTypes.h"
+
+#include "BsMemoryAllocator.h"
+
+// Useful threading defines
+#include "BsThreadDefines.h"
+
+// Commonly used standard headers
+#include "BsStdHeaders.h"
+
+// Forward declarations
+#include "BsFwdDeclUtil.h"
+
+#include "BsRTTIPrerequisites.h"
+
+#include "BsString.h"
+#include "BsMessageHandlerFwd.h"
+#include "BsUtil.h"
+#include "BsPath.h"
+#include "BsStringID.h"
+#include "BsEvent.h"
+#include "BsPlatformUtility.h"
 #include "BsCrashHandler.h"

+ 62 - 81
BansheeUtility/Include/BsQuaternion.h

@@ -6,9 +6,11 @@
 
 namespace BansheeEngine 
 {
-    /**
-     * @brief	Represents a quaternion used for 3D rotations.
-     */
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** Represents a quaternion used for 3D rotations. */
     class BS_UTILITY_EXPORT Quaternion
     {
 	private:
@@ -22,32 +24,26 @@ namespace BansheeEngine
 			:w(w), z(z), y(y), x(x)
 		{ }
 
-        /**
-         * @brief	Construct a quaternion from a rotation matrix.
-         */
+        /** Construct a quaternion from a rotation matrix. */
         explicit Quaternion(const Matrix3& rot)
         {
             fromRotationMatrix(rot);
         }
 
-        /**
-         * @brief	Construct a quaternion from an angle/axis.
-         */
+        /** Construct a quaternion from an angle/axis. */
         explicit Quaternion(const Vector3& axis, const Radian& angle)
         {
             fromAxisAngle(axis, angle);
         }
 
-        /**
-         * @brief	Construct a quaternion from 3 orthonormal local axes.
-         */
+        /** Construct a quaternion from 3 orthonormal local axes. */
         explicit Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
         {
             fromAxes(xaxis, yaxis, zaxis);
         }
 
         /**
-         * @brief	Construct a quaternion from euler angles, YXZ ordering.
+         * Construct a quaternion from euler angles, YXZ ordering.
          * 			
 		 * @see		Quaternion::fromEulerAngles
          */
@@ -57,7 +53,7 @@ namespace BansheeEngine
 		}
 
         /**
-         * @brief	Construct a quaternion from euler angles, custom ordering.
+         * Construct a quaternion from euler angles, custom ordering.
          * 			
 		 * @see		Quaternion::fromEulerAngles
          */
@@ -66,9 +62,7 @@ namespace BansheeEngine
 			fromEulerAngles(xAngle, yAngle, zAngle, order);
 		}
 
-		/**
-		 * @brief	Exchange the contents of this quaternion with another.
-		 */
+		/** Exchange the contents of this quaternion with another. */
 		void swap(Quaternion& other)
 		{
 			std::swap(w, other.w);
@@ -92,95 +86,90 @@ namespace BansheeEngine
 		}
 
 		/**
-		 * @brief	Initializes the quaternion from a 3x3 rotation matrix.
+		 * Initializes the quaternion from a 3x3 rotation matrix.
 		 * 			
 		 * @note	It's up to the caller to ensure the matrix is orthonormal.
 		 */
 		void fromRotationMatrix(const Matrix3& mat);
 
 		/**
-		 * @brief	Initializes the quaternion from an angle axis pair. Quaternion
-		 * 			will represent a rotation of "angle" radians around "axis".
+		 * Initializes the quaternion from an angle axis pair. Quaternion will represent a rotation of "angle" radians 
+		 * around "axis".
 		 */
         void fromAxisAngle(const Vector3& axis, const Radian& angle);
 
         /**
-         * @brief	Initializes the quaternion from orthonormal set of axes. Quaternion
-         * 			will represent a rotation from base axes to the specified set of axes.
+         * Initializes the quaternion from orthonormal set of axes. Quaternion will represent a rotation from base axes 
+		 * to the specified set of axes.
          * 			
 		 * @note	It's up to the caller to ensure the axes are orthonormal.
          */
         void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
         
         /**
-         * @brief	Creates a quaternion from the provided Pitch/Yaw/Roll angles.
+         * Creates a quaternion from the provided Pitch/Yaw/Roll angles.
          *
-		 * @param	xAngle	Rotation about x axis. (AKA Pitch)
-		 * @param	yAngle	Rotation about y axis. (AKA Yaw)
-		 * @param	zAngle	Rotation about z axis. (AKA Roll)
+		 * @param[in]	xAngle	Rotation about x axis. (AKA Pitch)
+		 * @param[in]	yAngle	Rotation about y axis. (AKA Yaw)
+		 * @param[in]	zAngle	Rotation about z axis. (AKA Roll)
          *
-         * @note	Since different values will be produced depending in which order are the rotations applied, this method assumes
-		 * 			they are applied in YXZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
+         * @note	
+		 * Since different values will be produced depending in which order are the rotations applied, this method assumes
+		 * they are applied in YXZ order. If you need a specific order, use the overloaded fromEulerAngles() method instead.
          */
         void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
 
         /**
-         * @brief	Creates a quaternion from the provided Pitch/Yaw/Roll angles.
+         * Creates a quaternion from the provided Pitch/Yaw/Roll angles.
          *
-		 * @param	xAngle	Rotation about x axis. (AKA Pitch)
-		 * @param	yAngle	Rotation about y axis. (AKA Yaw)
-		 * @param	zAngle	Rotation about z axis. (AKA Roll)
-		 * @param	order 	The order in which rotations will be extracted.
-		 * 					Different values can be retrieved depending on the order.
+		 * @param[in]	xAngle	Rotation about x axis. (AKA Pitch)
+		 * @param[in]	yAngle	Rotation about y axis. (AKA Yaw)
+		 * @param[in]	zAngle	Rotation about z axis. (AKA Roll)
+		 * @param[in]	order 	The order in which rotations will be extracted. Different values can be retrieved depending 
+		 *						on the order.
          */
         void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
 
 		/**
-		 * @brief	Converts a quaternion to a rotation matrix.
+		 * Converts a quaternion to a rotation matrix.
 		 */
 		void toRotationMatrix(Matrix3& mat) const;
 
 		/**
-		 * @brief	Converts a quaternion to an angle axis pair.
+		 * Converts a quaternion to an angle axis pair.
 		 *
-		 * @param [out]	axis 	The axis around the which rotation takes place.
-		 * @param [out]	angle	The angle in radians determining amount of rotation around the axis.
+		 * @param[out]	axis 	The axis around the which rotation takes place.
+		 * @param[out]	angle	The angle in radians determining amount of rotation around the axis.
 		 */
 		void toAxisAngle(Vector3& axis, Radian& angle) const;
 
 		/**
-		 * @brief	Converts a quaternion to an orthonormal set of axes.
+		 * Converts a quaternion to an orthonormal set of axes.
 		 *
-		 * @param [out]	xAxis	The X axis.
-		 * @param [out]	yAxis	The Y axis.
-		 * @param [out]	zAxis	The Z axis.
+		 * @param[out]	xAxis	The X axis.
+		 * @param[out]	yAxis	The Y axis.
+		 * @param[out]	zAxis	The Z axis.
 		 */
 		void toAxes(Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) const;
 
 		/**
-         * @brief	Extracts Pitch/Yaw/Roll rotations from this quaternion.
+         * Extracts Pitch/Yaw/Roll rotations from this quaternion.
          *
-         * @param [out]	xAngle	Rotation about x axis. (AKA Pitch)
-         * @param [out]	yAngle  Rotation about y axis. (AKA Yaw)
-         * @param [out]	zAngle 	Rotation about z axis. (AKA Roll)
+         * @param[out]	xAngle	Rotation about x axis. (AKA Pitch)
+         * @param[out]	yAngle  Rotation about y axis. (AKA Yaw)
+         * @param[out]	zAngle 	Rotation about z axis. (AKA Roll)
          *
          * @return	True if unique solution was found, false otherwise.
          */
         bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
 
-        /**
-         * @brief	Gets the positive x-axis of the coordinate system transformed by this quaternion.
-         */
+        /** Gets the positive x-axis of the coordinate system transformed by this quaternion. */
         Vector3 xAxis() const;
 
-        /**
-         * @brief	Gets the positive y-axis of the coordinate system transformed by this quaternion.
-         */
+        /** Gets the positive y-axis of the coordinate system transformed by this quaternion. */
         Vector3 yAxis() const;
 
-		/**
-         * @brief	Gets the positive z-axis of the coordinate system transformed by this quaternion.
-         */
+		/** Gets the positive z-axis of the coordinate system transformed by this quaternion. */
         Vector3 zAxis() const;
 
         Quaternion& operator= (const Quaternion& rhs)
@@ -211,64 +200,52 @@ namespace BansheeEngine
 
 		friend Quaternion operator* (float lhs, const Quaternion& rhs);
 
-        /**
-         * @brief	Calculates the dot product of this quaternion and another.
-         */
+        /** Calculates the dot product of this quaternion and another. */
         float dot(const Quaternion& other) const;  
 
-        /**
-         * @brief	Normalizes this quaternion, and returns the previous length.
-         */
+        /** Normalizes this quaternion, and returns the previous length. */
         float normalize(); 
 
         /**
-         * @brief	Gets the inverse.
+         * Gets the inverse.
          *
          * @note	Quaternion must be non-zero.
          */
         Quaternion inverse() const; 
 
-        /**
-         * @brief	Rotates the provided vector.
-         */
+        /** Rotates the provided vector. */
         Vector3 rotate(const Vector3& vec) const;
 
         /**
-         * @brief	Orients the quaternion so its negative z axis points to the provided direction.
+         * Orients the quaternion so its negative z axis points to the provided direction.
 		 *
-		 * @param	forwardDir	Direction to orient towards.
+		 * @param[in]	forwardDir	Direction to orient towards.
          */
 		void lookRotation(const Vector3& forwardDir);
 
         /**
-         * @brief	Orients the quaternion so its negative z axis points to the provided direction.
+         * Orients the quaternion so its negative z axis points to the provided direction.
 		 *
-		 * @param	forwardDir	Direction to orient towards.
-		 * @param	upDir		Constrains y axis orientation to a plane this vector lies on. This rule might be broken
-		 *						if forward and up direction are nearly parallel.
+		 * @param[in]	forwardDir	Direction to orient towards.
+		 * @param[in]	upDir		Constrains y axis orientation to a plane this vector lies on. This rule might be broken
+		 *							if forward and up direction are nearly parallel.
          */
 		void lookRotation(const Vector3& forwardDir, const Vector3& upDir);
 
-		/**
-		* @brief	Query if any of the components of the quaternion are NaN.
-		 */
+		/** Query if any of the components of the quaternion are not a number. */
 		bool isNaN() const
 		{
 			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
 		}
 
         /**
-         * @brief	Performs spherical interpolation between two quaternions. Spherical interpolation 
-         *          neatly interpolates between two rotations without modifying the size of the vector 
-         *          it is applied to (unlike linear interpolation).
+         * Performs spherical interpolation between two quaternions. Spherical interpolation neatly interpolates between 
+		 * two rotations without modifying the size of the vector it is applied to (unlike linear interpolation).
          */
         static Quaternion slerp(float t, const Quaternion& p,
             const Quaternion& q, bool shortestPath = true);
 
-        /**
-		 * @brief	Gets the shortest arc quaternion to rotate this vector to the destination
-		 *		vector.
-         */
+        /** Gets the shortest arc quaternion to rotate this vector to the destination vector. */
         static Quaternion getRotationFromTo(const Vector3& from, const Vector3& dest, const Vector3& fallbackAxis = Vector3::ZERO);
 
         static const float EPSILON;
@@ -282,5 +259,9 @@ namespace BansheeEngine
 			static const EulerAngleOrderData EA_LOOKUP[6];
     };
 
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
 	BS_ALLOW_MEMCPY_SERIALIZATION(Quaternion);
+	/** @endcond */
 }

+ 614 - 642
BansheeUtility/Include/BsRTTIPrerequisites.h

@@ -1,643 +1,615 @@
-#pragma once
-
-namespace BansheeEngine
-{
-	/**
-	* @brief	Helper method when serializing known data types that have valid
-	* 			RTTIPlainType specialization.
-	* 			
-	*			Returns the size of the element. If elements serializable type is 
-	*			specialized with hasDynamicSize == true, the dynamic size is calculated, 
-	*			otherwise sizeof() is used.
-	 */
-	template<class ElemType>
-	UINT32 rttiGetElemSize(const ElemType& data)
-	{
-		if(RTTIPlainType<ElemType>::hasDynamicSize == 1)
-			return RTTIPlainType<ElemType>::getDynamicSize(data);
-		else
-			return sizeof(ElemType);
-	}
-
-	/**
-	 * @brief	Helper method when serializing known data types that have valid
-	 * 			RTTIPlainType specialization.
-	 * 			
-	 *			Writes the specified data into memory, advances the memory pointer by the
-	 *			bytes written and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiWriteElem(const ElemType& data, char* memory)
-	{
-		RTTIPlainType<ElemType>::toMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	/**
-	* @brief	Helper method when serializing known data types that have valid
-	* 			RTTIPlainType specialization.
-	* 			
-	*			Writes the specified data into memory, advances the memory pointer by the
-	*			bytes written and returns pointer to new memory. Also increases the size 
-	 *			value by the size of the written element.
-	 */
-	template<class ElemType>
-	char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size)
-	{
-		RTTIPlainType<ElemType>::toMemory(data, memory);
-
-		UINT32 elemSize = rttiGetElemSize(data);
-		size += elemSize;
-
-		return memory + elemSize;
-	}
-
-
-	/**
-	 * @brief	Helper method when serializing known data types that have valid
-	 * 			RTTIPlainType specialization.
-	 * 			
-	 *			Reads the specified data into memory, advances the memory pointer by the
-	 *			bytes read and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiReadElem(ElemType& data, char* memory)
-	{
-		RTTIPlainType<ElemType>::fromMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	/**
-	 * @brief	Helper method when serializing known data types that have valid
-	 * 			RTTIPlainType specialization.
-	 * 			
-	 *			Reads the specified data into memory, advances the memory pointer by the
-	 *			bytes read and returns pointer to new memory. Also increases the size 
-	 *			value by the size of the read element.
-	 */
-	template<class ElemType>
-	char* rttiReadElem(ElemType& data, char* memory, UINT32& size)
-	{
-		RTTIPlainType<ElemType>::fromMemory(data, memory);
-
-		UINT32 elemSize = rttiGetElemSize(data);
-		size += elemSize;
-
-		return memory + elemSize;
-	}
-
-	/**
-	 * @brief	Template that you may specialize with a class if you want to provide
-	 * 			simple serialization for it. 
-	 * 			
-	 *			Any type that uses the "plain" field in the RTTI system must specialize this class.
-	 * 			
-	 * @note	Normally you will want to implement IReflectable interface if you want to provide serialization
-	 * 			as that interface properly handles versioning, nested objects, pointer handling and more.
-	 * 			
-	 *			This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or
-	 *			types you cannot modify so they implement IReflectable interface (like std::string or std::vector).
-	 *			
-	 * @see		RTTIType
-	 * @see		RTTIField
-	 */
-	template<class T>
-	struct RTTIPlainType 
-	{ 
-		static_assert(std::is_pod<T>::value, 
-			"Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
-			" (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
-
-		enum { id = 0 /**< Unique id for the serializable type. */ }; 
-		enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, e.g. int) or 1 (Dynamic size with no size restriction, e.g. string) */ };
-
-		/**
-		 * @brief	Serializes the provided object into the provided pre-allocated
-		 * 			memory buffer.
-		 */
-		static void toMemory(const T& data, char* memory)	
-		{ 
-			memcpy(memory, &data, sizeof(T)); 
-		}
-
-		/**
-		 * @brief	Deserializes a previously allocated object from the provided
-		 * 			memory buffer. Return the number of bytes read from the memory buffer.
-		 */
-		static UINT32 fromMemory(T& data, char* memory)
-		{
-			memcpy(&data, memory, sizeof(T)); 
-			return sizeof(T);
-		}
-
-		/**
-		 * @brief	Returns the size of the provided object. (Works for both
-		 * 			static and dynamic size types)
-		 */
-		static UINT32 getDynamicSize(const T& data)
-		{ 
-			return sizeof(T);
-		}
-	};
-
-	/**
-	 * @brief	Tell the RTTI system that the specified type may be serialized just by
-	 * 			using a memcpy.
-	 *
-	 * @note	Internally this creates a basic RTTIPlainType specialization for the type.
-	 * 
-	 * @see		RTTIPlainType
-	 */
-#define BS_ALLOW_MEMCPY_SERIALIZATION(type)				\
-	template<> struct RTTIPlainType<##type##>			\
-	{	enum { id=0 }; enum { hasDynamicSize = 0 };		\
-	static void toMemory(const type& data, char* memory)	\
-	{ memcpy(memory, &data, sizeof(##type##)); }			\
-	static UINT32 fromMemory(##type##& data, char* memory)	\
-	{ memcpy(&data, memory, sizeof(##type##)); return sizeof(##type##); }			\
-	static UINT32 getDynamicSize(const type& data)		\
-	{ return sizeof(##type##); }				\
-	}; 
-
-	/**
-	 * @brief	RTTIPlainType for std::vector.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
-	{	
-		enum { id = TID_Vector }; enum { hasDynamicSize = 1 };
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
-				RTTIPlainType<T>::toMemory(*iter, memory);
-
-				memory += elementSize;
-				size += elementSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				T element;
-				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
-				data.push_back(element);
-
-				memory += elementSize;
-			}
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * @brief	RTTIPlainType for std::set.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-		template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>>
-	{	
-		enum { id = TID_Set }; enum { hasDynamicSize = 1 };
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
-				RTTIPlainType<T>::toMemory(*iter, memory);
-
-				memory += elementSize;
-				size += elementSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				T element;
-				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
-				data.insert(element);
-
-				memory += elementSize;
-			}
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data)
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * @brief	RTTIPlainType for std::map.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
-	{	
-		enum { id = TID_Map }; enum { hasDynamicSize = 1 };
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
-				RTTIPlainType<Key>::toMemory(iter->first, memory);
-
-				memory += keySize;
-				size += keySize;
-
-				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
-				RTTIPlainType<Value>::toMemory(iter->second, memory);
-
-				memory += valueSize;
-				size += valueSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::fromMemory
-		 */
-		static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				Value value;
-				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
-				memory += valueSize;
-
-				data[key] = value; 
-			}
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::getDynamicSize
-		 */
-		static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);		
-				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * @brief	RTTIPlainType for std::unordered_map.
-	 *
-	 * @see		RTTIPlainType
-	 */
-	template<class Key, class Value> 
-	struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>>
-	{
-		enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 };
-
-		typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType;
-
-		/**
-		* @copydoc		RTTIPlainType::toMemory
-		*/
-		static void toMemory(MapType& data, char* memory)
-		{
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
-				RTTIPlainType<Key>::toMemory(iter->first, memory);
-
-				memory += keySize;
-				size += keySize;
-
-				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
-				RTTIPlainType<Value>::toMemory(iter->second, memory);
-
-				memory += valueSize;
-				size += valueSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::fromMemory
-		 */
-		static UINT32 fromMemory(MapType& data, char* memory)
-		{
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			for (UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				Value value;
-				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
-				memory += valueSize;
-
-				data[key] = value;
-			}
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::getDynamicSize
-		 */
-		static UINT32 getDynamicSize(const MapType& data)
-		{
-			UINT64 dataSize = sizeof(UINT32)* 2;
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
-				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}
-	};
-
-	/**
-	 * @brief	RTTIPlainType for std::unordered_set.
-	 *
-	 * @see		RTTIPlainType
-	 */
-	template<class Key> 
-	struct RTTIPlainType<std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>>>
-	{
-		enum { id = TID_UnorderedSet }; enum { hasDynamicSize = 1 };
-
-		typedef std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>> MapType;
-
-		/**
-		* @copydoc		RTTIPlainType::toMemory
-		*/
-		static void toMemory(MapType& data, char* memory)
-		{
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(*iter);
-				RTTIPlainType<Key>::toMemory(*iter, memory);
-
-				memory += keySize;
-				size += keySize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::fromMemory
-		 */
-		static UINT32 fromMemory(MapType& data, char* memory)
-		{
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			for (UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				data.insert(key);
-			}
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::getDynamicSize
-		 */
-		static UINT32 getDynamicSize(const MapType& data)
-		{
-			UINT64 dataSize = sizeof(UINT32)* 2;
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(*iter);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}
-	};
-
-	/**
-	 * @brief	RTTIPlainType for std::pair.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class A, class B> struct RTTIPlainType<std::pair<A, B>>
-	{	
-		enum { id = TID_Pair }; enum { hasDynamicSize = 1 };
-
-		/**
-		 * @copydoc		RTTIPlainType::toMemory
-		 */
-		static void toMemory(const std::pair<A, B>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 firstSize = RTTIPlainType<A>::getDynamicSize(data.first);
-			RTTIPlainType<A>::toMemory(data.first, memory);
-
-			memory += firstSize;
-			size += firstSize;
-
-			UINT32 secondSize = RTTIPlainType<B>::getDynamicSize(data.second);
-			RTTIPlainType<B>::toMemory(data.second, memory);
-
-			memory += secondSize;
-			size += secondSize;
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::fromMemory
-		 */
-		static UINT32 fromMemory(std::pair<A, B>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory);
-			memory += firstSize;
-
-			UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory);
-			memory += secondSize;
-
-			return size;
-		}
-
-		/**
-		 * @copydoc		RTTIPlainType::getDynamicSize
-		 */
-		static UINT32 getDynamicSize(const std::pair<A, B>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32);
-			dataSize += RTTIPlainType<A>::getDynamicSize(data.first);		
-			dataSize += RTTIPlainType<B>::getDynamicSize(data.second);
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup Utility 
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI
+	 *  @{
+	 */
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Returns the size of the element. If elements serializable type is 
+	 * specialized with hasDynamicSize == true, the dynamic size is calculated, 
+	 * otherwise sizeof() is used.
+	 */
+	template<class ElemType>
+	UINT32 rttiGetElemSize(const ElemType& data)
+	{
+		if(RTTIPlainType<ElemType>::hasDynamicSize == 1)
+			return RTTIPlainType<ElemType>::getDynamicSize(data);
+		else
+			return sizeof(ElemType);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Writes the specified data into memory, advances the memory pointer by the
+	 * bytes written and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiWriteElem(const ElemType& data, char* memory)
+	{
+		RTTIPlainType<ElemType>::toMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Writes the specified data into memory, advances the memory pointer by the
+	 * bytes written and returns pointer to new memory. Also increases the size 
+	 * value by the size of the written element.
+	 */
+	template<class ElemType>
+	char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size)
+	{
+		RTTIPlainType<ElemType>::toMemory(data, memory);
+
+		UINT32 elemSize = rttiGetElemSize(data);
+		size += elemSize;
+
+		return memory + elemSize;
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Reads the specified data into memory, advances the memory pointer by the
+	 * bytes read and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiReadElem(ElemType& data, char* memory)
+	{
+		RTTIPlainType<ElemType>::fromMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Reads the specified data into memory, advances the memory pointer by the
+	 * bytes read and returns pointer to new memory. Also increases the size 
+	 * value by the size of the read element.
+	 */
+	template<class ElemType>
+	char* rttiReadElem(ElemType& data, char* memory, UINT32& size)
+	{
+		RTTIPlainType<ElemType>::fromMemory(data, memory);
+
+		UINT32 elemSize = rttiGetElemSize(data);
+		size += elemSize;
+
+		return memory + elemSize;
+	}
+
+	/**
+	 * Template that you may specialize with a class if you want to provide simple serialization for it. 
+	 * 			
+	 * Any type that uses the "plain" field in the RTTI system must specialize this class.
+	 * 			
+	 * @note	
+	 * Normally you will want to implement IReflectable interface if you want to provide serialization
+	 * as that interface properly handles versioning, nested objects, pointer handling and more.
+	 *
+	 * @note			
+	 * This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or
+	 * types you cannot modify so they implement IReflectable interface (like std::string or std::vector).
+	 *			
+	 * @see		RTTITypeBase
+	 * @see		RTTIField
+	 */
+	template<class T>
+	struct RTTIPlainType 
+	{ 
+		static_assert(std::is_pod<T>::value, 
+			"Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
+			" (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
+
+		enum { id = 0 /**< Unique id for the serializable type. */ }; 
+		enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, e.g. int) or 1 (Dynamic size with no size restriction, e.g. string) */ };
+
+		/** Serializes the provided object into the provided pre-allocated memory buffer. */
+		static void toMemory(const T& data, char* memory)	
+		{ 
+			memcpy(memory, &data, sizeof(T)); 
+		}
+
+		/** 
+		 *  Deserializes a previously allocated object from the provided memory buffer. Return the number of bytes read 
+		 *  from the memory buffer.
+		 */
+		static UINT32 fromMemory(T& data, char* memory)
+		{
+			memcpy(&data, memory, sizeof(T)); 
+			return sizeof(T);
+		}
+
+		/** Returns the size of the provided object. (Works for both static and dynamic size types) */
+		static UINT32 getDynamicSize(const T& data)
+		{ 
+			return sizeof(T);
+		}
+	};
+
+	/**
+	 * Tell the RTTI system that the specified type may be serialized just by using a memcpy.
+	 *
+	 * @note	Internally this creates a basic RTTIPlainType specialization for the type.
+	 * 
+	 * @see		RTTIPlainType
+	 */
+#define BS_ALLOW_MEMCPY_SERIALIZATION(type)				\
+	template<> struct RTTIPlainType<##type##>			\
+	{	enum { id=0 }; enum { hasDynamicSize = 0 };		\
+	static void toMemory(const type& data, char* memory)	\
+	{ memcpy(memory, &data, sizeof(##type##)); }			\
+	static UINT32 fromMemory(##type##& data, char* memory)	\
+	{ memcpy(&data, memory, sizeof(##type##)); return sizeof(##type##); }			\
+	static UINT32 getDynamicSize(const type& data)		\
+	{ return sizeof(##type##); }				\
+	}; 
+
+	/** @cond SPECIALIZATIONS */
+
+	/**
+	 * RTTIPlainType for std::vector.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
+	{	
+		enum { id = TID_Vector }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
+				RTTIPlainType<T>::toMemory(*iter, memory);
+
+				memory += elementSize;
+				size += elementSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				T element;
+				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
+				data.push_back(element);
+
+				memory += elementSize;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::set.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>>
+	{	
+		enum { id = TID_Set }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
+				RTTIPlainType<T>::toMemory(*iter, memory);
+
+				memory += elementSize;
+				size += elementSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				T element;
+				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
+				data.insert(element);
+
+				memory += elementSize;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data)
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::map.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
+	{	
+		enum { id = TID_Map }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
+				RTTIPlainType<Key>::toMemory(iter->first, memory);
+
+				memory += keySize;
+				size += keySize;
+
+				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
+				RTTIPlainType<Value>::toMemory(iter->second, memory);
+
+				memory += valueSize;
+				size += valueSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				Value value;
+				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
+				memory += valueSize;
+
+				data[key] = value; 
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);		
+				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::unordered_map.
+	 *
+	 * @see		RTTIPlainType
+	 */
+	template<class Key, class Value> 
+	struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>>
+	{
+		enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 };
+
+		typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType;
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(MapType& data, char* memory)
+		{
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
+				RTTIPlainType<Key>::toMemory(iter->first, memory);
+
+				memory += keySize;
+				size += keySize;
+
+				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
+				RTTIPlainType<Value>::toMemory(iter->second, memory);
+
+				memory += valueSize;
+				size += valueSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(MapType& data, char* memory)
+		{
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			for (UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				Value value;
+				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
+				memory += valueSize;
+
+				data[key] = value;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const MapType& data)
+		{
+			UINT64 dataSize = sizeof(UINT32)* 2;
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
+				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}
+	};
+
+	/**
+	 * RTTIPlainType for std::unordered_set.
+	 *
+	 * @see		RTTIPlainType
+	 */
+	template<class Key> 
+	struct RTTIPlainType<std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>>>
+	{
+		enum { id = TID_UnorderedSet }; enum { hasDynamicSize = 1 };
+
+		typedef std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>> MapType;
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(MapType& data, char* memory)
+		{
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(*iter);
+				RTTIPlainType<Key>::toMemory(*iter, memory);
+
+				memory += keySize;
+				size += keySize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(MapType& data, char* memory)
+		{
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			for (UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				data.insert(key);
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const MapType& data)
+		{
+			UINT64 dataSize = sizeof(UINT32)* 2;
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(*iter);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}
+	};
+
+	/**
+	 * RTTIPlainType for std::pair.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class A, class B> struct RTTIPlainType<std::pair<A, B>>
+	{	
+		enum { id = TID_Pair }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::pair<A, B>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 firstSize = RTTIPlainType<A>::getDynamicSize(data.first);
+			RTTIPlainType<A>::toMemory(data.first, memory);
+
+			memory += firstSize;
+			size += firstSize;
+
+			UINT32 secondSize = RTTIPlainType<B>::getDynamicSize(data.second);
+			RTTIPlainType<B>::toMemory(data.second, memory);
+
+			memory += secondSize;
+			size += secondSize;
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(std::pair<A, B>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory);
+			memory += firstSize;
+
+			UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory);
+			memory += secondSize;
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const std::pair<A, B>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32);
+			dataSize += RTTIPlainType<A>::getDynamicSize(data.first);		
+			dataSize += RTTIPlainType<B>::getDynamicSize(data.second);
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/** @endcond */
+
+	/** @} */
+	/** @} */
 }

+ 74 - 64
BansheeUtility/Include/BsRadian.h

@@ -1,65 +1,75 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsDegree.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Wrapper class which indicates a given angle value is in Radians.
-	 * 			
-	 *	@note Radian values are interchangeable with Degree values, and conversions
-	 *	will be done automatically between them.
-	 */
-	class BS_UTILITY_EXPORT Radian
-	{
-		float mRad;
-
-	public:
-		explicit Radian(float r = 0.0f) : mRad(r) {}
-		Radian(const Degree& d);
-		Radian& operator= (const float& f) { mRad = f; return *this; }
-		Radian& operator= (const Radian& r) { mRad = r.mRad; return *this; }
-		Radian& operator= (const Degree& d);
-
-		float valueDegrees() const;
-		float valueRadians() const { return mRad; }
-
-		/**
-		 * @brief  Wraps the angle in [0, 2 *  PI) range
-		 */
-		Radian wrap();
-
-        const Radian& operator+ () const { return *this; }
-		Radian operator+ (const Radian& r) const { return Radian (mRad + r.mRad); }
-		Radian operator+ (const Degree& d) const;
-		Radian& operator+= (const Radian& r) { mRad += r.mRad; return *this; }
-		Radian& operator+= (const Degree& d);
-		Radian operator- () const { return Radian(-mRad); }
-		Radian operator- (const Radian& r) const { return Radian (mRad - r.mRad); }
-		Radian operator- (const Degree& d) const;
-		Radian& operator-= (const Radian& r) { mRad -= r.mRad; return *this; }
-		Radian& operator-= (const Degree& d);
-		Radian operator* (float f) const { return Radian (mRad * f); }
-        Radian operator* (const Radian& f) const { return Radian (mRad * f.mRad); }
-		Radian& operator*= (float f) { mRad *= f; return *this; }
-		Radian operator/ (float f) const { return Radian (mRad / f); }
-		Radian& operator/= (float f) { mRad /= f; return *this; }
-
-		friend Radian operator* (float lhs, const Radian& rhs) { return Radian(lhs * rhs.mRad); }
-		friend Radian operator/ (float lhs, const Radian& rhs) { return Radian(lhs / rhs.mRad); }
-		friend Radian operator+ (Radian& lhs, float rhs) { return Radian(lhs.mRad + rhs); }
-		friend Radian operator+ (float lhs, const Radian& rhs) { return Radian(lhs + rhs.mRad); }
-		friend Radian operator- (const Radian& lhs, float rhs) { return Radian(lhs.mRad - rhs); }
-		friend Radian operator- (const float lhs, const Radian& rhs) { return Radian(lhs - rhs.mRad); }
-
-		bool operator<  (const Radian& r) const { return mRad <  r.mRad; }
-		bool operator<= (const Radian& r) const { return mRad <= r.mRad; }
-		bool operator== (const Radian& r) const { return mRad == r.mRad; }
-		bool operator!= (const Radian& r) const { return mRad != r.mRad; }
-		bool operator>= (const Radian& r) const { return mRad >= r.mRad; }
-		bool operator>  (const Radian& r) const { return mRad >  r.mRad; }
-	};
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Radian);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsDegree.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/**
+	 * Wrapper class which indicates a given angle value is in radians.
+	 * 			
+	 * @note 
+	 * Radian values are interchangeable with Degree values, and conversions will be done automatically between them.
+	 */
+	class BS_UTILITY_EXPORT Radian
+	{
+	public:
+		explicit Radian(float r = 0.0f) : mRad(r) {}
+		Radian(const Degree& d);
+		Radian& operator= (const float& f) { mRad = f; return *this; }
+		Radian& operator= (const Radian& r) { mRad = r.mRad; return *this; }
+		Radian& operator= (const Degree& d);
+
+		/** Returns the value of the angle in degrees. */
+		float valueDegrees() const;
+
+		/** Returns the value of the angle in radians. */
+		float valueRadians() const { return mRad; }
+
+		/** Wraps the angle in [0, 2 *  PI) range. */
+		Radian wrap();
+
+        const Radian& operator+ () const { return *this; }
+		Radian operator+ (const Radian& r) const { return Radian (mRad + r.mRad); }
+		Radian operator+ (const Degree& d) const;
+		Radian& operator+= (const Radian& r) { mRad += r.mRad; return *this; }
+		Radian& operator+= (const Degree& d);
+		Radian operator- () const { return Radian(-mRad); }
+		Radian operator- (const Radian& r) const { return Radian (mRad - r.mRad); }
+		Radian operator- (const Degree& d) const;
+		Radian& operator-= (const Radian& r) { mRad -= r.mRad; return *this; }
+		Radian& operator-= (const Degree& d);
+		Radian operator* (float f) const { return Radian (mRad * f); }
+        Radian operator* (const Radian& f) const { return Radian (mRad * f.mRad); }
+		Radian& operator*= (float f) { mRad *= f; return *this; }
+		Radian operator/ (float f) const { return Radian (mRad / f); }
+		Radian& operator/= (float f) { mRad /= f; return *this; }
+
+		friend Radian operator* (float lhs, const Radian& rhs) { return Radian(lhs * rhs.mRad); }
+		friend Radian operator/ (float lhs, const Radian& rhs) { return Radian(lhs / rhs.mRad); }
+		friend Radian operator+ (Radian& lhs, float rhs) { return Radian(lhs.mRad + rhs); }
+		friend Radian operator+ (float lhs, const Radian& rhs) { return Radian(lhs + rhs.mRad); }
+		friend Radian operator- (const Radian& lhs, float rhs) { return Radian(lhs.mRad - rhs); }
+		friend Radian operator- (const float lhs, const Radian& rhs) { return Radian(lhs - rhs.mRad); }
+
+		bool operator<  (const Radian& r) const { return mRad <  r.mRad; }
+		bool operator<= (const Radian& r) const { return mRad <= r.mRad; }
+		bool operator== (const Radian& r) const { return mRad == r.mRad; }
+		bool operator!= (const Radian& r) const { return mRad != r.mRad; }
+		bool operator>= (const Radian& r) const { return mRad >= r.mRad; }
+		bool operator>  (const Radian& r) const { return mRad >  r.mRad; }
+
+	private:
+		float mRad;
+	};
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Radian);
+	/** @endcond */
 }

+ 80 - 89
BansheeUtility/Include/BsRay.h

@@ -1,90 +1,81 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine 
-{
-    /**
-     * @brief	A ray in 3D space represented with an origin and direction.
-     */
-    class BS_UTILITY_EXPORT Ray
-    {
-    public:
-        Ray()
-			:mOrigin(Vector3::ZERO), mDirection(Vector3::UNIT_Z) 
-		{ }
-
-        Ray(const Vector3& origin, const Vector3& direction)
-            :mOrigin(origin), mDirection(direction) 
-		{ }
-
-        void setOrigin(const Vector3& origin) { mOrigin = origin; } 
-        const Vector3& getOrigin(void) const { return mOrigin; } 
-
-        void setDirection(const Vector3& dir) { mDirection = dir; } 
-        const Vector3& getDirection(void) const {return mDirection;} 
-
-		/**
-		 * @brief	Gets the position of a point t units along the ray.
-		 */
-		Vector3 getPoint(float t) const 
-		{ 
-			return Vector3(mOrigin + (mDirection * t));
-		}
-		
-		/**
-		 * @brief	Gets the position of a point t units along the ray.
-		 */
-		Vector3 operator*(float t) const 
-		{ 
-			return getPoint(t);
-		}
-
-		/**
-		 * @brief	Transforms the ray by the given matrix.
-		 */
-		void transform(const Matrix4& matrix);
-
-		/**
-		 * @brief	Transforms the ray by the given matrix.
-		 *
-		 * @note	Provided matrix must be affine.
-		 */
-		void transformAffine(const Matrix4& matrix);
-
-		/**
-		 * @brief	Ray/plane intersection, returns boolean result and distance to intersection point.
-		 */
-		std::pair<bool, float> intersects(const Plane& p) const;
-
-		/**
-		 * @brief	Ray/sphere intersection, returns boolean result and distance to nearest intersection point.
-		 */
-		std::pair<bool, float> intersects(const Sphere& s) const;
-
-		/**
-		 * @brief	Ray/axis aligned box intersection, returns boolean result and distance to nearest intersection point.
-		 */
-		std::pair<bool, float> intersects(const AABox& box) const;
-
-        /**
-         * @brief	Ray/triangle intersection, returns boolean result and distance to intersection point.
-         *
-         * @param	a				Triangle first vertex.
-         * @param	b				Triangle second vertex.
-         * @param	c				Triangle third vertex.
-         * @param	normal			The normal of the triangle. Doesn't need to be normalized.
-         * @param	positiveSide	(optional) Should intersections with the positive side (normal facing) count.
-         * @param	negativeSide	(optional) Should intersections with the negative side (opposite of normal facing) count.
-         *
-         * @return	Boolean result if intersection happened and distance to intersection point.
-         */
-        std::pair<bool, float> intersects(const Vector3& a, const Vector3& b, const Vector3& c, 
-			const Vector3& normal, bool positiveSide = true, bool negativeSide = true) const;
-
-	protected:
-		Vector3 mOrigin;
-		Vector3 mDirection;
-    };
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** A ray in 3D space represented with an origin and direction. */
+    class BS_UTILITY_EXPORT Ray
+    {
+    public:
+        Ray()
+			:mOrigin(Vector3::ZERO), mDirection(Vector3::UNIT_Z) 
+		{ }
+
+        Ray(const Vector3& origin, const Vector3& direction)
+            :mOrigin(origin), mDirection(direction) 
+		{ }
+
+        void setOrigin(const Vector3& origin) { mOrigin = origin; } 
+        const Vector3& getOrigin(void) const { return mOrigin; } 
+
+        void setDirection(const Vector3& dir) { mDirection = dir; } 
+        const Vector3& getDirection(void) const {return mDirection;} 
+
+		/** Gets the position of a point t units along the ray. */
+		Vector3 getPoint(float t) const 
+		{ 
+			return Vector3(mOrigin + (mDirection * t));
+		}
+		
+		/** Gets the position of a point t units along the ray. */
+		Vector3 operator*(float t) const 
+		{ 
+			return getPoint(t);
+		}
+
+		/** Transforms the ray by the given matrix. */
+		void transform(const Matrix4& matrix);
+
+		/**
+		 * Transforms the ray by the given matrix.
+		 *
+		 * @note	Provided matrix must be affine.
+		 */
+		void transformAffine(const Matrix4& matrix);
+
+		/** Ray/plane intersection, returns boolean result and distance to intersection point. */
+		std::pair<bool, float> intersects(const Plane& p) const;
+
+		/** Ray/sphere intersection, returns boolean result and distance to nearest intersection point. */
+		std::pair<bool, float> intersects(const Sphere& s) const;
+
+		/** Ray/axis aligned box intersection, returns boolean result and distance to nearest intersection point. */
+		std::pair<bool, float> intersects(const AABox& box) const;
+
+        /**
+         * Ray/triangle intersection, returns boolean result and distance to intersection point.
+         *
+         * @param[in]	a				Triangle first vertex.
+         * @param[in]	b				Triangle second vertex.
+         * @param[in]	c				Triangle third vertex.
+         * @param[in]	normal			The normal of the triangle. Doesn't need to be normalized.
+         * @param[in]	positiveSide	(optional) Should intersections with the positive side (normal facing) count.
+         * @param[in]	negativeSide	(optional) Should intersections with the negative side (opposite of normal facing) count.
+         * @return						Boolean result if intersection happened and distance to intersection point.
+         */
+        std::pair<bool, float> intersects(const Vector3& a, const Vector3& b, const Vector3& c, 
+			const Vector3& normal, bool positiveSide = true, bool negativeSide = true) const;
+
+	protected:
+		Vector3 mOrigin;
+		Vector3 mDirection;
+    };
+
+	/** @} */
 }

+ 61 - 65
BansheeUtility/Include/BsRect2.h

@@ -1,66 +1,62 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a 2D rectangle using real values.
-	 * 			Rectangle is represented with an origin in top left and width/height.
-	 */
-	class BS_UTILITY_EXPORT Rect2
-	{
-	public:
-		Rect2();
-		Rect2(float _x, float _y, float _width, float _height);
-
-		float x, y, width, height;
-
-		/**
-		 * @brief	Returns true if the rectangle contains the provided point.
-		 */
-		bool contains(const Vector2& point) const;
-
-		/**
-		 * @brief	Returns true if the rectangle overlaps the provided rectangle.
-		 * 			Also returns true if the rectangles are contained within each other completely
-		 * 			(no intersecting edges).
-		 */
-		bool overlaps(const Rect2& other) const;
-
-		/**
-		 * @brief	Extends this rectangle so that the provided rectangle is
-		 * 			completely contained within it.
-		 */
-		void encapsulate(const Rect2& other);
-
-		/**
-		 * @brief	Clips current rectangle so that it does not overlap
-		 * 			the provided rectangle.
-		 */
-		void clip(const Rect2& clipRect);
-
-		/**
-		 * @brief	Transforms the bounds by the given matrix.
-		 * 			Resulting value is an axis aligned rectangle encompassing the transformed points.
-		 * 			
-		 * @note	Since the resulting value is an AA rectangle of the original transformed rectangle, the bounds
-		 * 			will be larger than needed. Oriented rectangle would provide a much tighter fit.
-		 */
-		void transform(const Matrix4& matrix);
-
-		inline bool operator== (const Rect2& rhs) const
-		{
-			return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
-		}
-
-		inline bool operator!= (const Rect2& rhs) const
-		{
-			return !(*this == rhs);
-		}
-
-		static const Rect2 EMPTY;
-	};
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Rect2);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Represents a 2D rectangle using real values. Rectangle is represented with an origin in top left and width/height. */
+	class BS_UTILITY_EXPORT Rect2
+	{
+	public:
+		Rect2();
+		Rect2(float _x, float _y, float _width, float _height);
+
+		float x, y, width, height;
+
+		/** Returns true if the rectangle contains the provided point. */
+		bool contains(const Vector2& point) const;
+
+		/**
+		 * Returns true if the rectangle overlaps the provided rectangle. Also returns true if the rectangles are contained 
+		 * within each other completely (no intersecting edges).
+		 */
+		bool overlaps(const Rect2& other) const;
+
+		/** Extends this rectangle so that the provided rectangle is completely contained within it. */
+		void encapsulate(const Rect2& other);
+
+		/** Clips current rectangle so that it does not overlap the provided rectangle. */
+		void clip(const Rect2& clipRect);
+
+		/**
+		 * Transforms the bounds by the given matrix. Resulting value is an axis aligned rectangle encompassing the 
+		 * transformed points.
+		 * 			
+		 * @note	Since the resulting value is an AA rectangle of the original transformed rectangle, the bounds
+		 * 			will be larger than needed. Oriented rectangle would provide a much tighter fit.
+		 */
+		void transform(const Matrix4& matrix);
+
+		bool operator== (const Rect2& rhs) const
+		{
+			return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
+		}
+
+		bool operator!= (const Rect2& rhs) const
+		{
+			return !(*this == rhs);
+		}
+
+		static const Rect2 EMPTY;
+	};
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Rect2);
+	/** @endcond */
 }

+ 70 - 77
BansheeUtility/Include/BsRect2I.h

@@ -1,78 +1,71 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a 2D rectangle using integer values.
-	 * 			Rectangle is represented with an origin in top left and width/height.
-	 */
-	class BS_UTILITY_EXPORT Rect2I
-	{
-	public:
-		Rect2I();
-		Rect2I(int _x, int _y, int _width, int _height);
-
-		int x, y, width, height;
-
-		/**
-		 * @brief	Returns true if the rectangle contains the provided point.
-		 */
-		bool contains(const Vector2I& point) const;
-
-		/**
-		 * @brief	Returns true if the rectangle overlaps the provided rectangle.
-		 * 			Also returns true if the rectangles are contained within each other completely
-		 * 			(no intersecting edges).
-		 */
-		bool overlaps(const Rect2I& other) const;
-
-		/**
-		 * @brief	Extends this rectangle so that the provided rectangle is
-		 * 			completely contained within it.
-		 */
-		void encapsulate(const Rect2I& other);
-
-		/**
-		 * @brief	Clips current rectangle so that it does not overlap
-		 * 			the provided rectangle.
-		 */
-		void clip(const Rect2I& clipRect);
-
-		/**
-		 * @brief	Cuts the current rectangle with the provided rectangle and outputs
-		 *			the pieces. The pieces will contain all area of the current rectangle
-		 *			without including the cut rectangle area.
-		 */
-		void cut(const Rect2I& cutRect, Vector<Rect2I>& pieces);
-
-		/**
-		 * @brief	Cuts the current rectangle with the provided rectangles and outputs
-		 *			the pieces. The pieces will contain all area of the current rectangle
-		 *			without including the cut rectangles area.
-		 */
-		void cut(const Vector<Rect2I>& cutRects, Vector<Rect2I>& pieces);
-
-		/**
-		 * @brief	Transforms the bounds by the given matrix.
-		 * 			Resulting value is an axis aligned rectangle encompassing the transformed points.
-		 * 			
-		 * @note	Since the resulting value is an AA rectangle of the original transformed rectangle, the bounds
-		 * 			will be larger than needed. Oriented rectangle would provide a much tighter fit.
-		 */
-		void transform(const Matrix4& matrix);
-
-		inline bool operator== (const Rect2I& rhs) const
-		{
-			return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
-		}
-
-		inline bool operator!= (const Rect2I& rhs) const
-		{
-			return !(*this == rhs);
-		}
-
-		static const Rect2I EMPTY;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Represents a 2D rectangle using integer values. Rectangle is represented with an origin in top left and width/height. */
+	class BS_UTILITY_EXPORT Rect2I
+	{
+	public:
+		Rect2I();
+		Rect2I(int _x, int _y, int _width, int _height);
+
+		int x, y, width, height;
+
+		/** Returns true if the rectangle contains the provided point. */
+		bool contains(const Vector2I& point) const;
+
+		/**
+		 * Returns true if the rectangle overlaps the provided rectangle. Also returns true if the rectangles are contained 
+		 * within each other completely (no intersecting edges).
+		 */
+		bool overlaps(const Rect2I& other) const;
+
+		/** Extends this rectangle so that the provided rectangle is completely contained within it. */
+		void encapsulate(const Rect2I& other);
+
+		/** Clips current rectangle so that it does not overlap the provided rectangle. */
+		void clip(const Rect2I& clipRect);
+
+		/**
+		 * Cuts the current rectangle with the provided rectangle and outputs the pieces. The pieces will contain all area 
+		 * of the current rectangle without including the cut rectangle area.
+		 */
+		void cut(const Rect2I& cutRect, Vector<Rect2I>& pieces);
+
+		/**
+		 * Cuts the current rectangle with the provided rectangles and outputs the pieces. The pieces will contain all area 
+		 * of the current rectangle without including the cut rectangles area.
+		 */
+		void cut(const Vector<Rect2I>& cutRects, Vector<Rect2I>& pieces);
+
+		/**
+		 * Transforms the bounds by the given matrix. Resulting value is an axis aligned rectangle encompassing the 
+		 * transformed points.
+		 * 			
+		 * @note	
+		 * Since the resulting value is an AA rectangle of the original transformed rectangle, the bounds will be larger 
+		 * than needed. Oriented rectangle would provide a much tighter fit.
+		 */
+		void transform(const Matrix4& matrix);
+
+		inline bool operator== (const Rect2I& rhs) const
+		{
+			return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
+		}
+
+		inline bool operator!= (const Rect2I& rhs) const
+		{
+			return !(*this == rhs);
+		}
+
+		static const Rect2I EMPTY;
+	};
+
+	/** @} */
 }

+ 71 - 76
BansheeUtility/Include/BsRect3.h

@@ -1,77 +1,72 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a rectangle in three dimensional space. It is represented
-	 *			by two axes that extend from the specified origin. Axes should be perpendicular
-	 *			to each other and they extend in both positive and negative directions from the
-	 *			origin by the amount specified by extents.
-	 */
-	class BS_UTILITY_EXPORT Rect3
-	{
-	public:
-		Rect3();
-
-		Rect3(const Vector3& center, const std::array<Vector3, 2>& axes,
-			const std::array<float, 2>& extents);
-
-		/**
-		 * @brief	Find the nearest points of the provided ray and the rectangle.
-		 *
-		 * @return	A set of nearest points and nearest distance.
-		 *			First value in the set corresponds to nearest point on the ray, and the second to the nearest point on the rectangle.
-		 *			They are same in the case of intersection. When ray is parallel to the rectangle there are two sets of nearest points
-		 *			but only one the set nearest to the ray origin is returned.
-		 */
-		std::pair<std::array<Vector3, 2>, float> getNearestPoint(const Ray& ray) const;
-
-		/**
-		 * @brief	Find the nearest point on the rectangle to the provided point.
-		 *
-		 * @return	Nearest point and distance to nearest point.
-		 */
-		std::pair<Vector3, float> getNearestPoint(const Vector3& point) const;
-
-		/**
-		 * @brief	Ray/rectangle intersection.
-		 *
-		 * @return	Boolean result and distance to intersection point.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray) const;
-
-		/**
-		 * @brief	Gets the origin of the rectangle. 
-		 */
-		const Vector3& getCenter() const { return mCenter; }
-
-		/**
-		 * @brief	Returns the rectangle's horizontal axis.
-		 */
-		const Vector3& getAxisHorz() const { return mAxisHorz; }
-
-		/**
-		 * @brief	Returns the rectangle's vertical axis.
-		 */
-		const Vector3& getAxisVert() const { return mAxisVert; }
-
-		/**
-		 * @brief	Gets the extent of the rectangle along its horizontal axis.
-		 */
-		const float& getExtentHorz() const { return mExtentHorz; }
-
-		/**
-		 * @brief	Gets the extent of the rectangle along its vertical axis.
-		 */
-		const float& getExtentVertical() const { return mExtentVert; }
-	private:
-		Vector3 mCenter;
-		Vector3 mAxisHorz;
-		Vector3 mAxisVert;
-		float mExtentHorz;
-		float mExtentVert;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/**
+	 * Represents a rectangle in three dimensional space. It is represented by two axes that extend from the specified 
+	 * origin. Axes should be perpendicular to each other and they extend in both positive and negative directions from the
+	 * origin by the amount specified by extents.
+	 */
+	class BS_UTILITY_EXPORT Rect3
+	{
+	public:
+		Rect3();
+
+		Rect3(const Vector3& center, const std::array<Vector3, 2>& axes,
+			const std::array<float, 2>& extents);
+
+		/**
+		 * Find the nearest points of the provided ray and the rectangle.
+		 *
+		 * @return	A set of nearest points and nearest distance. First value in the set corresponds to nearest point on 
+		 *			the ray, and the second to the nearest point on the rectangle. They are same in the case of intersection. 
+		 *			When ray is parallel to the rectangle there are two sets of nearest points but only one the set nearest 
+		 *			to the ray origin is returned.
+		 */
+		std::pair<std::array<Vector3, 2>, float> getNearestPoint(const Ray& ray) const;
+
+		/**
+		 * Find the nearest point on the rectangle to the provided point.
+		 *
+		 * @return	Nearest point and distance to nearest point.
+		 */
+		std::pair<Vector3, float> getNearestPoint(const Vector3& point) const;
+
+		/**
+		 * Ray/rectangle intersection.
+		 *
+		 * @return	Boolean result and distance to intersection point.
+		 */
+		std::pair<bool, float> intersects(const Ray& ray) const;
+
+		/** Gets the origin of the rectangle. */
+		const Vector3& getCenter() const { return mCenter; }
+
+		/** Returns the rectangle's horizontal axis. */
+		const Vector3& getAxisHorz() const { return mAxisHorz; }
+
+		/** Returns the rectangle's vertical axis. */
+		const Vector3& getAxisVert() const { return mAxisVert; }
+
+		/** Gets the extent of the rectangle along its horizontal axis. */
+		const float& getExtentHorz() const { return mExtentHorz; }
+
+		/** Gets the extent of the rectangle along its vertical axis. */
+		const float& getExtentVertical() const { return mExtentVert; }
+	private:
+		Vector3 mCenter;
+		Vector3 mAxisHorz;
+		Vector3 mAxisVert;
+		float mExtentHorz;
+		float mExtentVert;
+	};
+
+	/** @} */
 }

+ 81 - 101
BansheeUtility/Include/BsSphere.h

@@ -1,102 +1,82 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine 
-{
-    /**
-     * @brief	A sphere represented by a center point and a radius.
-     */
-    class BS_UTILITY_EXPORT Sphere
-    {
-    public:
-        /**
-         * @brief	Default constructor. Creates a unit sphere around the origin.
-         */
-        Sphere() : mRadius(1.0), mCenter(Vector3::ZERO) 
-		{ }
-
-        Sphere(const Vector3& center, float radius)
-            :mRadius(radius), mCenter(center) 
-		{ }
-
-        /**
-         * @brief	Returns the radius of the sphere.
-         */
-        float getRadius(void) const { return mRadius; }
-
-        /**
-         * @brief	Sets the radius of the sphere.
-         */
-        void setRadius(float radius) { mRadius = radius; }
-
-        /**
-         * @brief	Returns the center point of the sphere.
-         */
-        const Vector3& getCenter(void) const { return mCenter; }
-
-        /**
-         * @brief	Sets the center point of the sphere.
-         */
-        void setCenter(const Vector3& center) { mCenter = center; }
-
-		/**
-		 * @brief	Merges the two spheres, creating a new
-		 * 			sphere that encapsulates them both.
-		 */
-		void merge(const Sphere& rhs);
-
-		/**
-		 * @brief	Expands the sphere so it includes
-		 * 			the provided point.
-		 */
-		void merge(const Vector3& point);
-
-		/**
-		 * @brief	Transforms the sphere by the given matrix.
-		 */
-		void transform(const Matrix4& matrix);
-
-		/**
-		 * @brief	Returns whether or not this sphere contains the provided point.
-		 */
-		bool contains(const Vector3& v) const
-		{
-            return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
-		}
-
-		/**
-		 * @brief	Returns whether or not this sphere intersects another sphere.
-		 */
-		bool intersects(const Sphere& s) const
-		{
-            return (s.mCenter - mCenter).squaredLength() <=
-                Math::sqr(s.mRadius + mRadius);
-		}
-
-		/**
-		 * @brief	Returns whether or not this sphere intersects a box.
-		 */
-		bool intersects(const AABox& box) const;
-
-		/**
-		 * @brief	Returns whether or not this sphere intersects a plane.
-		 */
-		bool intersects(const Plane& plane) const;
-
-		/**
-		 * @brief	Ray/sphere intersection, returns boolean result and distance to nearest intersection.
-		 * 			
-		 * @param	discardInside	(optional) If true the intersection will be discarded if ray origin
-		 * 							is located within the sphere.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray, bool discardInside = true) const;
-
-	private:
-		float mRadius;
-		Vector3 mCenter;
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Sphere);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** A sphere represented by a center point and a radius. */
+    class BS_UTILITY_EXPORT Sphere
+    {
+    public:
+        /** Default constructor. Creates a unit sphere around the origin. */
+        Sphere() : mRadius(1.0), mCenter(Vector3::ZERO) 
+		{ }
+
+        Sphere(const Vector3& center, float radius)
+            :mRadius(radius), mCenter(center) 
+		{ }
+
+        /** Returns the radius of the sphere. */
+        float getRadius(void) const { return mRadius; }
+
+        /** Sets the radius of the sphere. */
+        void setRadius(float radius) { mRadius = radius; }
+
+        /** Returns the center point of the sphere. */
+        const Vector3& getCenter(void) const { return mCenter; }
+
+        /** Sets the center point of the sphere. */
+        void setCenter(const Vector3& center) { mCenter = center; }
+
+		/** Merges the two spheres, creating a new sphere that encapsulates them both. */
+		void merge(const Sphere& rhs);
+
+		/** Expands the sphere so it includes the provided point. */
+		void merge(const Vector3& point);
+
+		/** Transforms the sphere by the given matrix. */
+		void transform(const Matrix4& matrix);
+
+		/** Returns whether or not this sphere contains the provided point. */
+		bool contains(const Vector3& v) const
+		{
+            return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
+		}
+
+		/** Returns whether or not this sphere intersects another sphere. */
+		bool intersects(const Sphere& s) const
+		{
+            return (s.mCenter - mCenter).squaredLength() <=
+                Math::sqr(s.mRadius + mRadius);
+		}
+
+		/** Returns whether or not this sphere intersects a box. */
+		bool intersects(const AABox& box) const;
+
+		/** Returns whether or not this sphere intersects a plane. */
+		bool intersects(const Plane& plane) const;
+
+		/**
+		 * Ray/sphere intersection, returns boolean result and distance to nearest intersection.
+		 * 			
+		 * @param[in]	discardInside	(optional) If true the intersection will be discarded if ray origin
+		 * 								is located within the sphere.
+		 */
+		std::pair<bool, float> intersects(const Ray& ray, bool discardInside = true) const;
+
+	private:
+		float mRadius;
+		Vector3 mCenter;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Sphere);
+	/** @endcond */
 }

+ 192 - 167
BansheeUtility/Include/BsStdHeaders.h

@@ -1,168 +1,193 @@
-#pragma once
-
-#ifdef __BORLANDC__
-    #define __STD_ALGORITHM
-#endif
-
-#include <cassert>
-#include <cstdio>
-#include <cstdlib>
-#include <ctime>
-#include <cstring>
-#include <cstdarg>
-#include <cmath>
-
-#include <memory>
-
-// STL containers
-#include <vector>
-#include <stack>
-#include <map>
-#include <string>
-#include <set>
-#include <list>
-#include <deque>
-#include <queue>
-#include <bitset>
-#include <array>
-
-// Note - not in the original STL, but exists in SGI STL and STLport
-// For gcc 4.3 see http://gcc.gnu.org/gcc-4.3/changes.html
-#if (BS_COMPILER == BS_COMPILER_GNUC)
-#   if BS_COMP_VER >= 430
-#       include <tr1/unordered_map>
-#       include <tr1/unordered_set> 
-#   else
-#       include <ext/hash_map>
-#       include <ext/hash_set>
-#   endif
-#else
-#   if (BS_COMPILER == BS_COMPILER_MSVC) && BS_COMP_VER >= 1600 // VC++ 10.0
-#    	include <unordered_map>
-#    	include <unordered_set>
-#	else
-#   	include <hash_set>
-#   	include <hash_map>
-#	endif
-#endif 
-
-// STL algorithms & functions
-#include <algorithm>
-#include <functional>
-#include <limits>
-
-// C++ Stream stuff
-#include <fstream>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-
-#ifdef __BORLANDC__
-namespace BansheeEngine
-{
-    using namespace std;
-}
-#endif
-
-extern "C" {
-
-#   include <sys/types.h>
-#   include <sys/stat.h>
-
-}
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-#  undef min
-#  undef max
-#	if !defined(NOMINMAX) && defined(_MSC_VER)
-#		define NOMINMAX // required to stop windows.h messing up std::min
-#	endif
-#  if defined( __MINGW32__ )
-#    include <unistd.h>
-#  endif
-#endif
-
-#if BS_PLATFORM == BS_PLATFORM_LINUX
-extern "C" {
-
-#   include <unistd.h>
-#   include <dlfcn.h>
-
-}
-#endif
-
-#if BS_PLATFORM == BS_PLATFORM_APPLE
-extern "C" {
-#   include <unistd.h>
-#   include <sys/param.h>
-#   include <CoreFoundation/CoreFoundation.h>
-}
-#endif
-
-namespace BansheeEngine
-{
-	// Standard containers, for easier access in my own namespace
-	template <typename T, typename A = StdAlloc<T>> 
-	using Deque = std::deque<T, A>;
-
-	template <typename T, typename A = StdAlloc<T>> 
-	using Vector = std::vector<T, A>;
-
-	template <typename T, typename A = StdAlloc<T>> 
-	using List = std::list<T, A>;
-
-	template <typename T, typename A = StdAlloc<T>> 
-	using Stack = std::stack<T, std::deque<T, A>>;
-
-	template <typename T, typename A = StdAlloc<T>>
-	using Queue = std::queue<T, std::deque<T, A>>;
-
-	template <typename T, typename P = std::less<T>, typename A = StdAlloc<T>> 
-	using Set = std::set<T, P, A>;
-
-	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>> 
-	using Map = std::map<K, V, P, A>;
-
-	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>> 
-	using MultiMap = std::multimap<K, V, P, A>;
-
-	template <typename T, typename H = std::hash<T>, typename C = std::equal_to<T>, typename A = StdAlloc<T>> 
-	using UnorderedSet = std::unordered_set<T, H, C, A>;
-
-	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>> 
-	using UnorderedMap = std::unordered_map<K, V, H, C, A>;
-
-	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>> 
-	using UnorderedMultimap = std::unordered_multimap<K, V, H, C, A>;
-
-	template <typename T>
-	using SPtr = std::shared_ptr<T>;
-
-	/**
-	 * @brief	Create a new shared pointer using a custom allocator category.
-	 */
-	template<class Type, class AllocCategory, class... Args> 
-	std::shared_ptr<Type> bs_shared_ptr_new(Args &&... args) 
-	{
-		return std::allocate_shared<Type>(StdAlloc<Type, AllocCategory>(), std::forward<Args>(args)...);
-	}
-
-	/**
-	 * @brief	Create a new shared pointer using the default allocator category.
-	 */
-	template<class Type, class... Args>
-	std::shared_ptr<Type> bs_shared_ptr_new(Args &&... args)
-	{
-		return std::allocate_shared<Type>(StdAlloc<Type, GenAlloc>(), std::forward<Args>(args)...);
-	}
-
-	/**
-	 * @brief	Create a new shared pointer from a previously constructed object.
-	 *			Pointer specific data will be allocated using the provided allocator category.
-	 */
-	template<class Type, class MainAlloc = GenAlloc, class PtrDataAlloc = GenAlloc>
-	std::shared_ptr<Type> bs_shared_ptr(Type* data) 
-	{
-		return std::shared_ptr<Type>(data, &bs_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());
-	}
+#pragma once
+
+#ifdef __BORLANDC__
+    #define __STD_ALGORITHM
+#endif
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <cstring>
+#include <cstdarg>
+#include <cmath>
+
+#include <memory>
+
+// STL containers
+#include <vector>
+#include <stack>
+#include <map>
+#include <string>
+#include <set>
+#include <list>
+#include <deque>
+#include <queue>
+#include <bitset>
+#include <array>
+
+// Note - not in the original STL, but exists in SGI STL and STLport
+// For gcc 4.3 see http://gcc.gnu.org/gcc-4.3/changes.html
+#if (BS_COMPILER == BS_COMPILER_GNUC)
+#   if BS_COMP_VER >= 430
+#       include <tr1/unordered_map>
+#       include <tr1/unordered_set> 
+#   else
+#       include <ext/hash_map>
+#       include <ext/hash_set>
+#   endif
+#else
+#   if (BS_COMPILER == BS_COMPILER_MSVC) && BS_COMP_VER >= 1600 // VC++ 10.0
+#    	include <unordered_map>
+#    	include <unordered_set>
+#	else
+#   	include <hash_set>
+#   	include <hash_map>
+#	endif
+#endif 
+
+// STL algorithms & functions
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+// C++ Stream stuff
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+#ifdef __BORLANDC__
+namespace BansheeEngine
+{
+    using namespace std;
+}
+#endif
+
+extern "C" {
+
+#   include <sys/types.h>
+#   include <sys/stat.h>
+
+}
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+#  undef min
+#  undef max
+#	if !defined(NOMINMAX) && defined(_MSC_VER)
+#		define NOMINMAX // required to stop windows.h messing up std::min
+#	endif
+#  if defined( __MINGW32__ )
+#    include <unistd.h>
+#  endif
+#endif
+
+#if BS_PLATFORM == BS_PLATFORM_LINUX
+extern "C" {
+
+#   include <unistd.h>
+#   include <dlfcn.h>
+
+}
+#endif
+
+#if BS_PLATFORM == BS_PLATFORM_APPLE
+extern "C" {
+#   include <unistd.h>
+#   include <sys/param.h>
+#   include <CoreFoundation/CoreFoundation.h>
+}
+#endif
+
+namespace BansheeEngine
+{
+	/** @addtogroup Containers
+	 *  @{
+	 */
+
+	/** Double ended queue. Allows for fast insertion and removal at both its beggining and end. */
+	template <typename T, typename A = StdAlloc<T>> 
+	using Deque = std::deque<T, A>;
+
+	/** Dynamically sized array that stores element contigously. */
+	template <typename T, typename A = StdAlloc<T>> 
+	using Vector = std::vector<T, A>;
+
+	/** Container that supports constant time insertion and removal, but without fast random access to elements. */
+	template <typename T, typename A = StdAlloc<T>> 
+	using List = std::list<T, A>;
+
+	/** First-in, last-out data structure. */
+	template <typename T, typename A = StdAlloc<T>> 
+	using Stack = std::stack<T, std::deque<T, A>>;
+
+	/** First-in, first-out data structure. */
+	template <typename T, typename A = StdAlloc<T>>
+	using Queue = std::queue<T, std::deque<T, A>>;
+
+	/** An associative container containing an ordered set of elements. */
+	template <typename T, typename P = std::less<T>, typename A = StdAlloc<T>> 
+	using Set = std::set<T, P, A>;
+
+	/** An associative container containing an ordered set of key-value pairs. */
+	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>> 
+	using Map = std::map<K, V, P, A>;
+
+	/** An associative container containing an ordered set of key-value pairs where multiple elements can have the same key. */
+	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>> 
+	using MultiMap = std::multimap<K, V, P, A>;
+
+	/** An associative container containing an unordered set of elements. Usually faster than Set for larger data sets. */
+	template <typename T, typename H = std::hash<T>, typename C = std::equal_to<T>, typename A = StdAlloc<T>> 
+	using UnorderedSet = std::unordered_set<T, H, C, A>;
+
+	/** An associative container containing an ordered set of key-value pairs. Usually faster than Map for larger data sets. */
+	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>> 
+	using UnorderedMap = std::unordered_map<K, V, H, C, A>;
+
+	/** 
+	 * An associative container containing an ordered set of key-value pairs where multiple elements can have the same key.
+	 * Usually faster than MultiMap for larger data sets.
+	 */
+	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>> 
+	using UnorderedMultimap = std::unordered_multimap<K, V, H, C, A>;
+
+	/** @} */
+
+	/** @addtogroup Memory
+	 *  @{
+	 */
+
+	/** 
+	 * Smart pointer that retains shared ownership of an project through a pointer. The object is destroyed automatically 
+	 * when the last shared pointer to the object is destroyed.
+	 */
+	template <typename T>
+	using SPtr = std::shared_ptr<T>;
+
+	/** Create a new shared pointer using a custom allocator category. */
+	template<class Type, class AllocCategory, class... Args> 
+	SPtr<Type> bs_shared_ptr_new(Args &&... args)
+	{
+		return std::allocate_shared<Type>(StdAlloc<Type, AllocCategory>(), std::forward<Args>(args)...);
+	}
+
+	/** Create a new shared pointer using the default allocator category. */
+	template<class Type, class... Args>
+	SPtr<Type> bs_shared_ptr_new(Args &&... args)
+	{
+		return std::allocate_shared<Type>(StdAlloc<Type, GenAlloc>(), std::forward<Args>(args)...);
+	}
+
+	/**
+	 * Create a new shared pointer from a previously constructed object.
+	 * Pointer specific data will be allocated using the provided allocator category.
+	 */
+	template<class Type, class MainAlloc = GenAlloc, class PtrDataAlloc = GenAlloc>
+	SPtr<Type> bs_shared_ptr(Type* data)
+	{
+		return std::shared_ptr<Type>(data, &bs_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());
+	}
+
+	/** @} */
 }

+ 30 - 27
BansheeUtility/Include/BsTorus.h

@@ -1,28 +1,31 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a torus at the world center. Outer radius represents
-	 *			the distance from the center, and inner radius represents the radius of the tube.
-	 *			Inner radius must be less or equal than the outer radius.
-	 */
-	class BS_UTILITY_EXPORT Torus
-	{
-	public:
-		Torus();
-		Torus(const Vector3& normal, float outerRadius, float innerRadius);
-
-		/**
-		 * @brief	Ray/torus intersection, returns boolean result and distance to nearest intersection point.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray) const;
-
-		Vector3 normal;
-		float outerRadius;
-		float innerRadius;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/**
+	 * Represents a torus at the world center. Outer radius represents the distance from the center, and inner radius 
+	 * represents the radius of the tube. Inner radius must be less or equal than the outer radius.
+	 */
+	class BS_UTILITY_EXPORT Torus
+	{
+	public:
+		Torus();
+		Torus(const Vector3& normal, float outerRadius, float innerRadius);
+
+		/** Ray/torus intersection, returns boolean result and distance to nearest intersection point. */
+		std::pair<bool, float> intersects(const Ray& ray) const;
+
+		Vector3 normal;
+		float outerRadius;
+		float innerRadius;
+	};
+
+	/** @} */
 }

+ 371 - 407
BansheeUtility/Include/BsVector2.h

@@ -1,408 +1,372 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsMath.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A two dimensional vector.
-	 */
-    class BS_UTILITY_EXPORT Vector2
-    {
-    public:
-        float x, y;
-
-    public:
-        Vector2()
-			:x(0.0f), y(0.0f)
-        { }
-
-        Vector2(float x, float y)
-            :x(x), y(y)
-        { }
-
-		/**
-		 * @brief	Exchange the contents of this vector with another.
-		 */
-		void swap(Vector2& other)
-		{
-			std::swap(x, other.x);
-			std::swap(y, other.y);
-		}
-
-		float operator[] (UINT32 i) const
-        {
-            assert(i < 2);
-
-            return *(&x+i);
-        }
-
-		float& operator[] (UINT32 i)
-        {
-            assert(i < 2);
-
-            return *(&x+i);
-        }
-		
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		float* ptr()
-		{
-			return &x;
-		}
-
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		const float* ptr() const
-		{
-			return &x;
-		}
-
-        Vector2& operator= (const Vector2& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-
-            return *this;
-        }
-
-		Vector2& operator= (float rhs)
-		{
-			x = rhs;
-			y = rhs;
-
-			return *this;
-		}
-
-        bool operator== (const Vector2& rhs) const
-        {
-            return (x == rhs.x && y == rhs.y);
-        }
-
-        bool operator!= (const Vector2& rhs) const
-        {
-            return (x != rhs.x || y != rhs.y);
-        }
-
-        Vector2 operator+ (const Vector2& rhs) const
-        {
-            return Vector2(x + rhs.x, y + rhs.y);
-        }
-
-        Vector2 operator- (const Vector2& rhs) const
-        {
-            return Vector2(x - rhs.x, y - rhs.y);
-        }
-
-        Vector2 operator* (const float rhs) const
-        {
-            return Vector2(x * rhs, y * rhs);
-        }
-
-        Vector2 operator* (const Vector2& rhs) const
-        {
-            return Vector2(x * rhs.x, y * rhs.y);
-        }
-
-        Vector2 operator/ (const float rhs) const
-        {
-            assert(rhs != 0.0);
-
-            float fInv = 1.0f / rhs;
-
-            return Vector2(x * fInv, y * fInv);
-        }
-
-        Vector2 operator/ (const Vector2& rhs) const
-        {
-            return Vector2(x / rhs.x, y / rhs.y);
-        }
-
-        const Vector2& operator+ () const
-        {
-            return *this;
-        }
-
-        Vector2 operator- () const
-        {
-            return Vector2(-x, -y);
-        }
-
-        friend Vector2 operator* (float lhs, const Vector2& rhs)
-        {
-            return Vector2(lhs * rhs.x, lhs * rhs.y);
-        }
-
-        friend Vector2 operator/ (float lhs, const Vector2& rhs)
-        {
-            return Vector2(lhs / rhs.x, lhs / rhs.y);
-        }
-
-        friend Vector2 operator+ (Vector2& lhs, float rhs)
-        {
-            return Vector2(lhs.x + rhs, lhs.y + rhs);
-        }
-
-        friend Vector2 operator+ (float lhs, const Vector2& rhs)
-        {
-            return Vector2(lhs + rhs.x, lhs + rhs.y);
-        }
-
-        friend Vector2 operator- (const Vector2& lhs, float rhs)
-        {
-            return Vector2(lhs.x - rhs, lhs.y - rhs);
-        }
-
-        friend Vector2 operator- (const float lhs, const Vector2& rhs)
-        {
-            return Vector2(lhs - rhs.x, lhs - rhs.y);
-        }
-
-        Vector2& operator+= (const Vector2& rhs)
-        {
-            x += rhs.x;
-            y += rhs.y;
-
-            return *this;
-        }
-
-        Vector2& operator+= (float rhs)
-        {
-            x += rhs;
-            y += rhs;
-
-            return *this;
-        }
-
-        Vector2& operator-= (const Vector2& rhs)
-        {
-            x -= rhs.x;
-            y -= rhs.y;
-
-            return *this;
-        }
-
-        Vector2& operator-= (float rhs)
-        {
-            x -= rhs;
-            y -= rhs;
-
-            return *this;
-        }
-
-        Vector2& operator*= (float rhs)
-        {
-            x *= rhs;
-            y *= rhs;
-
-            return *this;
-        }
-
-        Vector2& operator*= (const Vector2& rhs)
-        {
-            x *= rhs.x;
-            y *= rhs.y;
-
-            return *this;
-        }
-
-        Vector2& operator/= (float rhs)
-        {
-            assert(rhs != 0.0f);
-
-            float inv = 1.0f / rhs;
-
-            x *= inv;
-            y *= inv;
-
-            return *this;
-        }
-
-        Vector2& operator/= (const Vector2& rhs)
-        {
-            x /= rhs.x;
-            y /= rhs.y;
-
-            return *this;
-        }
-
-        /**
-         * @brief	Returns the length (magnitude) of the vector.
-         */
-        float length() const
-        {
-            return Math::sqrt(x * x + y * y);
-        }
-
-        /**
-         * @brief	Returns the square of the length(magnitude) of the vector.
-         */
-        float squaredLength() const
-        {
-            return x * x + y * y;
-        }
-
-        /**
-         * @brief	Returns the distance to another vector.
-         */
-        float distance(const Vector2& rhs) const
-        {
-            return (*this - rhs).length();
-        }
-
-        /**
-         * @brief	Returns the square of the distance to another vector.
-         */
-        float sqrdDistance(const Vector2& rhs) const
-        {
-            return (*this - rhs).squaredLength();
-        }
-
-        /**
-         * @brief	Calculates the dot (scalar) product of this vector with another.
-         */
-        float dot(const Vector2& vec) const
-        {
-            return x * vec.x + y * vec.y;
-        }
-
-        /**
-         * @brief	Normalizes the vector.
-         */
-        float normalize()
-        {
-            float len = Math::sqrt(x * x + y * y);
-
-            // Will also work for zero-sized vectors, but will change nothing
-            if (len > 1e-08)
-            {
-                float invLen = 1.0f / len;
-                x *= invLen;
-                y *= invLen;
-            }
-
-            return len;
-        }
-
-        /**
-         * @brief	Generates a vector perpendicular to this vector.
-         */
-        Vector2 perpendicular() const
-        {
-            return Vector2 (-y, x);
-        }
-
-        /**
-		 * @brief	Calculates the 2 dimensional cross-product of 2 vectors, which results
-		 *		in a single floating point value which is 2 times the area of the triangle.
-         */
-        float cross(const Vector2& other) const
-        {
-            return x * other.y - y * other.x;
-        }
-
-        /**
-		 * @brief	Sets this vector's components to the minimum of its own and the
-		 *		ones of the passed in vector.
-         */
-        void floor(const Vector2& cmp)
-        {
-            if(cmp.x < x) x = cmp.x;
-            if(cmp.y < y) y = cmp.y;
-        }
-
-        /**
-		 * @brief	Sets this vector's components to the maximum of its own and the
-		 *		ones of the passed in vector.
-         */
-        void ceil(const Vector2& cmp)
-        {
-            if(cmp.x > x) x = cmp.x;
-            if(cmp.y > y) y = cmp.y;
-        }
-
-        /**
-         * @brief	Returns true if this vector is zero length.
-         */
-        bool isZeroLength() const
-        {
-            float sqlen = (x * x) + (y * y);
-            return (sqlen < (1e-06 * 1e-06));
-        }
-
-        /**
-		 * @brief	Calculates a reflection vector to the plane with the given normal.
-         */
-        Vector2 reflect(const Vector2& normal) const
-        {
-            return Vector2(*this - (2 * this->dot(normal) * normal));
-        }
-
-		/**
-		 * @brief	Performs Gram-Schmidt orthonormalization
-		 */
-		static void orthonormalize(Vector2& u, Vector2& v)
-		{
-			u.normalize();
-
-			float dot = u.dot(v); 
-			v -= u*dot;
-			v.normalize();
-		}
-
-		/**
-		 * @brief	Normalizes the provided vector and returns a new normalized instance.
-		 */
-		static Vector2 normalize(const Vector2& val)
-		{
-			float len = Math::sqrt(val.x * val.x + val.y * val.y);
-
-			// Will also work for zero-sized vectors, but will change nothing
-			Vector2 normalizedVec;
-			if (len > 1e-08)
-			{
-				float invLen = 1.0f / len;
-				normalizedVec.x *= invLen;
-				normalizedVec.y *= invLen;
-			}
-
-			return normalizedVec;
-		}
-
-		/**
-		 * @brief	Checks are any of the vector components NaN.
-		 */
-		bool isNaN() const
-		{
-			return Math::isNaN(x) || Math::isNaN(y);
-		}
-
-		/**
-		 * @brief	Returns the minimum of all the vector components as a 
-		 *			new vector.
-		 */
-		static Vector2 min(const Vector2& a, const Vector2& b)
-		{
-			return Vector2(std::min(a.x, b.x), std::min(a.y, b.y));
-		}
-
-		/**
-		 * @brief	Returns the maximum of all the vector components as a 
-		 *			new vector.
-		 */
-		static Vector2 max(const Vector2& a, const Vector2& b)
-		{
-			return Vector2(std::max(a.x, b.x), std::max(a.y, b.y));
-		}
-
-        static const Vector2 ZERO;
-		static const Vector2 ONE;
-		static const Vector2 UNIT_X;
-		static const Vector2 UNIT_Y;
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Vector2);
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsMath.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A two dimensional vector. */
+    class BS_UTILITY_EXPORT Vector2
+    {
+    public:
+        float x, y;
+
+    public:
+        Vector2()
+			:x(0.0f), y(0.0f)
+        { }
+
+        Vector2(float x, float y)
+            :x(x), y(y)
+        { }
+
+		/** Exchange the contents of this vector with another. */
+		void swap(Vector2& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+		}
+
+		float operator[] (UINT32 i) const
+        {
+            assert(i < 2);
+
+            return *(&x+i);
+        }
+
+		float& operator[] (UINT32 i)
+        {
+            assert(i < 2);
+
+            return *(&x+i);
+        }
+		
+		/** Pointer accessor for direct copying. */
+		float* ptr()
+		{
+			return &x;
+		}
+
+		/** Pointer accessor for direct copying. */
+		const float* ptr() const
+		{
+			return &x;
+		}
+
+        Vector2& operator= (const Vector2& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+
+            return *this;
+        }
+
+		Vector2& operator= (float rhs)
+		{
+			x = rhs;
+			y = rhs;
+
+			return *this;
+		}
+
+        bool operator== (const Vector2& rhs) const
+        {
+            return (x == rhs.x && y == rhs.y);
+        }
+
+        bool operator!= (const Vector2& rhs) const
+        {
+            return (x != rhs.x || y != rhs.y);
+        }
+
+        Vector2 operator+ (const Vector2& rhs) const
+        {
+            return Vector2(x + rhs.x, y + rhs.y);
+        }
+
+        Vector2 operator- (const Vector2& rhs) const
+        {
+            return Vector2(x - rhs.x, y - rhs.y);
+        }
+
+        Vector2 operator* (const float rhs) const
+        {
+            return Vector2(x * rhs, y * rhs);
+        }
+
+        Vector2 operator* (const Vector2& rhs) const
+        {
+            return Vector2(x * rhs.x, y * rhs.y);
+        }
+
+        Vector2 operator/ (const float rhs) const
+        {
+            assert(rhs != 0.0);
+
+            float fInv = 1.0f / rhs;
+
+            return Vector2(x * fInv, y * fInv);
+        }
+
+        Vector2 operator/ (const Vector2& rhs) const
+        {
+            return Vector2(x / rhs.x, y / rhs.y);
+        }
+
+        const Vector2& operator+ () const
+        {
+            return *this;
+        }
+
+        Vector2 operator- () const
+        {
+            return Vector2(-x, -y);
+        }
+
+        friend Vector2 operator* (float lhs, const Vector2& rhs)
+        {
+            return Vector2(lhs * rhs.x, lhs * rhs.y);
+        }
+
+        friend Vector2 operator/ (float lhs, const Vector2& rhs)
+        {
+            return Vector2(lhs / rhs.x, lhs / rhs.y);
+        }
+
+        friend Vector2 operator+ (Vector2& lhs, float rhs)
+        {
+            return Vector2(lhs.x + rhs, lhs.y + rhs);
+        }
+
+        friend Vector2 operator+ (float lhs, const Vector2& rhs)
+        {
+            return Vector2(lhs + rhs.x, lhs + rhs.y);
+        }
+
+        friend Vector2 operator- (const Vector2& lhs, float rhs)
+        {
+            return Vector2(lhs.x - rhs, lhs.y - rhs);
+        }
+
+        friend Vector2 operator- (const float lhs, const Vector2& rhs)
+        {
+            return Vector2(lhs - rhs.x, lhs - rhs.y);
+        }
+
+        Vector2& operator+= (const Vector2& rhs)
+        {
+            x += rhs.x;
+            y += rhs.y;
+
+            return *this;
+        }
+
+        Vector2& operator+= (float rhs)
+        {
+            x += rhs;
+            y += rhs;
+
+            return *this;
+        }
+
+        Vector2& operator-= (const Vector2& rhs)
+        {
+            x -= rhs.x;
+            y -= rhs.y;
+
+            return *this;
+        }
+
+        Vector2& operator-= (float rhs)
+        {
+            x -= rhs;
+            y -= rhs;
+
+            return *this;
+        }
+
+        Vector2& operator*= (float rhs)
+        {
+            x *= rhs;
+            y *= rhs;
+
+            return *this;
+        }
+
+        Vector2& operator*= (const Vector2& rhs)
+        {
+            x *= rhs.x;
+            y *= rhs.y;
+
+            return *this;
+        }
+
+        Vector2& operator/= (float rhs)
+        {
+            assert(rhs != 0.0f);
+
+            float inv = 1.0f / rhs;
+
+            x *= inv;
+            y *= inv;
+
+            return *this;
+        }
+
+        Vector2& operator/= (const Vector2& rhs)
+        {
+            x /= rhs.x;
+            y /= rhs.y;
+
+            return *this;
+        }
+
+        /** Returns the length (magnitude) of the vector. */
+        float length() const
+        {
+            return Math::sqrt(x * x + y * y);
+        }
+
+        /** Returns the square of the length(magnitude) of the vector. */
+        float squaredLength() const
+        {
+            return x * x + y * y;
+        }
+
+        /** Returns the distance to another vector. */
+        float distance(const Vector2& rhs) const
+        {
+            return (*this - rhs).length();
+        }
+
+        /** Returns the square of the distance to another vector. */
+        float sqrdDistance(const Vector2& rhs) const
+        {
+            return (*this - rhs).squaredLength();
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another. */
+        float dot(const Vector2& vec) const
+        {
+            return x * vec.x + y * vec.y;
+        }
+
+        /** Normalizes the vector. */
+        float normalize()
+        {
+            float len = Math::sqrt(x * x + y * y);
+
+            // Will also work for zero-sized vectors, but will change nothing
+            if (len > 1e-08)
+            {
+                float invLen = 1.0f / len;
+                x *= invLen;
+                y *= invLen;
+            }
+
+            return len;
+        }
+
+        /** Generates a vector perpendicular to this vector. */
+        Vector2 perpendicular() const
+        {
+            return Vector2 (-y, x);
+        }
+
+        /**
+		 * Calculates the 2 dimensional cross-product of 2 vectors, which results in a single floating point value which 
+		 * is 2 times the area of the triangle.
+         */
+        float cross(const Vector2& other) const
+        {
+            return x * other.y - y * other.x;
+        }
+
+        /** Sets this vector's components to the minimum of its own and the ones of the passed in vector. */
+        void floor(const Vector2& cmp)
+        {
+            if(cmp.x < x) x = cmp.x;
+            if(cmp.y < y) y = cmp.y;
+        }
+
+        /** Sets this vector's components to the maximum of its own and the ones of the passed in vector. */
+        void ceil(const Vector2& cmp)
+        {
+            if(cmp.x > x) x = cmp.x;
+            if(cmp.y > y) y = cmp.y;
+        }
+
+        /** Returns true if this vector is zero length. */
+        bool isZeroLength() const
+        {
+            float sqlen = (x * x) + (y * y);
+            return (sqlen < (1e-06 * 1e-06));
+        }
+
+        /** Calculates a reflection vector to the plane with the given normal. */
+        Vector2 reflect(const Vector2& normal) const
+        {
+            return Vector2(*this - (2 * this->dot(normal) * normal));
+        }
+
+		/** Performs Gram-Schmidt orthonormalization. */
+		static void orthonormalize(Vector2& u, Vector2& v)
+		{
+			u.normalize();
+
+			float dot = u.dot(v); 
+			v -= u*dot;
+			v.normalize();
+		}
+
+		/** Normalizes the provided vector and returns a new normalized instance. */
+		static Vector2 normalize(const Vector2& val)
+		{
+			float len = Math::sqrt(val.x * val.x + val.y * val.y);
+
+			// Will also work for zero-sized vectors, but will change nothing
+			Vector2 normalizedVec;
+			if (len > 1e-08)
+			{
+				float invLen = 1.0f / len;
+				normalizedVec.x *= invLen;
+				normalizedVec.y *= invLen;
+			}
+
+			return normalizedVec;
+		}
+
+		/** Checks are any of the vector components NaN. */
+		bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y);
+		}
+
+		/** Returns the minimum of all the vector components as a new vector. */
+		static Vector2 min(const Vector2& a, const Vector2& b)
+		{
+			return Vector2(std::min(a.x, b.x), std::min(a.y, b.y));
+		}
+
+		/** Returns the maximum of all the vector components as a new vector. */
+		static Vector2 max(const Vector2& a, const Vector2& b)
+		{
+			return Vector2(std::max(a.x, b.x), std::max(a.y, b.y));
+		}
+
+        static const Vector2 ZERO;
+		static const Vector2 ONE;
+		static const Vector2 UNIT_X;
+		static const Vector2 UNIT_Y;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Vector2);
+	/** @endcond */
 }

+ 199 - 204
BansheeUtility/Include/BsVector2I.h

@@ -1,205 +1,200 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A two dimensional vector with integer
-	 *			coordinates.
-	 */
-	struct BS_UTILITY_EXPORT Vector2I
-	{
-		INT32 x;
-		INT32 y;
-
-		Vector2I()
-			:x(0), y(0)
-		{ }
-
-		inline Vector2I(INT32 _x, INT32 _y )
-            :x(_x), y(_y)
-        { }
-
-        explicit Vector2I(int val)
-            :x(val), y(val)
-        { }
-
-		/**
-		 * @brief	Exchange the contents of this vector with another.
-		 */
-		void swap(Vector2I& other)
-		{
-			std::swap(x, other.x);
-			std::swap(y, other.y);
-		}
-
-		/**
-		 * @brief	Returns the manhattan distance between this and another point.
-		 */
-		UINT32 manhattanDist(const Vector2I& other)
-		{
-			return (UINT32)fabs(float(other.x - x)) + (UINT32)fabs(float(other.y - y));
-		}
-
-		INT32 operator[] (size_t i) const
-        {
-            assert(i < 2);
-
-            return *(&x+i);
-        }
-
-		INT32& operator[] (size_t i)
-        {
-            assert(i < 2);
-
-            return *(&x+i);
-        }
-
-        Vector2I& operator= (const Vector2I& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-
-            return *this;
-        }
-
-		Vector2I& operator= (int val)
-		{
-			x = val;
-			y = val;
-
-			return *this;
-		}
-
-        bool operator== (const Vector2I& rhs) const
-        {
-            return (x == rhs.x && y == rhs.y);
-        }
-
-        bool operator!= (const Vector2I& rhs) const
-        {
-            return (x != rhs.x || y != rhs.y);
-        }
-
-        Vector2I operator+ (const Vector2I& rhs) const
-        {
-            return Vector2I(x + rhs.x, y + rhs.y);
-        }
-
-        Vector2I operator- (const Vector2I& rhs) const
-        {
-            return Vector2I(x - rhs.x, y - rhs.y);
-        }
-
-        Vector2I operator* (int val) const
-        {
-            return Vector2I(x * val, y * val);
-        }
-
-        Vector2I operator* (const Vector2I& rhs) const
-        {
-            return Vector2I(x * rhs.x, y * rhs.y);
-        }
-
-        Vector2I operator/ (int val) const
-        {
-            assert(val != 0);
-
-            return Vector2I(x / val, y / val);
-        }
-
-        Vector2I operator/ (const Vector2I& rhs) const
-        {
-            return Vector2I(x / rhs.x, y / rhs.y);
-        }
-
-        const Vector2I& operator+ () const
-        {
-            return *this;
-        }
-
-        Vector2I operator- () const
-        {
-            return Vector2I(-x, -y);
-        }
-
-        friend Vector2I operator* (int lhs, const Vector2I& rhs)
-        {
-            return Vector2I(lhs * rhs.x, lhs * rhs.y);
-        }
-
-        friend Vector2I operator/ (int lhs, const Vector2I& rhs)
-        {
-            return Vector2I(lhs / rhs.x, lhs / rhs.y);
-        }
-
-        Vector2I& operator+= (const Vector2I& rhs)
-        {
-            x += rhs.x;
-            y += rhs.y;
-
-            return *this;
-        }
-
-        Vector2I& operator-= (const Vector2I& rhs)
-        {
-            x -= rhs.x;
-            y -= rhs.y;
-
-            return *this;
-        }
-
-        Vector2I& operator*= (INT32 val)
-        {
-            x *= val;
-            y *= val;
-
-            return *this;
-        }
-
-        Vector2I& operator*= (const Vector2I& rhs)
-        {
-            x *= rhs.x;
-            y *= rhs.y;
-
-            return *this;
-        }
-
-        Vector2I& operator/= (INT32 val)
-        {
-            assert(val != 0);
-
-            x /= val;
-            y /= val;
-
-            return *this;
-        }
-
-        Vector2I& operator/= (const Vector2I& rhs)
-        {
-            x /= rhs.x;
-            y /= rhs.y;
-
-            return *this;
-        }
-
-        /**
-         * @brief	Returns the square of the length(magnitude) of the vector.
-         */
-        INT32 squaredLength() const
-        {
-            return x * x + y * y;
-        }
-
-        /**
-         * @brief	Calculates the dot (scalar) product of this vector with another.
-         */
-		INT32 dot(const Vector2I& vec) const
-        {
-            return x * vec.x + y * vec.y;
-        }
-
-		static const Vector2I ZERO;
-	};
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A two dimensional vector with integer coordinates.*/
+	struct BS_UTILITY_EXPORT Vector2I
+	{
+		INT32 x;
+		INT32 y;
+
+		Vector2I()
+			:x(0), y(0)
+		{ }
+
+		inline Vector2I(INT32 _x, INT32 _y )
+            :x(_x), y(_y)
+        { }
+
+        explicit Vector2I(int val)
+            :x(val), y(val)
+        { }
+
+		/** Exchange the contents of this vector with another. */
+		void swap(Vector2I& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+		}
+
+		/** Returns the manhattan distance between this and another point. */
+		UINT32 manhattanDist(const Vector2I& other) const
+		{
+			return (UINT32)fabs(float(other.x - x)) + (UINT32)fabs(float(other.y - y));
+		}
+
+		INT32 operator[] (size_t i) const
+        {
+            assert(i < 2);
+
+            return *(&x+i);
+        }
+
+		INT32& operator[] (size_t i)
+        {
+            assert(i < 2);
+
+            return *(&x+i);
+        }
+
+        Vector2I& operator= (const Vector2I& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+
+            return *this;
+        }
+
+		Vector2I& operator= (int val)
+		{
+			x = val;
+			y = val;
+
+			return *this;
+		}
+
+        bool operator== (const Vector2I& rhs) const
+        {
+            return (x == rhs.x && y == rhs.y);
+        }
+
+        bool operator!= (const Vector2I& rhs) const
+        {
+            return (x != rhs.x || y != rhs.y);
+        }
+
+        Vector2I operator+ (const Vector2I& rhs) const
+        {
+            return Vector2I(x + rhs.x, y + rhs.y);
+        }
+
+        Vector2I operator- (const Vector2I& rhs) const
+        {
+            return Vector2I(x - rhs.x, y - rhs.y);
+        }
+
+        Vector2I operator* (int val) const
+        {
+            return Vector2I(x * val, y * val);
+        }
+
+        Vector2I operator* (const Vector2I& rhs) const
+        {
+            return Vector2I(x * rhs.x, y * rhs.y);
+        }
+
+        Vector2I operator/ (int val) const
+        {
+            assert(val != 0);
+
+            return Vector2I(x / val, y / val);
+        }
+
+        Vector2I operator/ (const Vector2I& rhs) const
+        {
+            return Vector2I(x / rhs.x, y / rhs.y);
+        }
+
+        const Vector2I& operator+ () const
+        {
+            return *this;
+        }
+
+        Vector2I operator- () const
+        {
+            return Vector2I(-x, -y);
+        }
+
+        friend Vector2I operator* (int lhs, const Vector2I& rhs)
+        {
+            return Vector2I(lhs * rhs.x, lhs * rhs.y);
+        }
+
+        friend Vector2I operator/ (int lhs, const Vector2I& rhs)
+        {
+            return Vector2I(lhs / rhs.x, lhs / rhs.y);
+        }
+
+        Vector2I& operator+= (const Vector2I& rhs)
+        {
+            x += rhs.x;
+            y += rhs.y;
+
+            return *this;
+        }
+
+        Vector2I& operator-= (const Vector2I& rhs)
+        {
+            x -= rhs.x;
+            y -= rhs.y;
+
+            return *this;
+        }
+
+        Vector2I& operator*= (INT32 val)
+        {
+            x *= val;
+            y *= val;
+
+            return *this;
+        }
+
+        Vector2I& operator*= (const Vector2I& rhs)
+        {
+            x *= rhs.x;
+            y *= rhs.y;
+
+            return *this;
+        }
+
+        Vector2I& operator/= (INT32 val)
+        {
+            assert(val != 0);
+
+            x /= val;
+            y /= val;
+
+            return *this;
+        }
+
+        Vector2I& operator/= (const Vector2I& rhs)
+        {
+            x /= rhs.x;
+            y /= rhs.y;
+
+            return *this;
+        }
+
+        /** Returns the square of the length(magnitude) of the vector. */
+        INT32 squaredLength() const
+        {
+            return x * x + y * y;
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another. */
+		INT32 dot(const Vector2I& vec) const
+        {
+            return x * vec.x + y * vec.y;
+        }
+
+		static const Vector2I ZERO;
+	};
+
+	/** @} */
 }

+ 450 - 499
BansheeUtility/Include/BsVector3.h

@@ -1,499 +1,450 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsMath.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A three dimensional vector.
-	 */
-    class BS_UTILITY_EXPORT Vector3
-    {
-    public:
-		float x, y, z;
-
-    public:
-        Vector3()
-			:x(0.0f), y(0.0f), z(0.0f)
-        { }
-
-        Vector3(float x, float y, float z)
-            :x(x), y(y), z(z)
-        { }
-
-		explicit Vector3(const Vector4& vec);
-
-		/**
-		 * @brief	Exchange the contents of this vector with another.
-		 */
-		void swap(Vector3& other)
-		{
-			std::swap(x, other.x);
-			std::swap(y, other.y);
-			std::swap(z, other.z);
-		}
-
-		float operator[] (UINT32 i) const
-        {
-            assert(i < 3);
-
-            return *(&x+i);
-        }
-
-		float& operator[] (UINT32 i)
-        {
-            assert(i < 3);
-
-            return *(&x+i);
-        }
-
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		float* ptr()
-		{
-			return &x;
-		}
-
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		const float* ptr() const
-		{
-			return &x;
-		}
-
-        Vector3& operator= (const Vector3& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-            z = rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator= (float rhs)
-        {
-            x = rhs;
-            y = rhs;
-            z = rhs;
-
-            return *this;
-        }
-
-        bool operator== (const Vector3& rhs) const
-        {
-            return (x == rhs.x && y == rhs.y && z == rhs.z);
-        }
-
-        bool operator!= (const Vector3& rhs) const
-        {
-            return (x != rhs.x || y != rhs.y || z != rhs.z);
-        }
-
-        Vector3 operator+ (const Vector3& rhs) const
-        {
-            return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);
-        }
-
-        Vector3 operator- (const Vector3& rhs) const
-        {
-            return Vector3(x - rhs.x, y - rhs.y, z - rhs.z);
-        }
-
-        Vector3 operator* (float rhs) const
-        {
-            return Vector3(x * rhs, y * rhs, z * rhs);
-        }
-
-        Vector3 operator* (const Vector3& rhs) const
-        {
-            return Vector3(x * rhs.x, y * rhs.y, z * rhs.z);
-        }
-
-        Vector3 operator/ (float val) const
-        {
-            assert(val != 0.0);
-
-            float fInv = 1.0f / val;
-            return Vector3(x * fInv, y * fInv, z * fInv);
-        }
-
-        Vector3 operator/ (const Vector3& rhs) const
-        {
-            return Vector3(x / rhs.x, y / rhs.y, z / rhs.z);
-        }
-
-        const Vector3& operator+ () const
-        {
-            return *this;
-        }
-
-        Vector3 operator- () const
-        {
-            return Vector3(-x, -y, -z);
-        }
-
-        friend Vector3 operator* (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
-        }
-
-        friend Vector3 operator/ (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
-        }
-
-        friend Vector3 operator+ (const Vector3& lhs, float rhs)
-        {
-            return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs);
-        }
-
-        friend Vector3 operator+ (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
-        }
-
-        friend Vector3 operator- (const Vector3& lhs, float rhs)
-        {
-            return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
-        }
-
-        friend Vector3 operator- (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
-        }
-
-        Vector3& operator+= (const Vector3& rhs)
-        {
-            x += rhs.x;
-            y += rhs.y;
-            z += rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator+= (float rhs)
-        {
-            x += rhs;
-            y += rhs;
-            z += rhs;
-
-            return *this;
-        }
-
-        Vector3& operator-= (const Vector3& rhs)
-        {
-            x -= rhs.x;
-            y -= rhs.y;
-            z -= rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator-= (float rhs)
-        {
-            x -= rhs;
-            y -= rhs;
-            z -= rhs;
-
-            return *this;
-        }
-
-        Vector3& operator*= (float rhs)
-        {
-            x *= rhs;
-            y *= rhs;
-            z *= rhs;
-
-            return *this;
-        }
-
-        Vector3& operator*= (const Vector3& rhs)
-        {
-            x *= rhs.x;
-            y *= rhs.y;
-            z *= rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator/= (float rhs)
-        {
-            assert(rhs != 0.0f);
-
-            float inv = 1.0f / rhs;
-
-            x *= inv;
-            y *= inv;
-            z *= inv;
-
-            return *this;
-        }
-
-        Vector3& operator/= (const Vector3& rhs)
-        {
-            x /= rhs.x;
-            y /= rhs.y;
-            z /= rhs.z;
-
-            return *this;
-        }
-
-        /**
-         * @brief	Returns the length (magnitude) of the vector.
-         */
-        float length() const
-        {
-            return Math::sqrt(x * x + y * y + z * z);
-        }
-
-        /**
-         * @brief	Returns the square of the length(magnitude) of the vector.
-         */
-        float squaredLength() const
-        {
-            return x * x + y * y + z * z;
-        }
-
-        /**
-         * @brief	Returns the distance to another vector.
-         */
-        float distance(const Vector3& rhs) const
-        {
-            return (*this - rhs).length();
-        }
-
-        /**
-         * @brief	Returns the square of the distance to another vector.
-         */
-        float squaredDistance(const Vector3& rhs) const
-        {
-            return (*this - rhs).squaredLength();
-        }
-
-        /**
-         * @brief	Calculates the dot (scalar) product of this vector with another
-         */
-        float dot(const Vector3& vec) const
-        {
-            return x * vec.x + y * vec.y + z * vec.z;
-        }
-
-        /**
-         * @brief	Normalizes the vector.
-         */
-        float normalize()
-        {
-            float len = Math::sqrt(x * x + y * y + z * z);
-
-            // Will also work for zero-sized vectors, but will change nothing
-            if (len > 1e-08)
-            {
-                float invLen = 1.0f / len;
-                x *= invLen;
-                y *= invLen;
-                z *= invLen;
-            }
-
-            return len;
-        }
-
-        /**
-		 * @brief	Calculates the cross-product of 2 vectors, i.e. the vector that
-		 *		lies perpendicular to them both.
-         */
-        Vector3 cross(const Vector3& other) const
-        {
-            return Vector3(
-                y * other.z - z * other.y,
-                z * other.x - x * other.z,
-                x * other.y - y * other.x);
-        }
-
-        /**
-		 * @brief	Sets this vector's components to the minimum of its own and the
-		 *		ones of the passed in vector.
-         */
-        void floor(const Vector3& cmp)
-        {
-            if(cmp.x < x) x = cmp.x;
-            if(cmp.y < y) y = cmp.y;
-            if(cmp.z < z) z = cmp.z;
-        }
-
-        /**
-		 * @brief	Sets this vector's components to the maximum of its own and the
-		 *		ones of the passed in vector.
-         */
-        void ceil(const Vector3& cmp)
-        {
-            if(cmp.x > x) x = cmp.x;
-            if(cmp.y > y) y = cmp.y;
-            if(cmp.z > z) z = cmp.z;
-        }
-
-        /**   
-        *  @brief	Generates a vector perpendicular to this vector.
-        */
-        Vector3 perpendicular() const
-        {
-            static const float squareZero = (float)(1e-06 * 1e-06);
-
-            Vector3 perp = this->cross(Vector3::UNIT_X);
-
-            if(perp.squaredLength() < squareZero)
-                perp = this->cross(Vector3::UNIT_Y);
-
-			perp.normalize();
-            return perp;
-        }
-
-		/**
-		 * @brief	Gets the angle between 2 vectors.
-		 */
-		Radian angleBetween(const Vector3& dest)
-		{
-			float lenProduct = length() * dest.length();
-
-			// Divide by zero check
-			if(lenProduct < 1e-6f)
-				lenProduct = 1e-6f;
-
-			float f = dot(dest) / lenProduct;
-
-			f = Math::clamp(f, -1.0f, 1.0f);
-			return Math::acos(f);
-
-		}
-
-        /**
-         * @brief	Returns true if this vector is zero length.
-         */
-        bool isZeroLength() const
-        {
-            float sqlen = (x * x) + (y * y) + (z * z);
-            return (sqlen < (1e-06 * 1e-06));
-        }
-
-        /**
-		 * @brief	Calculates a reflection vector to the plane with the given normal.
-         */
-        Vector3 reflect(const Vector3& normal) const
-        {
-            return Vector3(*this - (2 * this->dot(normal) * normal));
-        }
-
-		/**
-		 * @brief	Calculates two vectors orthonormal to the current vector, and
-		 *			normalizes the current vector if not already.
-		 */
-		void orthogonalComplement(Vector3& a, Vector3& b)
-		{
-			if (fabs(x) > fabs(y))
-				a = Vector3(-z, 0, x);
-			else
-				a = Vector3(0, z, -y);
-
-			b = cross(a);
-
-			orthonormalize(*this, a, b);
-		}
-
-		/**
-		 * @brief	Performs Gram-Schmidt orthonormalization
-		 */
-		static void orthonormalize(Vector3& vec0, Vector3& vec1, Vector3& vec2)
-		{
-			vec0.normalize();
-
-			float dot0 = vec0.dot(vec1); 
-			vec1 -= dot0*vec0;
-			vec1.normalize();
-
-			float dot1 = vec1.dot(vec2);
-			dot0 = vec0.dot(vec2);
-			vec2 -= dot0*vec0 + dot1*vec1;
-			vec2.normalize();
-		}
-
-        /**
-         * @brief	Calculates the dot (scalar) product of two vectors
-         */
-		static float dot(const Vector3& a, const Vector3& b)
-		{
-			return a.x * b.x + a.y * b.y + a.z * b.z;
-		}
-
-		/**
-		 * @brief	Normalizes the provided vector and returns a new normalized instance.
-		 */
-		static Vector3 normalize(const Vector3& val)
-		{
-			float len = Math::sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
-
-			// Will also work for zero-sized vectors, but will change nothing
-			if (len > 1e-08)
-			{
-				float invLen = 1.0f / len;
-
-				Vector3 normalizedVec;
-				normalizedVec.x = val.x * invLen;
-				normalizedVec.y = val.y * invLen;
-				normalizedVec.z = val.z * invLen;
-
-				return normalizedVec;
-			}
-			else
-				return val;
-		}
-
-		/**
-		 * @brief	Calculates the cross-product of 2 vectors, i.e. the vector that
-		 *			lies perpendicular to them both.
-         */
-		static Vector3 cross(const Vector3& a, const Vector3& b)
-        {
-            return Vector3(
-				a.y * b.z - a.z * b.y,
-				a.z * b.x - a.x * b.z,
-				a.x * b.y - a.y * b.x);
-        }
-
-		/**
-		 * @brief	Checks are any of the vector components NaN.
-		 */
-		bool isNaN() const
-		{
-			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
-		}
-
-		/**
-		 * @brief	Returns the minimum of all the vector components as a 
-		 *			new vector.
-		 */
-		static Vector3 min(const Vector3& a, const Vector3& b)
-		{
-			return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
-		}
-
-		/**
-		 * @brief	Returns the maximum of all the vector components as a 
-		 *			new vector.
-		 */
-		static Vector3 max(const Vector3& a, const Vector3& b)
-		{
-			return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
-		}
-
-        static const Vector3 ZERO;
-		static const Vector3 ONE;
-		static const Vector3 INF;
-        static const Vector3 UNIT_X;
-        static const Vector3 UNIT_Y;
-        static const Vector3 UNIT_Z;
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Vector3);
-}
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsMath.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A three dimensional vector. */
+    class BS_UTILITY_EXPORT Vector3
+    {
+    public:
+		float x, y, z;
+
+    public:
+        Vector3()
+			:x(0.0f), y(0.0f), z(0.0f)
+        { }
+
+        Vector3(float x, float y, float z)
+            :x(x), y(y), z(z)
+        { }
+
+		explicit Vector3(const Vector4& vec);
+
+		/** Exchange the contents of this vector with another. */
+		void swap(Vector3& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+		}
+
+		float operator[] (UINT32 i) const
+        {
+            assert(i < 3);
+
+            return *(&x+i);
+        }
+
+		float& operator[] (UINT32 i)
+        {
+            assert(i < 3);
+
+            return *(&x+i);
+        }
+
+		/** Pointer accessor for direct copying. */
+		float* ptr()
+		{
+			return &x;
+		}
+
+		/** Pointer accessor for direct copying. */
+		const float* ptr() const
+		{
+			return &x;
+		}
+
+        Vector3& operator= (const Vector3& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+            z = rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator= (float rhs)
+        {
+            x = rhs;
+            y = rhs;
+            z = rhs;
+
+            return *this;
+        }
+
+        bool operator== (const Vector3& rhs) const
+        {
+            return (x == rhs.x && y == rhs.y && z == rhs.z);
+        }
+
+        bool operator!= (const Vector3& rhs) const
+        {
+            return (x != rhs.x || y != rhs.y || z != rhs.z);
+        }
+
+        Vector3 operator+ (const Vector3& rhs) const
+        {
+            return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);
+        }
+
+        Vector3 operator- (const Vector3& rhs) const
+        {
+            return Vector3(x - rhs.x, y - rhs.y, z - rhs.z);
+        }
+
+        Vector3 operator* (float rhs) const
+        {
+            return Vector3(x * rhs, y * rhs, z * rhs);
+        }
+
+        Vector3 operator* (const Vector3& rhs) const
+        {
+            return Vector3(x * rhs.x, y * rhs.y, z * rhs.z);
+        }
+
+        Vector3 operator/ (float val) const
+        {
+            assert(val != 0.0);
+
+            float fInv = 1.0f / val;
+            return Vector3(x * fInv, y * fInv, z * fInv);
+        }
+
+        Vector3 operator/ (const Vector3& rhs) const
+        {
+            return Vector3(x / rhs.x, y / rhs.y, z / rhs.z);
+        }
+
+        const Vector3& operator+ () const
+        {
+            return *this;
+        }
+
+        Vector3 operator- () const
+        {
+            return Vector3(-x, -y, -z);
+        }
+
+        friend Vector3 operator* (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
+        }
+
+        friend Vector3 operator/ (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
+        }
+
+        friend Vector3 operator+ (const Vector3& lhs, float rhs)
+        {
+            return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs);
+        }
+
+        friend Vector3 operator+ (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
+        }
+
+        friend Vector3 operator- (const Vector3& lhs, float rhs)
+        {
+            return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
+        }
+
+        friend Vector3 operator- (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
+        }
+
+        Vector3& operator+= (const Vector3& rhs)
+        {
+            x += rhs.x;
+            y += rhs.y;
+            z += rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator+= (float rhs)
+        {
+            x += rhs;
+            y += rhs;
+            z += rhs;
+
+            return *this;
+        }
+
+        Vector3& operator-= (const Vector3& rhs)
+        {
+            x -= rhs.x;
+            y -= rhs.y;
+            z -= rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator-= (float rhs)
+        {
+            x -= rhs;
+            y -= rhs;
+            z -= rhs;
+
+            return *this;
+        }
+
+        Vector3& operator*= (float rhs)
+        {
+            x *= rhs;
+            y *= rhs;
+            z *= rhs;
+
+            return *this;
+        }
+
+        Vector3& operator*= (const Vector3& rhs)
+        {
+            x *= rhs.x;
+            y *= rhs.y;
+            z *= rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator/= (float rhs)
+        {
+            assert(rhs != 0.0f);
+
+            float inv = 1.0f / rhs;
+
+            x *= inv;
+            y *= inv;
+            z *= inv;
+
+            return *this;
+        }
+
+        Vector3& operator/= (const Vector3& rhs)
+        {
+            x /= rhs.x;
+            y /= rhs.y;
+            z /= rhs.z;
+
+            return *this;
+        }
+
+        /** Returns the length (magnitude) of the vector. */
+        float length() const
+        {
+            return Math::sqrt(x * x + y * y + z * z);
+        }
+
+        /** Returns the square of the length(magnitude) of the vector. */
+        float squaredLength() const
+        {
+            return x * x + y * y + z * z;
+        }
+
+        /**	Returns the distance to another vector. */
+        float distance(const Vector3& rhs) const
+        {
+            return (*this - rhs).length();
+        }
+
+        /** Returns the square of the distance to another vector. */
+        float squaredDistance(const Vector3& rhs) const
+        {
+            return (*this - rhs).squaredLength();
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another. */
+        float dot(const Vector3& vec) const
+        {
+            return x * vec.x + y * vec.y + z * vec.z;
+        }
+
+        /** Normalizes the vector. */
+        float normalize()
+        {
+            float len = Math::sqrt(x * x + y * y + z * z);
+
+            // Will also work for zero-sized vectors, but will change nothing
+            if (len > 1e-08)
+            {
+                float invLen = 1.0f / len;
+                x *= invLen;
+                y *= invLen;
+                z *= invLen;
+            }
+
+            return len;
+        }
+
+        /** Calculates the cross-product of 2 vectors, i.e. the vector that lies perpendicular to them both. */
+        Vector3 cross(const Vector3& other) const
+        {
+            return Vector3(
+                y * other.z - z * other.y,
+                z * other.x - x * other.z,
+                x * other.y - y * other.x);
+        }
+
+        /** Sets this vector's components to the minimum of its own and the ones of the passed in vector. */
+        void floor(const Vector3& cmp)
+        {
+            if(cmp.x < x) x = cmp.x;
+            if(cmp.y < y) y = cmp.y;
+            if(cmp.z < z) z = cmp.z;
+        }
+
+        /** Sets this vector's components to the maximum of its own and the ones of the passed in vector. */
+        void ceil(const Vector3& cmp)
+        {
+            if(cmp.x > x) x = cmp.x;
+            if(cmp.y > y) y = cmp.y;
+            if(cmp.z > z) z = cmp.z;
+        }
+
+        /** Generates a vector perpendicular to this vector. */
+        Vector3 perpendicular() const
+        {
+            static const float squareZero = (float)(1e-06 * 1e-06);
+
+            Vector3 perp = this->cross(Vector3::UNIT_X);
+
+            if(perp.squaredLength() < squareZero)
+                perp = this->cross(Vector3::UNIT_Y);
+
+			perp.normalize();
+            return perp;
+        }
+
+		/** Gets the angle between 2 vectors. */
+		Radian angleBetween(const Vector3& dest) const
+		{
+			float lenProduct = length() * dest.length();
+
+			// Divide by zero check
+			if(lenProduct < 1e-6f)
+				lenProduct = 1e-6f;
+
+			float f = dot(dest) / lenProduct;
+
+			f = Math::clamp(f, -1.0f, 1.0f);
+			return Math::acos(f);
+
+		}
+
+        /** Returns true if this vector is zero length. */
+        bool isZeroLength() const
+        {
+            float sqlen = (x * x) + (y * y) + (z * z);
+            return (sqlen < (1e-06 * 1e-06));
+        }
+
+        /** Calculates a reflection vector to the plane with the given normal. */
+        Vector3 reflect(const Vector3& normal) const
+        {
+            return Vector3(*this - (2 * this->dot(normal) * normal));
+        }
+
+		/** Calculates two vectors orthonormal to the current vector, and normalizes the current vector if not already. */
+		void orthogonalComplement(Vector3& a, Vector3& b)
+		{
+			if (fabs(x) > fabs(y))
+				a = Vector3(-z, 0, x);
+			else
+				a = Vector3(0, z, -y);
+
+			b = cross(a);
+
+			orthonormalize(*this, a, b);
+		}
+
+		/** Performs Gram-Schmidt orthonormalization. */
+		static void orthonormalize(Vector3& vec0, Vector3& vec1, Vector3& vec2)
+		{
+			vec0.normalize();
+
+			float dot0 = vec0.dot(vec1); 
+			vec1 -= dot0*vec0;
+			vec1.normalize();
+
+			float dot1 = vec1.dot(vec2);
+			dot0 = vec0.dot(vec2);
+			vec2 -= dot0*vec0 + dot1*vec1;
+			vec2.normalize();
+		}
+
+        /** Calculates the dot (scalar) product of two vectors. */
+		static float dot(const Vector3& a, const Vector3& b)
+		{
+			return a.x * b.x + a.y * b.y + a.z * b.z;
+		}
+
+		/** Normalizes the provided vector and returns a new normalized instance. */
+		static Vector3 normalize(const Vector3& val)
+		{
+			float len = Math::sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
+
+			// Will also work for zero-sized vectors, but will change nothing
+			if (len > 1e-08)
+			{
+				float invLen = 1.0f / len;
+
+				Vector3 normalizedVec;
+				normalizedVec.x = val.x * invLen;
+				normalizedVec.y = val.y * invLen;
+				normalizedVec.z = val.z * invLen;
+
+				return normalizedVec;
+			}
+			else
+				return val;
+		}
+
+		/** Calculates the cross-product of 2 vectors, i.e. the vector that lies perpendicular to them both. */
+		static Vector3 cross(const Vector3& a, const Vector3& b)
+        {
+            return Vector3(
+				a.y * b.z - a.z * b.y,
+				a.z * b.x - a.x * b.z,
+				a.x * b.y - a.y * b.x);
+        }
+
+		/** Checks are any of the vector components NaN. */
+		bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
+		}
+
+		/** Returns the minimum of all the vector components as a new vector. */
+		static Vector3 min(const Vector3& a, const Vector3& b)
+		{
+			return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
+		}
+
+		/** Returns the maximum of all the vector components as a new vector. */
+		static Vector3 max(const Vector3& a, const Vector3& b)
+		{
+			return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
+		}
+
+        static const Vector3 ZERO;
+		static const Vector3 ONE;
+		static const Vector3 INF;
+        static const Vector3 UNIT_X;
+        static const Vector3 UNIT_Y;
+        static const Vector3 UNIT_Z;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Vector3);
+	/** @endcond */
+}

+ 284 - 288
BansheeUtility/Include/BsVector4.h

@@ -1,288 +1,284 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A four dimensional vector.
-	 */
-    class BS_UTILITY_EXPORT Vector4
-    {
-    public:
-        float x, y, z, w;
-
-    public:
-        Vector4()
-			:x(0.0f), y(0.0f), z(0.0f), w(0.0f)
-        { }
-
-        Vector4(float x, float y, float z, float w)
-            :x(x), y(y), z(z), w(w)
-        { }
-
-		explicit Vector4(const Vector3& vec, float w = 0.0f)
-			:x(vec.x), y(vec.y), z(vec.z), w(w)
-		{ }
-
-		/**
-		 * @brief	Exchange the contents of this vector with another.
-		 */
-		void swap(Vector4& other)
-		{
-			std::swap(x, other.x);
-			std::swap(y, other.y);
-			std::swap(z, other.z);
-			std::swap(w, other.w);
-		}
-	
-		float operator[] (UINT32 i) const
-        {
-            assert (i < 4);
-
-            return *(&x+i);
-        }
-
-		float& operator[] (UINT32 i)
-        {
-            assert(i < 4);
-
-            return *(&x+i);
-        }
-
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		float* ptr()
-		{
-			return &x;
-		}
-
-		/** 
-		 * @brief	Pointer accessor for direct copying.
-		 */
-		const float* ptr() const
-		{
-			return &x;
-		}
-
-        Vector4& operator= (const Vector4& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-            z = rhs.z;
-            w = rhs.w;
-
-            return *this;
-        }
-
-		Vector4& operator= (float rhs)
-		{
-			x = rhs;
-			y = rhs;
-			z = rhs;
-			w = rhs;
-
-			return *this;
-		}
-
-        bool operator== (const Vector4& rhs) const
-        {
-            return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w);
-        }
-
-        bool operator!= (const Vector4& rhs) const
-        {
-            return (x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w);
-        }
-
-        Vector4& operator= (const Vector3& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-            z = rhs.z;
-            w = 1.0f;
-
-            return *this;
-        }
-
-        Vector4 operator+ (const Vector4& rhs) const
-        {
-            return Vector4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w);
-        }
-
-        Vector4 operator- (const Vector4& rhs) const
-        {
-            return Vector4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w);
-        }
-
-        Vector4 operator* (float rhs) const
-        {
-            return Vector4(x * rhs, y * rhs, z * rhs, w * rhs);
-        }
-
-        Vector4 operator* (const Vector4& rhs) const
-        {
-            return Vector4(rhs.x * x, rhs.y * y, rhs.z * z, rhs.w * w);
-        }
-
-        Vector4 operator/ (float rhs) const
-        {
-            assert(rhs != 0.0f);
-
-            float inv = 1.0f / rhs;
-            return Vector4(x * inv, y * inv, z * inv, w * inv);
-        }
-
-        Vector4 operator/ (const Vector4& rhs) const
-        {
-            return Vector4(x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w);
-        }
-
-        const Vector4& operator+ () const
-        {
-            return *this;
-        }
-
-        Vector4 operator- () const
-        {
-            return Vector4(-x, -y, -z, -w);
-        }
-
-        friend Vector4 operator* (float lhs, const Vector4& rhs)
-        {
-            return Vector4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w);
-        }
-
-        friend Vector4 operator/ (float lhs, const Vector4& rhs)
-        {
-            return Vector4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w);
-        }
-
-        friend Vector4 operator+ (const Vector4& lhs, float rhs)
-        {
-            return Vector4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs);
-        }
-
-        friend Vector4 operator+ (float lhs, const Vector4& rhs)
-        {
-            return Vector4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w);
-        }
-
-        friend Vector4 operator- (const Vector4& lhs, float rhs)
-        {
-            return Vector4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs);
-        }
-
-        friend Vector4 operator- (float lhs, Vector4& rhs)
-        {
-            return Vector4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w);
-        }
-
-        Vector4& operator+= (const Vector4& rhs)
-        {
-            x += rhs.x;
-            y += rhs.y;
-            z += rhs.z;
-            w += rhs.w;
-
-            return *this;
-        }
-
-        Vector4& operator-= (const Vector4& rhs)
-        {
-            x -= rhs.x;
-            y -= rhs.y;
-            z -= rhs.z;
-            w -= rhs.w;
-
-            return *this;
-        }
-
-        Vector4& operator*= (float rhs)
-        {
-            x *= rhs;
-            y *= rhs;
-            z *= rhs;
-            w *= rhs;
-
-            return *this;
-        }
-
-        Vector4& operator+= (float rhs)
-        {
-            x += rhs;
-            y += rhs;
-            z += rhs;
-            w += rhs;
-
-            return *this;
-        }
-
-        Vector4& operator-= (float rhs)
-        {
-            x -= rhs;
-            y -= rhs;
-            z -= rhs;
-            w -= rhs;
-
-            return *this;
-        }
-
-        Vector4& operator*= (Vector4& rhs)
-        {
-            x *= rhs.x;
-            y *= rhs.y;
-            z *= rhs.z;
-            w *= rhs.w;
-
-            return *this;
-        }
-
-        Vector4& operator/= (float rhs)
-        {
-            assert(rhs != 0.0f);
-
-            float inv = 1.0f / rhs;
-
-            x *= inv;
-            y *= inv;
-            z *= inv;
-            w *= inv;
-
-            return *this;
-        }
-
-        Vector4& operator/= (const Vector4& rhs)
-        {
-            x /= rhs.x;
-            y /= rhs.y;
-            z /= rhs.z;
-            w /= rhs.w;
-
-            return *this;
-        }
-
-        /**
-         * @brief	Calculates the dot (scalar) product of this vector with another.
-         */
-        float dot(const Vector4& vec) const
-        {
-            return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
-        }
-
-		/**
-		 * @brief	Checks are any of the vector components NaN.
-		 */
-		bool isNaN() const
-		{
-			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
-		}
-
-        static const Vector4 ZERO;
-    };
-
-	BS_ALLOW_MEMCPY_SERIALIZATION(Vector4);
-}
-
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A four dimensional vector. */
+    class BS_UTILITY_EXPORT Vector4
+    {
+    public:
+        float x, y, z, w;
+
+    public:
+        Vector4()
+			:x(0.0f), y(0.0f), z(0.0f), w(0.0f)
+        { }
+
+        Vector4(float x, float y, float z, float w)
+            :x(x), y(y), z(z), w(w)
+        { }
+
+		explicit Vector4(const Vector3& vec, float w = 0.0f)
+			:x(vec.x), y(vec.y), z(vec.z), w(w)
+		{ }
+
+		/** Exchange the contents of this vector with another. */
+		void swap(Vector4& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+			std::swap(w, other.w);
+		}
+	
+		float operator[] (UINT32 i) const
+        {
+            assert (i < 4);
+
+            return *(&x+i);
+        }
+
+		float& operator[] (UINT32 i)
+        {
+            assert(i < 4);
+
+            return *(&x+i);
+        }
+
+		/** Pointer accessor for direct copying. */
+		float* ptr()
+		{
+			return &x;
+		}
+
+		/** Pointer accessor for direct copying. */
+		const float* ptr() const
+		{
+			return &x;
+		}
+
+        Vector4& operator= (const Vector4& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+            z = rhs.z;
+            w = rhs.w;
+
+            return *this;
+        }
+
+		Vector4& operator= (float rhs)
+		{
+			x = rhs;
+			y = rhs;
+			z = rhs;
+			w = rhs;
+
+			return *this;
+		}
+
+        bool operator== (const Vector4& rhs) const
+        {
+            return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w);
+        }
+
+        bool operator!= (const Vector4& rhs) const
+        {
+            return (x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w);
+        }
+
+        Vector4& operator= (const Vector3& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+            z = rhs.z;
+            w = 1.0f;
+
+            return *this;
+        }
+
+        Vector4 operator+ (const Vector4& rhs) const
+        {
+            return Vector4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w);
+        }
+
+        Vector4 operator- (const Vector4& rhs) const
+        {
+            return Vector4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w);
+        }
+
+        Vector4 operator* (float rhs) const
+        {
+            return Vector4(x * rhs, y * rhs, z * rhs, w * rhs);
+        }
+
+        Vector4 operator* (const Vector4& rhs) const
+        {
+            return Vector4(rhs.x * x, rhs.y * y, rhs.z * z, rhs.w * w);
+        }
+
+        Vector4 operator/ (float rhs) const
+        {
+            assert(rhs != 0.0f);
+
+            float inv = 1.0f / rhs;
+            return Vector4(x * inv, y * inv, z * inv, w * inv);
+        }
+
+        Vector4 operator/ (const Vector4& rhs) const
+        {
+            return Vector4(x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w);
+        }
+
+        const Vector4& operator+ () const
+        {
+            return *this;
+        }
+
+        Vector4 operator- () const
+        {
+            return Vector4(-x, -y, -z, -w);
+        }
+
+        friend Vector4 operator* (float lhs, const Vector4& rhs)
+        {
+            return Vector4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w);
+        }
+
+        friend Vector4 operator/ (float lhs, const Vector4& rhs)
+        {
+            return Vector4(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z, lhs / rhs.w);
+        }
+
+        friend Vector4 operator+ (const Vector4& lhs, float rhs)
+        {
+            return Vector4(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs, lhs.w + rhs);
+        }
+
+        friend Vector4 operator+ (float lhs, const Vector4& rhs)
+        {
+            return Vector4(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z, lhs + rhs.w);
+        }
+
+        friend Vector4 operator- (const Vector4& lhs, float rhs)
+        {
+            return Vector4(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs, lhs.w - rhs);
+        }
+
+        friend Vector4 operator- (float lhs, Vector4& rhs)
+        {
+            return Vector4(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z, lhs - rhs.w);
+        }
+
+        Vector4& operator+= (const Vector4& rhs)
+        {
+            x += rhs.x;
+            y += rhs.y;
+            z += rhs.z;
+            w += rhs.w;
+
+            return *this;
+        }
+
+        Vector4& operator-= (const Vector4& rhs)
+        {
+            x -= rhs.x;
+            y -= rhs.y;
+            z -= rhs.z;
+            w -= rhs.w;
+
+            return *this;
+        }
+
+        Vector4& operator*= (float rhs)
+        {
+            x *= rhs;
+            y *= rhs;
+            z *= rhs;
+            w *= rhs;
+
+            return *this;
+        }
+
+        Vector4& operator+= (float rhs)
+        {
+            x += rhs;
+            y += rhs;
+            z += rhs;
+            w += rhs;
+
+            return *this;
+        }
+
+        Vector4& operator-= (float rhs)
+        {
+            x -= rhs;
+            y -= rhs;
+            z -= rhs;
+            w -= rhs;
+
+            return *this;
+        }
+
+        Vector4& operator*= (Vector4& rhs)
+        {
+            x *= rhs.x;
+            y *= rhs.y;
+            z *= rhs.z;
+            w *= rhs.w;
+
+            return *this;
+        }
+
+        Vector4& operator/= (float rhs)
+        {
+            assert(rhs != 0.0f);
+
+            float inv = 1.0f / rhs;
+
+            x *= inv;
+            y *= inv;
+            z *= inv;
+            w *= inv;
+
+            return *this;
+        }
+
+        Vector4& operator/= (const Vector4& rhs)
+        {
+            x /= rhs.x;
+            y /= rhs.y;
+            z /= rhs.z;
+            w /= rhs.w;
+
+            return *this;
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another. */
+        float dot(const Vector4& vec) const
+        {
+            return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
+        }
+
+		/** 	Checks are any of the vector components NaN. */
+		bool isNaN() const
+		{
+			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
+		}
+
+        static const Vector4 ZERO;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Vector4);
+	/** @endcond */
+}
+

+ 68 - 65
BansheeUtility/Include/BsVectorNI.h

@@ -1,66 +1,69 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A N dimensional vector with integer
-	 *			coordinates.
-	 */
-	template<int N>
-	struct VectorNI
-	{
-		INT32 v[N];
-
-		VectorNI()
-		{ 
-			memset(v, 0, sizeof(v));
-		}
-
-		VectorNI(INT32 val[N])
-		{ 
-			memcpy(v, val, sizeof(v));
-		}
-
-		INT32 operator[] (size_t i) const
-		{
-			assert(i < N);
-
-			return v[i];
-		}
-
-		INT32& operator[] (size_t i)
-		{
-			assert(i < N);
-
-			return v[i];
-		}
-
-		VectorNI& operator= (const VectorNI& rhs)
-		{
-			memcpy(v, rhs.v, sizeof(v));
-
-			return *this;
-		}
-
-		bool operator== (const Vector2I& rhs) const
-		{
-			for (UINT32 i = 0; i < N; i++)
-			{
-				if (v[i] != rhs.v[i])
-					return false;
-			}
-
-			return true;
-		}
-
-		bool operator!= (const Vector2I& rhs) const
-		{
-			return !operator==(*this, rhs);
-		}
-	};
-
-	typedef VectorNI<3> Vector3I;
-	typedef VectorNI<4> Vector4I;
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A N dimensional vector with integer coordinates. */
+	template<int N>
+	struct VectorNI
+	{
+		INT32 v[N];
+
+		VectorNI()
+		{ 
+			memset(v, 0, sizeof(v));
+		}
+
+		VectorNI(INT32 val[N])
+		{ 
+			memcpy(v, val, sizeof(v));
+		}
+
+		INT32 operator[] (size_t i) const
+		{
+			assert(i < N);
+
+			return v[i];
+		}
+
+		INT32& operator[] (size_t i)
+		{
+			assert(i < N);
+
+			return v[i];
+		}
+
+		VectorNI& operator= (const VectorNI& rhs)
+		{
+			memcpy(v, rhs.v, sizeof(v));
+
+			return *this;
+		}
+
+		bool operator== (const Vector2I& rhs) const
+		{
+			for (UINT32 i = 0; i < N; i++)
+			{
+				if (v[i] != rhs.v[i])
+					return false;
+			}
+
+			return true;
+		}
+
+		bool operator!= (const Vector2I& rhs) const
+		{
+			return !operator==(*this, rhs);
+		}
+	};
+
+	/** @} */
+
+	typedef VectorNI<3> Vector3I;
+	typedef VectorNI<4> Vector4I;
 }