Browse Source

Fixed capsule and plane collider gizmos
Improved capsule/plane collider and char. controller inspectors
Fixed a bug with trigonometry math in managed code that was causing rotation handles to go haywire

BearishSun 9 years ago
parent
commit
a39df2ee58

+ 5 - 2
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -226,11 +226,14 @@ namespace BansheeEngine
 		Vector3 topHemisphere = position + Vector3(0.0f, halfHeight, 0.0f);
 		Vector3 botHemisphere = position + Vector3(0.0f, -halfHeight, 0.0f);
 
-		drawWireArc(topHemisphere, Vector3::UNIT_X, radius, Degree(0.0f), Degree(180.0f));
+		drawWireArc(topHemisphere, Vector3::UNIT_X, radius, Degree(270.0f), Degree(180.0f));
 		drawWireArc(topHemisphere, Vector3::UNIT_Z, radius, Degree(0.0f), Degree(180.0f));
 
-		drawWireArc(botHemisphere, Vector3::UNIT_X, radius, Degree(180.0f), Degree(180.0f));
+		drawWireArc(botHemisphere, Vector3::UNIT_X, radius, Degree(90.0f), Degree(180.0f));
 		drawWireArc(botHemisphere, Vector3::UNIT_Z, radius, Degree(180.0f), Degree(180.0f));
+
+		drawWireDisc(topHemisphere, Vector3::UNIT_Y, radius);
+		drawWireDisc(botHemisphere, Vector3::UNIT_Y, radius);
 	}
 
 	void GizmoManager::drawLine(const Vector3& start, const Vector3& end)

+ 1041 - 1041
Source/BansheeEngine/Source/BsShapeMeshes3D.cpp

@@ -1,1042 +1,1042 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsShapeMeshes3D.h"
-#include "BsRect2.h"
-#include "BsMesh.h"
-#include "BsTime.h"
-#include "BsVector2.h"
-#include "BsQuaternion.h"
-#include "BsSphere.h"
-#include "BsMaterial.h"
-#include "BsPass.h"
-#include "BsCoreApplication.h"
-#include "BsRenderQueue.h"
-#include "BsException.h"
-#include "BsCCamera.h"
-#include "BsBuiltinResources.h"
-#include "BsVertexDataDesc.h"
-
-// DEBUG ONLY
-#include "BsDebug.h"
-
-namespace BansheeEngine
-{
-	const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
-	const UINT32 ShapeMeshes3D::NUM_INDICES_AA_LINE = 30;
-
-	inline UINT8* writeVector3(UINT8* buffer, UINT32 stride, const Vector3& value)
-	{
-		*(Vector3*)buffer = value;
-		return buffer + stride;
-	}
-
-	void ShapeMeshes3D::wireAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		assert((vertexOffset + 8) <= meshData->getNumVertices());
-		assert((indexOffset + 24) <= meshData->getNumIndices());	
-
-		wireAABox(box, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::solidAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* normalData = meshData->getElementData(VES_NORMAL);
-
-		assert((vertexOffset + 24) <= meshData->getNumVertices());
-		assert((indexOffset + 36) <= meshData->getNumIndices());
-
-		solidAABox(box, positionData, normalData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::wireSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		UINT32 requiredNumVertices, requiredNumIndices;
-		getNumElementsWireSphere(quality, requiredNumVertices, requiredNumIndices);
-
-		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
-		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
-
-		UINT32 verticesPerArc = (quality + 1) * 5;
-		UINT32 indicesPerArc = (verticesPerArc - 1) * 2;
-
-		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_X, meshData,
-			vertexOffset, indexOffset, quality);
-
-		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Y, meshData,
-			vertexOffset + verticesPerArc, indexOffset + indicesPerArc, quality);
-
-		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Z, meshData,
-			vertexOffset + verticesPerArc * 2, indexOffset + indicesPerArc * 2, quality);
-	}
-
-	void ShapeMeshes3D::solidSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* normalData = meshData->getElementData(VES_NORMAL);
-
-		UINT32 requiredNumVertices, requiredNumIndices;
-		getNumElementsSphere(quality, requiredNumVertices, requiredNumIndices);
-
-		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
-		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
-
-		solidSphere(sphere, positionData, normalData, vertexOffset, 
-			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::wireDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
-		UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		wireArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::solidDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
-		UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		solidArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
-		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		UINT32 requiredNumVertices, requiredNumIndices;
-		getNumElementsWireArc(quality, requiredNumVertices, requiredNumIndices);
-
-		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
-		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
-
-		wireArc(center, radius, normal, startAngle, amountAngle, positionData, vertexOffset,
-			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
-		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* normalData = meshData->getElementData(VES_NORMAL);
-
-		UINT32 requiredNumVertices, requiredNumIndices;
-		getNumElementsArc(quality, requiredNumVertices, requiredNumIndices);
-
-		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
-		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
-
-		solidArc(center, radius, normal, startAngle, amountAngle, positionData, normalData, vertexOffset,
-			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
-		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		assert((vertexOffset + 8) <= meshData->getNumVertices());
-		assert((indexOffset + 24) <= meshData->getNumIndices());
-
-		wireFrustum(position, aspect, FOV, near, far, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
-		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* normalData = meshData->getElementData(VES_NORMAL);
-
-		UINT32 requiredNumVertices, requiredNumIndices;
-		getNumElementsCone(quality, requiredNumVertices, requiredNumIndices);
-
-		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
-		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
-
-		solidCone(base, normal, height, radius, positionData, normalData, vertexOffset,
-			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
-	}
-
-	void ShapeMeshes3D::solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* normalData = meshData->getElementData(VES_NORMAL);
-
-		assert((vertexOffset + 8) <= meshData->getNumVertices());
-		assert((indexOffset + 12) <= meshData->getNumIndices());
-
-		solidQuad(area, positionData, normalData, vertexOffset,
-			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		assert((vertexOffset + 2) <= meshData->getNumVertices());
-		assert((indexOffset + 2) <= meshData->getNumIndices());
-
-		pixelLine(a, b, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::pixelLineList(const Vector<Vector3>& linePoints, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		assert(linePoints.size() % 2 == 0);
-
-		assert((vertexOffset + linePoints.size() * 2) <= meshData->getNumVertices());
-		assert((indexOffset + linePoints.size() * 2) <= meshData->getNumIndices());
-
-		UINT32 curVertOffset = vertexOffset;
-		UINT32 curIdxOffset = indexOffset;
-
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-
-		UINT32 numPoints = (UINT32)linePoints.size();
-		for (UINT32 i = 0; i < numPoints; i += 2)
-		{
-			pixelLine(linePoints[i], linePoints[i + 1], positionData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
-
-			curVertOffset += 2;
-			curIdxOffset += 2;
-		}
-	}
-
-	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, 
-		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* colorData = meshData->getElementData(VES_COLOR);
-
-		assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
-		assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
-
-		antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
-	void ShapeMeshes3D::antialiasedLineList(const Vector<Vector3>& linePoints, const Vector3& up, float width, float borderWidth, 
-		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		assert(linePoints.size() % 2 == 0);
-
-		assert((vertexOffset + linePoints.size() * 4) <= meshData->getNumVertices());
-		assert((indexOffset + linePoints.size() * 15) <= meshData->getNumIndices());
-
-		UINT32 curVertOffset = vertexOffset;
-		UINT32 curIdxOffset = indexOffset;
-
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* colorData = meshData->getElementData(VES_COLOR);
-
-		UINT32 numPoints = (UINT32)linePoints.size();
-		for (UINT32 i = 0; i < numPoints; i += 2)
-		{
-			antialiasedLine(linePoints[i], linePoints[i + 1], up, width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
-
-			curVertOffset += NUM_VERTICES_AA_LINE;
-			curIdxOffset += NUM_INDICES_AA_LINE;
-		}
-	}
-
-	/************************************************************************/
-	/* 								ELEMENT COUNT                      		*/
-	/************************************************************************/
-
-	void ShapeMeshes3D::getNumElementsAABox(UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = 24;
-		numIndices = 36;
-	}
-
-	void ShapeMeshes3D::getNumElementsWireAABox(UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = 8;
-		numIndices = 24;
-	}
-
-	void ShapeMeshes3D::getNumElementsSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = 20 * (3 * ((UINT32)std::pow(4, quality)));
-		numIndices = numVertices;
-	}
-
-	void ShapeMeshes3D::getNumElementsWireSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		getNumElementsWireArc(quality, numVertices, numIndices);
-		numVertices *= 3;
-		numIndices *= 3;
-	}
-
-	void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = ((quality + 1) * 5 + 1) * 2;
-		numIndices = ((quality + 1) * 5 - 1) * 6;
-	}
-
-	void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = (quality + 1) * 5;
-		numIndices = ((quality + 1) * 5 - 1) * 2;
-	}
-
-	void ShapeMeshes3D::getNumElementsDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		getNumElementsArc(quality, numVertices, numIndices);
-	}
-
-	void ShapeMeshes3D::getNumElementsWireDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		getNumElementsWireArc(quality, numVertices, numIndices);
-	}
-
-	void ShapeMeshes3D::getNumElementsCone(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = ((quality + 1) * 4) * 3 + 1;
-		numIndices = ((quality + 1) * 4) * 6;
-	}
-
-	void ShapeMeshes3D::getNumElementsQuad(UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = 8;
-		numIndices = 12;
-	}
-
-	void ShapeMeshes3D::getNumElementsFrustum(UINT32& numVertices, UINT32& numIndices)
-	{
-		numVertices = 8;
-		numIndices = 36;
-	}
-
-	void ShapeMeshes3D::wireAABox(const AABox& box, UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		outVertices += vertexOffset * vertexStride;
-
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
-
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
-
-		outIndices += indexOffset;
-
-		// Front
-		outIndices[0] = vertexOffset + 0;
-		outIndices[1] = vertexOffset + 1;
-
-		outIndices[2] = vertexOffset + 1;
-		outIndices[3] = vertexOffset + 2;
-
-		outIndices[4] = vertexOffset + 2;
-		outIndices[5] = vertexOffset + 3;
-
-		outIndices[6] = vertexOffset + 3;
-		outIndices[7] = vertexOffset + 0;
-
-		// Center
-		outIndices[8] = vertexOffset + 0;
-		outIndices[9] = vertexOffset + 5;
-
-		outIndices[10] = vertexOffset + 1;
-		outIndices[11] = vertexOffset + 4;
-
-		outIndices[12] = vertexOffset + 2;
-		outIndices[13] = vertexOffset + 7;
-
-		outIndices[14] = vertexOffset + 3;
-		outIndices[15] = vertexOffset + 6;
-
-		// Back
-		outIndices[16] = vertexOffset + 4;
-		outIndices[17] = vertexOffset + 5;
-
-		outIndices[18] = vertexOffset + 5;
-		outIndices[19] = vertexOffset + 6;
-
-		outIndices[20] = vertexOffset + 6;
-		outIndices[21] = vertexOffset + 7;
-
-		outIndices[22] = vertexOffset + 7;
-		outIndices[23] = vertexOffset + 4;
-	}
-
-	void ShapeMeshes3D::solidAABox(const AABox& box, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride,
-		UINT32* outIndices, UINT32 indexOffset)
-	{
-		outVertices += (vertexOffset * vertexStride);
-		Vector3* corners = (Vector3*)outVertices;
-
-		// Front face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
-
-		// Back face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
-
-		// Left face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
-
-		// Right face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
-
-		// Top face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
-
-		// Bottom face
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
-		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
-
-		static const Vector3 faceNormals[6] = 
-		{
-			Vector3(0, 0, 1),
-			Vector3(0, 0, -1),
-			Vector3(-1, 0, 0),
-			Vector3(1, 0, 0),
-			Vector3(0, 1, 0),
-			Vector3(0, -1, 0)
-		};
-
-		outNormals += (vertexOffset * vertexStride);
-		for (UINT32 face = 0; face < 6; face++)
-		{
-			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
-			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
-			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
-			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
-		}
-
-		UINT32* indices = outIndices + indexOffset;
-		for (UINT32 face = 0; face < 6; face++)
-		{
-			UINT32 faceVertOffset = vertexOffset + face * 4;
-
-			indices[face * 6 + 0] = faceVertOffset + 2;
-			indices[face * 6 + 1] = faceVertOffset + 1;
-			indices[face * 6 + 2] = faceVertOffset + 0;
-			indices[face * 6 + 3] = faceVertOffset + 0;
-			indices[face * 6 + 4] = faceVertOffset + 3;
-			indices[face * 6 + 5] = faceVertOffset + 2;
-		}
-	}
-
-	void ShapeMeshes3D::solidSphere(const Sphere& sphere, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, 
-		UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
-	{
-		// Create icosahedron
-		static const float x = 0.525731112119133606f;
-		static const float z = 0.850650808352039932f;
-
-		static const Vector3 vertices[12] = 
-		{
-			Vector3(-x,		0.0f,	z),
-			Vector3(x,		0.0f,	z),
-			Vector3(-x,		0.0f,	-z),
-			Vector3(x,		0.0f,	-z),
-			Vector3(0.0f,	z,		x),
-			Vector3(0.0f,	z,		-x),
-			Vector3(0.0f,	-z,		x),
-			Vector3(0.0f,	-z,		-x),
-			Vector3(z,		x,		0.0f),
-			Vector3(-z,		x,		0.0f),
-			Vector3(z,		-x,		0.0f),
-			Vector3(-z,		-x,		0.0f)
-		};
-
-		static const UINT32 triangles[20][3] = 
-		{
-				{ 0, 4, 1 },  { 0, 9, 4 },	{ 9, 5, 4 },	{ 4, 5, 8 },
-				{ 4, 8, 1 },  { 8, 10, 1 }, { 8, 3, 10 },	{ 5, 3, 8 },
-				{ 5, 2, 3 },  { 2, 7, 3 },	{ 7, 10, 3 },	{ 7, 6, 10 },
-				{ 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 },	{ 6, 1, 10 },
-				{ 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 },	{ 7, 2, 11 }
-		};
-
-		// Tessellate it
-		UINT32 curVertOffset = vertexOffset;
-		for (int i = 0; i < 20; ++i) 
-		{
-			curVertOffset += subdivideTriangleOnSphere(sphere.getCenter(), sphere.getRadius(), quality,
-				vertices[triangles[i][2]], vertices[triangles[i][1]], vertices[triangles[i][0]],
-				outVertices, outNormals, curVertOffset, vertexStride);
-		}
-
-		// Create indices
-		outIndices += indexOffset;
-
-		UINT32 numIndices = 20 * (3 * (UINT32)std::pow(4, quality));
-		for (UINT32 i = 0; i < numIndices; i += 3)
-		{
-			outIndices[i] = vertexOffset + i + 2;
-			outIndices[i + 1] = vertexOffset + i + 1;
-			outIndices[i + 2] = vertexOffset + i + 0;
-		}
-	}
-
-	void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle, 
-		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
-	{
-		UINT32 numVertices = (quality + 1) * 5;
-
-		generateArcVertices(center, normal, radius, startAngle, amountAngle,
-			numVertices, outVertices, vertexOffset, vertexStride);
-
-		outIndices += indexOffset;
-		UINT32 numLines = numVertices - 1;
-		for (UINT32 i = 0; i < numLines; i++)
-		{
-			outIndices[i * 2 + 0] = vertexOffset + i;
-			outIndices[i * 2 + 1] = vertexOffset + i + 1;
-		}
-	}
-
-	void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle, 
-		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
-	{
-		outVertices += vertexOffset * vertexStride;
-		outNormals += vertexOffset * vertexStride;
-		outIndices += indexOffset;
-
-		bool reverseOrder = amountAngle.valueDegrees() < 0.0f;
-		Vector3 visibleNormal = normal;
-
-		outVertices = writeVector3(outVertices, vertexStride, center);
-		outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
-
-		UINT32 numArcVertices = (quality + 1) * 5;
-		generateArcVertices(center, normal, radius, startAngle, amountAngle,
-			numArcVertices, outVertices, vertexOffset, vertexStride);
-
-		UINT8* otherSideVertices = outVertices + (numArcVertices * vertexStride);
-		UINT8* otherSideNormals = outNormals + (numArcVertices * vertexStride);
-
-		otherSideVertices = writeVector3(otherSideVertices, vertexStride, center);
-		otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
-
-		for (UINT32 i = 0; i < numArcVertices; i++)
-		{
-			otherSideVertices = writeVector3(otherSideVertices, vertexStride, *(Vector3*)outVertices);
-			outVertices += vertexStride;
-
-			outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
-			otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
-		}
-
-		UINT32 numTriangles = numArcVertices - 1;
-
-		// If angle is negative the order of vertices is reversed so we need to reverse the indexes too
-		UINT32 frontSideOffset = vertexOffset + (reverseOrder ? (numArcVertices + 1) : 0);
-		UINT32 backSideOffset = vertexOffset + (!reverseOrder ? (numArcVertices + 1) : 0);
-
-		for (UINT32 i = 0; i < numTriangles; i++)
-		{
-			outIndices[i * 6 + 0] = frontSideOffset + 0;
-			outIndices[i * 6 + 1] = frontSideOffset + i + 1;
-			outIndices[i * 6 + 2] = frontSideOffset + i;
-
-			outIndices[i * 6 + 3] = backSideOffset + 0;
-			outIndices[i * 6 + 4] = backSideOffset + i;
-			outIndices[i * 6 + 5] = backSideOffset + i + 1;
-		}
-	}
-
-	void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
-		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		float fovTan = Math::tan(FOV * 0.5f);
-
-		Vector3 nearPoint(0, 0, near);
-		Vector3 nearWidth(near * fovTan * aspect, 0, 0);
-		Vector3 nearHeight(0, (near * fovTan) / aspect, 0);
-
-		Vector3 farPoint(0, 0, far);
-		Vector3 farWidth(far * fovTan * aspect, 0, 0);
-		Vector3 farHeight(0, (far * fovTan) / aspect, 0);
-
-		Vector3 points[8] = 
-		{
-			nearPoint + nearWidth + nearHeight,
-			nearPoint - nearWidth + nearHeight,
-			nearPoint - nearWidth - nearHeight,
-			nearPoint + nearWidth - nearHeight,
-			farPoint + farWidth + farHeight,
-			farPoint - farWidth + farHeight,
-			farPoint - farWidth - farHeight,
-			farPoint + farWidth - farHeight
-		};
-
-		outVertices += vertexOffset * vertexStride;
-
-		for (UINT32 i = 0; i < 8; i++)
-			outVertices = writeVector3(outVertices, vertexStride, position + points[i]);
-
-		outIndices += indexOffset;
-
-		// Front
-		outIndices[0] = vertexOffset + 0; outIndices[1] = vertexOffset + 1;
-		outIndices[2] = vertexOffset + 1; outIndices[3] = vertexOffset + 2;
-		outIndices[4] = vertexOffset + 2; outIndices[5] = vertexOffset + 3;
-		outIndices[6] = vertexOffset + 3; outIndices[7] = vertexOffset + 0;
-
-		// Center
-		outIndices[8] = vertexOffset + 0; outIndices[9] = vertexOffset + 4;
-		outIndices[10] = vertexOffset + 1; outIndices[11] = vertexOffset + 5;
-		outIndices[12] = vertexOffset + 2; outIndices[13] = vertexOffset + 6;
-		outIndices[14] = vertexOffset + 3; outIndices[15] = vertexOffset + 7;
-
-		// Back
-		outIndices[16] = vertexOffset + 4; outIndices[17] = vertexOffset + 5;
-		outIndices[18] = vertexOffset + 5; outIndices[19] = vertexOffset + 6;
-		outIndices[20] = vertexOffset + 6; outIndices[21] = vertexOffset + 7;
-		outIndices[22] = vertexOffset + 7; outIndices[23] = vertexOffset + 4;
-	}
-
-	void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
-		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
-	{
-		outVertices += vertexOffset * vertexStride;
-		outIndices += indexOffset;
-
-		if (outNormals != nullptr)
-			outNormals += vertexOffset * vertexStride;
-
-		// Generate base disc
-		UINT32 numArcVertices = (quality + 1) * 4;
-
-		generateArcVertices(base, normal, radius, Degree(0), Degree(360),
-			numArcVertices + 1, outVertices, 0, vertexStride);
-
-		outVertices += numArcVertices * vertexStride;
-		outVertices = writeVector3(outVertices, vertexStride, base); // Write base vertex
-
-		UINT32 baseIdx = numArcVertices;
-
-		if (outNormals != nullptr)
-		{
-			UINT32 totalNumBaseVertices = numArcVertices + 1;
-			for (UINT32 i = 0; i < totalNumBaseVertices; i++)
-				outNormals = writeVector3(outNormals, vertexStride, -normal);
-		}
-
-		UINT32 numTriangles = numArcVertices;
-		for (UINT32 i = 0; i < numTriangles - 1; i++)
-		{
-			outIndices[i * 3 + 0] = vertexOffset + baseIdx;
-			outIndices[i * 3 + 1] = vertexOffset + i;
-			outIndices[i * 3 + 2] = vertexOffset + i + 1;
-		}
-
-		{
-			UINT32 i = numTriangles - 1;
-			outIndices[i * 3 + 0] = vertexOffset + baseIdx;
-			outIndices[i * 3 + 1] = vertexOffset + i;
-			outIndices[i * 3 + 2] = vertexOffset + 0;
-		}
-
-		//// Generate cone
-		// Base vertices
-		generateArcVertices(base, normal, radius, Degree(0), Degree(360),
-			numArcVertices + 1, outVertices, 0, vertexStride);
-
-		Vector3 topVertex = base + normal * height;
-
-		// Normals
-		if (outNormals != nullptr)
-		{
-			UINT8* outNormalsBase = outNormals;
-			UINT8* outNormalsTop = outNormals + numArcVertices * vertexStride;
-			for (INT32 i = 0; i < (INT32)numArcVertices; i++)
-			{
-				int offsetA = i == 0 ? numArcVertices - 1 : i - 1;
-				int offsetB = i;
-				int offsetC = (i + 1) % numArcVertices;
-
-				Vector3* a = (Vector3*)(outVertices + (offsetA * vertexStride));
-				Vector3* b = (Vector3*)(outVertices + (offsetB * vertexStride));
-				Vector3* c = (Vector3*)(outVertices + (offsetC * vertexStride));
-
-				Vector3 toTop = topVertex - *b;
-
-				Vector3 normalLeft = Vector3::cross(toTop, *a - *b);
-				normalLeft.normalize();
-
-				Vector3 normalRight = Vector3::cross(*c - *b, toTop);
-				normalRight.normalize();
-
-				Vector3 triNormal = Vector3::normalize(normalLeft + normalRight);
-
-				outNormalsBase = writeVector3(outNormalsBase, vertexStride, triNormal);
-				outNormalsTop = writeVector3(outNormalsTop, vertexStride, triNormal);
-			}
-		}
-
-		// Top vertices (All same position, but need them separate because of different normals)
-		outVertices += numArcVertices * vertexStride;
-
-		for (UINT32 i = 0; i < numArcVertices; i++)
-			outVertices = writeVector3(outVertices, vertexStride, topVertex);
-
-		outIndices += numTriangles * 3;
-		UINT32 curVertBaseOffset = vertexOffset + numArcVertices + 1;
-		UINT32 curVertTopOffset = curVertBaseOffset + numArcVertices;
-		for (UINT32 i = 0; i < numTriangles - 1; i++)
-		{
-			outIndices[i * 3 + 0] = curVertTopOffset + i;
-			outIndices[i * 3 + 1] = curVertBaseOffset + i + 1;
-			outIndices[i * 3 + 2] = curVertBaseOffset + i;
-		}
-
-		{
-			UINT32 i = numTriangles - 1;
-			outIndices[i * 3 + 0] = curVertTopOffset + i;
-			outIndices[i * 3 + 1] = curVertBaseOffset + 0;
-			outIndices[i * 3 + 2] = curVertBaseOffset + i;
-		}
-	}
-
-	void ShapeMeshes3D::solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		outVertices += (vertexOffset * vertexStride);
-
-		Vector3 topLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
-		Vector3 topRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
-		Vector3 botRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
-		Vector3 botLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
-
-		outVertices = writeVector3(outVertices, vertexStride, topLeft);
-		outVertices = writeVector3(outVertices, vertexStride, topRight);
-		outVertices = writeVector3(outVertices, vertexStride, botRight);
-		outVertices = writeVector3(outVertices, vertexStride, botLeft);
-
-		outVertices = writeVector3(outVertices, vertexStride, topLeft);
-		outVertices = writeVector3(outVertices, vertexStride, topRight);
-		outVertices = writeVector3(outVertices, vertexStride, botRight);
-		outVertices = writeVector3(outVertices, vertexStride, botLeft);
-
-		Vector3 normal = area.getAxisHorz().cross(area.getAxisVert());
-		Vector3 reverseNormal = -normal;
-
-		outNormals += (vertexOffset * vertexStride);
-		outNormals = writeVector3(outNormals, vertexStride, normal);
-		outNormals = writeVector3(outNormals, vertexStride, normal);
-		outNormals = writeVector3(outNormals, vertexStride, normal);
-		outNormals = writeVector3(outNormals, vertexStride, normal);
-
-		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
-		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
-		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
-		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
-
-		outIndices += indexOffset;
-		outIndices[0] = vertexOffset;
-		outIndices[1] = vertexOffset + 1;
-		outIndices[2] = vertexOffset + 2;
-
-		outIndices[3] = vertexOffset;
-		outIndices[4] = vertexOffset + 2;
-		outIndices[5] = vertexOffset + 3;
-
-		outIndices[6] = vertexOffset + 4;
-		outIndices[7] = vertexOffset + 6;
-		outIndices[8] = vertexOffset + 5;
-
-		outIndices[9] = vertexOffset + 4;
-		outIndices[10] = vertexOffset + 7;
-		outIndices[11] = vertexOffset + 6;
-	}
-
-	Vector3 ShapeMeshes3D::calcCenter(UINT8* vertices, UINT32 numVertices, UINT32 vertexStride)
-	{
-		Vector3 center = Vector3::ZERO;
-		for(UINT32 i = 0; i < numVertices; i++)
-		{
-			Vector3* curVert = (Vector3*)vertices;
-			center += *curVert;
-
-			vertices += vertexStride;
-		}
-
-		center /= (float)numVertices;
-		return center;
-	}
-
-	void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, UINT8* outVertices,
-		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		outVertices += (vertexOffset * vertexStride);
-
-		Vector3* vertices = (Vector3*)outVertices;
-		(*vertices) = a;
-
-		vertices = (Vector3*)(outVertices + vertexStride);
-		(*vertices) = b;
-
-		outIndices += indexOffset;
-		outIndices[0] = vertexOffset + 0;
-		outIndices[1] = vertexOffset + 1;
-	}
-
-	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
-		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		Vector3 dir = b - a;
-		dir.normalize();
-
-		Vector3 right = dir.cross(up);
-		right.normalize();
-
-		Vector<Vector3> points(4);
-
-		float r = width * 0.5f;
-		dir = dir * r;
-		right = right * r;
-
-		Vector3 v0 = a - dir - right;
-		Vector3 v1 = a - dir + right;
-		Vector3 v2 = b + dir + right;
-		Vector3 v3 = b + dir - right;
-
-		points[0] = v0;
-		points[1] = v1;
-		points[2] = v2;
-		points[3] = v3;
-
-		antialiasedPolygon(points, up, borderWidth, color, outVertices, outColors, vertexOffset, vertexStride, outIndices, indexOffset);
-	}
-
-	void ShapeMeshes3D::pixelSolidPolygon(const Vector<Vector3>& points, UINT8* outVertices,
-		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		outVertices += (vertexOffset * vertexStride);
-
-		for (auto& point : points)
-		{
-			Vector3* vertices = (Vector3*)outVertices;
-			(*vertices) = point;
-
-			outVertices += vertexStride;
-		}
-
-		outIndices += indexOffset;
-		INT32 numPoints = (INT32)points.size();
-		UINT32 idxCnt = 0;
-		for (int i = 2; i < numPoints; i++)
-		{
-			outIndices[idxCnt++] = vertexOffset;
-			outIndices[idxCnt++] = vertexOffset + i - 1;
-			outIndices[idxCnt++] = vertexOffset + i;
-		}
-	}
-
-	void ShapeMeshes3D::pixelWirePolygon(const Vector<Vector3>& points, UINT8* outVertices,
-		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		INT32 numPoints = (INT32)points.size();
-		UINT32 curVertOffset = vertexOffset;
-		UINT32 curIdxOffset = indexOffset;
-		for (INT32 i = 0, j = numPoints - 1; i < numPoints; j = i++)
-		{
-			pixelLine(points[j], points[i], outVertices, curVertOffset, vertexStride, outIndices, curIdxOffset);
-			curVertOffset += 2;
-			curIdxOffset += 2;
-		}
-	}
-
-	void ShapeMeshes3D::antialiasedPolygon(const Vector<Vector3>& points, const Vector3& up, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
-		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
-	{
-		UINT32 numCoords = (UINT32)points.size();
-
-		outVertices += vertexOffset * vertexStride;
-		outColors += vertexOffset * vertexStride;
-		Vector<Vector3> tempNormals(numCoords);
-
-		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
-		{
-			const Vector3& v0 = points[j];
-			const Vector3& v1 = points[i];
-
-			Vector3 dir = v1 - v0;
-			Vector3 right = dir.cross(up);
-			right.normalize();
-
-			tempNormals[j] = right;
-
-			// Also start populating the vertex array
-			Vector3* vertices = (Vector3*)outVertices;
-			*vertices = v1;
-
-			UINT32* colors = (UINT32*)outColors;
-			*colors = color.getAsRGBA();
-
-			outVertices += vertexStride;
-			outColors += vertexStride;
-		}
-
-		Color transparentColor = color;
-		transparentColor.a = 0.0f;
-
-		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
-		{
-			const Vector3& n0 = tempNormals[j];
-			const Vector3& n1 = tempNormals[i];
-
-			Vector3 avgNrm = (n0 + n1) * 0.5f;
-			float magSqrd = avgNrm.squaredLength();
-
-			if (magSqrd > 0.000001f)
-			{
-				float scale = 1.0f / magSqrd;
-				if (scale > 10.0f)
-					scale = 10.0f;
-
-				avgNrm = avgNrm * scale;
-			}
-
-			Vector3 tempCoord = points[i] + avgNrm * borderWidth;
-
-			// Move it to the vertex array
-			Vector3* vertices = (Vector3*)outVertices;
-			*vertices = tempCoord;
-
-			UINT32* colors = (UINT32*)outColors;
-			*colors = transparentColor.getAsRGBA();
-
-			outVertices += vertexStride;
-			outColors += vertexStride;
-		}
-
-		// Populate index buffer
-		outIndices += indexOffset;
-
-		UINT32 idxCnt = 0;
-		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
-		{
-			outIndices[idxCnt++] = vertexOffset + i;
-			outIndices[idxCnt++] = vertexOffset + j;
-			outIndices[idxCnt++] = vertexOffset + numCoords + j;
-
-			outIndices[idxCnt++] = vertexOffset + numCoords + j;
-			outIndices[idxCnt++] = vertexOffset + numCoords + i;
-			outIndices[idxCnt++] = vertexOffset + i;
-		}
-
-		for (UINT32 i = 2; i < numCoords; ++i)
-		{
-			outIndices[idxCnt++] = vertexOffset + 0;
-			outIndices[idxCnt++] = vertexOffset + i - 1;
-			outIndices[idxCnt++] = vertexOffset + i;
-		}
-	}
-
-	UINT32 ShapeMeshes3D::subdivideTriangleOnSphere(const Vector3& center, float radius, UINT32 numLevels,
-		const Vector3& a, const Vector3& b, const Vector3& c,
-		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride)
-	{
-		outVertices += (vertexOffset * vertexStride);
-
-		if (outNormals != nullptr)
-			outNormals += (vertexOffset * vertexStride);
-
-		UINT32 numVertices = 0;
-
-		if (numLevels > 0)
-		{
-			Vector3 sub1 = Vector3::normalize((a + b) * 0.5f);
-			Vector3 sub2 = Vector3::normalize((b + c) * 0.5f);
-			Vector3 sub3 = Vector3::normalize((c + a) * 0.5f);
-
-			numLevels--;
-
-			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, a, sub1, sub3, outVertices, 
-				outNormals, numVertices, vertexStride);
-			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, b, sub2, outVertices, 
-				outNormals, numVertices, vertexStride);
-			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, sub2, sub3, outVertices, 
-				outNormals, numVertices, vertexStride);
-			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub3, sub2, c, outVertices, 
-				outNormals, numVertices, vertexStride);
-		}
-		else
-		{
-			*((Vector3*)outVertices) = center + a * radius;
-			outVertices += vertexStride;
-			
-			*((Vector3*)outVertices) = center + b * radius;
-			outVertices += vertexStride;
-			
-			*((Vector3*)outVertices) = center + c * radius;
-			outVertices += vertexStride;
-
-			if (outNormals != nullptr)
-			{
-				*((Vector3*)outNormals) = a;
-				outNormals += vertexStride;
-
-				*((Vector3*)outNormals) = b;
-				outNormals += vertexStride;
-
-				*((Vector3*)outNormals) = c;
-				outNormals += vertexStride;
-			}
-
-			numVertices += 3;
-		}
-
-		return numVertices;
-	}
-
-	void ShapeMeshes3D::generateArcVertices(const Vector3& center, const Vector3& up, float radius, Degree startAngle, Degree angleAmount, UINT32 numVertices,
-		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride)
-	{
-		assert(numVertices >= 2);
-
-		Quaternion alignWithStart = Quaternion(-Vector3::UNIT_Y, startAngle);
-		Quaternion alignWithUp = Quaternion::getRotationFromTo(Vector3::UNIT_Y, up);
-
-		Vector3 right = alignWithUp.rotate(alignWithStart.rotate(Vector3::UNIT_X));
-		right.normalize();
-
-		Quaternion increment(up, angleAmount / (float)(numVertices - 1));
-
-		outVertices += vertexOffset * vertexStride;
-		Vector3 curDirection = right * radius;
-		for (UINT32 i = 0; i < numVertices; i++)
-		{
-			outVertices = writeVector3(outVertices, vertexStride, center + curDirection);
-			curDirection = increment.rotate(curDirection);
-		}
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsShapeMeshes3D.h"
+#include "BsRect2.h"
+#include "BsMesh.h"
+#include "BsTime.h"
+#include "BsVector2.h"
+#include "BsQuaternion.h"
+#include "BsSphere.h"
+#include "BsMaterial.h"
+#include "BsPass.h"
+#include "BsCoreApplication.h"
+#include "BsRenderQueue.h"
+#include "BsException.h"
+#include "BsCCamera.h"
+#include "BsBuiltinResources.h"
+#include "BsVertexDataDesc.h"
+
+// DEBUG ONLY
+#include "BsDebug.h"
+
+namespace BansheeEngine
+{
+	const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
+	const UINT32 ShapeMeshes3D::NUM_INDICES_AA_LINE = 30;
+
+	inline UINT8* writeVector3(UINT8* buffer, UINT32 stride, const Vector3& value)
+	{
+		*(Vector3*)buffer = value;
+		return buffer + stride;
+	}
+
+	void ShapeMeshes3D::wireAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		assert((vertexOffset + 8) <= meshData->getNumVertices());
+		assert((indexOffset + 24) <= meshData->getNumIndices());	
+
+		wireAABox(box, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::solidAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		assert((vertexOffset + 24) <= meshData->getNumVertices());
+		assert((indexOffset + 36) <= meshData->getNumIndices());
+
+		solidAABox(box, positionData, normalData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::wireSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		UINT32 requiredNumVertices, requiredNumIndices;
+		getNumElementsWireSphere(quality, requiredNumVertices, requiredNumIndices);
+
+		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
+		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
+
+		UINT32 verticesPerArc = (quality + 1) * 5;
+		UINT32 indicesPerArc = (verticesPerArc - 1) * 2;
+
+		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_X, meshData,
+			vertexOffset, indexOffset, quality);
+
+		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Y, meshData,
+			vertexOffset + verticesPerArc, indexOffset + indicesPerArc, quality);
+
+		wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Z, meshData,
+			vertexOffset + verticesPerArc * 2, indexOffset + indicesPerArc * 2, quality);
+	}
+
+	void ShapeMeshes3D::solidSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		UINT32 requiredNumVertices, requiredNumIndices;
+		getNumElementsSphere(quality, requiredNumVertices, requiredNumIndices);
+
+		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
+		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
+
+		solidSphere(sphere, positionData, normalData, vertexOffset, 
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::wireDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
+		UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		wireArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::solidDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
+		UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		solidArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
+		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		UINT32 requiredNumVertices, requiredNumIndices;
+		getNumElementsWireArc(quality, requiredNumVertices, requiredNumIndices);
+
+		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
+		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
+
+		wireArc(center, radius, normal, startAngle, amountAngle, positionData, vertexOffset,
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
+		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		UINT32 requiredNumVertices, requiredNumIndices;
+		getNumElementsArc(quality, requiredNumVertices, requiredNumIndices);
+
+		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
+		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
+
+		solidArc(center, radius, normal, startAngle, amountAngle, positionData, normalData, vertexOffset,
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
+		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		assert((vertexOffset + 8) <= meshData->getNumVertices());
+		assert((indexOffset + 24) <= meshData->getNumIndices());
+
+		wireFrustum(position, aspect, FOV, near, far, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
+		const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		UINT32 requiredNumVertices, requiredNumIndices;
+		getNumElementsCone(quality, requiredNumVertices, requiredNumIndices);
+
+		assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
+		assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
+
+		solidCone(base, normal, height, radius, positionData, normalData, vertexOffset,
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
+	}
+
+	void ShapeMeshes3D::solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* normalData = meshData->getElementData(VES_NORMAL);
+
+		assert((vertexOffset + 8) <= meshData->getNumVertices());
+		assert((indexOffset + 12) <= meshData->getNumIndices());
+
+		solidQuad(area, positionData, normalData, vertexOffset,
+			meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		assert((vertexOffset + 2) <= meshData->getNumVertices());
+		assert((indexOffset + 2) <= meshData->getNumIndices());
+
+		pixelLine(a, b, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::pixelLineList(const Vector<Vector3>& linePoints, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		assert(linePoints.size() % 2 == 0);
+
+		assert((vertexOffset + linePoints.size() * 2) <= meshData->getNumVertices());
+		assert((indexOffset + linePoints.size() * 2) <= meshData->getNumIndices());
+
+		UINT32 curVertOffset = vertexOffset;
+		UINT32 curIdxOffset = indexOffset;
+
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+
+		UINT32 numPoints = (UINT32)linePoints.size();
+		for (UINT32 i = 0; i < numPoints; i += 2)
+		{
+			pixelLine(linePoints[i], linePoints[i + 1], positionData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
+
+			curVertOffset += 2;
+			curIdxOffset += 2;
+		}
+	}
+
+	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, 
+		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* colorData = meshData->getElementData(VES_COLOR);
+
+		assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
+		assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
+
+		antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
+	void ShapeMeshes3D::antialiasedLineList(const Vector<Vector3>& linePoints, const Vector3& up, float width, float borderWidth, 
+		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		assert(linePoints.size() % 2 == 0);
+
+		assert((vertexOffset + linePoints.size() * 4) <= meshData->getNumVertices());
+		assert((indexOffset + linePoints.size() * 15) <= meshData->getNumIndices());
+
+		UINT32 curVertOffset = vertexOffset;
+		UINT32 curIdxOffset = indexOffset;
+
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* colorData = meshData->getElementData(VES_COLOR);
+
+		UINT32 numPoints = (UINT32)linePoints.size();
+		for (UINT32 i = 0; i < numPoints; i += 2)
+		{
+			antialiasedLine(linePoints[i], linePoints[i + 1], up, width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
+
+			curVertOffset += NUM_VERTICES_AA_LINE;
+			curIdxOffset += NUM_INDICES_AA_LINE;
+		}
+	}
+
+	/************************************************************************/
+	/* 								ELEMENT COUNT                      		*/
+	/************************************************************************/
+
+	void ShapeMeshes3D::getNumElementsAABox(UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = 24;
+		numIndices = 36;
+	}
+
+	void ShapeMeshes3D::getNumElementsWireAABox(UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = 8;
+		numIndices = 24;
+	}
+
+	void ShapeMeshes3D::getNumElementsSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = 20 * (3 * ((UINT32)std::pow(4, quality)));
+		numIndices = numVertices;
+	}
+
+	void ShapeMeshes3D::getNumElementsWireSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		getNumElementsWireArc(quality, numVertices, numIndices);
+		numVertices *= 3;
+		numIndices *= 3;
+	}
+
+	void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = ((quality + 1) * 5 + 1) * 2;
+		numIndices = ((quality + 1) * 5 - 1) * 6;
+	}
+
+	void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = (quality + 1) * 5;
+		numIndices = ((quality + 1) * 5 - 1) * 2;
+	}
+
+	void ShapeMeshes3D::getNumElementsDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		getNumElementsArc(quality, numVertices, numIndices);
+	}
+
+	void ShapeMeshes3D::getNumElementsWireDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		getNumElementsWireArc(quality, numVertices, numIndices);
+	}
+
+	void ShapeMeshes3D::getNumElementsCone(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = ((quality + 1) * 4) * 3 + 1;
+		numIndices = ((quality + 1) * 4) * 6;
+	}
+
+	void ShapeMeshes3D::getNumElementsQuad(UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = 8;
+		numIndices = 12;
+	}
+
+	void ShapeMeshes3D::getNumElementsFrustum(UINT32& numVertices, UINT32& numIndices)
+	{
+		numVertices = 8;
+		numIndices = 36;
+	}
+
+	void ShapeMeshes3D::wireAABox(const AABox& box, UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += vertexOffset * vertexStride;
+
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
+
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
+
+		outIndices += indexOffset;
+
+		// Front
+		outIndices[0] = vertexOffset + 0;
+		outIndices[1] = vertexOffset + 1;
+
+		outIndices[2] = vertexOffset + 1;
+		outIndices[3] = vertexOffset + 2;
+
+		outIndices[4] = vertexOffset + 2;
+		outIndices[5] = vertexOffset + 3;
+
+		outIndices[6] = vertexOffset + 3;
+		outIndices[7] = vertexOffset + 0;
+
+		// Center
+		outIndices[8] = vertexOffset + 0;
+		outIndices[9] = vertexOffset + 5;
+
+		outIndices[10] = vertexOffset + 1;
+		outIndices[11] = vertexOffset + 4;
+
+		outIndices[12] = vertexOffset + 2;
+		outIndices[13] = vertexOffset + 7;
+
+		outIndices[14] = vertexOffset + 3;
+		outIndices[15] = vertexOffset + 6;
+
+		// Back
+		outIndices[16] = vertexOffset + 4;
+		outIndices[17] = vertexOffset + 5;
+
+		outIndices[18] = vertexOffset + 5;
+		outIndices[19] = vertexOffset + 6;
+
+		outIndices[20] = vertexOffset + 6;
+		outIndices[21] = vertexOffset + 7;
+
+		outIndices[22] = vertexOffset + 7;
+		outIndices[23] = vertexOffset + 4;
+	}
+
+	void ShapeMeshes3D::solidAABox(const AABox& box, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride,
+		UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += (vertexOffset * vertexStride);
+		Vector3* corners = (Vector3*)outVertices;
+
+		// Front face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
+
+		// Back face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
+
+		// Left face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
+
+		// Right face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
+
+		// Top face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
+
+		// Bottom face
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
+		outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
+
+		static const Vector3 faceNormals[6] = 
+		{
+			Vector3(0, 0, 1),
+			Vector3(0, 0, -1),
+			Vector3(-1, 0, 0),
+			Vector3(1, 0, 0),
+			Vector3(0, 1, 0),
+			Vector3(0, -1, 0)
+		};
+
+		outNormals += (vertexOffset * vertexStride);
+		for (UINT32 face = 0; face < 6; face++)
+		{
+			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
+			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
+			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
+			outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
+		}
+
+		UINT32* indices = outIndices + indexOffset;
+		for (UINT32 face = 0; face < 6; face++)
+		{
+			UINT32 faceVertOffset = vertexOffset + face * 4;
+
+			indices[face * 6 + 0] = faceVertOffset + 2;
+			indices[face * 6 + 1] = faceVertOffset + 1;
+			indices[face * 6 + 2] = faceVertOffset + 0;
+			indices[face * 6 + 3] = faceVertOffset + 0;
+			indices[face * 6 + 4] = faceVertOffset + 3;
+			indices[face * 6 + 5] = faceVertOffset + 2;
+		}
+	}
+
+	void ShapeMeshes3D::solidSphere(const Sphere& sphere, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, 
+		UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
+	{
+		// Create icosahedron
+		static const float x = 0.525731112119133606f;
+		static const float z = 0.850650808352039932f;
+
+		static const Vector3 vertices[12] = 
+		{
+			Vector3(-x,		0.0f,	z),
+			Vector3(x,		0.0f,	z),
+			Vector3(-x,		0.0f,	-z),
+			Vector3(x,		0.0f,	-z),
+			Vector3(0.0f,	z,		x),
+			Vector3(0.0f,	z,		-x),
+			Vector3(0.0f,	-z,		x),
+			Vector3(0.0f,	-z,		-x),
+			Vector3(z,		x,		0.0f),
+			Vector3(-z,		x,		0.0f),
+			Vector3(z,		-x,		0.0f),
+			Vector3(-z,		-x,		0.0f)
+		};
+
+		static const UINT32 triangles[20][3] = 
+		{
+				{ 0, 4, 1 },  { 0, 9, 4 },	{ 9, 5, 4 },	{ 4, 5, 8 },
+				{ 4, 8, 1 },  { 8, 10, 1 }, { 8, 3, 10 },	{ 5, 3, 8 },
+				{ 5, 2, 3 },  { 2, 7, 3 },	{ 7, 10, 3 },	{ 7, 6, 10 },
+				{ 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 },	{ 6, 1, 10 },
+				{ 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 },	{ 7, 2, 11 }
+		};
+
+		// Tessellate it
+		UINT32 curVertOffset = vertexOffset;
+		for (int i = 0; i < 20; ++i) 
+		{
+			curVertOffset += subdivideTriangleOnSphere(sphere.getCenter(), sphere.getRadius(), quality,
+				vertices[triangles[i][2]], vertices[triangles[i][1]], vertices[triangles[i][0]],
+				outVertices, outNormals, curVertOffset, vertexStride);
+		}
+
+		// Create indices
+		outIndices += indexOffset;
+
+		UINT32 numIndices = 20 * (3 * (UINT32)std::pow(4, quality));
+		for (UINT32 i = 0; i < numIndices; i += 3)
+		{
+			outIndices[i] = vertexOffset + i + 2;
+			outIndices[i + 1] = vertexOffset + i + 1;
+			outIndices[i + 2] = vertexOffset + i + 0;
+		}
+	}
+
+	void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle, 
+		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
+	{
+		UINT32 numVertices = (quality + 1) * 5;
+
+		generateArcVertices(center, normal, radius, startAngle, amountAngle,
+			numVertices, outVertices, vertexOffset, vertexStride);
+
+		outIndices += indexOffset;
+		UINT32 numLines = numVertices - 1;
+		for (UINT32 i = 0; i < numLines; i++)
+		{
+			outIndices[i * 2 + 0] = vertexOffset + i;
+			outIndices[i * 2 + 1] = vertexOffset + i + 1;
+		}
+	}
+
+	void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle, 
+		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
+	{
+		outVertices += vertexOffset * vertexStride;
+		outNormals += vertexOffset * vertexStride;
+		outIndices += indexOffset;
+
+		bool reverseOrder = amountAngle.valueDegrees() < 0.0f;
+		Vector3 visibleNormal = normal;
+
+		outVertices = writeVector3(outVertices, vertexStride, center);
+		outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
+
+		UINT32 numArcVertices = (quality + 1) * 5;
+		generateArcVertices(center, normal, radius, startAngle, amountAngle,
+			numArcVertices, outVertices, vertexOffset, vertexStride);
+
+		UINT8* otherSideVertices = outVertices + (numArcVertices * vertexStride);
+		UINT8* otherSideNormals = outNormals + (numArcVertices * vertexStride);
+
+		otherSideVertices = writeVector3(otherSideVertices, vertexStride, center);
+		otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
+
+		for (UINT32 i = 0; i < numArcVertices; i++)
+		{
+			otherSideVertices = writeVector3(otherSideVertices, vertexStride, *(Vector3*)outVertices);
+			outVertices += vertexStride;
+
+			outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
+			otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
+		}
+
+		UINT32 numTriangles = numArcVertices - 1;
+
+		// If angle is negative the order of vertices is reversed so we need to reverse the indexes too
+		UINT32 frontSideOffset = vertexOffset + (reverseOrder ? (numArcVertices + 1) : 0);
+		UINT32 backSideOffset = vertexOffset + (!reverseOrder ? (numArcVertices + 1) : 0);
+
+		for (UINT32 i = 0; i < numTriangles; i++)
+		{
+			outIndices[i * 6 + 0] = frontSideOffset + 0;
+			outIndices[i * 6 + 1] = frontSideOffset + i + 1;
+			outIndices[i * 6 + 2] = frontSideOffset + i;
+
+			outIndices[i * 6 + 3] = backSideOffset + 0;
+			outIndices[i * 6 + 4] = backSideOffset + i;
+			outIndices[i * 6 + 5] = backSideOffset + i + 1;
+		}
+	}
+
+	void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
+		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		float fovTan = Math::tan(FOV * 0.5f);
+
+		Vector3 nearPoint(0, 0, near);
+		Vector3 nearWidth(near * fovTan * aspect, 0, 0);
+		Vector3 nearHeight(0, (near * fovTan) / aspect, 0);
+
+		Vector3 farPoint(0, 0, far);
+		Vector3 farWidth(far * fovTan * aspect, 0, 0);
+		Vector3 farHeight(0, (far * fovTan) / aspect, 0);
+
+		Vector3 points[8] = 
+		{
+			nearPoint + nearWidth + nearHeight,
+			nearPoint - nearWidth + nearHeight,
+			nearPoint - nearWidth - nearHeight,
+			nearPoint + nearWidth - nearHeight,
+			farPoint + farWidth + farHeight,
+			farPoint - farWidth + farHeight,
+			farPoint - farWidth - farHeight,
+			farPoint + farWidth - farHeight
+		};
+
+		outVertices += vertexOffset * vertexStride;
+
+		for (UINT32 i = 0; i < 8; i++)
+			outVertices = writeVector3(outVertices, vertexStride, position + points[i]);
+
+		outIndices += indexOffset;
+
+		// Front
+		outIndices[0] = vertexOffset + 0; outIndices[1] = vertexOffset + 1;
+		outIndices[2] = vertexOffset + 1; outIndices[3] = vertexOffset + 2;
+		outIndices[4] = vertexOffset + 2; outIndices[5] = vertexOffset + 3;
+		outIndices[6] = vertexOffset + 3; outIndices[7] = vertexOffset + 0;
+
+		// Center
+		outIndices[8] = vertexOffset + 0; outIndices[9] = vertexOffset + 4;
+		outIndices[10] = vertexOffset + 1; outIndices[11] = vertexOffset + 5;
+		outIndices[12] = vertexOffset + 2; outIndices[13] = vertexOffset + 6;
+		outIndices[14] = vertexOffset + 3; outIndices[15] = vertexOffset + 7;
+
+		// Back
+		outIndices[16] = vertexOffset + 4; outIndices[17] = vertexOffset + 5;
+		outIndices[18] = vertexOffset + 5; outIndices[19] = vertexOffset + 6;
+		outIndices[20] = vertexOffset + 6; outIndices[21] = vertexOffset + 7;
+		outIndices[22] = vertexOffset + 7; outIndices[23] = vertexOffset + 4;
+	}
+
+	void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
+		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
+	{
+		outVertices += vertexOffset * vertexStride;
+		outIndices += indexOffset;
+
+		if (outNormals != nullptr)
+			outNormals += vertexOffset * vertexStride;
+
+		// Generate base disc
+		UINT32 numArcVertices = (quality + 1) * 4;
+
+		generateArcVertices(base, normal, radius, Degree(0), Degree(360),
+			numArcVertices + 1, outVertices, 0, vertexStride);
+
+		outVertices += numArcVertices * vertexStride;
+		outVertices = writeVector3(outVertices, vertexStride, base); // Write base vertex
+
+		UINT32 baseIdx = numArcVertices;
+
+		if (outNormals != nullptr)
+		{
+			UINT32 totalNumBaseVertices = numArcVertices + 1;
+			for (UINT32 i = 0; i < totalNumBaseVertices; i++)
+				outNormals = writeVector3(outNormals, vertexStride, -normal);
+		}
+
+		UINT32 numTriangles = numArcVertices;
+		for (UINT32 i = 0; i < numTriangles - 1; i++)
+		{
+			outIndices[i * 3 + 0] = vertexOffset + baseIdx;
+			outIndices[i * 3 + 1] = vertexOffset + i;
+			outIndices[i * 3 + 2] = vertexOffset + i + 1;
+		}
+
+		{
+			UINT32 i = numTriangles - 1;
+			outIndices[i * 3 + 0] = vertexOffset + baseIdx;
+			outIndices[i * 3 + 1] = vertexOffset + i;
+			outIndices[i * 3 + 2] = vertexOffset + 0;
+		}
+
+		//// Generate cone
+		// Base vertices
+		generateArcVertices(base, normal, radius, Degree(0), Degree(360),
+			numArcVertices + 1, outVertices, 0, vertexStride);
+
+		Vector3 topVertex = base + normal * height;
+
+		// Normals
+		if (outNormals != nullptr)
+		{
+			UINT8* outNormalsBase = outNormals;
+			UINT8* outNormalsTop = outNormals + numArcVertices * vertexStride;
+			for (INT32 i = 0; i < (INT32)numArcVertices; i++)
+			{
+				int offsetA = i == 0 ? numArcVertices - 1 : i - 1;
+				int offsetB = i;
+				int offsetC = (i + 1) % numArcVertices;
+
+				Vector3* a = (Vector3*)(outVertices + (offsetA * vertexStride));
+				Vector3* b = (Vector3*)(outVertices + (offsetB * vertexStride));
+				Vector3* c = (Vector3*)(outVertices + (offsetC * vertexStride));
+
+				Vector3 toTop = topVertex - *b;
+
+				Vector3 normalLeft = Vector3::cross(toTop, *a - *b);
+				normalLeft.normalize();
+
+				Vector3 normalRight = Vector3::cross(*c - *b, toTop);
+				normalRight.normalize();
+
+				Vector3 triNormal = Vector3::normalize(normalLeft + normalRight);
+
+				outNormalsBase = writeVector3(outNormalsBase, vertexStride, triNormal);
+				outNormalsTop = writeVector3(outNormalsTop, vertexStride, triNormal);
+			}
+		}
+
+		// Top vertices (All same position, but need them separate because of different normals)
+		outVertices += numArcVertices * vertexStride;
+
+		for (UINT32 i = 0; i < numArcVertices; i++)
+			outVertices = writeVector3(outVertices, vertexStride, topVertex);
+
+		outIndices += numTriangles * 3;
+		UINT32 curVertBaseOffset = vertexOffset + numArcVertices + 1;
+		UINT32 curVertTopOffset = curVertBaseOffset + numArcVertices;
+		for (UINT32 i = 0; i < numTriangles - 1; i++)
+		{
+			outIndices[i * 3 + 0] = curVertTopOffset + i;
+			outIndices[i * 3 + 1] = curVertBaseOffset + i + 1;
+			outIndices[i * 3 + 2] = curVertBaseOffset + i;
+		}
+
+		{
+			UINT32 i = numTriangles - 1;
+			outIndices[i * 3 + 0] = curVertTopOffset + i;
+			outIndices[i * 3 + 1] = curVertBaseOffset + 0;
+			outIndices[i * 3 + 2] = curVertBaseOffset + i;
+		}
+	}
+
+	void ShapeMeshes3D::solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += (vertexOffset * vertexStride);
+
+		Vector3 topLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
+		Vector3 topRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
+		Vector3 botRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
+		Vector3 botLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
+
+		outVertices = writeVector3(outVertices, vertexStride, topLeft);
+		outVertices = writeVector3(outVertices, vertexStride, topRight);
+		outVertices = writeVector3(outVertices, vertexStride, botRight);
+		outVertices = writeVector3(outVertices, vertexStride, botLeft);
+
+		outVertices = writeVector3(outVertices, vertexStride, topLeft);
+		outVertices = writeVector3(outVertices, vertexStride, topRight);
+		outVertices = writeVector3(outVertices, vertexStride, botRight);
+		outVertices = writeVector3(outVertices, vertexStride, botLeft);
+
+		Vector3 normal = area.getAxisHorz().cross(area.getAxisVert());
+		Vector3 reverseNormal = -normal;
+
+		outNormals += (vertexOffset * vertexStride);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+		outNormals = writeVector3(outNormals, vertexStride, normal);
+
+		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
+		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
+		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
+		outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
+
+		outIndices += indexOffset;
+		outIndices[0] = vertexOffset;
+		outIndices[1] = vertexOffset + 1;
+		outIndices[2] = vertexOffset + 2;
+
+		outIndices[3] = vertexOffset;
+		outIndices[4] = vertexOffset + 2;
+		outIndices[5] = vertexOffset + 3;
+
+		outIndices[6] = vertexOffset + 4;
+		outIndices[7] = vertexOffset + 6;
+		outIndices[8] = vertexOffset + 5;
+
+		outIndices[9] = vertexOffset + 4;
+		outIndices[10] = vertexOffset + 7;
+		outIndices[11] = vertexOffset + 6;
+	}
+
+	Vector3 ShapeMeshes3D::calcCenter(UINT8* vertices, UINT32 numVertices, UINT32 vertexStride)
+	{
+		Vector3 center = Vector3::ZERO;
+		for(UINT32 i = 0; i < numVertices; i++)
+		{
+			Vector3* curVert = (Vector3*)vertices;
+			center += *curVert;
+
+			vertices += vertexStride;
+		}
+
+		center /= (float)numVertices;
+		return center;
+	}
+
+	void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, UINT8* outVertices,
+		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += (vertexOffset * vertexStride);
+
+		Vector3* vertices = (Vector3*)outVertices;
+		(*vertices) = a;
+
+		vertices = (Vector3*)(outVertices + vertexStride);
+		(*vertices) = b;
+
+		outIndices += indexOffset;
+		outIndices[0] = vertexOffset + 0;
+		outIndices[1] = vertexOffset + 1;
+	}
+
+	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
+		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		Vector3 dir = b - a;
+		dir.normalize();
+
+		Vector3 right = dir.cross(up);
+		right.normalize();
+
+		Vector<Vector3> points(4);
+
+		float r = width * 0.5f;
+		dir = dir * r;
+		right = right * r;
+
+		Vector3 v0 = a - dir - right;
+		Vector3 v1 = a - dir + right;
+		Vector3 v2 = b + dir + right;
+		Vector3 v3 = b + dir - right;
+
+		points[0] = v0;
+		points[1] = v1;
+		points[2] = v2;
+		points[3] = v3;
+
+		antialiasedPolygon(points, up, borderWidth, color, outVertices, outColors, vertexOffset, vertexStride, outIndices, indexOffset);
+	}
+
+	void ShapeMeshes3D::pixelSolidPolygon(const Vector<Vector3>& points, UINT8* outVertices,
+		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		outVertices += (vertexOffset * vertexStride);
+
+		for (auto& point : points)
+		{
+			Vector3* vertices = (Vector3*)outVertices;
+			(*vertices) = point;
+
+			outVertices += vertexStride;
+		}
+
+		outIndices += indexOffset;
+		INT32 numPoints = (INT32)points.size();
+		UINT32 idxCnt = 0;
+		for (int i = 2; i < numPoints; i++)
+		{
+			outIndices[idxCnt++] = vertexOffset;
+			outIndices[idxCnt++] = vertexOffset + i - 1;
+			outIndices[idxCnt++] = vertexOffset + i;
+		}
+	}
+
+	void ShapeMeshes3D::pixelWirePolygon(const Vector<Vector3>& points, UINT8* outVertices,
+		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		INT32 numPoints = (INT32)points.size();
+		UINT32 curVertOffset = vertexOffset;
+		UINT32 curIdxOffset = indexOffset;
+		for (INT32 i = 0, j = numPoints - 1; i < numPoints; j = i++)
+		{
+			pixelLine(points[j], points[i], outVertices, curVertOffset, vertexStride, outIndices, curIdxOffset);
+			curVertOffset += 2;
+			curIdxOffset += 2;
+		}
+	}
+
+	void ShapeMeshes3D::antialiasedPolygon(const Vector<Vector3>& points, const Vector3& up, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
+		UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
+	{
+		UINT32 numCoords = (UINT32)points.size();
+
+		outVertices += vertexOffset * vertexStride;
+		outColors += vertexOffset * vertexStride;
+		Vector<Vector3> tempNormals(numCoords);
+
+		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
+		{
+			const Vector3& v0 = points[j];
+			const Vector3& v1 = points[i];
+
+			Vector3 dir = v1 - v0;
+			Vector3 right = dir.cross(up);
+			right.normalize();
+
+			tempNormals[j] = right;
+
+			// Also start populating the vertex array
+			Vector3* vertices = (Vector3*)outVertices;
+			*vertices = v1;
+
+			UINT32* colors = (UINT32*)outColors;
+			*colors = color.getAsRGBA();
+
+			outVertices += vertexStride;
+			outColors += vertexStride;
+		}
+
+		Color transparentColor = color;
+		transparentColor.a = 0.0f;
+
+		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
+		{
+			const Vector3& n0 = tempNormals[j];
+			const Vector3& n1 = tempNormals[i];
+
+			Vector3 avgNrm = (n0 + n1) * 0.5f;
+			float magSqrd = avgNrm.squaredLength();
+
+			if (magSqrd > 0.000001f)
+			{
+				float scale = 1.0f / magSqrd;
+				if (scale > 10.0f)
+					scale = 10.0f;
+
+				avgNrm = avgNrm * scale;
+			}
+
+			Vector3 tempCoord = points[i] + avgNrm * borderWidth;
+
+			// Move it to the vertex array
+			Vector3* vertices = (Vector3*)outVertices;
+			*vertices = tempCoord;
+
+			UINT32* colors = (UINT32*)outColors;
+			*colors = transparentColor.getAsRGBA();
+
+			outVertices += vertexStride;
+			outColors += vertexStride;
+		}
+
+		// Populate index buffer
+		outIndices += indexOffset;
+
+		UINT32 idxCnt = 0;
+		for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
+		{
+			outIndices[idxCnt++] = vertexOffset + i;
+			outIndices[idxCnt++] = vertexOffset + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
+
+			outIndices[idxCnt++] = vertexOffset + numCoords + j;
+			outIndices[idxCnt++] = vertexOffset + numCoords + i;
+			outIndices[idxCnt++] = vertexOffset + i;
+		}
+
+		for (UINT32 i = 2; i < numCoords; ++i)
+		{
+			outIndices[idxCnt++] = vertexOffset + 0;
+			outIndices[idxCnt++] = vertexOffset + i - 1;
+			outIndices[idxCnt++] = vertexOffset + i;
+		}
+	}
+
+	UINT32 ShapeMeshes3D::subdivideTriangleOnSphere(const Vector3& center, float radius, UINT32 numLevels,
+		const Vector3& a, const Vector3& b, const Vector3& c,
+		UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride)
+	{
+		outVertices += (vertexOffset * vertexStride);
+
+		if (outNormals != nullptr)
+			outNormals += (vertexOffset * vertexStride);
+
+		UINT32 numVertices = 0;
+
+		if (numLevels > 0)
+		{
+			Vector3 sub1 = Vector3::normalize((a + b) * 0.5f);
+			Vector3 sub2 = Vector3::normalize((b + c) * 0.5f);
+			Vector3 sub3 = Vector3::normalize((c + a) * 0.5f);
+
+			numLevels--;
+
+			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, a, sub1, sub3, outVertices, 
+				outNormals, numVertices, vertexStride);
+			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, b, sub2, outVertices, 
+				outNormals, numVertices, vertexStride);
+			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, sub2, sub3, outVertices, 
+				outNormals, numVertices, vertexStride);
+			numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub3, sub2, c, outVertices, 
+				outNormals, numVertices, vertexStride);
+		}
+		else
+		{
+			*((Vector3*)outVertices) = center + a * radius;
+			outVertices += vertexStride;
+			
+			*((Vector3*)outVertices) = center + b * radius;
+			outVertices += vertexStride;
+			
+			*((Vector3*)outVertices) = center + c * radius;
+			outVertices += vertexStride;
+
+			if (outNormals != nullptr)
+			{
+				*((Vector3*)outNormals) = a;
+				outNormals += vertexStride;
+
+				*((Vector3*)outNormals) = b;
+				outNormals += vertexStride;
+
+				*((Vector3*)outNormals) = c;
+				outNormals += vertexStride;
+			}
+
+			numVertices += 3;
+		}
+
+		return numVertices;
+	}
+
+	void ShapeMeshes3D::generateArcVertices(const Vector3& center, const Vector3& up, float radius, Degree startAngle, Degree angleAmount, UINT32 numVertices,
+		UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride)
+	{
+		assert(numVertices >= 2);
+		
+		Quaternion alignWithStart = Quaternion(-Vector3::UNIT_Y, startAngle);
+		Quaternion alignWithUp = Quaternion::getRotationFromTo(Vector3::UNIT_Y, up);
+
+		Vector3 right = alignWithUp.rotate(alignWithStart.rotate(Vector3::UNIT_X));
+		right.normalize();
+
+		Quaternion increment(up, angleAmount / (float)(numVertices - 1));
+
+		outVertices += vertexOffset * vertexStride;
+		Vector3 curDirection = right * radius;
+		for (UINT32 i = 0; i < numVertices; i++)
+		{
+			outVertices = writeVector3(outVertices, vertexStride, center + curDirection);
+			curDirection = increment.rotate(curDirection);
+		}
+	}
 }

+ 17 - 6
Source/MBansheeEditor/Inspectors/CapsuleColliderInspector.cs

@@ -11,10 +11,12 @@ namespace BansheeEditor
     public class CapsuleColliderInspector : ColliderInspector
     {
         private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center"));
-        private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
+        private GUIVector3Field orientationField = new GUIVector3Field(new LocEdString("Orientation"));
         private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
         private GUIFloatField halfHeightField = new GUIFloatField(new LocEdString("Half height"));
 
+        private Vector3 orientation;
+
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
@@ -49,9 +51,16 @@ namespace BansheeEditor
             centerField.OnFocusLost += ConfirmModify;
             centerField.OnConfirmed += ConfirmModify;
 
-            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
-            normalField.OnFocusLost += ConfirmModify;
-            normalField.OnConfirmed += ConfirmModify;
+            orientationField.OnChanged += x =>
+            {
+                orientation = x;
+                Quaternion rotation = Quaternion.FromEuler(x);
+
+                collider.Normal = rotation.Rotate(Vector3.YAxis);
+                MarkAsModified();
+            };
+            orientationField.OnFocusLost += ConfirmModify;
+            orientationField.OnConfirmed += ConfirmModify;
 
             radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); };
             radiusField.OnFocusLost += ConfirmModify;
@@ -62,10 +71,12 @@ namespace BansheeEditor
             halfHeightField.OnConfirmed += ConfirmModify;
 
             Layout.AddElement(centerField);
-            Layout.AddElement(normalField);
+            Layout.AddElement(orientationField);
             Layout.AddElement(radiusField);
             Layout.AddElement(halfHeightField);
 
+            orientation = Quaternion.FromToRotation(Vector3.YAxis, collider.Normal).ToEuler();
+
             base.BuildGUI(collider);
         }
 
@@ -76,7 +87,7 @@ namespace BansheeEditor
         protected void Refresh(CapsuleCollider collider)
         {
             centerField.Value = collider.Center;
-            normalField.Value = collider.Normal;
+            orientationField.Value = orientation;
             radiusField.Value = collider.Radius;
             halfHeightField.Value = collider.HalfHeight;
 

+ 177 - 166
Source/MBansheeEditor/Inspectors/CharacterControllerInspector.cs

@@ -1,167 +1,178 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="CharacterController"/> component.
-    /// </summary>
-    [CustomInspector(typeof(CharacterController))]
-    internal class CharacterControllerInspector : Inspector
-    {
-        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
-        private GUIFloatField heightField = new GUIFloatField(new LocEdString("Height"));
-        private GUIVector3Field upField = new GUIVector3Field(new LocEdString("Up"));
-        private GUIFloatField contactOffsetField = new GUIFloatField(new LocEdString("Contact offset"));
-        private GUIFloatField minMoveDistanceField = new GUIFloatField(new LocEdString("Min. move distance"));
-
-        private GUIEnumField climbingModeField = new GUIEnumField(typeof (CharacterClimbingMode),
-            new LocEdString("Climbing mode"));
-        private GUIFloatField stepOffsetField = new GUIFloatField(new LocEdString("Step offset"));
-        
-        private GUIEnumField nonWalkableModeField = new GUIEnumField(typeof (CharacterNonWalkableMode),
-            new LocEdString("Non-walkable mode"));
-        private GUISliderField slopeLimitField = new GUISliderField(0, 180, new LocEdString("Slope limit"));
-
-        private GUIListBoxField layerField = new GUIListBoxField(Layers.Names, false, new LocEdString("Layer"));
-
-        private ulong layersValue = 0;
-        private InspectableState modifyState;
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            BuildGUI();
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            CharacterController controller = InspectedObject as CharacterController;
-            if (controller == null)
-                return InspectableState.NotModified;
-
-            radiusField.Value = controller.Radius;
-            heightField.Value = controller.Height;
-            upField.Value = controller.Up;
-            contactOffsetField.Value = controller.ContactOffset;
-            minMoveDistanceField.Value = controller.MinMoveDistance;
-            climbingModeField.Value = (ulong)controller.ClimbingMode;
-            stepOffsetField.Value = controller.StepOffset;
-            nonWalkableModeField.Value = (ulong)controller.NonWalkableMode;
-            slopeLimitField.Value = controller.SlopeLimit.Degrees;
-
-            if (layersValue != controller.Layer)
-            {
-                bool[] states = new bool[64];
-                for (int i = 0; i < states.Length; i++)
-                    states[i] = (controller.Layer & Layers.Values[i]) == Layers.Values[i];
-
-                layerField.States = states;
-                layersValue = controller.Layer;
-            }
-
-            InspectableState oldState = modifyState;
-            if (modifyState.HasFlag(InspectableState.Modified))
-                modifyState = InspectableState.NotModified;
-
-            return oldState;
-        }
-
-        /// <summary>
-        /// Recreates all the GUI elements used by this inspector.
-        /// </summary>
-        private void BuildGUI()
-        {
-            CharacterController controller = InspectedObject as CharacterController;
-            if (controller == null)
-                return;
-
-            radiusField.OnChanged += x => { controller.Radius = x; MarkAsModified(); };
-            radiusField.OnConfirmed += ConfirmModify;
-            radiusField.OnFocusLost += ConfirmModify;
-
-            heightField.OnChanged += x => { controller.Height = x; MarkAsModified(); };
-            heightField.OnConfirmed += ConfirmModify;
-            heightField.OnFocusLost += ConfirmModify;
-
-            upField.OnChanged += x => { controller.Up = x; MarkAsModified(); };
-            upField.OnConfirmed += ConfirmModify;
-            upField.OnFocusLost += ConfirmModify;
-
-            contactOffsetField.OnChanged += x => { controller.ContactOffset = x; MarkAsModified(); };
-            contactOffsetField.OnConfirmed += ConfirmModify;
-            contactOffsetField.OnFocusLost += ConfirmModify;
-
-            minMoveDistanceField.OnChanged += x => { controller.MinMoveDistance = x; MarkAsModified(); };
-            minMoveDistanceField.OnConfirmed += ConfirmModify;
-            minMoveDistanceField.OnFocusLost += ConfirmModify;
-
-            climbingModeField.OnSelectionChanged += x =>
-            {
-                controller.ClimbingMode = (CharacterClimbingMode)x;
-
-                MarkAsModified();
-                ConfirmModify();
-            };
-
-            stepOffsetField.OnChanged += x => { controller.StepOffset = x; MarkAsModified(); };
-            stepOffsetField.OnConfirmed += ConfirmModify;
-            stepOffsetField.OnFocusLost += ConfirmModify;
-
-            nonWalkableModeField.OnSelectionChanged += x =>
-            {
-                controller.NonWalkableMode = (CharacterNonWalkableMode)x;
-
-                MarkAsModified();
-                ConfirmModify();
-            };
-
-            slopeLimitField.OnChanged += x => { controller.SlopeLimit = new Degree(x); MarkAsModified(); };
-            slopeLimitField.OnFocusLost += ConfirmModify;
-
-            layerField.OnSelectionChanged += x =>
-            {
-                ulong layer = 0;
-                bool[] states = layerField.States;
-                for (int i = 0; i < states.Length; i++)
-                    layer |= states[i] ? Layers.Values[i] : 0;
-
-                layersValue = layer;
-                controller.Layer = layer;
-
-                MarkAsModified();
-                ConfirmModify();
-            };
-
-            Layout.AddElement(radiusField);
-            Layout.AddElement(heightField);
-            Layout.AddElement(upField);
-            Layout.AddElement(contactOffsetField);
-            Layout.AddElement(minMoveDistanceField);
-            Layout.AddElement(climbingModeField);
-            Layout.AddElement(stepOffsetField);
-            Layout.AddElement(nonWalkableModeField);
-            Layout.AddElement(slopeLimitField);
-            Layout.AddElement(layerField);
-        }
-
-        /// <summary>
-        /// Marks the contents of the inspector as modified.
-        /// </summary>
-        protected void MarkAsModified()
-        {
-            modifyState |= InspectableState.ModifyInProgress;
-        }
-
-        /// <summary>
-        /// Confirms any queued modifications.
-        /// </summary>
-        protected void ConfirmModify()
-        {
-            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
-                modifyState |= InspectableState.Modified;
-        }
-    }
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="CharacterController"/> component.
+    /// </summary>
+    [CustomInspector(typeof(CharacterController))]
+    internal class CharacterControllerInspector : Inspector
+    {
+        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
+        private GUIFloatField heightField = new GUIFloatField(new LocEdString("Height"));
+        private GUIVector3Field orientationField = new GUIVector3Field(new LocEdString("Orientation"));
+        private GUIFloatField contactOffsetField = new GUIFloatField(new LocEdString("Contact offset"));
+        private GUIFloatField minMoveDistanceField = new GUIFloatField(new LocEdString("Min. move distance"));
+
+        private GUIEnumField climbingModeField = new GUIEnumField(typeof (CharacterClimbingMode),
+            new LocEdString("Climbing mode"));
+        private GUIFloatField stepOffsetField = new GUIFloatField(new LocEdString("Step offset"));
+        
+        private GUIEnumField nonWalkableModeField = new GUIEnumField(typeof (CharacterNonWalkableMode),
+            new LocEdString("Non-walkable mode"));
+        private GUISliderField slopeLimitField = new GUISliderField(0, 180, new LocEdString("Slope limit"));
+
+        private GUIListBoxField layerField = new GUIListBoxField(Layers.Names, false, new LocEdString("Layer"));
+
+        private ulong layersValue = 0;
+        private InspectableState modifyState;
+
+        private Vector3 orientation;
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BuildGUI();
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            CharacterController controller = InspectedObject as CharacterController;
+            if (controller == null)
+                return InspectableState.NotModified;
+
+            radiusField.Value = controller.Radius;
+            heightField.Value = controller.Height;
+            orientationField.Value = orientation;
+            contactOffsetField.Value = controller.ContactOffset;
+            minMoveDistanceField.Value = controller.MinMoveDistance;
+            climbingModeField.Value = (ulong)controller.ClimbingMode;
+            stepOffsetField.Value = controller.StepOffset;
+            nonWalkableModeField.Value = (ulong)controller.NonWalkableMode;
+            slopeLimitField.Value = controller.SlopeLimit.Degrees;
+
+            if (layersValue != controller.Layer)
+            {
+                bool[] states = new bool[64];
+                for (int i = 0; i < states.Length; i++)
+                    states[i] = (controller.Layer & Layers.Values[i]) == Layers.Values[i];
+
+                layerField.States = states;
+                layersValue = controller.Layer;
+            }
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            CharacterController controller = InspectedObject as CharacterController;
+            if (controller == null)
+                return;
+
+            radiusField.OnChanged += x => { controller.Radius = x; MarkAsModified(); };
+            radiusField.OnConfirmed += ConfirmModify;
+            radiusField.OnFocusLost += ConfirmModify;
+
+            heightField.OnChanged += x => { controller.Height = x; MarkAsModified(); };
+            heightField.OnConfirmed += ConfirmModify;
+            heightField.OnFocusLost += ConfirmModify;
+
+            orientationField.OnChanged += x =>
+            {
+                orientation = x;
+                Quaternion rotation = Quaternion.FromEuler(x);
+
+                controller.Up = rotation.Rotate(Vector3.YAxis);
+                MarkAsModified();
+            };
+            orientationField.OnConfirmed += ConfirmModify;
+            orientationField.OnFocusLost += ConfirmModify;
+
+            contactOffsetField.OnChanged += x => { controller.ContactOffset = x; MarkAsModified(); };
+            contactOffsetField.OnConfirmed += ConfirmModify;
+            contactOffsetField.OnFocusLost += ConfirmModify;
+
+            minMoveDistanceField.OnChanged += x => { controller.MinMoveDistance = x; MarkAsModified(); };
+            minMoveDistanceField.OnConfirmed += ConfirmModify;
+            minMoveDistanceField.OnFocusLost += ConfirmModify;
+
+            climbingModeField.OnSelectionChanged += x =>
+            {
+                controller.ClimbingMode = (CharacterClimbingMode)x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            stepOffsetField.OnChanged += x => { controller.StepOffset = x; MarkAsModified(); };
+            stepOffsetField.OnConfirmed += ConfirmModify;
+            stepOffsetField.OnFocusLost += ConfirmModify;
+
+            nonWalkableModeField.OnSelectionChanged += x =>
+            {
+                controller.NonWalkableMode = (CharacterNonWalkableMode)x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            slopeLimitField.OnChanged += x => { controller.SlopeLimit = new Degree(x); MarkAsModified(); };
+            slopeLimitField.OnFocusLost += ConfirmModify;
+
+            layerField.OnSelectionChanged += x =>
+            {
+                ulong layer = 0;
+                bool[] states = layerField.States;
+                for (int i = 0; i < states.Length; i++)
+                    layer |= states[i] ? Layers.Values[i] : 0;
+
+                layersValue = layer;
+                controller.Layer = layer;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            Layout.AddElement(radiusField);
+            Layout.AddElement(heightField);
+            Layout.AddElement(orientationField);
+            Layout.AddElement(contactOffsetField);
+            Layout.AddElement(minMoveDistanceField);
+            Layout.AddElement(climbingModeField);
+            Layout.AddElement(stepOffsetField);
+            Layout.AddElement(nonWalkableModeField);
+            Layout.AddElement(slopeLimitField);
+            Layout.AddElement(layerField);
+
+            orientation = Quaternion.FromToRotation(Vector3.YAxis, controller.Up).ToEuler();
+        }
+
+        /// <summary>
+        /// Marks the contents of the inspector as modified.
+        /// </summary>
+        protected void MarkAsModified()
+        {
+            modifyState |= InspectableState.ModifyInProgress;
+        }
+
+        /// <summary>
+        /// Confirms any queued modifications.
+        /// </summary>
+        protected void ConfirmModify()
+        {
+            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
+                modifyState |= InspectableState.Modified;
+        }
+    }
 }

+ 12 - 2
Source/MBansheeEditor/Inspectors/PlaneColliderInspector.cs

@@ -13,6 +13,8 @@ namespace BansheeEditor
         private GUIVector3Field normalField = new GUIVector3Field(new LocEdString("Normal"));
         private GUIFloatField distanceField = new GUIFloatField(new LocEdString("Distance"));
 
+        private Vector3 normal;
+
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
@@ -43,7 +45,13 @@ namespace BansheeEditor
         /// </summary>
         protected void BuildGUI(PlaneCollider collider)
         {
-            normalField.OnChanged += x => { collider.Normal = x; MarkAsModified(); };
+            normalField.OnChanged += x =>
+            {
+                normal = x;
+                collider.Normal = x;
+
+                MarkAsModified();
+            };
             normalField.OnFocusLost += ConfirmModify;
             normalField.OnConfirmed += ConfirmModify;
 
@@ -54,6 +62,8 @@ namespace BansheeEditor
             Layout.AddElement(normalField);
             Layout.AddElement(distanceField);
 
+            normal = collider.Normal;
+
             base.BuildGUI(collider);
         }
 
@@ -63,7 +73,7 @@ namespace BansheeEditor
         /// <param name="collider">Collider to update the GUI from.</param>
         protected void Refresh(PlaneCollider collider)
         {
-            normalField.Value = collider.Normal;
+            normalField.Value = normal;
             distanceField.Value = collider.Distance;
 
             base.Refresh(collider);

+ 35 - 30
Source/MBansheeEditor/Scene/Gizmos/CharacterControllerGizmo.cs

@@ -1,30 +1,35 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Handles drawing of gizmos for the <see cref="CharacterController"/> component.
-    /// </summary>
-    internal class CharacterControllerGizmo
-    {
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="controller">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected)]
-        private static void Draw(CharacterController controller)
-        {
-            SceneObject so = controller.SceneObject;
-
-            Vector3 offset = so.Position;
-            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, controller.Up);
-            Gizmos.Transform = Matrix4.TRS(-offset, rotation, Vector3.One);
-
-            Gizmos.Color = Color.Green;
-
-            Gizmos.DrawWireCapsule(offset, controller.Height, controller.Radius);
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Handles drawing of gizmos for the <see cref="CharacterController"/> component.
+    /// </summary>
+    internal class CharacterControllerGizmo
+    {
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="controller">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected)]
+        private static void Draw(CharacterController controller)
+        {
+            SceneObject so = controller.SceneObject;
+
+            Vector3 offset = so.Position;
+            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, controller.Up);
+
+            // Rotate around origin
+            Matrix4 rotMatrix = Matrix4.TRS(offset, Quaternion.Identity, Vector3.One) *
+                Matrix4.TRS(Vector3.Zero, rotation, Vector3.One) *
+                Matrix4.TRS(-offset, Quaternion.Identity, Vector3.One);
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform * rotMatrix;
+
+            Gizmos.DrawWireCapsule(offset, controller.Height, controller.Radius);
+        }
+    }
+}

+ 154 - 149
Source/MBansheeEditor/Scene/Gizmos/ColliderGizmos.cs

@@ -1,149 +1,154 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Handles drawing of gizmos for all the types of <see cref="Collider"/> component.
-    /// </summary>
-    internal class ColliderGizmos
-    {
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="collider">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
-        private static void DrawBoxCollider(BoxCollider collider)
-        {
-            SceneObject so = collider.SceneObject;
-
-            Gizmos.Color = Color.Green;
-            Vector3 scaledExtents = collider.Extents*so.Scale;
-
-            Gizmos.DrawWireCube(so.WorldTransform.MultiplyAffine(collider.Center), scaledExtents);
-        }
-
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="collider">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
-        private static void DrawSphereCollider(SphereCollider collider)
-        {
-            SceneObject so = collider.SceneObject;
-
-            Gizmos.Color = Color.Green;
-
-            Vector3 scale = so.Scale;
-            float scaledRadius = collider.Radius * MathEx.Max(scale.x, scale.y, scale.z);
-
-            Gizmos.DrawWireSphere(so.WorldTransform.MultiplyAffine(collider.Center), scaledRadius);
-        }
-
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="collider">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
-        private static void DrawCapsuleCollider(CapsuleCollider collider)
-        {
-            SceneObject so = collider.SceneObject;
-
-            Vector3 offset = so.WorldTransform.MultiplyAffine(collider.Center);
-            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, collider.Normal);
-            Gizmos.Transform = Matrix4.TRS(-offset, rotation, Vector3.One);
-
-            Gizmos.Color = Color.Green;
-
-            Vector3 scale = so.Scale;
-            float scaledHeight = collider.HalfHeight*2.0f*scale.y;
-            float scaledRadius = collider.Radius*MathEx.Max(scale.x, scale.z);
-
-            Gizmos.DrawWireCapsule(offset, scaledHeight, scaledRadius);
-        }
-
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="collider">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
-        private static void DrawMeshCollider(MeshCollider collider)
-        {
-            PhysicsMesh mesh = collider.Mesh;
-            if (mesh == null)
-                return;
-
-            SceneObject so = collider.SceneObject;
-
-            Gizmos.Transform = so.WorldTransform;
-            Gizmos.Color = Color.Green;
-
-            MeshData meshData = mesh.MeshData;
-
-            int numTriangles = meshData.IndexCount/3;
-            int[] indices = meshData.Indices;
-            Vector3[] vertices = meshData.Positions;
-            Vector3[] linePoints = new Vector3[numTriangles*6];
-
-            for (int i = 0; i < numTriangles; i++)
-            {
-                int lineIdx = i*6;
-
-                linePoints[lineIdx + 0] = vertices[indices[i * 3 + 0]];
-                linePoints[lineIdx + 1] = vertices[indices[i * 3 + 1]];
-
-                linePoints[lineIdx + 2] = vertices[indices[i * 3 + 1]];
-                linePoints[lineIdx + 3] = vertices[indices[i * 3 + 2]];
-
-                linePoints[lineIdx + 4] = vertices[indices[i * 3 + 2]];
-                linePoints[lineIdx + 5] = vertices[indices[i * 3 + 0]];
-            }
-
-            Gizmos.DrawLineList(linePoints);
-        }
-
-        /// <summary>
-        /// Method called by the runtime when gizmos are meant to be drawn.
-        /// </summary>
-        /// <param name="collider">Collider to draw gizmos for.</param>
-        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
-        private static void DrawPlaneCollider(PlaneCollider collider)
-        {
-            SceneObject so = collider.SceneObject;
-
-            Gizmos.Color = Color.Green;
-
-            Vector3 localNormal = collider.Normal;
-            Vector3 localCenter = localNormal * collider.Distance;
-
-            Vector3 bottomLeft = new Vector3(0.0f, -0.5f, -0.5f);
-            Vector3 topLeft = new Vector3(0.0f, 0.5f, -0.5f);
-            Vector3 topRight = new Vector3(0.0f, 0.5f, 0.5f);
-            Vector3 bottomRight = new Vector3(0.0f, -0.5f, 0.5f);
-
-            bottomLeft += localCenter;
-            topLeft += localCenter;
-            topRight += localCenter;
-            bottomRight += localCenter;
-
-            bottomLeft = so.WorldTransform.MultiplyAffine(bottomLeft);
-            topLeft = so.WorldTransform.MultiplyAffine(topLeft);
-            topRight = so.WorldTransform.MultiplyAffine(topRight);
-            bottomRight = so.WorldTransform.MultiplyAffine(bottomRight);
-
-            Vector3 center = so.WorldTransform.MultiplyAffine(localCenter);
-            Vector3 normal = localNormal;
-            normal = so.WorldTransform.MultiplyDirection(normal);
-
-            // Draw sides
-            Gizmos.DrawLine(bottomLeft, topLeft);
-            Gizmos.DrawLine(topLeft, topRight);
-            Gizmos.DrawLine(topRight, bottomRight);
-            Gizmos.DrawLine(bottomRight, bottomLeft);
-
-            // Draw normal
-            Gizmos.DrawLine(center, center + normal*0.5f);
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Handles drawing of gizmos for all the types of <see cref="Collider"/> component.
+    /// </summary>
+    internal class ColliderGizmos
+    {
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawBoxCollider(BoxCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform;
+
+            Vector3 scaledExtents = collider.Extents*so.Scale;
+            Gizmos.DrawWireCube(so.WorldTransform.MultiplyAffine(collider.Center), scaledExtents);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawSphereCollider(SphereCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform;
+
+            Vector3 scale = so.Scale;
+            float scaledRadius = collider.Radius * MathEx.Max(scale.x, scale.y, scale.z);
+
+            Gizmos.DrawWireSphere(so.WorldTransform.MultiplyAffine(collider.Center), scaledRadius);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawCapsuleCollider(CapsuleCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Vector3 offset = collider.Center;
+            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, collider.Normal);
+
+            // Rotate around origin
+            Matrix4 rotMatrix = Matrix4.TRS(offset, Quaternion.Identity, Vector3.One) * 
+                Matrix4.TRS(Vector3.Zero, rotation, Vector3.One) * 
+                Matrix4.TRS(-offset, Quaternion.Identity, Vector3.One);
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform * rotMatrix;
+
+            Vector3 scale = so.Scale;
+            float scaledHeight = collider.HalfHeight*2.0f*scale.y;
+            float scaledRadius = collider.Radius*MathEx.Max(scale.x, scale.z);
+
+            Gizmos.DrawWireCapsule(offset, scaledHeight, scaledRadius);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawMeshCollider(MeshCollider collider)
+        {
+            PhysicsMesh mesh = collider.Mesh;
+            if (mesh == null)
+                return;
+
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform;
+
+            MeshData meshData = mesh.MeshData;
+
+            int numTriangles = meshData.IndexCount/3;
+            int[] indices = meshData.Indices;
+            Vector3[] vertices = meshData.Positions;
+            Vector3[] linePoints = new Vector3[numTriangles*6];
+
+            for (int i = 0; i < numTriangles; i++)
+            {
+                int lineIdx = i*6;
+
+                linePoints[lineIdx + 0] = vertices[indices[i * 3 + 0]];
+                linePoints[lineIdx + 1] = vertices[indices[i * 3 + 1]];
+
+                linePoints[lineIdx + 2] = vertices[indices[i * 3 + 1]];
+                linePoints[lineIdx + 3] = vertices[indices[i * 3 + 2]];
+
+                linePoints[lineIdx + 4] = vertices[indices[i * 3 + 2]];
+                linePoints[lineIdx + 5] = vertices[indices[i * 3 + 0]];
+            }
+
+            Gizmos.DrawLineList(linePoints);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawPlaneCollider(PlaneCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Vector3 normal = collider.Normal;
+            Vector3 center = normal * collider.Distance;
+
+            // Rotate around origin
+            Quaternion rotation = Quaternion.FromToRotation(Vector3.XAxis, normal);
+            Matrix4 rotMatrix = Matrix4.TRS(center, Quaternion.Identity, Vector3.One) *
+                Matrix4.TRS(Vector3.Zero, rotation, Vector3.One) *
+                Matrix4.TRS(-center, Quaternion.Identity, Vector3.One);
+
+            Gizmos.Color = Color.Green;
+            Gizmos.Transform = so.WorldTransform * rotMatrix;
+
+            Vector3 bottomLeft = new Vector3(0.0f, -0.5f, -0.5f);
+            Vector3 topLeft = new Vector3(0.0f, 0.5f, -0.5f);
+            Vector3 topRight = new Vector3(0.0f, 0.5f, 0.5f);
+            Vector3 bottomRight = new Vector3(0.0f, -0.5f, 0.5f);
+
+            bottomLeft += center;
+            topLeft += center;
+            topRight += center;
+            bottomRight += center;
+
+            // Draw sides
+            Gizmos.DrawLine(bottomLeft, topLeft);
+            Gizmos.DrawLine(topLeft, topRight);
+            Gizmos.DrawLine(topRight, bottomRight);
+            Gizmos.DrawLine(bottomRight, bottomLeft);
+
+            // Draw normal
+            Gizmos.DrawLine(center, center + Vector3.XAxis*0.5f);
+        }
+    }
+}

+ 247 - 247
Source/MBansheeEditor/Scene/RotateHandle.cs

@@ -1,247 +1,247 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Handle that allows an object to be rotated around the three primary axes, as well as a free axis currently
-    /// facing the camera.
-    /// </summary>
-    public sealed class RotateHandle : DefaultHandle
-    {
-        private Quaternion delta;
-
-        private HandleSliderDisc xAxis;
-        private HandleSliderDisc yAxis;
-        private HandleSliderDisc zAxis;
-
-        private HandleSliderDisc freeAxis;
-
-        private bool isDragged;
-        private Quaternion dragStartRotation;
-
-        /// <summary>
-        /// Amount of rotation applied since the last frame. Only valid while the handle is being dragged.
-        /// </summary>
-        public Quaternion Delta
-        {
-            get { return delta; }
-        }
-
-        /// <inheritdoc/>
-        internal override bool IsDragged()
-        {
-            return xAxis.State == HandleSlider.StateType.Active ||
-                    yAxis.State == HandleSlider.StateType.Active ||
-                    zAxis.State == HandleSlider.StateType.Active ||
-                    freeAxis.State == HandleSlider.StateType.Active;
-        }
-
-        /// <summary>
-        /// Creates a new rotation handle.
-        /// </summary>
-        public RotateHandle()
-        {
-            xAxis = new HandleSliderDisc(this, Vector3.XAxis, 1.0f);
-            yAxis = new HandleSliderDisc(this, Vector3.YAxis, 1.0f);
-            zAxis = new HandleSliderDisc(this, Vector3.ZAxis, 1.0f);
-            freeAxis = new HandleSliderDisc(this, -Vector3.ZAxis, 1.2f);
-        }
-
-        /// <inheritdoc/>
-        protected internal override void PreInput()
-        {
-            xAxis.Position = position;
-            yAxis.Position = position;
-            zAxis.Position = position;
-            freeAxis.Position = position;
-
-            Quaternion handleRotation = isDragged ? dragStartRotation : Rotation;
-            xAxis.Rotation = handleRotation;
-            yAxis.Rotation = handleRotation;
-            zAxis.Rotation = handleRotation;
-            freeAxis.Rotation = EditorApplication.SceneViewCamera.SceneObject.Rotation;
-
-            xAxis.SetCutoffPlane(GetXStartAngle(isDragged), true);
-            yAxis.SetCutoffPlane(GetYStartAngle(isDragged), true);
-            zAxis.SetCutoffPlane(GetZStartAngle(isDragged), true);
-        }
-
-        /// <inheritdoc/>
-        protected internal override void PostInput()
-        {
-            if (IsDragged())
-            {
-                if (!isDragged)
-                {
-                    isDragged = true;
-                    dragStartRotation = Rotation;
-                }
-            }
-            else
-            {
-                isDragged = false;
-                dragStartRotation = Quaternion.Identity;
-            }
-
-            Degree xValue = (Degree)0.0f;
-            Degree yValue = (Degree)0.0f;
-            Degree zValue = (Degree)0.0f;
-            Degree freeAxisValue = (Degree)0.0f;
-
-            if (Handles.RotateHandleSnapActive)
-            {
-                xValue = Handles.SnapValue(xAxis.Delta, Handles.RotateSnapAmount);
-                yValue = Handles.SnapValue(yAxis.Delta, Handles.RotateSnapAmount);
-                zValue = Handles.SnapValue(zAxis.Delta, Handles.RotateSnapAmount);
-                freeAxisValue = Handles.SnapValue(freeAxis.Delta, Handles.RotateSnapAmount);
-            }
-            else
-            {
-                xValue = xAxis.Delta;
-                yValue = yAxis.Delta;
-                zValue = zAxis.Delta;
-                freeAxisValue = freeAxis.Delta;
-            }
-
-            Vector3 cameraForward = -(dragStartRotation.Inverse * EditorApplication.SceneViewCamera.SceneObject.Rotation).Forward;
-
-            delta = Quaternion.FromEuler(xValue, yValue, zValue);
-            delta *= Quaternion.FromAxisAngle(cameraForward, freeAxisValue);
-        }
-
-        /// <inheritdoc/>
-        protected internal override void Draw()
-        {
-            HandleDrawing.Layer = 1;
-            HandleDrawing.Transform = Matrix4.TRS(Position, Rotation, Vector3.One);
-            float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
-
-            // Draw arcs
-            if (xAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.Color = Color.White;
-            else if(xAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.Color = Color.BansheeOrange;
-            else
-                HandleDrawing.Color = Color.Red;
-
-            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.XAxis, 1.0f, GetXStartAngle(false), new Degree(-180.0f), handleSize);
-
-            if (yAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.Color = Color.White;
-            else if (yAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.Color = Color.BansheeOrange;
-            else
-                HandleDrawing.Color = Color.Green;
-
-            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.YAxis, 1.0f, GetYStartAngle(false), new Degree(-180.0f), handleSize);
-
-            if (zAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.Color = Color.White;
-            else if (zAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.Color = Color.BansheeOrange;
-            else
-                HandleDrawing.Color = Color.Blue;
-
-            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 1.0f, GetZStartAngle(false), new Degree(-180.0f), handleSize);
-
-            // Draw "bounds" and free handle
-            Color gray = new Color(1.0f, 1.0f, 1.0f, 0.3f);
-            Vector3 cameraNormal = EditorApplication.SceneViewCamera.SceneObject.Rotation.Rotate(Vector3.ZAxis);
-            HandleDrawing.Transform = Matrix4.TRS(Position, Quaternion.Identity, Vector3.One);
-            HandleDrawing.Color = gray;
-
-            HandleDrawing.DrawWireDisc(cameraNormal * 0.1f, cameraNormal, 1.0f, handleSize);
-
-            if (freeAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.Color = Color.White;
-            else if (freeAxis.State == HandleSlider.StateType.Hover)
-                HandleDrawing.Color = Color.BansheeOrange;
-            else
-                HandleDrawing.Color = gray;
-
-            HandleDrawing.DrawWireDisc(Vector3.Zero, cameraNormal, 1.2f, handleSize);
-
-            // Draw active rotation pie
-            HandleDrawing.Color = gray;
-            HandleDrawing.Transform = Matrix4.TRS(Position, EditorApplication.SceneViewCamera.SceneObject.Rotation, Vector3.One);
-
-            if (freeAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.DrawArc(Vector3.Zero, -Vector3.ZAxis, 1.2f, freeAxis.StartAngle, freeAxis.Delta, handleSize);
-
-            HandleDrawing.Transform = Matrix4.TRS(Position, dragStartRotation, Vector3.One);
-
-            if (xAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.DrawArc(Vector3.Zero, Vector3.XAxis, 1.0f, xAxis.StartAngle, xAxis.Delta, handleSize);
-            else if (yAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.DrawArc(Vector3.Zero, Vector3.YAxis, 1.0f, yAxis.StartAngle, yAxis.Delta, handleSize);
-            else if (zAxis.State == HandleSlider.StateType.Active)
-                HandleDrawing.DrawArc(Vector3.Zero, Vector3.ZAxis, 1.0f, zAxis.StartAngle, zAxis.Delta, handleSize);
-        }
-
-        /// <summary>
-        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
-        /// the arc starts for the X axis.
-        /// </summary>
-        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
-        ///                      to the value when handle drag started. This is useful because we do not want the visible
-        ///                      arc to change while the user is in the process of rotating the handle.</param>
-        /// <returns>Angle at which to display the visible arc for the X axis rotations.</returns>
-        private Degree GetXStartAngle(bool frozen)
-        {
-            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
-
-            Vector3 xStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.XAxis);
-            return PointOnCircleToAngle(Vector3.XAxis, xStartDir);
-        }
-
-        /// <summary>
-        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
-        /// the arc starts for the Y axis.
-        /// </summary>
-        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
-        ///                      to the value when handle drag started. This is useful because we do not want the visible
-        ///                      arc to change while the user is in the process of rotating the handle.</param>
-        /// <returns>Angle at which to display the visible arc for the Y axis rotations.</returns>
-        private Degree GetYStartAngle(bool frozen)
-        {
-            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
-
-            Vector3 yStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.YAxis);
-            return PointOnCircleToAngle(Vector3.YAxis, yStartDir);
-        }
-
-        /// <summary>
-        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
-        /// the arc starts for the Z axis.
-        /// </summary>
-        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
-        ///                      to the value when handle drag started. This is useful because we do not want the visible
-        ///                      arc to change while the user is in the process of rotating the handle.</param>
-        /// <returns>Angle at which to display the visible arc for the Z axis rotations.</returns>
-        private Degree GetZStartAngle(bool frozen)
-        {
-            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
-
-            Vector3 zStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.ZAxis);
-            return PointOnCircleToAngle(Vector3.ZAxis, zStartDir);
-        }
-
-        /// <summary>
-        /// Converts a point on the circle to an angle on the circle.
-        /// </summary>
-        /// <param name="up">Up vector determining the orientation of the circle.</param>
-        /// <param name="point">Point along a unit circle centered around the origin.</param>
-        /// <returns>Angle at which the provided point is located on the circle.</returns>
-        private Degree PointOnCircleToAngle(Vector3 up, Vector3 point)
-        {
-            Quaternion rot = Quaternion.FromToRotation(up, Vector3.YAxis);
-
-            Matrix4 worldToPlane = Matrix4.TRS(Vector3.Zero, rot, Vector3.One);
-            point = worldToPlane.MultiplyDirection(point);
-
-            return (MathEx.Atan2(-point.z, -point.x) + MathEx.Pi) * MathEx.Rad2Deg;
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Handle that allows an object to be rotated around the three primary axes, as well as a free axis currently
+    /// facing the camera.
+    /// </summary>
+    public sealed class RotateHandle : DefaultHandle
+    {
+        private Quaternion delta;
+
+        private HandleSliderDisc xAxis;
+        private HandleSliderDisc yAxis;
+        private HandleSliderDisc zAxis;
+
+        private HandleSliderDisc freeAxis;
+
+        private bool isDragged;
+        private Quaternion dragStartRotation;
+
+        /// <summary>
+        /// Amount of rotation applied since the last frame. Only valid while the handle is being dragged.
+        /// </summary>
+        public Quaternion Delta
+        {
+            get { return delta; }
+        }
+
+        /// <inheritdoc/>
+        internal override bool IsDragged()
+        {
+            return xAxis.State == HandleSlider.StateType.Active ||
+                    yAxis.State == HandleSlider.StateType.Active ||
+                    zAxis.State == HandleSlider.StateType.Active ||
+                    freeAxis.State == HandleSlider.StateType.Active;
+        }
+
+        /// <summary>
+        /// Creates a new rotation handle.
+        /// </summary>
+        public RotateHandle()
+        {
+            xAxis = new HandleSliderDisc(this, Vector3.XAxis, 1.0f);
+            yAxis = new HandleSliderDisc(this, Vector3.YAxis, 1.0f);
+            zAxis = new HandleSliderDisc(this, Vector3.ZAxis, 1.0f);
+            freeAxis = new HandleSliderDisc(this, -Vector3.ZAxis, 1.2f);
+        }
+
+        /// <inheritdoc/>
+        protected internal override void PreInput()
+        {
+            xAxis.Position = position;
+            yAxis.Position = position;
+            zAxis.Position = position;
+            freeAxis.Position = position;
+
+            Quaternion handleRotation = isDragged ? dragStartRotation : Rotation;
+            xAxis.Rotation = handleRotation;
+            yAxis.Rotation = handleRotation;
+            zAxis.Rotation = handleRotation;
+            freeAxis.Rotation = EditorApplication.SceneViewCamera.SceneObject.Rotation;
+
+            xAxis.SetCutoffPlane(GetXStartAngle(isDragged), true);
+            yAxis.SetCutoffPlane(GetYStartAngle(isDragged), true);
+            zAxis.SetCutoffPlane(GetZStartAngle(isDragged), true);
+        }
+
+        /// <inheritdoc/>
+        protected internal override void PostInput()
+        {
+            if (IsDragged())
+            {
+                if (!isDragged)
+                {
+                    isDragged = true;
+                    dragStartRotation = Rotation;
+                }
+            }
+            else
+            {
+                isDragged = false;
+                dragStartRotation = Quaternion.Identity;
+            }
+
+            Degree xValue = (Degree)0.0f;
+            Degree yValue = (Degree)0.0f;
+            Degree zValue = (Degree)0.0f;
+            Degree freeAxisValue = (Degree)0.0f;
+
+            if (Handles.RotateHandleSnapActive)
+            {
+                xValue = Handles.SnapValue(xAxis.Delta, Handles.RotateSnapAmount);
+                yValue = Handles.SnapValue(yAxis.Delta, Handles.RotateSnapAmount);
+                zValue = Handles.SnapValue(zAxis.Delta, Handles.RotateSnapAmount);
+                freeAxisValue = Handles.SnapValue(freeAxis.Delta, Handles.RotateSnapAmount);
+            }
+            else
+            {
+                xValue = xAxis.Delta;
+                yValue = yAxis.Delta;
+                zValue = zAxis.Delta;
+                freeAxisValue = freeAxis.Delta;
+            }
+
+            Vector3 cameraForward = -(dragStartRotation.Inverse * EditorApplication.SceneViewCamera.SceneObject.Rotation).Forward;
+
+            delta = Quaternion.FromEuler(xValue, yValue, zValue);
+            delta *= Quaternion.FromAxisAngle(cameraForward, freeAxisValue);
+        }
+
+        /// <inheritdoc/>
+        protected internal override void Draw()
+        {
+            HandleDrawing.Layer = 1;
+            HandleDrawing.Transform = Matrix4.TRS(Position, Rotation, Vector3.One);
+            float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
+
+            // Draw arcs
+            if (xAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.Color = Color.White;
+            else if(xAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.Color = Color.BansheeOrange;
+            else
+                HandleDrawing.Color = Color.Red;
+
+            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.XAxis, 1.0f, GetXStartAngle(false), new Degree(-180.0f), handleSize);
+
+            if (yAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.Color = Color.White;
+            else if (yAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.Color = Color.BansheeOrange;
+            else
+                HandleDrawing.Color = Color.Green;
+
+            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.YAxis, 1.0f, GetYStartAngle(false), new Degree(-180.0f), handleSize);
+
+            if (zAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.Color = Color.White;
+            else if (zAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.Color = Color.BansheeOrange;
+            else
+                HandleDrawing.Color = Color.Blue;
+
+            HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 1.0f, GetZStartAngle(false), new Degree(-180.0f), handleSize);
+
+            // Draw "bounds" and free handle
+            Color gray = new Color(1.0f, 1.0f, 1.0f, 0.3f);
+            Vector3 cameraNormal = EditorApplication.SceneViewCamera.SceneObject.Rotation.Rotate(Vector3.ZAxis);
+            HandleDrawing.Transform = Matrix4.TRS(Position, Quaternion.Identity, Vector3.One);
+            HandleDrawing.Color = gray;
+
+            HandleDrawing.DrawWireDisc(cameraNormal * 0.1f, cameraNormal, 1.0f, handleSize);
+
+            if (freeAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.Color = Color.White;
+            else if (freeAxis.State == HandleSlider.StateType.Hover)
+                HandleDrawing.Color = Color.BansheeOrange;
+            else
+                HandleDrawing.Color = gray;
+
+            HandleDrawing.DrawWireDisc(Vector3.Zero, cameraNormal, 1.2f, handleSize);
+
+            // Draw active rotation pie
+            HandleDrawing.Color = gray;
+            HandleDrawing.Transform = Matrix4.TRS(Position, EditorApplication.SceneViewCamera.SceneObject.Rotation, Vector3.One);
+
+            if (freeAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.DrawArc(Vector3.Zero, -Vector3.ZAxis, 1.2f, freeAxis.StartAngle, freeAxis.Delta, handleSize);
+
+            HandleDrawing.Transform = Matrix4.TRS(Position, dragStartRotation, Vector3.One);
+
+            if (xAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.DrawArc(Vector3.Zero, Vector3.XAxis, 1.0f, xAxis.StartAngle, xAxis.Delta, handleSize);
+            else if (yAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.DrawArc(Vector3.Zero, Vector3.YAxis, 1.0f, yAxis.StartAngle, yAxis.Delta, handleSize);
+            else if (zAxis.State == HandleSlider.StateType.Active)
+                HandleDrawing.DrawArc(Vector3.Zero, Vector3.ZAxis, 1.0f, zAxis.StartAngle, zAxis.Delta, handleSize);
+        }
+
+        /// <summary>
+        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
+        /// the arc starts for the X axis.
+        /// </summary>
+        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
+        ///                      to the value when handle drag started. This is useful because we do not want the visible
+        ///                      arc to change while the user is in the process of rotating the handle.</param>
+        /// <returns>Angle at which to display the visible arc for the X axis rotations.</returns>
+        private Degree GetXStartAngle(bool frozen)
+        {
+            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
+
+            Vector3 xStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.XAxis);
+            return PointOnCircleToAngle(Vector3.XAxis, xStartDir);
+        }
+
+        /// <summary>
+        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
+        /// the arc starts for the Y axis.
+        /// </summary>
+        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
+        ///                      to the value when handle drag started. This is useful because we do not want the visible
+        ///                      arc to change while the user is in the process of rotating the handle.</param>
+        /// <returns>Angle at which to display the visible arc for the Y axis rotations.</returns>
+        private Degree GetYStartAngle(bool frozen)
+        {
+            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
+
+            Vector3 yStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.YAxis);
+            return PointOnCircleToAngle(Vector3.YAxis, yStartDir);
+        }
+
+        /// <summary>
+        /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which 
+        /// the arc starts for the Z axis.
+        /// </summary>
+        /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
+        ///                      to the value when handle drag started. This is useful because we do not want the visible
+        ///                      arc to change while the user is in the process of rotating the handle.</param>
+        /// <returns>Angle at which to display the visible arc for the Z axis rotations.</returns>
+        private Degree GetZStartAngle(bool frozen)
+        {
+            Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
+
+            Vector3 zStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.ZAxis);
+            return PointOnCircleToAngle(Vector3.ZAxis, zStartDir);
+        }
+
+        /// <summary>
+        /// Converts a point on the circle to an angle on the circle.
+        /// </summary>
+        /// <param name="up">Up vector determining the orientation of the circle.</param>
+        /// <param name="point">Point along a unit circle centered around the origin.</param>
+        /// <returns>Angle at which the provided point is located on the circle.</returns>
+        private Degree PointOnCircleToAngle(Vector3 up, Vector3 point)
+        {
+            Quaternion rot = Quaternion.FromToRotation(up, Vector3.YAxis);
+
+            Matrix4 worldToPlane = Matrix4.TRS(Vector3.Zero, rot, Vector3.One);
+            point = worldToPlane.MultiplyDirection(point);
+
+            return (MathEx.Atan2(-point.z, -point.x) + MathEx.Pi);
+        }
+    }
+}

+ 595 - 595
Source/MBansheeEngine/Math/MathEx.cs

@@ -1,595 +1,595 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Values that represent in which order are euler angles applied when used in transformations.
-    /// </summary>
-    public enum EulerAngleOrder
-	{
-		XYZ,
-		XZY,
-		YXZ,
-		YZX,
-		ZXY,
-		ZYX
-	};
-
-    /// <summary>
-    /// Utility class providing common scalar math operations.
-    /// </summary>
-    public class MathEx
-    {
-        /// <summary>
-        /// Pi constant.
-        /// </summary>
-        public static readonly Radian Pi = new Radian(3.141593f);
-
-        /// <summary>
-        /// Two times pi constant.
-        /// </summary>
-        public static readonly Radian TwoPi = new Radian(Pi * 2.0f);
-
-        /// <summary>
-        /// Half of pi constant.
-        /// </summary>
-        public static readonly Radian HalfPi = new Radian(Pi * 0.5f);
-
-        /// <summary>
-        /// Constant that converts degrees to radians.
-        /// </summary>
-        public static readonly float Deg2Rad = Pi.Radians / 180.0f;
-
-        /// <summary>
-        /// Constant that converts radians to degrees.
-        /// </summary>
-        public static readonly float Rad2Deg = 180.0f / Pi.Radians;
-
-        /// <summary>
-        /// Returns the minimum value of the two provided.
-        /// </summary>
-        /// <param name="a">First value to compare.</param>
-        /// <param name="b">Second value to compare.</param>
-        /// <returns>Minimum of the two values.</returns>
-        public static float Min(float a, float b)
-        {
-            if (a < b)
-                return a;
-            
-            return b;
-        }
-
-        /// <summary>
-        /// Returns the minimum value of all the values provided.
-        /// </summary>
-        /// <param name="values">Values to compare.</param>
-        /// <returns>Minimum of all the values.</returns>
-        public static float Min(params float[] values)
-        {
-            int length = values.Length;
-            if (length == 0)
-                return 0.0f;
-
-            float min = values[0];
-            for (int i = 1; i < length; i++)
-            {
-                if (values[i] < min)
-                    min = values[i];
-            }
-
-            return min;
-        }
-
-        /// <summary>
-        /// Returns the minimum value of the two provided.
-        /// </summary>
-        /// <param name="a">First value to compare.</param>
-        /// <param name="b">Second value to compare.</param>
-        /// <returns>Minimum of the two values.</returns>
-        public static int Min(int a, int b)
-        {
-            if (a < b)
-                return a;
-
-            return b;
-        }
-
-        /// <summary>
-        /// Returns the minimum value of all the values provided.
-        /// </summary>
-        /// <param name="values">Values to compare.</param>
-        /// <returns>Minimum of all the values.</returns>
-        public static int Min(params int[] values)
-        {
-            int length = values.Length;
-            if (length == 0)
-                return 0;
-
-            int min = values[0];
-            for (int i = 1; i < length; i++)
-            {
-                if (values[i] < min)
-                    min = values[i];
-            }
-
-            return min;
-        }
-
-        /// <summary>
-        /// Returns the maximum value of the two provided.
-        /// </summary>
-        /// <param name="a">First value to compare.</param>
-        /// <param name="b">Second value to compare.</param>
-        /// <returns>Maximum of the two values.</returns>
-        public static float Max(float a, float b)
-        {
-            if (a > b)
-                return a;
-
-            return b;
-        }
-
-        /// <summary>
-        /// Returns the maximum value of all the values provided.
-        /// </summary>
-        /// <param name="values">Values to compare.</param>
-        /// <returns>Maximum of all the values.</returns>
-        public static float Max(params float[] values)
-        {
-            int length = values.Length;
-            if (length == 0)
-                return 0.0f;
-
-            float max = values[0];
-            for (int i = 1; i < length; i++)
-            {
-                if (values[i] > max)
-                    max = values[i];
-            }
-
-            return max;
-        }
-
-        /// <summary>
-        /// Returns the maximum value of the two provided.
-        /// </summary>
-        /// <param name="a">First value to compare.</param>
-        /// <param name="b">Second value to compare.</param>
-        /// <returns>Maximum of the two values.</returns>
-        public static int Max(int a, int b)
-        {
-            if (a > b)
-                return a;
-            else
-                return b;
-        }
-
-        /// <summary>
-        /// Returns the maximum value of all the values provided.
-        /// </summary>
-        /// <param name="values">Values to compare.</param>
-        /// <returns>Maximum of all the values.</returns>
-        public static int Max(params int[] values)
-        {
-            int length = values.Length;
-            if (length == 0)
-                return 0;
-
-            int max = values[0];
-            for (int i = 1; i < length; ++i)
-            {
-                if (values[i] > max)
-                    max = values[i];
-            }
-
-            return max;
-        }
-
-        /// <summary>
-        /// Returns the absolute value of the provided parameter.
-        /// </summary>
-        /// <param name="f">Parameter to take absolute value of.</param>
-        /// <returns>Absolute value of <paramref name="f"/>.</returns>
-        public static float Abs(float f)
-        {
-            return Math.Abs(f);
-        }
-
-        /// <summary>
-        /// Returns the absolute value of the provided parameter.
-        /// </summary>
-        /// <param name="value">Parameter to take absolute value of.</param>
-        /// <returns>Absolute value of <paramref name="value"/>.</returns>
-        public static int Abs(int value)
-        {
-            return Math.Abs(value);
-        }
-
-        /// <summary>
-        /// Raises <paramref name="f"/> to the power of <paramref name="p"/>.
-        /// </summary>
-        /// <param name="f">Value to raise to a power.</param>
-        /// <param name="p">Power to raise the value to.</param>
-        /// <returns><paramref name="f"/> raised to the power of <paramref name="p"/>.</returns>
-        public static float Pow(float f, float p)
-        {
-            return (float)Math.Pow(f, p);
-        }
-
-        /// <summary>
-        /// Raises e to the power of <paramref name="power"/>.
-        /// </summary>
-        /// <param name="power">Power to raise e to.</param>
-        /// <returns>e raised to the power of <paramref name="power"/>.</returns>
-        public static float Exp(float power)
-        {
-            return (float)Math.Exp(power);
-        }
-
-        /// <summary>
-        /// Returns the logarithm of a number in a specified base.
-        /// </summary>
-        /// <param name="f">Value to get the logarithm of.</param>
-        /// <param name="p">Base of the logarithm</param>
-        /// <returns>Logarithm of a number in the specified base.</returns>
-        public static float Log(float f, float p)
-        {
-            return (float)Math.Log(f, p);
-        }
-
-        /// <summary>
-        /// Returns the natural logarithm (base e).
-        /// </summary>
-        /// <param name="f">Value to get the logarithm of.</param>
-        /// <returns>Natural logarithm of a number.</returns>
-        public static float Log(float f)
-        {
-            return (float)Math.Log(f);
-        }
-
-        /// <summary>
-        /// Returns the logarithm of a number in base 10.
-        /// </summary>
-        /// <param name="f">Value to get the logarithm of.</param>
-        /// <returns>Logarithm of a number in base 10.</returns>
-        public static float Log10(float f)
-        {
-            return (float)Math.Log10(f);
-        }
-
-        /// <summary>
-        /// Returns the smallest integral value that is greater than or equal to the provided value.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Smallest integral value that is greater than or equal to the provided value.</returns>
-        public static float Ceil(float f)
-        {
-            return (float)Math.Ceiling(f);
-        }
-
-        /// <summary>
-        /// Returns the largest integral value that is lesser than or equal to the provided value.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Largest integral value that is lessert than or equal to the provided value.</returns>
-        public static float Floor(float f)
-        {
-            return (float)Math.Floor(f);
-        }
-
-        /// <summary>
-        /// Rounds the provided value to the nearest integral.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Value rounded to the nearest integral.</returns>
-        public static float Round(float f)
-        {
-            return (float)Math.Round(f);
-        }
-
-        /// <summary>
-        /// Returns the smallest integral value that is greater than or equal to the provided value.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Smallest integral value that is greater than or equal to the provided value.</returns>
-        public static int CeilToInt(float f)
-        {
-            return (int)Math.Ceiling(f);
-        }
-
-        /// <summary>
-        /// Returns the largest integral value that is lesser than or equal to the provided value.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Largest integral value that is lessert than or equal to the provided value.</returns>
-        public static int FloorToInt(float f)
-        {
-            return (int)Math.Floor(f);
-        }
-
-        /// <summary>
-        /// Rounds the provided value to the nearest integral.
-        /// </summary>
-        /// <param name="f">Value to round.</param>
-        /// <returns>Value rounded to the nearest integral.</returns>
-        public static int RoundToInt(float f)
-        {
-            return (int)Math.Round(f);
-        }
-
-        /// <summary>
-        /// Returns the sign of the provided value (positive or negative).
-        /// </summary>
-        /// <param name="f">Value to get the sign of.</param>
-        /// <returns>-1.0f if negative or 1.0f if positive.</returns>
-        public static float Sign(float f)
-        {
-            return f >= 0.0f ? 1.0f : -1.0f;
-        }
-
-        /// <summary>
-        /// Returns the sine of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Sine of the angle.</returns>
-        public static float Sin(float f)
-        {
-            return (float)Math.Sin(f);
-        }
-
-        /// <summary>
-        /// Returns the cosine of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Cosine of the angle.</returns>
-        public static float Cos(float f)
-        {
-            return (float)Math.Cos(f);
-        }
-
-        /// <summary>
-        /// Returns the tangent of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Tangent of the angle.</returns>
-        public static float Tan(float f)
-        {
-            return (float)Math.Tan(f);
-        }
-
-        /// <summary>
-        /// Returns the angle whose sine is the specified number.
-        /// </summary>
-        /// <param name="f">Sine of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Asin(float f)
-        {
-            return (Radian)Math.Asin(f);
-        }
-
-        /// <summary>
-        /// Returns the angle whose cosine is the specified number.
-        /// </summary>
-        /// <param name="f">Cosine of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Acos(float f)
-        {
-            return (Radian)Math.Acos(f);
-        }
-
-        /// <summary>
-        /// Returns the angle whose tangent is the specified number.
-        /// </summary>
-        /// <param name="f">Tangent of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Atan(float f)
-        {
-            return (Radian)Math.Atan(f);
-        }
-
-        /// <summary>
-        /// Returns an angle of a point.
-        /// </summary>
-        /// <param name="y">Y coordinate of the point.</param>
-        /// <param name="x">X coordinate of the point.</param>
-        /// <returns>Angle in radians in range [Pi, -Pi].</returns>
-        public static Radian Atan2(float y, float x)
-        {
-            return (Radian)Math.Atan2(y, x);
-        }
-
-        /// <summary>
-        /// Returns the sine of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Sine of the angle.</returns>
-        public static float Sin(Radian f)
-        {
-            return (float)Math.Sin(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns the cosine of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Cosine of the angle.</returns>
-        public static float Cos(Radian f)
-        {
-            return (float)Math.Cos(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns the tangent of the provided value.
-        /// </summary>
-        /// <param name="f">Angle in radians.</param>
-        /// <returns>Tangent of the angle.</returns>
-        public static float Tan(Radian f)
-        {
-            return (float)Math.Tan(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns the angle whose sine is the specified number.
-        /// </summary>
-        /// <param name="f">Sine of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Asin(Radian f)
-        {
-            return (Radian)Math.Asin(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns the angle whose cosine is the specified number.
-        /// </summary>
-        /// <param name="f">Cosine of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Acos(Radian f)
-        {
-            return (Radian)Math.Acos(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns the angle whose tangent is the specified number.
-        /// </summary>
-        /// <param name="f">Tangent of an angle.</param>
-        /// <returns>Angle in radians.</returns>
-        public static Radian Atan(Radian f)
-        {
-            return (Radian)Math.Atan(f.Radians);
-        }
-
-        /// <summary>
-        /// Returns an angle of a point.
-        /// </summary>
-        /// <param name="y">Y coordinate of the point.</param>
-        /// <param name="x">X coordinate of the point.</param>
-        /// <returns>Angle in radians in range [Pi, -Pi].</returns>
-        public static Radian Atan2(Radian y, Radian x)
-        {
-            return (Radian)Math.Atan2(y.Radians, x.Radians);
-        }
-
-        /// <summary>
-        /// Returns a square root of the provided value.
-        /// </summary>
-        /// <param name="f">Value to take the square root of. Must not be negative.</param>
-        /// <returns>Square root of the provided value.</returns>
-        public static float Sqrt(float f)
-        {
-            return (float)Math.Sqrt(f);
-        }
-
-        /// <summary>
-        /// Returns an inverse square root (1/sqrt(x)) of the provided value.
-        /// </summary>
-        /// <param name="f">Value to take the inverse square root of. Must not be negative or zero.</param>
-        /// <returns>Inverse square root of the provided value.</returns>
-        public static float InvSqrt(float f)
-        {
-            return 1.0f/(float) Math.Sqrt(f);
-        }
-
-        /// <summary>
-        /// Clamps a value between two other values.
-        /// </summary>
-        /// <param name="value">Value to clamp.</param>
-        /// <param name="min">Minimum value of the range to clamp. Must be lower than <paramref name="max"/></param>
-        /// <param name="max">Maximum value of the range to clamp. Must be higher than <paramref name="min"/></param>
-        /// <returns>Returns unchanged value if it is in valid range, otherwise returns value clamped to the range
-        /// extremes. </returns>
-        public static float Clamp(float value, float min, float max)
-        {
-            if (value < min)
-                value = min;
-            else if (value > max)
-                value = max;
-
-            return value;
-        }
-
-        /// <summary>
-        /// Clamps a value between two other values.
-        /// </summary>
-        /// <param name="value">Value to clamp.</param>
-        /// <param name="min">Minimum value of the range to clamp. Must be lower than <paramref name="max"/></param>
-        /// <param name="max">Maximum value of the range to clamp. Must be higher than <paramref name="min"/></param>
-        /// <returns>Returns unchanged value if it is in valid range, otherwise returns value clamped to the range
-        /// extremes. </returns>
-        public static int Clamp(int value, int min, int max)
-        {
-            if (value < min)
-                value = min;
-            else if (value > max)
-                value = max;
-
-            return value;
-        }
-
-        /// <summary>
-        /// Clamps a value between zero and one.
-        /// </summary>
-        /// <param name="value">Value to clamp.</param>
-        /// <returns>Returns unchanged value if it is in [0, 1] range, otherwise returns value clamped to the range. 
-        /// </returns>
-        public static float Clamp01(float value)
-        {
-            if (value < 0.0)
-                return 0.0f;
-
-            if (value > 1.0)
-                return 1f;
-            
-            return value;
-        }
-
-        /// <summary>
-        /// Linearly interpolates between two values.
-        /// </summary>
-        /// <param name="a">Starting value to interpolate from.</param>
-        /// <param name="b">Ending value to interpolate towards.</param>
-        /// <param name="t">Interpolation factor in specified range.</param>
-        /// <param name="tmin">Minimum value for the range of <see cref="t"/></param>
-        /// <param name="tmax">Maximum value for the range of <see cref="t"/></param>
-        /// <returns>Interpolated value.</returns>
-        public static float Lerp(float a, float b, float t, float tmin = 0.0f, float tmax = 1.0f)
-        {
-            t = Clamp01((t - tmin) / (tmax - tmin));
-
-            return a * (1.0f - t) + b * t;
-        }
-
-        /// <summary>
-        /// Wraps an angle in [0, 360) range. Values lower than zero, or higher or equal to 360
-        /// will get wrapped around back into [0, 360) range.
-        /// </summary>
-        /// <param name="angle">Angle to wrap.</param>
-        /// <returns>Angle in [0, 360) range.</returns>
-        public static Degree WrapAngle(Degree angle)
-        {
-            const float inv360 = 1.0f/360.0f;
-            float angleVal = angle.Degrees;
-            float wrapCount = (float)MathEx.Floor(MathEx.Abs(angleVal * inv360));
-
-            if (angleVal > 0.0f)
-                angleVal -= 360.0f * wrapCount;
-            else
-                angleVal += 360.0f * wrapCount;
-
-            return new Degree(angleVal);
-        }
-
-        /// <summary>
-        /// Compares two floating point numbers with an error margin.
-        /// </summary>
-        /// <param name="a">First number to compare.</param>
-        /// <param name="b">Second number to compare.</param>
-        /// <param name="epsilon">Error margin within which the numbers should be considered equal.</param>
-        /// <returns>True if equal, false otherwise.</returns>
-        public static bool ApproxEquals(float a, float b, float epsilon = 1.192092896e-07F)
-        {
-            return Abs(b - a) <= epsilon;
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Values that represent in which order are euler angles applied when used in transformations.
+    /// </summary>
+    public enum EulerAngleOrder
+	{
+		XYZ,
+		XZY,
+		YXZ,
+		YZX,
+		ZXY,
+		ZYX
+	};
+
+    /// <summary>
+    /// Utility class providing common scalar math operations.
+    /// </summary>
+    public class MathEx
+    {
+        /// <summary>
+        /// Pi constant.
+        /// </summary>
+        public static readonly Radian Pi = new Radian(3.14159265359f);
+
+        /// <summary>
+        /// Two times pi constant.
+        /// </summary>
+        public static readonly Radian TwoPi = new Radian(3.14159265359f * 2.0f);
+
+        /// <summary>
+        /// Half of pi constant.
+        /// </summary>
+        public static readonly Radian HalfPi = new Radian(3.14159265359f * 0.5f);
+
+        /// <summary>
+        /// Constant that converts degrees to radians.
+        /// </summary>
+        public static readonly float Deg2Rad = 3.14159265359f / 180.0f;
+
+        /// <summary>
+        /// Constant that converts radians to degrees.
+        /// </summary>
+        public static readonly float Rad2Deg = 180.0f / 3.14159265359f;
+
+        /// <summary>
+        /// Returns the minimum value of the two provided.
+        /// </summary>
+        /// <param name="a">First value to compare.</param>
+        /// <param name="b">Second value to compare.</param>
+        /// <returns>Minimum of the two values.</returns>
+        public static float Min(float a, float b)
+        {
+            if (a < b)
+                return a;
+            
+            return b;
+        }
+
+        /// <summary>
+        /// Returns the minimum value of all the values provided.
+        /// </summary>
+        /// <param name="values">Values to compare.</param>
+        /// <returns>Minimum of all the values.</returns>
+        public static float Min(params float[] values)
+        {
+            int length = values.Length;
+            if (length == 0)
+                return 0.0f;
+
+            float min = values[0];
+            for (int i = 1; i < length; i++)
+            {
+                if (values[i] < min)
+                    min = values[i];
+            }
+
+            return min;
+        }
+
+        /// <summary>
+        /// Returns the minimum value of the two provided.
+        /// </summary>
+        /// <param name="a">First value to compare.</param>
+        /// <param name="b">Second value to compare.</param>
+        /// <returns>Minimum of the two values.</returns>
+        public static int Min(int a, int b)
+        {
+            if (a < b)
+                return a;
+
+            return b;
+        }
+
+        /// <summary>
+        /// Returns the minimum value of all the values provided.
+        /// </summary>
+        /// <param name="values">Values to compare.</param>
+        /// <returns>Minimum of all the values.</returns>
+        public static int Min(params int[] values)
+        {
+            int length = values.Length;
+            if (length == 0)
+                return 0;
+
+            int min = values[0];
+            for (int i = 1; i < length; i++)
+            {
+                if (values[i] < min)
+                    min = values[i];
+            }
+
+            return min;
+        }
+
+        /// <summary>
+        /// Returns the maximum value of the two provided.
+        /// </summary>
+        /// <param name="a">First value to compare.</param>
+        /// <param name="b">Second value to compare.</param>
+        /// <returns>Maximum of the two values.</returns>
+        public static float Max(float a, float b)
+        {
+            if (a > b)
+                return a;
+
+            return b;
+        }
+
+        /// <summary>
+        /// Returns the maximum value of all the values provided.
+        /// </summary>
+        /// <param name="values">Values to compare.</param>
+        /// <returns>Maximum of all the values.</returns>
+        public static float Max(params float[] values)
+        {
+            int length = values.Length;
+            if (length == 0)
+                return 0.0f;
+
+            float max = values[0];
+            for (int i = 1; i < length; i++)
+            {
+                if (values[i] > max)
+                    max = values[i];
+            }
+
+            return max;
+        }
+
+        /// <summary>
+        /// Returns the maximum value of the two provided.
+        /// </summary>
+        /// <param name="a">First value to compare.</param>
+        /// <param name="b">Second value to compare.</param>
+        /// <returns>Maximum of the two values.</returns>
+        public static int Max(int a, int b)
+        {
+            if (a > b)
+                return a;
+            else
+                return b;
+        }
+
+        /// <summary>
+        /// Returns the maximum value of all the values provided.
+        /// </summary>
+        /// <param name="values">Values to compare.</param>
+        /// <returns>Maximum of all the values.</returns>
+        public static int Max(params int[] values)
+        {
+            int length = values.Length;
+            if (length == 0)
+                return 0;
+
+            int max = values[0];
+            for (int i = 1; i < length; ++i)
+            {
+                if (values[i] > max)
+                    max = values[i];
+            }
+
+            return max;
+        }
+
+        /// <summary>
+        /// Returns the absolute value of the provided parameter.
+        /// </summary>
+        /// <param name="f">Parameter to take absolute value of.</param>
+        /// <returns>Absolute value of <paramref name="f"/>.</returns>
+        public static float Abs(float f)
+        {
+            return Math.Abs(f);
+        }
+
+        /// <summary>
+        /// Returns the absolute value of the provided parameter.
+        /// </summary>
+        /// <param name="value">Parameter to take absolute value of.</param>
+        /// <returns>Absolute value of <paramref name="value"/>.</returns>
+        public static int Abs(int value)
+        {
+            return Math.Abs(value);
+        }
+
+        /// <summary>
+        /// Raises <paramref name="f"/> to the power of <paramref name="p"/>.
+        /// </summary>
+        /// <param name="f">Value to raise to a power.</param>
+        /// <param name="p">Power to raise the value to.</param>
+        /// <returns><paramref name="f"/> raised to the power of <paramref name="p"/>.</returns>
+        public static float Pow(float f, float p)
+        {
+            return (float)Math.Pow(f, p);
+        }
+
+        /// <summary>
+        /// Raises e to the power of <paramref name="power"/>.
+        /// </summary>
+        /// <param name="power">Power to raise e to.</param>
+        /// <returns>e raised to the power of <paramref name="power"/>.</returns>
+        public static float Exp(float power)
+        {
+            return (float)Math.Exp(power);
+        }
+
+        /// <summary>
+        /// Returns the logarithm of a number in a specified base.
+        /// </summary>
+        /// <param name="f">Value to get the logarithm of.</param>
+        /// <param name="p">Base of the logarithm</param>
+        /// <returns>Logarithm of a number in the specified base.</returns>
+        public static float Log(float f, float p)
+        {
+            return (float)Math.Log(f, p);
+        }
+
+        /// <summary>
+        /// Returns the natural logarithm (base e).
+        /// </summary>
+        /// <param name="f">Value to get the logarithm of.</param>
+        /// <returns>Natural logarithm of a number.</returns>
+        public static float Log(float f)
+        {
+            return (float)Math.Log(f);
+        }
+
+        /// <summary>
+        /// Returns the logarithm of a number in base 10.
+        /// </summary>
+        /// <param name="f">Value to get the logarithm of.</param>
+        /// <returns>Logarithm of a number in base 10.</returns>
+        public static float Log10(float f)
+        {
+            return (float)Math.Log10(f);
+        }
+
+        /// <summary>
+        /// Returns the smallest integral value that is greater than or equal to the provided value.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Smallest integral value that is greater than or equal to the provided value.</returns>
+        public static float Ceil(float f)
+        {
+            return (float)Math.Ceiling(f);
+        }
+
+        /// <summary>
+        /// Returns the largest integral value that is lesser than or equal to the provided value.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Largest integral value that is lessert than or equal to the provided value.</returns>
+        public static float Floor(float f)
+        {
+            return (float)Math.Floor(f);
+        }
+
+        /// <summary>
+        /// Rounds the provided value to the nearest integral.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Value rounded to the nearest integral.</returns>
+        public static float Round(float f)
+        {
+            return (float)Math.Round(f);
+        }
+
+        /// <summary>
+        /// Returns the smallest integral value that is greater than or equal to the provided value.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Smallest integral value that is greater than or equal to the provided value.</returns>
+        public static int CeilToInt(float f)
+        {
+            return (int)Math.Ceiling(f);
+        }
+
+        /// <summary>
+        /// Returns the largest integral value that is lesser than or equal to the provided value.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Largest integral value that is lessert than or equal to the provided value.</returns>
+        public static int FloorToInt(float f)
+        {
+            return (int)Math.Floor(f);
+        }
+
+        /// <summary>
+        /// Rounds the provided value to the nearest integral.
+        /// </summary>
+        /// <param name="f">Value to round.</param>
+        /// <returns>Value rounded to the nearest integral.</returns>
+        public static int RoundToInt(float f)
+        {
+            return (int)Math.Round(f);
+        }
+
+        /// <summary>
+        /// Returns the sign of the provided value (positive or negative).
+        /// </summary>
+        /// <param name="f">Value to get the sign of.</param>
+        /// <returns>-1.0f if negative or 1.0f if positive.</returns>
+        public static float Sign(float f)
+        {
+            return f >= 0.0f ? 1.0f : -1.0f;
+        }
+
+        /// <summary>
+        /// Returns the sine of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Sine of the angle.</returns>
+        public static float Sin(float f)
+        {
+            return (float)Math.Sin(f);
+        }
+
+        /// <summary>
+        /// Returns the cosine of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Cosine of the angle.</returns>
+        public static float Cos(float f)
+        {
+            return (float)Math.Cos(f);
+        }
+
+        /// <summary>
+        /// Returns the tangent of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Tangent of the angle.</returns>
+        public static float Tan(float f)
+        {
+            return (float)Math.Tan(f);
+        }
+
+        /// <summary>
+        /// Returns the angle whose sine is the specified number.
+        /// </summary>
+        /// <param name="f">Sine of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Asin(float f)
+        {
+            return (Radian)Math.Asin(f);
+        }
+
+        /// <summary>
+        /// Returns the angle whose cosine is the specified number.
+        /// </summary>
+        /// <param name="f">Cosine of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Acos(float f)
+        {
+            return (Radian)Math.Acos(f);
+        }
+
+        /// <summary>
+        /// Returns the angle whose tangent is the specified number.
+        /// </summary>
+        /// <param name="f">Tangent of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Atan(float f)
+        {
+            return (Radian)Math.Atan(f);
+        }
+
+        /// <summary>
+        /// Returns an angle of a point.
+        /// </summary>
+        /// <param name="y">Y coordinate of the point.</param>
+        /// <param name="x">X coordinate of the point.</param>
+        /// <returns>Angle in radians in range [Pi, -Pi].</returns>
+        public static Radian Atan2(float y, float x)
+        {
+            return (Radian)Math.Atan2(y, x);
+        }
+
+        /// <summary>
+        /// Returns the sine of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Sine of the angle.</returns>
+        public static float Sin(Radian f)
+        {
+            return (float)Math.Sin(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns the cosine of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Cosine of the angle.</returns>
+        public static float Cos(Radian f)
+        {
+            return (float)Math.Cos(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns the tangent of the provided value.
+        /// </summary>
+        /// <param name="f">Angle in radians.</param>
+        /// <returns>Tangent of the angle.</returns>
+        public static float Tan(Radian f)
+        {
+            return (float)Math.Tan(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns the angle whose sine is the specified number.
+        /// </summary>
+        /// <param name="f">Sine of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Asin(Radian f)
+        {
+            return (Radian)Math.Asin(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns the angle whose cosine is the specified number.
+        /// </summary>
+        /// <param name="f">Cosine of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Acos(Radian f)
+        {
+            return (Radian)Math.Acos(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns the angle whose tangent is the specified number.
+        /// </summary>
+        /// <param name="f">Tangent of an angle.</param>
+        /// <returns>Angle in radians.</returns>
+        public static Radian Atan(Radian f)
+        {
+            return (Radian)Math.Atan(f.Radians);
+        }
+
+        /// <summary>
+        /// Returns an angle of a point.
+        /// </summary>
+        /// <param name="y">Y coordinate of the point.</param>
+        /// <param name="x">X coordinate of the point.</param>
+        /// <returns>Angle in radians in range [Pi, -Pi].</returns>
+        public static Radian Atan2(Radian y, Radian x)
+        {
+            return (Radian)Math.Atan2(y.Radians, x.Radians);
+        }
+
+        /// <summary>
+        /// Returns a square root of the provided value.
+        /// </summary>
+        /// <param name="f">Value to take the square root of. Must not be negative.</param>
+        /// <returns>Square root of the provided value.</returns>
+        public static float Sqrt(float f)
+        {
+            return (float)Math.Sqrt(f);
+        }
+
+        /// <summary>
+        /// Returns an inverse square root (1/sqrt(x)) of the provided value.
+        /// </summary>
+        /// <param name="f">Value to take the inverse square root of. Must not be negative or zero.</param>
+        /// <returns>Inverse square root of the provided value.</returns>
+        public static float InvSqrt(float f)
+        {
+            return 1.0f/(float) Math.Sqrt(f);
+        }
+
+        /// <summary>
+        /// Clamps a value between two other values.
+        /// </summary>
+        /// <param name="value">Value to clamp.</param>
+        /// <param name="min">Minimum value of the range to clamp. Must be lower than <paramref name="max"/></param>
+        /// <param name="max">Maximum value of the range to clamp. Must be higher than <paramref name="min"/></param>
+        /// <returns>Returns unchanged value if it is in valid range, otherwise returns value clamped to the range
+        /// extremes. </returns>
+        public static float Clamp(float value, float min, float max)
+        {
+            if (value < min)
+                value = min;
+            else if (value > max)
+                value = max;
+
+            return value;
+        }
+
+        /// <summary>
+        /// Clamps a value between two other values.
+        /// </summary>
+        /// <param name="value">Value to clamp.</param>
+        /// <param name="min">Minimum value of the range to clamp. Must be lower than <paramref name="max"/></param>
+        /// <param name="max">Maximum value of the range to clamp. Must be higher than <paramref name="min"/></param>
+        /// <returns>Returns unchanged value if it is in valid range, otherwise returns value clamped to the range
+        /// extremes. </returns>
+        public static int Clamp(int value, int min, int max)
+        {
+            if (value < min)
+                value = min;
+            else if (value > max)
+                value = max;
+
+            return value;
+        }
+
+        /// <summary>
+        /// Clamps a value between zero and one.
+        /// </summary>
+        /// <param name="value">Value to clamp.</param>
+        /// <returns>Returns unchanged value if it is in [0, 1] range, otherwise returns value clamped to the range. 
+        /// </returns>
+        public static float Clamp01(float value)
+        {
+            if (value < 0.0)
+                return 0.0f;
+
+            if (value > 1.0)
+                return 1f;
+            
+            return value;
+        }
+
+        /// <summary>
+        /// Linearly interpolates between two values.
+        /// </summary>
+        /// <param name="a">Starting value to interpolate from.</param>
+        /// <param name="b">Ending value to interpolate towards.</param>
+        /// <param name="t">Interpolation factor in specified range.</param>
+        /// <param name="tmin">Minimum value for the range of <see cref="t"/></param>
+        /// <param name="tmax">Maximum value for the range of <see cref="t"/></param>
+        /// <returns>Interpolated value.</returns>
+        public static float Lerp(float a, float b, float t, float tmin = 0.0f, float tmax = 1.0f)
+        {
+            t = Clamp01((t - tmin) / (tmax - tmin));
+
+            return a * (1.0f - t) + b * t;
+        }
+
+        /// <summary>
+        /// Wraps an angle in [0, 360) range. Values lower than zero, or higher or equal to 360
+        /// will get wrapped around back into [0, 360) range.
+        /// </summary>
+        /// <param name="angle">Angle to wrap.</param>
+        /// <returns>Angle in [0, 360) range.</returns>
+        public static Degree WrapAngle(Degree angle)
+        {
+            const float inv360 = 1.0f/360.0f;
+            float angleVal = angle.Degrees;
+            float wrapCount = (float)MathEx.Floor(MathEx.Abs(angleVal * inv360));
+
+            if (angleVal > 0.0f)
+                angleVal -= 360.0f * wrapCount;
+            else
+                angleVal += 360.0f * wrapCount;
+
+            return new Degree(angleVal);
+        }
+
+        /// <summary>
+        /// Compares two floating point numbers with an error margin.
+        /// </summary>
+        /// <param name="a">First number to compare.</param>
+        /// <param name="b">Second number to compare.</param>
+        /// <param name="epsilon">Error margin within which the numbers should be considered equal.</param>
+        /// <returns>True if equal, false otherwise.</returns>
+        public static bool ApproxEquals(float a, float b, float epsilon = 1.192092896e-07F)
+        {
+            return Abs(b - a) <= epsilon;
+        }
+    }
+}

+ 681 - 681
Source/MBansheeEngine/Math/Matrix3.cs

@@ -1,681 +1,681 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.InteropServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// A 3x3 matrix. Can be used for non-homogenous transformations of three dimensional vectors and points.
-    /// </summary>
-    [StructLayout(LayoutKind.Sequential), SerializeObject]
-    public struct Matrix3 // Note: Must match C++ class Matrix3
-    {
-        /// <summary>
-        /// Contains constant data that is used when calculating euler angles in a certain order.
-        /// </summary>
-        private struct EulerAngleOrderData
-		{
-            public EulerAngleOrderData(int a, int b, int c, float sign)
-            {
-                this.a = a;
-                this.b = b;
-                this.c = c;
-                this.sign = sign;
-            }
-
-			public int a, b, c;
-            public float sign;
-		};
-
-        private static EulerAngleOrderData[] EA_LOOKUP = 
-		{ new EulerAngleOrderData(0, 1, 2, 1.0f), new EulerAngleOrderData(0, 2, 1, -1.0f), new EulerAngleOrderData(1, 0, 2, -1.0f),
-		  new EulerAngleOrderData(1, 2, 0, 1.0f), new EulerAngleOrderData(2, 0, 1,  1.0f), new EulerAngleOrderData(2, 1, 0, -1.0f) };
-
-        /// <summary>
-        /// A matrix with all zero values.
-        /// </summary>
-        public static readonly Matrix3 Zero = new Matrix3();
-
-        /// <summary>
-        /// Identity matrix.
-        /// </summary>
-        public static readonly Matrix3 Identity = new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1);
-
-        public float m00;
-        public float m01;
-        public float m02;
-        public float m10;
-        public float m11;
-        public float m12;
-        public float m20;
-        public float m21;
-        public float m22;
-
-        /// <summary>
-        /// Creates a new matrix with the specified elements.
-        /// </summary>
-        public Matrix3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
-        {
-            this.m00 = m00;
-            this.m01 = m01;
-            this.m02 = m02;
-            this.m10 = m10;
-            this.m11 = m11;
-            this.m12 = m12;
-            this.m20 = m20;
-            this.m21 = m21;
-            this.m22 = m22;
-        }
-
-        /// <summary>
-        /// Value of the specified element in the matrix.
-        /// </summary>
-        /// <param name="row">Row index of the element to retrieve.</param>
-        /// <param name="column">Column index of the element to retrieve.</param>
-        /// <returns>Value of the element.</returns>
-        public float this[int row, int column]
-        {
-            get
-            {
-                return this[row * 3 + column];
-            }
-            set
-            {
-                this[row * 3 + column] = value;
-            }
-        }
-
-        /// <summary>
-        /// Value of the specified element in the matrix using a linear index.
-        /// Linear index can be calculated using the following formula: idx = row * 3 + column. 
-        /// </summary>
-        /// <param name="index">Linear index to get the value of.</param>
-        /// <returns>Value of the element.</returns>
-        public float this[int index]
-        {
-            get
-            {
-                switch (index)
-                {
-                    case 0:
-                        return m00;
-                    case 1:
-                        return m01;
-                    case 2:
-                        return m02;
-                    case 3:
-                        return m10;
-                    case 4:
-                        return m11;
-                    case 5:
-                        return m12;
-                    case 6:
-                        return m20;
-                    case 7:
-                        return m21;
-                    case 8:
-                        return m22;
-                    default:
-                        throw new IndexOutOfRangeException("Invalid matrix index.");
-                }
-
-            }
-            set
-            {
-                switch (index)
-                {
-                    case 0:
-                        m00 = value;
-                        break;
-                    case 1:
-                        m01 = value;
-                        break;
-                    case 2:
-                        m02 = value;
-                        break;
-                    case 3:
-                        m10 = value;
-                        break;
-                    case 4:
-                        m11 = value;
-                        break;
-                    case 5:
-                        m12 = value;
-                        break;
-                    case 6:
-                        m20 = value;
-                        break;
-                    case 7:
-                        m21 = value;
-                        break;
-                    case 8:
-                        m22 = value;
-                        break;
-                    default:
-                        throw new IndexOutOfRangeException("Invalid matrix index.");
-                }
-            }
-        }
-
-        public static Matrix3 operator *(Matrix3 lhs, Matrix3 rhs)
-        {
-            return new Matrix3()
-            {
-                m00 = lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10 + lhs.m02 * rhs.m20,
-                m01 = lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11 + lhs.m02 * rhs.m21,
-                m02 = lhs.m00 * rhs.m02 + lhs.m01 * rhs.m12 + lhs.m02 * rhs.m22,
-                m10 = lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10 + lhs.m12 * rhs.m20,
-                m11 = lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11 + lhs.m12 * rhs.m21,
-                m12 = lhs.m10 * rhs.m02 + lhs.m11 * rhs.m12 + lhs.m12 * rhs.m22,
-                m20 = lhs.m20 * rhs.m00 + lhs.m21 * rhs.m10 + lhs.m22 * rhs.m20,
-                m21 = lhs.m20 * rhs.m01 + lhs.m21 * rhs.m11 + lhs.m22 * rhs.m21,
-                m22 = lhs.m20 * rhs.m02 + lhs.m21 * rhs.m12 + lhs.m22 * rhs.m22,
-            };
-        }
-
-        public static bool operator== (Matrix3 lhs, Matrix3 rhs)
-        {
-            if (lhs.m00 == rhs.m00 && lhs.m01 == rhs.m01 && lhs.m02 == rhs.m02 && 
-                lhs.m10 == rhs.m10 && lhs.m11 == rhs.m11 && lhs.m12 == rhs.m12 &&
-                lhs.m20 == rhs.m20 && lhs.m21 == rhs.m21 && lhs.m22 == rhs.m22)
-                return true;
-            else
-                return false;
-        }
-
-        public static bool operator !=(Matrix3 lhs, Matrix3 rhs)
-        {
-            return !(lhs == rhs);
-        }
-
-        /// <inheritdoc/>
-        public override int GetHashCode()
-        {
-            float hash1 = m00.GetHashCode() ^ m10.GetHashCode() << 2 ^ m20.GetHashCode() >> 2;
-            float hash2 = m01.GetHashCode() ^ m11.GetHashCode() << 2 ^ m21.GetHashCode() >> 2;
-            float hash3 = m02.GetHashCode() ^ m12.GetHashCode() << 2 ^ m22.GetHashCode() >> 2;
-
-            return hash1.GetHashCode() ^ hash2.GetHashCode() << 2 ^ hash3.GetHashCode() >> 2;
-        }
-
-        /// <inheritdoc/>
-        public override bool Equals(object other)
-        {
-            if (!(other is Matrix3))
-                return false;
-
-            Matrix3 mat = (Matrix3)other;
-            if (m00 == mat.m00 && m01 == mat.m01 && m02 == mat.m02 &&
-                m10 == mat.m10 && m11 == mat.m11 && m12 == mat.m12 &&
-                m20 == mat.m20 && m21 == mat.m21 && m22 == mat.m22)
-                return true;
-            else
-                return false;
-        }
-
-        /// <summary>
-        /// Calculates an inverse of the matrix if it exists.
-        /// </summary>
-        public void Invert()
-        {
-            float[,] invVals = new float[3,3];
-
-            invVals[0, 0] = m11 * m22 - m12 * m21;
-            invVals[1, 0] = m12 * m20 - m10 * m22;
-            invVals[2, 0] = m10 * m21 - m11 * m20;
-
-            float det = m00 * invVals[0, 0] + m01 * invVals[1, 0] + m02 * invVals[2, 0];
-
-            if (MathEx.Abs(det) <= 1e-06f)
-                throw new DivideByZeroException("Matrix determinant is zero. Cannot invert.");
-
-            invVals[0, 1] = m02 * m21 - m01 * m22;
-            invVals[0, 2] = m01 * m12 - m02 * m11;
-
-            invVals[1, 1] = m00 * m22 - m02 * m20;
-            invVals[1, 2] = m02 * m10 - m00 * m12;
-
-            invVals[2, 1] = m01 * m20 - m00 * m21;
-            invVals[2, 2] = m00 * m11 - m01 * m10;
-
-            float invDet = 1.0f/det;
-            for (int row = 0; row < 3; row++)
-            {
-                for (int col = 0; col < 3; col++)
-                    invVals[row, col] *= invDet;
-            }
-        }
-
-        /// <summary>
-        /// Returns a transpose of the matrix (switched columns and rows).
-        /// </summary>
-        public void Transpose()
-        {
-            float tmp = m10;
-            m10 = m01;
-            m01 = tmp;
-
-            tmp = m20;
-            m20 = m02;
-            m02 = tmp;
-
-            tmp = m12;
-            m12 = m21;
-            m21 = tmp;
-        }
-
-        /// <summary>
-        /// Calculates the matrix determinant.
-        /// </summary>
-        /// <returns>Determinant of the matrix.</returns>
-        public float Determinant()
-        {
-            float cofactor00 = m11 * m22 - m12 * m21;
-            float cofactor10 = m12 * m20 - m10 * m22;
-            float cofactor20 = m10 * m21 - m11 * m20;
-
-            float det = m00 * cofactor00 + m01 * cofactor10 + m02 * cofactor20;
-
-            return det;
-        }
-
-        /// <summary>
-        /// Transforms the given vector by this matrix and returns the newly transformed vector.
-        /// </summary>
-        /// <param name="vec">Three dimensional vector to transform.</param>
-        /// <returns>Vector transformed by the matrix.</returns>
-        public Vector3 Transform(Vector3 vec)
-        {
-            Vector3 outVec;
-            outVec.x = m00 * vec.x + m01 * vec.y + m02 * vec.z;
-            outVec.y = m10 * vec.x + m11 * vec.y + m12 * vec.z;
-            outVec.z = m20 * vec.x + m21 * vec.y + m22 * vec.z;
-            return outVec;
-        }
-
-        /// <summary>
-        /// Decomposes the matrix into a set of values.
-        /// </summary>
-        /// <param name="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>
-        /// <param name="vecD">If the matrix is affine these will be scaling factors of the matrix.</param>
-        /// <param name="vecU">If the matrix is affine these will be shear factors of the matrix.</param>
-        public void QDUDecomposition(out Matrix3 matQ, out Vector3 vecD, out Vector3 vecU)
-        {
-            matQ = new Matrix3();
-            vecD = new Vector3();
-            vecU = new Vector3();
-
-            // Build orthogonal matrix Q
-            float invLength = MathEx.InvSqrt(m00*m00 + m10*m10 + m20*m20);
-            matQ.m00 = m00*invLength;
-            matQ.m10 = m10*invLength;
-            matQ.m20 = m20*invLength;
-
-            float dot = matQ.m00*m01 + matQ.m10*m11 + matQ.m20*m21;
-            matQ.m01 = m01-dot*matQ.m00;
-            matQ.m11 = m11-dot*matQ.m10;
-            matQ.m21 = m21-dot*matQ.m20;
-
-            invLength = MathEx.InvSqrt(matQ.m01*matQ.m01 + matQ.m11*matQ.m11 + matQ.m21*matQ.m21);
-            matQ.m01 *= invLength;
-            matQ.m11 *= invLength;
-            matQ.m21 *= invLength;
-
-            dot = matQ.m00*m02 + matQ.m10*m12 + matQ.m20*m22;
-            matQ.m02 = m02-dot*matQ.m00;
-            matQ.m12 = m12-dot*matQ.m10;
-            matQ.m22 = m22-dot*matQ.m20;
-
-            dot = matQ.m01*m02 + matQ.m11*m12 + matQ.m21*m22;
-            matQ.m02 -= dot*matQ.m01;
-            matQ.m12 -= dot*matQ.m11;
-            matQ.m22 -= dot*matQ.m21;
-
-            invLength = MathEx.InvSqrt(matQ.m02*matQ.m02 + matQ.m12*matQ.m12 + matQ.m22*matQ.m22);
-            matQ.m02 *= invLength;
-            matQ.m12 *= invLength;
-            matQ.m22 *= invLength;
-
-            // Guarantee that orthogonal matrix has determinant 1 (no reflections)
-            float fDet = matQ.m00*matQ.m11*matQ.m22 + matQ.m01*matQ.m12*matQ.m20 +
-                matQ.m02*matQ.m10*matQ.m21 - matQ.m02*matQ.m11*matQ.m20 -
-                matQ.m01*matQ.m10*matQ.m22 - matQ.m00*matQ.m12*matQ.m21;
-
-            if (fDet < 0.0f)
-            {
-                matQ.m00 = -matQ.m00;
-                matQ.m01 = -matQ.m01;
-                matQ.m02 = -matQ.m02;
-                matQ.m10 = -matQ.m10;
-                matQ.m11 = -matQ.m11;
-                matQ.m12 = -matQ.m12;
-                matQ.m20 = -matQ.m20;
-                matQ.m21 = -matQ.m21;
-                matQ.m21 = -matQ.m22;
-            }
-
-            // Build "right" matrix R
-            Matrix3 matRight = new Matrix3();
-            matRight.m00 = matQ.m00 * m00 + matQ.m10 * m10 + matQ.m20 * m20;
-            matRight.m01 = matQ.m00 * m01 + matQ.m10 * m11 + matQ.m20 * m21;
-            matRight.m11 = matQ.m01 * m01 + matQ.m11 * m11 + matQ.m21 * m21;
-            matRight.m02 = matQ.m00 * m02 + matQ.m10 * m12 + matQ.m20 * m22;
-            matRight.m12 = matQ.m01 * m02 + matQ.m11 * m12 + matQ.m21 * m22;
-            matRight.m22 = matQ.m02 * m02 + matQ.m12 * m12 + matQ.m22 * m22;
-
-            // The scaling component
-            vecD[0] = matRight.m00;
-            vecD[1] = matRight.m11;
-            vecD[2] = matRight.m22;
-
-            // The shear component
-            float invD0 = 1.0f/vecD[0];
-            vecU[0] = matRight.m01 * invD0;
-            vecU[1] = matRight.m02 * invD0;
-            vecU[2] = matRight.m12 / vecD[1];
-        }
-
-        /// <summary>
-        /// Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
-        /// </summary>
-        /// <returns>Euler angles in degrees representing the rotation in this matrix.</returns>
-        public Vector3 ToEulerAngles()
-        {
-            Radian xAngle = -MathEx.Asin(this[1, 2]);
-		    if (xAngle < MathEx.HalfPi)
-		    {
-			    if (xAngle > -MathEx.HalfPi)
-			    {
-				    Radian yAngle = MathEx.Atan2(this[0, 2], this[2, 2]);
-                    Radian zAngle = MathEx.Atan2(this[1, 0], this[1, 1]);
-
-                    return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
-			    }
-			    else
-			    {
-				    // Note: Not an unique solution.
-			        xAngle = -MathEx.HalfPi;
-                    Radian yAngle = MathEx.Atan2(-this[0, 1], this[0, 0]);
-				    Radian zAngle = (Radian)0.0f;
-				    
-                    return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
-			    }
-		    }
-		    else
-		    {
-			    // Note: Not an unique solution.
-                xAngle = MathEx.HalfPi;
-                Radian yAngle = MathEx.Atan2(this[0, 1], this[0, 0]);
-                Radian zAngle = (Radian)0.0f; 
-
-                return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
-		    }
-        }
-
-        /// <summary>
-        /// Converts an orthonormal matrix to quaternion representation.
-        /// </summary>
-        /// <returns>Quaternion representing the rotation in this matrix.</returns>
-        public Quaternion ToQuaternion()
-        {
-            return Quaternion.FromRotationMatrix(this);
-        }
-
-        /// <summary>
-        /// Converts an orthonormal matrix to axis angle representation.
-        /// </summary>
-        /// <param name="axis">Axis around which the rotation is performed.</param>
-        /// <param name="angle">Amount of rotation.</param>
-        public void ToAxisAngle(out Vector3 axis, out Degree angle)
-        {
-            float trace = m00 + m11 + m22;
-            float cos = 0.5f*(trace-1.0f);
-            Radian radians = (Radian)MathEx.Acos(cos);  // In [0, PI]
-            angle = radians;
-
-            if (radians > (Radian)0.0f)
-            {
-                if (radians < MathEx.Pi)
-                {
-                    axis.x = m21 - m12;
-                    axis.y = m02 - m20;
-                    axis.z = m10 - m01;
-
-                    axis.Normalize();
-                }
-                else
-                {
-                    // Angle is PI
-                    float halfInverse;
-                    if (m00 >= m11)
-                    {
-                        // r00 >= r11
-                        if (m00 >= m22)
-                        {
-                            // r00 is maximum diagonal term
-                            axis.x = 0.5f*MathEx.Sqrt(m00 - m11 - m22 + 1.0f);
-                            halfInverse = 0.5f/axis.x;
-                            axis.y = halfInverse*m01;
-                            axis.z = halfInverse*m02;
-                        }
-                        else
-                        {
-                            // r22 is maximum diagonal term
-                            axis.z = 0.5f*MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
-                            halfInverse = 0.5f/axis.z;
-                            axis.x = halfInverse*m02;
-                            axis.y = halfInverse*m12;
-                        }
-                    }
-                    else
-                    {
-                        // r11 > r00
-                        if (m11 >= m22)
-                        {
-                            // r11 is maximum diagonal term
-                            axis.y = 0.5f*MathEx.Sqrt(m11 - m00 - m22 + 1.0f);
-                            halfInverse  = 0.5f/axis.y;
-                            axis.x = halfInverse*m01;
-                            axis.z = halfInverse*m12;
-                        }
-                        else
-                        {
-                            // r22 is maximum diagonal term
-                            axis.z = 0.5f*MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
-                            halfInverse = 0.5f/axis.z;
-                            axis.x = halfInverse*m02;
-                            axis.y = halfInverse*m12;
-                        }
-                    }
-                }
-            }
-            else
-            {
-                // The angle is 0 and the matrix is the identity.  Any axis will
-                // work, so just use the x-axis.
-                axis.x = 1.0f;
-                axis.y = 0.0f;
-                axis.z = 0.0f;
-            }
-        }
-
-        /// <summary>
-        /// Calculates the inverse of the matrix if it exists.
-        /// </summary>
-        /// <param name="mat">Matrix to calculate the inverse of.</param>
-        /// <returns>Inverse of the matrix.</returns>
-        public static Matrix3 Inverse(Matrix3 mat)
-        {
-            Matrix3 copy = mat;
-            copy.Invert();
-            return copy;
-        }
-
-
-        /// <summary>
-        /// Calculates the transpose of the matrix.
-        /// </summary>
-        /// <param name="mat">Matrix to calculate the transpose of.</param>
-        /// <returns>Transpose of the matrix.</returns>
-        public static Matrix3 Transpose(Matrix3 mat)
-        {
-            Matrix3 copy = mat;
-            copy.Transpose();
-            return copy;
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation.
-        /// </summary>
-        /// <param name="euler">Euler angles in degrees.</param>
-        /// <param name="order">The order in which rotations will be applied. Different rotations can be created depending 
-        /// on the order.</param>
-        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
-        public static Matrix3 FromEuler(Vector3 euler, EulerAngleOrder order)
-        {
-            return FromEuler(new Degree(euler.x), new Degree(euler.y), new Degree(euler.y), order);
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation.
-        /// </summary>
-        /// <param name="xAngle">Pitch angle of rotation.</param>
-        /// <param name="yAngle">Yar angle of rotation.</param>
-        /// <param name="zAngle">Roll angle of rotation.</param>
-        /// <param name="order">The order in which rotations will be applied. Different rotations can be created depending
-        /// on the order.</param>
-        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
-        public static Matrix3 FromEuler(Radian xAngle, Radian yAngle, Radian zAngle, EulerAngleOrder order)
-        {
-            EulerAngleOrderData l = EA_LOOKUP[(int)order];
-
-		    Matrix3[] mats = new Matrix3[3];
-
-            float cx = MathEx.Cos(xAngle);
-            float sx = MathEx.Sin(xAngle);
-		    mats[0] = new Matrix3(
-			    1.0f, 0.0f, 0.0f,
-			    0.0f, cx, -sx,
-			    0.0f, sx, cx);
-
-            float cy = MathEx.Cos(yAngle);
-            float sy = MathEx.Sin(yAngle);
-		    mats[1] = new Matrix3(
-			    cy, 0.0f, sy,
-			    0.0f, 1.0f, 0.0f,
-			    -sy, 0.0f, cy);
-
-            float cz = MathEx.Cos(zAngle);
-            float sz = MathEx.Sin(zAngle);
-		    mats[2] = new Matrix3(
-			    cz, -sz, 0.0f,
-			    sz, cz, 0.0f,
-			    0.0f, 0.0f, 1.0f);
-	
-		    return mats[l.a]*(mats[l.b]*mats[l.c]);
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation. Angles are applied in YXZ 
-        /// order.
-        /// </summary>
-        /// <param name="euler">Euler angles in degrees.</param>
-        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
-        public static Matrix3 FromEuler(Vector3 euler)
-        {
-            return FromEuler(new Degree(euler.x), new Degree(euler.y), new Degree(euler.y));
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation. Angles are applied in YXZ 
-        /// order.
-        /// </summary>
-        /// <param name="xAngle">Pitch angle of rotation.</param>
-        /// <param name="yAngle">Yar angle of rotation.</param>
-        /// <param name="zAngle">Roll angle of rotation.</param>
-        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
-        public static Matrix3 FromEuler(Radian xAngle, Radian yAngle, Radian zAngle)
-        {
-            Matrix3 m = new Matrix3();
-
-		    float cx = MathEx.Cos(xAngle);
-		    float sx = MathEx.Sin(xAngle);
-
-		    float cy = MathEx.Cos(yAngle);
-		    float sy = MathEx.Sin(yAngle);
-
-            float cz = MathEx.Cos(zAngle);
-		    float sz = MathEx.Sin(zAngle);
-
-		    m[0, 0] = cy * cz + sx * sy * sz;
-		    m[0, 1] = cz * sx * sy - cy * sz;
-		    m[0, 2] = cx * sy;
-
-		    m[1, 0] = cx * sz;
-		    m[1, 1] = cx * cz;
-		    m[1, 2] = -sx;
-
-		    m[2, 0] = -cz * sy + cy * sx * sz;
-		    m[2, 1] = cy * cz * sx + sy * sz;
-		    m[2, 2] = cx * cy;
-
-            return m;
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from axis/angle rotation.
-        /// </summary>
-        /// <param name="axis">Axis around which the rotation is performed.</param>
-        /// <param name="angle">Amount of rotation.</param>
-        /// <returns>Rotation matrix that can rotate an object around the specified axis for the specified amount.</returns>
-        public static Matrix3 FromAxisAngle(Vector3 axis, Degree angle)
-        {
-            Matrix3 mat;
-
-            float cos = MathEx.Cos(angle);
-            float sin = MathEx.Sin(angle);
-            float oneMinusCos = 1.0f - cos;
-            float x2 = axis.x * axis.x;
-            float y2 = axis.y * axis.y;
-            float z2 = axis.z * axis.z;
-            float xym = axis.x * axis.y * oneMinusCos;
-            float xzm = axis.x * axis.z * oneMinusCos;
-            float yzm = axis.y * axis.z * oneMinusCos;
-            float xSin = axis.x * sin;
-            float ySin = axis.y * sin;
-            float zSin = axis.z * sin;
-
-            mat.m00 = x2 * oneMinusCos + cos;
-            mat.m01 = xym - zSin;
-            mat.m02 = xzm + ySin;
-            mat.m10 = xym + zSin;
-            mat.m11 = y2 * oneMinusCos + cos;
-            mat.m12 = yzm - xSin;
-            mat.m20 = xzm - ySin;
-            mat.m21 = yzm + xSin;
-            mat.m22 = z2 * oneMinusCos + cos;
-
-            return mat;
-        }
-
-        /// <summary>
-        /// Creates a rotation matrix from a quaternion rotation.
-        /// </summary>
-        /// <param name="quat">Quaternion to create the matrix from.</param>
-        /// <returns>Rotation matrix containing the equivalent rotation of the provided quaternion.</returns>
-        public static Matrix3 FromQuaternion(Quaternion quat)
-        {
-            return quat.ToRotationMatrix();
-        }
-
-        /// <inheritdoc/>
-        public override string ToString()
-        {
-            return String.Format("({0}, {1}, {2},\n{3}, {4}, {5}\n{6}, {7}, {8})",
-                m00, m01, m02, m10, m11, m12, m20, m21, m22);
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.InteropServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// A 3x3 matrix. Can be used for non-homogenous transformations of three dimensional vectors and points.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct Matrix3 // Note: Must match C++ class Matrix3
+    {
+        /// <summary>
+        /// Contains constant data that is used when calculating euler angles in a certain order.
+        /// </summary>
+        private struct EulerAngleOrderData
+		{
+            public EulerAngleOrderData(int a, int b, int c, float sign)
+            {
+                this.a = a;
+                this.b = b;
+                this.c = c;
+                this.sign = sign;
+            }
+
+			public int a, b, c;
+            public float sign;
+		};
+
+        private static EulerAngleOrderData[] EA_LOOKUP = 
+		{ new EulerAngleOrderData(0, 1, 2, 1.0f), new EulerAngleOrderData(0, 2, 1, -1.0f), new EulerAngleOrderData(1, 0, 2, -1.0f),
+		  new EulerAngleOrderData(1, 2, 0, 1.0f), new EulerAngleOrderData(2, 0, 1,  1.0f), new EulerAngleOrderData(2, 1, 0, -1.0f) };
+
+        /// <summary>
+        /// A matrix with all zero values.
+        /// </summary>
+        public static readonly Matrix3 Zero = new Matrix3();
+
+        /// <summary>
+        /// Identity matrix.
+        /// </summary>
+        public static readonly Matrix3 Identity = new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1);
+
+        public float m00;
+        public float m01;
+        public float m02;
+        public float m10;
+        public float m11;
+        public float m12;
+        public float m20;
+        public float m21;
+        public float m22;
+
+        /// <summary>
+        /// Creates a new matrix with the specified elements.
+        /// </summary>
+        public Matrix3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
+        {
+            this.m00 = m00;
+            this.m01 = m01;
+            this.m02 = m02;
+            this.m10 = m10;
+            this.m11 = m11;
+            this.m12 = m12;
+            this.m20 = m20;
+            this.m21 = m21;
+            this.m22 = m22;
+        }
+
+        /// <summary>
+        /// Value of the specified element in the matrix.
+        /// </summary>
+        /// <param name="row">Row index of the element to retrieve.</param>
+        /// <param name="column">Column index of the element to retrieve.</param>
+        /// <returns>Value of the element.</returns>
+        public float this[int row, int column]
+        {
+            get
+            {
+                return this[row * 3 + column];
+            }
+            set
+            {
+                this[row * 3 + column] = value;
+            }
+        }
+
+        /// <summary>
+        /// Value of the specified element in the matrix using a linear index.
+        /// Linear index can be calculated using the following formula: idx = row * 3 + column. 
+        /// </summary>
+        /// <param name="index">Linear index to get the value of.</param>
+        /// <returns>Value of the element.</returns>
+        public float this[int index]
+        {
+            get
+            {
+                switch (index)
+                {
+                    case 0:
+                        return m00;
+                    case 1:
+                        return m01;
+                    case 2:
+                        return m02;
+                    case 3:
+                        return m10;
+                    case 4:
+                        return m11;
+                    case 5:
+                        return m12;
+                    case 6:
+                        return m20;
+                    case 7:
+                        return m21;
+                    case 8:
+                        return m22;
+                    default:
+                        throw new IndexOutOfRangeException("Invalid matrix index.");
+                }
+
+            }
+            set
+            {
+                switch (index)
+                {
+                    case 0:
+                        m00 = value;
+                        break;
+                    case 1:
+                        m01 = value;
+                        break;
+                    case 2:
+                        m02 = value;
+                        break;
+                    case 3:
+                        m10 = value;
+                        break;
+                    case 4:
+                        m11 = value;
+                        break;
+                    case 5:
+                        m12 = value;
+                        break;
+                    case 6:
+                        m20 = value;
+                        break;
+                    case 7:
+                        m21 = value;
+                        break;
+                    case 8:
+                        m22 = value;
+                        break;
+                    default:
+                        throw new IndexOutOfRangeException("Invalid matrix index.");
+                }
+            }
+        }
+
+        public static Matrix3 operator *(Matrix3 lhs, Matrix3 rhs)
+        {
+            return new Matrix3()
+            {
+                m00 = lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10 + lhs.m02 * rhs.m20,
+                m01 = lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11 + lhs.m02 * rhs.m21,
+                m02 = lhs.m00 * rhs.m02 + lhs.m01 * rhs.m12 + lhs.m02 * rhs.m22,
+                m10 = lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10 + lhs.m12 * rhs.m20,
+                m11 = lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11 + lhs.m12 * rhs.m21,
+                m12 = lhs.m10 * rhs.m02 + lhs.m11 * rhs.m12 + lhs.m12 * rhs.m22,
+                m20 = lhs.m20 * rhs.m00 + lhs.m21 * rhs.m10 + lhs.m22 * rhs.m20,
+                m21 = lhs.m20 * rhs.m01 + lhs.m21 * rhs.m11 + lhs.m22 * rhs.m21,
+                m22 = lhs.m20 * rhs.m02 + lhs.m21 * rhs.m12 + lhs.m22 * rhs.m22,
+            };
+        }
+
+        public static bool operator== (Matrix3 lhs, Matrix3 rhs)
+        {
+            if (lhs.m00 == rhs.m00 && lhs.m01 == rhs.m01 && lhs.m02 == rhs.m02 && 
+                lhs.m10 == rhs.m10 && lhs.m11 == rhs.m11 && lhs.m12 == rhs.m12 &&
+                lhs.m20 == rhs.m20 && lhs.m21 == rhs.m21 && lhs.m22 == rhs.m22)
+                return true;
+            else
+                return false;
+        }
+
+        public static bool operator !=(Matrix3 lhs, Matrix3 rhs)
+        {
+            return !(lhs == rhs);
+        }
+
+        /// <inheritdoc/>
+        public override int GetHashCode()
+        {
+            float hash1 = m00.GetHashCode() ^ m10.GetHashCode() << 2 ^ m20.GetHashCode() >> 2;
+            float hash2 = m01.GetHashCode() ^ m11.GetHashCode() << 2 ^ m21.GetHashCode() >> 2;
+            float hash3 = m02.GetHashCode() ^ m12.GetHashCode() << 2 ^ m22.GetHashCode() >> 2;
+
+            return hash1.GetHashCode() ^ hash2.GetHashCode() << 2 ^ hash3.GetHashCode() >> 2;
+        }
+
+        /// <inheritdoc/>
+        public override bool Equals(object other)
+        {
+            if (!(other is Matrix3))
+                return false;
+
+            Matrix3 mat = (Matrix3)other;
+            if (m00 == mat.m00 && m01 == mat.m01 && m02 == mat.m02 &&
+                m10 == mat.m10 && m11 == mat.m11 && m12 == mat.m12 &&
+                m20 == mat.m20 && m21 == mat.m21 && m22 == mat.m22)
+                return true;
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// Calculates an inverse of the matrix if it exists.
+        /// </summary>
+        public void Invert()
+        {
+            float[,] invVals = new float[3,3];
+
+            invVals[0, 0] = m11 * m22 - m12 * m21;
+            invVals[1, 0] = m12 * m20 - m10 * m22;
+            invVals[2, 0] = m10 * m21 - m11 * m20;
+
+            float det = m00 * invVals[0, 0] + m01 * invVals[1, 0] + m02 * invVals[2, 0];
+
+            if (MathEx.Abs(det) <= 1e-06f)
+                throw new DivideByZeroException("Matrix determinant is zero. Cannot invert.");
+
+            invVals[0, 1] = m02 * m21 - m01 * m22;
+            invVals[0, 2] = m01 * m12 - m02 * m11;
+
+            invVals[1, 1] = m00 * m22 - m02 * m20;
+            invVals[1, 2] = m02 * m10 - m00 * m12;
+
+            invVals[2, 1] = m01 * m20 - m00 * m21;
+            invVals[2, 2] = m00 * m11 - m01 * m10;
+
+            float invDet = 1.0f/det;
+            for (int row = 0; row < 3; row++)
+            {
+                for (int col = 0; col < 3; col++)
+                    invVals[row, col] *= invDet;
+            }
+        }
+
+        /// <summary>
+        /// Returns a transpose of the matrix (switched columns and rows).
+        /// </summary>
+        public void Transpose()
+        {
+            float tmp = m10;
+            m10 = m01;
+            m01 = tmp;
+
+            tmp = m20;
+            m20 = m02;
+            m02 = tmp;
+
+            tmp = m12;
+            m12 = m21;
+            m21 = tmp;
+        }
+
+        /// <summary>
+        /// Calculates the matrix determinant.
+        /// </summary>
+        /// <returns>Determinant of the matrix.</returns>
+        public float Determinant()
+        {
+            float cofactor00 = m11 * m22 - m12 * m21;
+            float cofactor10 = m12 * m20 - m10 * m22;
+            float cofactor20 = m10 * m21 - m11 * m20;
+
+            float det = m00 * cofactor00 + m01 * cofactor10 + m02 * cofactor20;
+
+            return det;
+        }
+
+        /// <summary>
+        /// Transforms the given vector by this matrix and returns the newly transformed vector.
+        /// </summary>
+        /// <param name="vec">Three dimensional vector to transform.</param>
+        /// <returns>Vector transformed by the matrix.</returns>
+        public Vector3 Transform(Vector3 vec)
+        {
+            Vector3 outVec;
+            outVec.x = m00 * vec.x + m01 * vec.y + m02 * vec.z;
+            outVec.y = m10 * vec.x + m11 * vec.y + m12 * vec.z;
+            outVec.z = m20 * vec.x + m21 * vec.y + m22 * vec.z;
+            return outVec;
+        }
+
+        /// <summary>
+        /// Decomposes the matrix into a set of values.
+        /// </summary>
+        /// <param name="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>
+        /// <param name="vecD">If the matrix is affine these will be scaling factors of the matrix.</param>
+        /// <param name="vecU">If the matrix is affine these will be shear factors of the matrix.</param>
+        public void QDUDecomposition(out Matrix3 matQ, out Vector3 vecD, out Vector3 vecU)
+        {
+            matQ = new Matrix3();
+            vecD = new Vector3();
+            vecU = new Vector3();
+
+            // Build orthogonal matrix Q
+            float invLength = MathEx.InvSqrt(m00*m00 + m10*m10 + m20*m20);
+            matQ.m00 = m00*invLength;
+            matQ.m10 = m10*invLength;
+            matQ.m20 = m20*invLength;
+
+            float dot = matQ.m00*m01 + matQ.m10*m11 + matQ.m20*m21;
+            matQ.m01 = m01-dot*matQ.m00;
+            matQ.m11 = m11-dot*matQ.m10;
+            matQ.m21 = m21-dot*matQ.m20;
+
+            invLength = MathEx.InvSqrt(matQ.m01*matQ.m01 + matQ.m11*matQ.m11 + matQ.m21*matQ.m21);
+            matQ.m01 *= invLength;
+            matQ.m11 *= invLength;
+            matQ.m21 *= invLength;
+
+            dot = matQ.m00*m02 + matQ.m10*m12 + matQ.m20*m22;
+            matQ.m02 = m02-dot*matQ.m00;
+            matQ.m12 = m12-dot*matQ.m10;
+            matQ.m22 = m22-dot*matQ.m20;
+
+            dot = matQ.m01*m02 + matQ.m11*m12 + matQ.m21*m22;
+            matQ.m02 -= dot*matQ.m01;
+            matQ.m12 -= dot*matQ.m11;
+            matQ.m22 -= dot*matQ.m21;
+
+            invLength = MathEx.InvSqrt(matQ.m02*matQ.m02 + matQ.m12*matQ.m12 + matQ.m22*matQ.m22);
+            matQ.m02 *= invLength;
+            matQ.m12 *= invLength;
+            matQ.m22 *= invLength;
+
+            // Guarantee that orthogonal matrix has determinant 1 (no reflections)
+            float fDet = matQ.m00*matQ.m11*matQ.m22 + matQ.m01*matQ.m12*matQ.m20 +
+                matQ.m02*matQ.m10*matQ.m21 - matQ.m02*matQ.m11*matQ.m20 -
+                matQ.m01*matQ.m10*matQ.m22 - matQ.m00*matQ.m12*matQ.m21;
+
+            if (fDet < 0.0f)
+            {
+                matQ.m00 = -matQ.m00;
+                matQ.m01 = -matQ.m01;
+                matQ.m02 = -matQ.m02;
+                matQ.m10 = -matQ.m10;
+                matQ.m11 = -matQ.m11;
+                matQ.m12 = -matQ.m12;
+                matQ.m20 = -matQ.m20;
+                matQ.m21 = -matQ.m21;
+                matQ.m21 = -matQ.m22;
+            }
+
+            // Build "right" matrix R
+            Matrix3 matRight = new Matrix3();
+            matRight.m00 = matQ.m00 * m00 + matQ.m10 * m10 + matQ.m20 * m20;
+            matRight.m01 = matQ.m00 * m01 + matQ.m10 * m11 + matQ.m20 * m21;
+            matRight.m11 = matQ.m01 * m01 + matQ.m11 * m11 + matQ.m21 * m21;
+            matRight.m02 = matQ.m00 * m02 + matQ.m10 * m12 + matQ.m20 * m22;
+            matRight.m12 = matQ.m01 * m02 + matQ.m11 * m12 + matQ.m21 * m22;
+            matRight.m22 = matQ.m02 * m02 + matQ.m12 * m12 + matQ.m22 * m22;
+
+            // The scaling component
+            vecD[0] = matRight.m00;
+            vecD[1] = matRight.m11;
+            vecD[2] = matRight.m22;
+
+            // The shear component
+            float invD0 = 1.0f/vecD[0];
+            vecU[0] = matRight.m01 * invD0;
+            vecU[1] = matRight.m02 * invD0;
+            vecU[2] = matRight.m12 / vecD[1];
+        }
+
+        /// <summary>
+        /// Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
+        /// </summary>
+        /// <returns>Euler angles in degrees representing the rotation in this matrix.</returns>
+        public Vector3 ToEulerAngles()
+        {
+            Radian xAngle = -MathEx.Asin(this[1, 2]);
+		    if (xAngle < MathEx.HalfPi)
+		    {
+			    if (xAngle > -MathEx.HalfPi)
+			    {
+				    Radian yAngle = MathEx.Atan2(this[0, 2], this[2, 2]);
+                    Radian zAngle = MathEx.Atan2(this[1, 0], this[1, 1]);
+
+                    return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
+			    }
+			    else
+			    {
+				    // Note: Not an unique solution.
+			        xAngle = -MathEx.HalfPi;
+                    Radian yAngle = MathEx.Atan2(-this[0, 1], this[0, 0]);
+				    Radian zAngle = (Radian)0.0f;
+
+                    return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
+			    }
+		    }
+		    else
+		    {
+			    // Note: Not an unique solution.
+                xAngle = MathEx.HalfPi;
+                Radian yAngle = MathEx.Atan2(this[0, 1], this[0, 0]);
+                Radian zAngle = (Radian)0.0f;
+
+                return new Vector3(xAngle.Degrees, yAngle.Degrees, zAngle.Degrees);
+		    }
+        }
+
+        /// <summary>
+        /// Converts an orthonormal matrix to quaternion representation.
+        /// </summary>
+        /// <returns>Quaternion representing the rotation in this matrix.</returns>
+        public Quaternion ToQuaternion()
+        {
+            return Quaternion.FromRotationMatrix(this);
+        }
+
+        /// <summary>
+        /// Converts an orthonormal matrix to axis angle representation.
+        /// </summary>
+        /// <param name="axis">Axis around which the rotation is performed.</param>
+        /// <param name="angle">Amount of rotation.</param>
+        public void ToAxisAngle(out Vector3 axis, out Degree angle)
+        {
+            float trace = m00 + m11 + m22;
+            float cos = 0.5f*(trace-1.0f);
+            Radian radians = (Radian)MathEx.Acos(cos);  // In [0, PI]
+            angle = radians;
+
+            if (radians > (Radian)0.0f)
+            {
+                if (radians < MathEx.Pi)
+                {
+                    axis.x = m21 - m12;
+                    axis.y = m02 - m20;
+                    axis.z = m10 - m01;
+
+                    axis.Normalize();
+                }
+                else
+                {
+                    // Angle is PI
+                    float halfInverse;
+                    if (m00 >= m11)
+                    {
+                        // r00 >= r11
+                        if (m00 >= m22)
+                        {
+                            // r00 is maximum diagonal term
+                            axis.x = 0.5f*MathEx.Sqrt(m00 - m11 - m22 + 1.0f);
+                            halfInverse = 0.5f/axis.x;
+                            axis.y = halfInverse*m01;
+                            axis.z = halfInverse*m02;
+                        }
+                        else
+                        {
+                            // r22 is maximum diagonal term
+                            axis.z = 0.5f*MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
+                            halfInverse = 0.5f/axis.z;
+                            axis.x = halfInverse*m02;
+                            axis.y = halfInverse*m12;
+                        }
+                    }
+                    else
+                    {
+                        // r11 > r00
+                        if (m11 >= m22)
+                        {
+                            // r11 is maximum diagonal term
+                            axis.y = 0.5f*MathEx.Sqrt(m11 - m00 - m22 + 1.0f);
+                            halfInverse  = 0.5f/axis.y;
+                            axis.x = halfInverse*m01;
+                            axis.z = halfInverse*m12;
+                        }
+                        else
+                        {
+                            // r22 is maximum diagonal term
+                            axis.z = 0.5f*MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
+                            halfInverse = 0.5f/axis.z;
+                            axis.x = halfInverse*m02;
+                            axis.y = halfInverse*m12;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // The angle is 0 and the matrix is the identity.  Any axis will
+                // work, so just use the x-axis.
+                axis.x = 1.0f;
+                axis.y = 0.0f;
+                axis.z = 0.0f;
+            }
+        }
+
+        /// <summary>
+        /// Calculates the inverse of the matrix if it exists.
+        /// </summary>
+        /// <param name="mat">Matrix to calculate the inverse of.</param>
+        /// <returns>Inverse of the matrix.</returns>
+        public static Matrix3 Inverse(Matrix3 mat)
+        {
+            Matrix3 copy = mat;
+            copy.Invert();
+            return copy;
+        }
+
+
+        /// <summary>
+        /// Calculates the transpose of the matrix.
+        /// </summary>
+        /// <param name="mat">Matrix to calculate the transpose of.</param>
+        /// <returns>Transpose of the matrix.</returns>
+        public static Matrix3 Transpose(Matrix3 mat)
+        {
+            Matrix3 copy = mat;
+            copy.Transpose();
+            return copy;
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation.
+        /// </summary>
+        /// <param name="euler">Euler angles in degrees.</param>
+        /// <param name="order">The order in which rotations will be applied. Different rotations can be created depending 
+        /// on the order.</param>
+        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
+        public static Matrix3 FromEuler(Vector3 euler, EulerAngleOrder order)
+        {
+            return FromEuler(new Degree(euler.x), new Degree(euler.y), new Degree(euler.y), order);
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation.
+        /// </summary>
+        /// <param name="xAngle">Pitch angle of rotation.</param>
+        /// <param name="yAngle">Yar angle of rotation.</param>
+        /// <param name="zAngle">Roll angle of rotation.</param>
+        /// <param name="order">The order in which rotations will be applied. Different rotations can be created depending
+        /// on the order.</param>
+        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
+        public static Matrix3 FromEuler(Radian xAngle, Radian yAngle, Radian zAngle, EulerAngleOrder order)
+        {
+            EulerAngleOrderData l = EA_LOOKUP[(int)order];
+
+		    Matrix3[] mats = new Matrix3[3];
+
+            float cx = MathEx.Cos(xAngle);
+            float sx = MathEx.Sin(xAngle);
+		    mats[0] = new Matrix3(
+			    1.0f, 0.0f, 0.0f,
+			    0.0f, cx, -sx,
+			    0.0f, sx, cx);
+
+            float cy = MathEx.Cos(yAngle);
+            float sy = MathEx.Sin(yAngle);
+		    mats[1] = new Matrix3(
+			    cy, 0.0f, sy,
+			    0.0f, 1.0f, 0.0f,
+			    -sy, 0.0f, cy);
+
+            float cz = MathEx.Cos(zAngle);
+            float sz = MathEx.Sin(zAngle);
+		    mats[2] = new Matrix3(
+			    cz, -sz, 0.0f,
+			    sz, cz, 0.0f,
+			    0.0f, 0.0f, 1.0f);
+	
+		    return mats[l.a]*(mats[l.b]*mats[l.c]);
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation. Angles are applied in YXZ 
+        /// order.
+        /// </summary>
+        /// <param name="euler">Euler angles in degrees.</param>
+        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
+        public static Matrix3 FromEuler(Vector3 euler)
+        {
+            return FromEuler(new Degree(euler.x), new Degree(euler.y), new Degree(euler.y));
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from the provided euler angle (pitch/yaw/roll) rotation. Angles are applied in YXZ 
+        /// order.
+        /// </summary>
+        /// <param name="xAngle">Pitch angle of rotation.</param>
+        /// <param name="yAngle">Yar angle of rotation.</param>
+        /// <param name="zAngle">Roll angle of rotation.</param>
+        /// <returns>Rotation matrix that can rotate an object to the specified angles.</returns>
+        public static Matrix3 FromEuler(Radian xAngle, Radian yAngle, Radian zAngle)
+        {
+            Matrix3 m = new Matrix3();
+
+		    float cx = MathEx.Cos(xAngle);
+		    float sx = MathEx.Sin(xAngle);
+
+		    float cy = MathEx.Cos(yAngle);
+		    float sy = MathEx.Sin(yAngle);
+
+            float cz = MathEx.Cos(zAngle);
+		    float sz = MathEx.Sin(zAngle);
+
+		    m[0, 0] = cy * cz + sx * sy * sz;
+		    m[0, 1] = cz * sx * sy - cy * sz;
+		    m[0, 2] = cx * sy;
+
+		    m[1, 0] = cx * sz;
+		    m[1, 1] = cx * cz;
+		    m[1, 2] = -sx;
+
+		    m[2, 0] = -cz * sy + cy * sx * sz;
+		    m[2, 1] = cy * cz * sx + sy * sz;
+		    m[2, 2] = cx * cy;
+
+            return m;
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from axis/angle rotation.
+        /// </summary>
+        /// <param name="axis">Axis around which the rotation is performed.</param>
+        /// <param name="angle">Amount of rotation.</param>
+        /// <returns>Rotation matrix that can rotate an object around the specified axis for the specified amount.</returns>
+        public static Matrix3 FromAxisAngle(Vector3 axis, Degree angle)
+        {
+            Matrix3 mat;
+
+            float cos = MathEx.Cos(angle);
+            float sin = MathEx.Sin(angle);
+            float oneMinusCos = 1.0f - cos;
+            float x2 = axis.x * axis.x;
+            float y2 = axis.y * axis.y;
+            float z2 = axis.z * axis.z;
+            float xym = axis.x * axis.y * oneMinusCos;
+            float xzm = axis.x * axis.z * oneMinusCos;
+            float yzm = axis.y * axis.z * oneMinusCos;
+            float xSin = axis.x * sin;
+            float ySin = axis.y * sin;
+            float zSin = axis.z * sin;
+
+            mat.m00 = x2 * oneMinusCos + cos;
+            mat.m01 = xym - zSin;
+            mat.m02 = xzm + ySin;
+            mat.m10 = xym + zSin;
+            mat.m11 = y2 * oneMinusCos + cos;
+            mat.m12 = yzm - xSin;
+            mat.m20 = xzm - ySin;
+            mat.m21 = yzm + xSin;
+            mat.m22 = z2 * oneMinusCos + cos;
+
+            return mat;
+        }
+
+        /// <summary>
+        /// Creates a rotation matrix from a quaternion rotation.
+        /// </summary>
+        /// <param name="quat">Quaternion to create the matrix from.</param>
+        /// <returns>Rotation matrix containing the equivalent rotation of the provided quaternion.</returns>
+        public static Matrix3 FromQuaternion(Quaternion quat)
+        {
+            return quat.ToRotationMatrix();
+        }
+
+        /// <inheritdoc/>
+        public override string ToString()
+        {
+            return String.Format("({0}, {1}, {2},\n{3}, {4}, {5}\n{6}, {7}, {8})",
+                m00, m01, m02, m10, m11, m12, m20, m21, m22);
+        }
+    }
+}

+ 4 - 4
Source/MBansheeEngine/Math/Quaternion.cs

@@ -287,7 +287,7 @@ namespace BansheeEngine
 			    if (fallbackAxis != Vector3.Zero)
 			    {
 				    // Rotate 180 degrees about the fallback axis
-				    this = FromAxisAngle(fallbackAxis, MathEx.Pi * MathEx.Rad2Deg);
+				    this = FromAxisAngle(fallbackAxis, MathEx.Pi);
 			    }
 			    else
 			    {
@@ -296,7 +296,7 @@ namespace BansheeEngine
                     if (axis.SqrdLength < ((1e-06f * 1e-06f))) // Pick another if collinear
 					    axis = Vector3.Cross(Vector3.YAxis, fromDirection);
 				    axis.Normalize();
-                    this = FromAxisAngle(axis, MathEx.Pi * MathEx.Rad2Deg);
+                    this = FromAxisAngle(axis, MathEx.Pi);
 			    }
 		    }
 		    else
@@ -452,7 +452,7 @@ namespace BansheeEngine
         /// <returns>Angle between the rotations, in degrees.</returns>
         public static Degree Angle(Quaternion a, Quaternion b)
         {
-            return (MathEx.Acos(MathEx.Min(MathEx.Abs(Dot(a, b)), 1.0f)) * 2.0f * MathEx.Rad2Deg);
+            return (MathEx.Acos(MathEx.Min(MathEx.Abs(Dot(a, b)), 1.0f)) * 2.0f);
         }
 
         /// <summary>
@@ -465,7 +465,7 @@ namespace BansheeEngine
             float fSqrLength = x*x+y*y+z*z;
 		    if (fSqrLength > 0.0f)
 		    {
-                angle = 2.0f * MathEx.Acos(w) * MathEx.Rad2Deg;
+                angle = 2.0f * MathEx.Acos(w);
 			    float fInvLength = MathEx.InvSqrt(fSqrLength);
 			    axis.x = x*fInvLength;
 			    axis.y = y*fInvLength;

+ 71 - 71
Source/MBansheeEngine/Physics/SphereCollider.cs

@@ -1,71 +1,71 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Collider with sphere geometry.
-    /// </summary>
-    public sealed class SphereCollider : Collider
-    {
-        [SerializeField]
-        private float radius;
-
-        /// <summary>
-        /// Radius of the sphere.
-        /// </summary>
-        public float Radius
-        {
-            get { return radius; }
-            set
-            {
-                if (radius == value)
-                    return;
-
-                radius = value;
-
-                if (Native != null)
-                {
-                    Native.Radius = value;
-
-                    if (parent != null)
-                        parent.UpdateMassDistribution();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Position of the sphere shape, relative to the component's scene object.
-        /// </summary>
-        public Vector3 Center
-        {
-            get { return serializableData.localPosition; }
-            set
-            {
-                if (serializableData.localPosition == value)
-                    return;
-
-                serializableData.localPosition = value;
-
-                if (Native != null)
-                    UpdateTransform();
-            }
-        }
-
-        /// <summary>
-        /// Returns the native sphere collider wrapped by this component.
-        /// </summary>
-        private NativeSphereCollider Native
-        {
-            get { return (NativeSphereCollider)native; }
-        }
-
-        /// <inheritdoc/>
-        internal override NativeCollider CreateCollider()
-        {
-            NativeSphereCollider sphereCollider = new NativeSphereCollider();
-            sphereCollider.Radius = radius;
-
-            return sphereCollider;
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider with sphere geometry.
+    /// </summary>
+    public sealed class SphereCollider : Collider
+    {
+        [SerializeField]
+        private float radius = 1.0f;
+
+        /// <summary>
+        /// Radius of the sphere.
+        /// </summary>
+        public float Radius
+        {
+            get { return radius; }
+            set
+            {
+                if (radius == value)
+                    return;
+
+                radius = value;
+
+                if (Native != null)
+                {
+                    Native.Radius = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Position of the sphere shape, relative to the component's scene object.
+        /// </summary>
+        public Vector3 Center
+        {
+            get { return serializableData.localPosition; }
+            set
+            {
+                if (serializableData.localPosition == value)
+                    return;
+
+                serializableData.localPosition = value;
+
+                if (Native != null)
+                    UpdateTransform();
+            }
+        }
+
+        /// <summary>
+        /// Returns the native sphere collider wrapped by this component.
+        /// </summary>
+        private NativeSphereCollider Native
+        {
+            get { return (NativeSphereCollider)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeCollider CreateCollider()
+        {
+            NativeSphereCollider sphereCollider = new NativeSphereCollider();
+            sphereCollider.Radius = radius;
+
+            return sphereCollider;
+        }
+    }
+}