Quellcode durchsuchen

Refactored Math

Marko Pintera vor 12 Jahren
Ursprung
Commit
5fa7bee5a7
50 geänderte Dateien mit 1090 neuen und 1724 gelöschten Zeilen
  1. 2 2
      BansheeEngine/Source/BsCamera.cpp
  2. 2 2
      BansheeEngine/Source/BsGUIInputBox.cpp
  3. 5 5
      BansheeEngine/Source/BsGUIInputTool.cpp
  4. 4 4
      BansheeEngine/Source/BsGUILayoutX.cpp
  5. 4 4
      BansheeEngine/Source/BsGUILayoutY.cpp
  6. 3 3
      BansheeEngine/Source/BsGUIManager.cpp
  7. 4 4
      BansheeEngine/Source/BsGUIScrollArea.cpp
  8. 1 1
      BansheeEngine/Source/BsGUIScrollBar.cpp
  9. 13 13
      BansheeEngine/Source/BsGUIScrollBarHandle.cpp
  10. 2 2
      BansheeEngine/Source/BsGUIViewport.cpp
  11. 5 5
      BansheeEngine/Source/BsGUIWidget.cpp
  12. 1 1
      BansheeEngine/Source/BsProfilerOverlay.cpp
  13. 4 4
      BansheeEngine/Source/BsSprite.cpp
  14. 13 18
      CSharpWrap.txt
  15. 7 7
      CamelotClient/Source/BsDockManager.cpp
  16. 1 1
      CamelotClient/Source/BsEditorWidgetContainer.cpp
  17. 2 2
      CamelotClient/Source/BsGUITabbedTitleBar.cpp
  18. 1 1
      CamelotClient/Source/CmDebugCamera.cpp
  19. 2 2
      CamelotCore/Include/CmTextureRTTI.h
  20. 2 2
      CamelotCore/Source/CmInput.cpp
  21. 2 2
      CamelotCore/Source/CmMeshHeap.cpp
  22. 1 1
      CamelotCore/Source/CmOSInputHandler.cpp
  23. 1 1
      CamelotCore/Source/CmProfiler.cpp
  24. 1 1
      CamelotCore/Source/CmTexture.cpp
  25. 4 4
      CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp
  26. 6 0
      CamelotUtility/CamelotUtility.vcxproj
  27. 18 0
      CamelotUtility/CamelotUtility.vcxproj.filters
  28. 279 47
      CamelotUtility/Include/CmAABox.cpp
  29. 17 9
      CamelotUtility/Include/CmAABox.h
  30. 58 0
      CamelotUtility/Include/CmDegree.h
  31. 59 588
      CamelotUtility/Include/CmMath.h
  32. 6 1
      CamelotUtility/Include/CmMatrix4.h
  33. 3 0
      CamelotUtility/Include/CmPlane.h
  34. 58 0
      CamelotUtility/Include/CmRadian.h
  35. 33 12
      CamelotUtility/Include/CmRay.h
  36. 8 11
      CamelotUtility/Include/CmSphere.h
  37. 3 3
      CamelotUtility/Include/CmVector2.h
  38. 6 6
      CamelotUtility/Include/CmVector3.h
  39. 4 4
      CamelotUtility/Source/CmColor.cpp
  40. 39 0
      CamelotUtility/Source/CmDegree.cpp
  41. 61 867
      CamelotUtility/Source/CmMath.cpp
  42. 61 61
      CamelotUtility/Source/CmMatrix3.cpp
  43. 32 0
      CamelotUtility/Source/CmMatrix4.cpp
  44. 19 2
      CamelotUtility/Source/CmPlane.cpp
  45. 13 13
      CamelotUtility/Source/CmQuaternion.cpp
  46. 41 0
      CamelotUtility/Source/CmRadian.cpp
  47. 115 0
      CamelotUtility/Source/CmRay.cpp
  48. 4 4
      CamelotUtility/Source/CmRect.cpp
  49. 56 0
      CamelotUtility/Source/CmSphere.cpp
  50. 4 4
      CamelotUtility/Source/CmString.cpp

+ 2 - 2
BansheeEngine/Source/BsCamera.cpp

@@ -342,7 +342,7 @@ namespace BansheeEngine
 			else if (mProjType == PT_PERSPECTIVE)
 			{
 				Radian thetaY (mHorzFOV * 0.5f);
-				float tanThetaY = Math::Tan(thetaY);
+				float tanThetaY = Math::tan(thetaY);
 				float tanThetaX = tanThetaY * mAspect;
 
 				float nearFocal = mNearDist / mFocalLength;
@@ -550,7 +550,7 @@ namespace BansheeEngine
 			const Quaternion& orientation = sceneObject()->getWorldRotation();
 			const Vector3& position = sceneObject()->getWorldPosition();
 
-			mViewMatrix = Math::makeViewMatrix(position, orientation, 0);
+			mViewMatrix.makeView(position, orientation);
 		}
 	}
 	//-----------------------------------------------------------------------

+ 2 - 2
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -809,8 +809,8 @@ namespace BansheeEngine
 		Int2 newTextOffset;
 		INT32 maxScrollableWidth = std::max(0, (INT32)unclippedTextBounds.width - (INT32)textDesc.width);
 		INT32 maxScrollableHeight = std::max(0, (INT32)unclippedTextBounds.height - (INT32)textDesc.height);
-		newTextOffset.x = Math::Clamp(mTextOffset.x, -maxScrollableWidth, 0);
-		newTextOffset.y = Math::Clamp(mTextOffset.y, -maxScrollableHeight, 0);
+		newTextOffset.x = Math::clamp(mTextOffset.x, -maxScrollableWidth, 0);
+		newTextOffset.y = Math::clamp(mTextOffset.y, -maxScrollableHeight, 0);
 
 		if(newTextOffset != mTextOffset)
 		{

+ 5 - 5
BansheeEngine/Source/BsGUIInputTool.cpp

@@ -103,10 +103,10 @@ namespace BansheeEngine
 			UINT32 vertIdx = quadIdx * 4;
 
 			Rect charRect;
-			charRect.x = Math::RoundToInt(mQuads[vertIdx + 0].x);
-			charRect.y = Math::RoundToInt(mQuads[vertIdx + 0].y);
-			charRect.width = Math::RoundToInt(mQuads[vertIdx + 3].x - charRect.x);
-			charRect.height = Math::RoundToInt(mQuads[vertIdx + 3].y - charRect.y);
+			charRect.x = Math::roundToInt(mQuads[vertIdx + 0].x);
+			charRect.y = Math::roundToInt(mQuads[vertIdx + 0].y);
+			charRect.width = Math::roundToInt(mQuads[vertIdx + 3].x - charRect.x);
+			charRect.height = Math::roundToInt(mQuads[vertIdx + 3].y - charRect.y);
 
 			return charRect;
 		}
@@ -155,7 +155,7 @@ namespace BansheeEngine
 			centerX *= 0.5f;
 			centerX += textOffset.x;
 
-			float dist = Math::Abs(centerX - vecPos.x);
+			float dist = Math::abs(centerX - vecPos.x);
 			if(dist < nearestDist)
 			{
 				nearestChar = i + numNewlineChars;

+ 4 - 4
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -162,7 +162,7 @@ namespace BansheeEngine
 						continue;
 					}
 
-					UINT32 extraWidth = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraWidth = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementWidth = elementSizes[childIdx] + extraWidth;
 
 					// Clamp if needed
@@ -222,7 +222,7 @@ namespace BansheeEngine
 
 					float avgSize = totalRemainingSize * elementScaleWeights[childIdx];
 					
-					UINT32 extraWidth = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraWidth = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementWidth = (UINT32)std::max(0, (INT32)elementSizes[childIdx] - (INT32)extraWidth);
 
 					// Clamp if needed
@@ -292,7 +292,7 @@ namespace BansheeEngine
 					}
 
 					float avgSize = totalRemainingSize * elementScaleWeights[childIdx];
-					UINT32 extraWidth = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraWidth = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementWidth = elementSizes[childIdx] + extraWidth;
 
 					// Clamp if needed
@@ -364,7 +364,7 @@ namespace BansheeEngine
 
 				element->_setHeight(elemHeight);
 
-				INT32 yOffset = Math::CeilToInt(((INT32)height - (INT32)element->_getHeight()) * 0.5f);
+				INT32 yOffset = Math::ceilToInt(((INT32)height - (INT32)element->_getHeight()) * 0.5f);
 				yOffset = std::max(0, yOffset);
 
 				Int2 offset(x + xOffset, y + yOffset);

+ 4 - 4
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -156,7 +156,7 @@ namespace BansheeEngine
 						continue;
 					}
 
-					UINT32 extraHeight = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraHeight = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementHeight = elementSizes[childIdx] + extraHeight;
 
 					// Clamp if needed
@@ -216,7 +216,7 @@ namespace BansheeEngine
 
 					float avgSize = totalRemainingSize * elementScaleWeights[childIdx];
 
-					UINT32 extraHeight = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraHeight = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementHeight = (UINT32)std::max(0, (INT32)elementSizes[childIdx] - (INT32)extraHeight);
 
 					// Clamp if needed
@@ -286,7 +286,7 @@ namespace BansheeEngine
 					}
 
 					float avgSize = totalRemainingSize * elementScaleWeights[childIdx];
-					UINT32 extraHeight = std::min((UINT32)Math::CeilToInt(avgSize), remainingSize);
+					UINT32 extraHeight = std::min((UINT32)Math::ceilToInt(avgSize), remainingSize);
 					UINT32 elementHeight = elementSizes[childIdx] + extraHeight;
 
 					// Clamp if needed
@@ -357,7 +357,7 @@ namespace BansheeEngine
 				element->_setWidth(elemWidth);
 				element->_setHeight(elemHeight);
 
-				INT32 xOffset = Math::CeilToInt((INT32)(width - (INT32)element->_getWidth()) * 0.5f);
+				INT32 xOffset = Math::ceilToInt((INT32)(width - (INT32)element->_getWidth()) * 0.5f);
 				xOffset = std::max(0, xOffset);
 
 				Int2 offset(x + xOffset, y + yOffset);

+ 3 - 3
BansheeEngine/Source/BsGUIManager.cpp

@@ -656,7 +656,7 @@ namespace BansheeEngine
 					mLastCursorLocalPos = localPos;
 				}
 
-				if(Math::Abs(event.mouseWheelScrollAmount) > 0.00001f)
+				if(Math::abs(event.mouseWheelScrollAmount) > 0.00001f)
 				{
 					mMouseEvent.setMouseWheelScrollData(mElementUnderCursor, event.mouseWheelScrollAmount);
 					if(sendMouseEvent(mWidgetUnderCursor, mElementUnderCursor, mMouseEvent))
@@ -1180,7 +1180,7 @@ namespace BansheeEngine
 		const Matrix4& worldTfrm = widget.SO()->getWorldTfrm();
 
 		Vector4 vecLocalPos = worldTfrm.inverse().transform3x4(Vector4((float)windowPos.x, (float)windowPos.y, 0.0f, 1.0f));
-		Int2 curLocalPos(Math::RoundToInt(vecLocalPos.x), Math::RoundToInt(vecLocalPos.y));
+		Int2 curLocalPos(Math::roundToInt(vecLocalPos.x), Math::roundToInt(vecLocalPos.y));
 
 		return curLocalPos;
 	}
@@ -1209,7 +1209,7 @@ namespace BansheeEngine
 			float scaleX = renderTexture->getWidth() / (float)bridgeBounds.width;
 			float scaleY = renderTexture->getHeight() / (float)bridgeBounds.height;
 
-			return Int2(Math::RoundToInt(x * scaleX), Math::RoundToInt(y * scaleY));
+			return Int2(Math::roundToInt(x * scaleX), Math::roundToInt(y * scaleY));
 		}
 
 		return windowPos;

+ 4 - 4
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -126,7 +126,7 @@ namespace BansheeEngine
 			mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, mClippedContentHeight, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::FloorToInt(mVertScroll->getMaxHandleSize() * (mClippedContentHeight / (float)contentHeight));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (mClippedContentHeight / (float)contentHeight));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
 			UINT32 scrollableHeight = (UINT32)std::max(0, INT32(contentHeight) - INT32(mClippedContentHeight));
@@ -174,7 +174,7 @@ namespace BansheeEngine
 			mHorzScroll->_updateLayout(offset.x, offset.y, mClippedContentWidth, ScrollBarWidth, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::FloorToInt(mHorzScroll->getMaxHandleSize() * (mClippedContentWidth / (float)contentWidth));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (mClippedContentWidth / (float)contentWidth));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
 			UINT32 scrollableWidth = (UINT32)std::max(0, INT32(contentWidth) - INT32(mClippedContentWidth));
@@ -198,8 +198,8 @@ namespace BansheeEngine
 
 		if(hasScrollbars)
 		{
-			mContentLayout->_updateLayoutInternal(x - Math::FloorToInt(mHorzOffset), y - Math::FloorToInt(mVertOffset), 
-				mClippedContentWidth + Math::FloorToInt(mHorzOffset), mClippedContentHeight + Math::FloorToInt(mVertOffset), 
+			mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
+				mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight + Math::floorToInt(mVertOffset), 
 				layoutClipRect, widgetDepth, areaDepth);
 		}
 		

+ 1 - 1
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -147,7 +147,7 @@ namespace BansheeEngine
 
 	void GUIScrollBar::scroll(float amount)
 	{
-		float newHandlePos = Math::Clamp01(mHandleBtn->getHandlePos() - amount);
+		float newHandlePos = Math::clamp01(mHandleBtn->getHandlePos() - amount);
 
 		mHandleBtn->setHandlePos(newHandlePos);
 

+ 13 - 13
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -62,7 +62,7 @@ namespace BansheeEngine
 
 	void GUIScrollBarHandle::setHandlePos(float pct)
 	{
-		pct = Math::Clamp01(pct);
+		pct = Math::clamp01(pct);
 
 		UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
 		mHandlePos = pct * maxScrollAmount;
@@ -144,15 +144,15 @@ namespace BansheeEngine
 	{
 		Int2 offset = mOffset;
 		if(mHorizontal)
-			offset.x += Math::FloorToInt(mHandlePos);
+			offset.x += Math::floorToInt(mHandlePos);
 		else
-			offset.y += Math::FloorToInt(mHandlePos);
+			offset.y += Math::floorToInt(mHandlePos);
 
 		Rect clipRect = mClipRect;
 		if(mHorizontal)
-			clipRect.x -= Math::FloorToInt(mHandlePos);
+			clipRect.x -= Math::floorToInt(mHandlePos);
 		else
-			clipRect.y -= Math::FloorToInt(mHandlePos);
+			clipRect.y -= Math::floorToInt(mHandlePos);
 
 		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
 			vertexStride, indexStride, renderElementIdx, offset, clipRect);
@@ -195,12 +195,12 @@ namespace BansheeEngine
 
 			if(mHorizontal)
 			{
-				INT32 left = (INT32)mOffset.x + Math::FloorToInt(mHandlePos);
+				INT32 left = (INT32)mOffset.x + Math::floorToInt(mHandlePos);
 				mDragStartPos = ev.getPosition().x - left;
 			}
 			else
 			{
-				INT32 top = (INT32)mOffset.y + Math::FloorToInt(mHandlePos);
+				INT32 top = (INT32)mOffset.y + Math::floorToInt(mHandlePos);
 				mDragStartPos = ev.getPosition().y - top;
 			}
 
@@ -220,7 +220,7 @@ namespace BansheeEngine
 			}
 
 			float maxScrollAmount = (float)getMaxSize() - mHandleSize;
-			mHandlePos = Math::Clamp(mHandlePos, 0.0f, maxScrollAmount);
+			mHandlePos = Math::clamp(mHandlePos, 0.0f, maxScrollAmount);
 
 			if(!onHandleMoved.empty())
 			{
@@ -255,7 +255,7 @@ namespace BansheeEngine
 			INT32 handleOffset = 0;
 			if(mHorizontal)
 			{
-				INT32 handleLeft = (INT32)mOffset.x + Math::FloorToInt(mHandlePos);
+				INT32 handleLeft = (INT32)mOffset.x + Math::floorToInt(mHandlePos);
 				INT32 handleRight = handleLeft + mHandleSize;
 
 				if(ev.getPosition().x < handleLeft)
@@ -265,7 +265,7 @@ namespace BansheeEngine
 			}
 			else
 			{
-				INT32 handleTop = (INT32)mOffset.y + Math::FloorToInt(mHandlePos);
+				INT32 handleTop = (INT32)mOffset.y + Math::floorToInt(mHandlePos);
 				INT32 handleBottom = handleTop + mHandleSize;
 
 				if(ev.getPosition().y < handleTop)
@@ -276,7 +276,7 @@ namespace BansheeEngine
 
 			mHandlePos += handleOffset;
 			float maxScrollAmount = (float)getMaxSize() - mHandleSize;
-			mHandlePos = Math::Clamp(mHandlePos, 0.0f, maxScrollAmount);
+			mHandlePos = Math::clamp(mHandlePos, 0.0f, maxScrollAmount);
 
 			if(!onHandleMoved.empty())
 			{
@@ -312,7 +312,7 @@ namespace BansheeEngine
 	{
 		if(mHorizontal)
 		{
-			INT32 left = (INT32)mOffset.x + Math::FloorToInt(mHandlePos);
+			INT32 left = (INT32)mOffset.x + Math::floorToInt(mHandlePos);
 			INT32 right = left + mHandleSize;
 
 			if(pos.x >= left && pos.x < right)
@@ -320,7 +320,7 @@ namespace BansheeEngine
 		}
 		else
 		{
-			INT32 top = (INT32)mOffset.y + Math::FloorToInt(mHandlePos);
+			INT32 top = (INT32)mOffset.y + Math::floorToInt(mHandlePos);
 			INT32 bottom = top + mHandleSize;
 
 			if(pos.y >= top && pos.y < bottom)

+ 2 - 2
BansheeEngine/Source/BsGUIViewport.cpp

@@ -29,7 +29,7 @@ namespace BansheeEngine
 		if(guiRenderTarget != cameraRenderTarget)
 			CM_EXCEPT(InvalidParametersException, "Camera provided to GUIViewport must use the same render target as the GUIWidget this element is located on.")
 
-		mVerticalFOV = 2.0f * Math::ATan(Math::Tan(mFieldOfView.valueRadians() * 0.5f) * (1.0f / mAspectRatio));
+		mVerticalFOV = 2.0f * Math::atan(Math::tan(mFieldOfView.valueRadians() * 0.5f) * (1.0f / mAspectRatio));
 	}
 
 	GUIViewport::~GUIViewport()
@@ -98,7 +98,7 @@ namespace BansheeEngine
 	{
 		// TODO - This doesn't get called if element mesh is dirty!!! and I need to update the viewport when offset changes (in which case mesh is marked as dirty)
 		float currentAspect = mWidth / (float)mHeight;
-		Radian currentFOV = 2.0f * Math::ATan(Math::Tan(mVerticalFOV * 0.5f) * currentAspect);
+		Radian currentFOV = 2.0f * Math::atan(Math::tan(mVerticalFOV * 0.5f) * currentAspect);
 
 		mCamera->setHorzFOV(currentFOV);
 

+ 5 - 5
BansheeEngine/Source/BsGUIWidget.cpp

@@ -76,22 +76,22 @@ namespace BansheeEngine
 		if(!mWidgetIsDirty)
 		{
 			Vector3 posDiff = mLastFramePosition - position;
-			if(Math::Abs(posDiff.x) > diffEpsilon || Math::Abs(posDiff.y) > diffEpsilon || Math::Abs(posDiff.z) > diffEpsilon)
+			if(Math::abs(posDiff.x) > diffEpsilon || Math::abs(posDiff.y) > diffEpsilon || Math::abs(posDiff.z) > diffEpsilon)
 			{
 				mWidgetIsDirty = true;
 			}
 			else
 			{
 				Quaternion rotDiff = mLastFrameRotation - rotation;
-				if(Math::Abs(rotDiff.x) > diffEpsilon || Math::Abs(rotDiff.y) > diffEpsilon || 
-					Math::Abs(rotDiff.z) > diffEpsilon || Math::Abs(rotDiff.w) > diffEpsilon)
+				if(Math::abs(rotDiff.x) > diffEpsilon || Math::abs(rotDiff.y) > diffEpsilon || 
+					Math::abs(rotDiff.z) > diffEpsilon || Math::abs(rotDiff.w) > diffEpsilon)
 				{
 					mWidgetIsDirty = true;
 				}
 				else
 				{
 					Vector3 scaleDiff = mLastFrameScale - scale;
-					if(Math::Abs(scaleDiff.x) > diffEpsilon || Math::Abs(scaleDiff.y) > diffEpsilon || Math::Abs(scaleDiff.z) > diffEpsilon)
+					if(Math::abs(scaleDiff.x) > diffEpsilon || Math::abs(scaleDiff.y) > diffEpsilon || Math::abs(scaleDiff.z) > diffEpsilon)
 					{
 						mWidgetIsDirty = true;
 					}
@@ -310,7 +310,7 @@ namespace BansheeEngine
 		Vector3 vecPos((float)position.x, (float)position.y, 0.0f);
 		vecPos = worldTfrm.inverse().transform3x4(vecPos);
 
-		Int2 localPos(Math::RoundToInt(vecPos.x), Math::RoundToInt(vecPos.y));
+		Int2 localPos(Math::roundToInt(vecPos.x), Math::roundToInt(vecPos.y));
 		return mBounds.contains(localPos);
 	}
 

+ 1 - 1
BansheeEngine/Source/BsProfilerOverlay.cpp

@@ -374,7 +374,7 @@ namespace BansheeEngine
 		UINT32 width = (UINT32)std::max(0, (INT32)mTarget->getWidth() - PADDING * 2);
 		UINT32 height = (UINT32)std::max(0, (INT32)(mTarget->getHeight() - PADDING * 3)/2);
 
-		UINT32 labelsWidth = Math::CeilToInt(width * LABELS_CONTENT_RATIO);
+		UINT32 labelsWidth = Math::ceilToInt(width * LABELS_CONTENT_RATIO);
 		UINT32 contentWidth = width - labelsWidth;
 
 		mBasicAreaLabels->setPosition(PADDING, PADDING);

+ 4 - 4
BansheeEngine/Source/BsSprite.cpp

@@ -306,19 +306,19 @@ namespace BansheeEngine
 			float dv = (uvA->y - uvC->y) / (vecA->y - vecD->y);
 
 			// Clip left
-			float newLeft = Math::Clamp(vecA->x, left, right);
+			float newLeft = Math::clamp(vecA->x, left, right);
 			float uvLeftOffset = (newLeft - vecA->x) * du;
 
 			// Clip right
-			float newRight = Math::Clamp(vecB->x, left, right);
+			float newRight = Math::clamp(vecB->x, left, right);
 			float uvRightOffset = (vecB->x - newRight) * du;
 
 			// Clip top
-			float newTop = Math::Clamp(vecA->y, top, bottom);
+			float newTop = Math::clamp(vecA->y, top, bottom);
 			float uvTopOffset = (newTop - vecA->y) * dv;
 
 			// Clip bottom
-			float newBottom = Math::Clamp(vecC->y, top, bottom);
+			float newBottom = Math::clamp(vecC->y, top, bottom);
 			float uvBottomOffset = (vecC->y - newBottom) * dv;
 
 			vecA->x = newLeft;

+ 13 - 18
CSharpWrap.txt

@@ -108,24 +108,19 @@ For EditorWindow, add a new class in BansheeEditor, which pretty much does the j
 
   Math updates
 
-  Matrix
- - Transpose
- - Inverse
- - Determinant
- - Adjoint
- - ToAngle (2D), ToAxisAngle(3D) - extracts angle from a rotation matrix
- - Orthonormalize - normalizes a rotation matrix
- - EigenDecomposition
- - FromEulerAngles
- - Slerp
- - From/ToEulerAngles are probably useless for me. Just set up a FromTRS method that accepts a quaternion
-  - ToTRUS() - Decomposes a TRS matrix, with uniform scale. Make sure to warn the user it won' work without uniform scale
-
-Math
- - Fast* methods
- - Refactor entire C++ math library since it's still from Ogre
-
- Also visit Ray, Plane and other math classes
+Plane needs intersection methods for:
+ Ray, AABox, Sphere
+
+AABox.cpp is in Include folder
+
+Add "fast*" methods to Math
+
+Rename:
+Int2 -> Vector2I
+FRect -> Rect
+Rect -> RectI
+
+Add OOBB and intersection methods.
 
 Eventually make all math classes templates that work on both doubles and floats. (Very low priority)
 

+ 7 - 7
CamelotClient/Source/BsDockManager.cpp

@@ -70,7 +70,7 @@ namespace BansheeEditor
 			if(mIsHorizontal)
 			{
 				UINT32 remainingSize = (UINT32)std::max(0, (INT32)mHeight - (INT32)SliderSize);
-				UINT32 sizeTop = Math::FloorToInt(remainingSize * mSplitPosition);
+				UINT32 sizeTop = Math::floorToInt(remainingSize * mSplitPosition);
 				UINT32 sizeBottom = remainingSize - sizeTop;
 
 				mChildren[0]->setArea(mX, mY, mWidth, sizeTop);
@@ -81,7 +81,7 @@ namespace BansheeEditor
 			else
 			{
 				UINT32 remainingSize = (UINT32)std::max(0, (INT32)mWidth - (INT32)SliderSize);
-				UINT32 sizeLeft = Math::FloorToInt(remainingSize * mSplitPosition);
+				UINT32 sizeLeft = Math::floorToInt(remainingSize * mSplitPosition);
 				UINT32 sizeRight = remainingSize - sizeLeft;
 
 				mChildren[0]->setArea(mX, mY, sizeLeft, mHeight);
@@ -297,10 +297,10 @@ namespace BansheeEditor
 
 		UINT32 outWidth = std::max(0, (INT32)width - spacing * 2);
 		UINT32 outHeight = std::max(0, (INT32)height - spacing * 2);
-		UINT32 inWidth = (UINT32)Math::FloorToInt(innerScale * outWidth);
-		UINT32 inHeight = (UINT32)Math::FloorToInt(innerScale * outHeight);
-		INT32 inXOffset = Math::FloorToInt((outWidth - inWidth) * 0.5f);
-		INT32 inYOffset = Math::FloorToInt((outHeight - inHeight) * 0.5f);
+		UINT32 inWidth = (UINT32)Math::floorToInt(innerScale * outWidth);
+		UINT32 inHeight = (UINT32)Math::floorToInt(innerScale * outHeight);
+		INT32 inXOffset = Math::floorToInt((outWidth - inWidth) * 0.5f);
+		INT32 inYOffset = Math::floorToInt((outHeight - inHeight) * 0.5f);
 
 		Vector2 outTopLeft((float)x, (float)y);
 		Vector2 outTopRight((float)(x + outWidth), (float)y);
@@ -457,7 +457,7 @@ namespace BansheeEditor
 
 		Vector4 tfrmdPos = worldTfrm.transform3x4(Vector4((float)widgetRelPos.x, (float)widgetRelPos.y, 0.0f, 1.0f));
 		Vector2 windowPosVec(tfrmdPos.x, tfrmdPos.y);
-		Int2 windowPos(Math::RoundToInt(windowPosVec.x), Math::RoundToInt(windowPosVec.y));
+		Int2 windowPos(Math::roundToInt(windowPosVec.x), Math::roundToInt(windowPosVec.y));
 
 		DockContainer* mouseOverContainer = mRootContainer.findAtPos(windowPos);
 

+ 1 - 1
CamelotClient/Source/BsEditorWidgetContainer.cpp

@@ -77,7 +77,7 @@ namespace BansheeEditor
 				return;
 		}
 
-		idx = Math::Clamp(idx, 0U, (UINT32)mWidgets.size());
+		idx = Math::clamp(idx, 0U, (UINT32)mWidgets.size());
 
 		mTitleBar->insertTab(idx, widget.getName());
 		mWidgets.insert(mWidgets.begin() + idx, &widget);

+ 2 - 2
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -77,7 +77,7 @@ namespace BansheeEditor
 		GUITabButton* newTabToggle = GUITabButton::create(*mParentWidget, this, mUniqueTabIdx, name, EngineGUI::instance().getSkin().getStyle("TabbedBarBtn"));
 		GUIWindowDropArea* newDragDropElement = GUIWindowDropArea::create(*mParentWidget, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));
 
-		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size());
+		idx = Math::clamp(idx, 0U, (UINT32)mTabButtons.size());
 
 		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
 		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOff, this, _1));
@@ -100,7 +100,7 @@ namespace BansheeEditor
 		if(mTabButtons.size() == 0)
 			return;
 
-		idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size() - 1);
+		idx = Math::clamp(idx, 0U, (UINT32)mTabButtons.size() - 1);
 
 		GUIElement::destroy(mTabButtons[idx]);
 		GUIElement::destroy(mDragDropElements[idx]);

+ 1 - 1
CamelotClient/Source/CmDebugCamera.cpp

@@ -60,7 +60,7 @@ namespace CamelotFramework
 			if(fastMove)
 				multiplier = FAST_MODE_MULTIPLIER;
 
-			mCurrentSpeed = Math::Clamp(mCurrentSpeed + ACCELERATION * gTime().getFrameDelta(), START_SPEED, TOP_SPEED);
+			mCurrentSpeed = Math::clamp(mCurrentSpeed + ACCELERATION * gTime().getFrameDelta(), START_SPEED, TOP_SPEED);
 			mCurrentSpeed *= multiplier;
 		}
 		else

+ 2 - 2
CamelotCore/Include/CmTextureRTTI.h

@@ -31,7 +31,7 @@ namespace CamelotFramework
 
 		PixelDataPtr getPixelData(Texture* obj, UINT32 idx)
 		{
-			UINT32 face = (size_t)Math::Floor(idx / (float)(obj->getNumMipmaps() + 1));
+			UINT32 face = (size_t)Math::floor(idx / (float)(obj->getNumMipmaps() + 1));
 			UINT32 mipmap = idx % (obj->getNumMipmaps() + 1);
 
 			UINT32 subresourceIdx = obj->mapToSubresourceIdx(face, mipmap);
@@ -107,7 +107,7 @@ namespace CamelotFramework
 			Vector<PixelDataPtr>::type* pixelData = boost::any_cast<Vector<PixelDataPtr>::type*>(texture->mRTTIData);
 			for(size_t i = 0; i < pixelData->size(); i++)
 			{
-				UINT32 face = (size_t)Math::Floor(i / (float)(texture->getNumMipmaps() + 1));
+				UINT32 face = (size_t)Math::floor(i / (float)(texture->getNumMipmaps() + 1));
 				UINT32 mipmap = i % (texture->getNumMipmaps() + 1);
 
 				UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipmap);

+ 2 - 2
CamelotCore/Source/CmInput.cpp

@@ -219,8 +219,8 @@ namespace CamelotFramework
 
 		mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
 
-		mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
-		mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
+		mSmoothHorizontalAxis = Math::clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
+		mSmoothVerticalAxis = Math::clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
 
 		mMouseLastRel = Int2(0, 0);
 	}

+ 2 - 2
CamelotCore/Source/CmMeshHeap.cpp

@@ -121,7 +121,7 @@ namespace CamelotFramework
 			UINT32 newNumVertices = mNumVertices;
 			while(newNumVertices < (mNumVertices + meshData->getNumVertices()))
 			{
-				newNumVertices = Math::RoundToInt(newNumVertices * GrowPercent);
+				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
 			}
 
 			growVertexBuffer(newNumVertices);
@@ -153,7 +153,7 @@ namespace CamelotFramework
 			UINT32 newNumIndices = mNumIndices;
 			while(newNumIndices < (mNumIndices + meshData->getNumIndices()))
 			{
-				newNumIndices = Math::RoundToInt(newNumIndices * GrowPercent);
+				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
 			}
 
 			growIndexBuffer(newNumIndices);

+ 1 - 1
CamelotCore/Source/CmOSInputHandler.cpp

@@ -60,7 +60,7 @@ namespace CamelotFramework
 			mDoubleClicks = Queue<DoubleClick>::type();
 		}
 
-		if(mousePosition != mLastCursorPos || (Math::Abs(mouseScroll) > 0.00001f))
+		if(mousePosition != mLastCursorPos || (Math::abs(mouseScroll) > 0.00001f))
 		{
 			if(!onCursorMoved.empty())
 			{

+ 1 - 1
CamelotCore/Source/CmProfiler.cpp

@@ -54,7 +54,7 @@ namespace CamelotFramework
 
 	const ProfilerReport& Profiler::getReport(ProfiledThread thread, UINT32 idx) const
 	{
-		idx = Math::Clamp(idx, 0U, (UINT32)(NUM_SAVED_FRAMES - 1));
+		idx = Math::clamp(idx, 0U, (UINT32)(NUM_SAVED_FRAMES - 1));
 
 		if(thread == ProfiledThread::Core)
 		{

+ 1 - 1
CamelotCore/Source/CmTexture.cpp

@@ -180,7 +180,7 @@ namespace CamelotFramework
 	{
 		UINT32 numMipmaps = getNumMipmaps() + 1;
 
-		face = Math::FloorToInt((subresourceIdx) / (float)numMipmaps);
+		face = Math::floorToInt((subresourceIdx) / (float)numMipmaps);
 		mip = subresourceIdx % numMipmaps;
 	}
 

+ 4 - 4
CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp

@@ -123,8 +123,8 @@ namespace CamelotFramework
 		}
 		else if(mUsage == TU_STATIC)
 		{
-			mipLevel = Math::Clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
-			face = Math::Clamp(face, (UINT32)0, mDepth - 1);
+			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
+			face = Math::clamp(face, (UINT32)0, mDepth - 1);
 
 			if(getTextureType() == TEX_TYPE_3D)
 				face = 0;
@@ -551,8 +551,8 @@ namespace CamelotFramework
 		D3D11_MAPPED_SUBRESOURCE pMappedResource;
 		pMappedResource.pData = nullptr;
 
-		mipLevel = Math::Clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
-		face = Math::Clamp(face, (UINT32)0, mDepth - 1);
+		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
+		face = Math::clamp(face, (UINT32)0, mDepth - 1);
 
 		if(getTextureType() == TEX_TYPE_3D)
 			face = 0;

+ 6 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -247,13 +247,17 @@
     <ClCompile Include="Source\CmAsyncOp.cpp" />
     <ClCompile Include="Source\CmBitmapWriter.cpp" />
     <ClCompile Include="Source\CmBox.cpp" />
+    <ClCompile Include="Source\CmDegree.cpp" />
     <ClCompile Include="Source\CmFrameAlloc.cpp" />
     <ClCompile Include="Source\CmFRect.cpp" />
     <ClCompile Include="Source\CmInt2.cpp" />
     <ClCompile Include="Source\CmManagedDataBlock.cpp" />
     <ClCompile Include="Source\CmMemoryAllocator.cpp" />
     <ClCompile Include="Source\CmMemStack.cpp" />
+    <ClCompile Include="Source\CmRadian.cpp" />
+    <ClCompile Include="Source\CmRay.cpp" />
     <ClCompile Include="Source\CmRect.cpp" />
+    <ClCompile Include="Source\CmSphere.cpp" />
     <ClCompile Include="Source\CmStringTable.cpp" />
     <ClCompile Include="Source\CmTexAtlasGenerator.cpp" />
     <ClCompile Include="Source\CmUUID.cpp" />
@@ -266,6 +270,7 @@
     <ClInclude Include="Include\CmBox.h" />
     <ClInclude Include="Include\CmColor.h" />
     <ClInclude Include="Include\CmDebug.h" />
+    <ClInclude Include="Include\CmDegree.h" />
     <ClInclude Include="Include\CmDynLibManager.h" />
     <ClInclude Include="Include\CmException.h" />
     <ClInclude Include="Include\CmFileSerializer.h" />
@@ -282,6 +287,7 @@
     <ClInclude Include="Include\CmMemAllocProfiler.h" />
     <ClInclude Include="Include\CmModule.h" />
     <ClInclude Include="Include\CmPath.h" />
+    <ClInclude Include="Include\CmRadian.h" />
     <ClInclude Include="Include\CmRect.h" />
     <ClInclude Include="Include\CmRTTIField.h" />
     <ClInclude Include="Include\CmRTTIManagedDataBlockField.h" />

+ 18 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -231,6 +231,12 @@
     <ClInclude Include="Include\CmFrameAlloc.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmRadian.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmDegree.h">
+      <Filter>Header Files\Math</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmMath.cpp">
@@ -353,5 +359,17 @@
     <ClCompile Include="Source\CmFrameAlloc.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmRadian.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmDegree.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmSphere.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmRay.cpp">
+      <Filter>Source Files\Math</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 279 - 47
CamelotUtility/Include/CmAABox.cpp

@@ -1,4 +1,7 @@
 #include "CmAABox.h"
+#include "CmRay.h"
+#include "CmPlane.h"
+#include "CmSphere.h"
 
 namespace CamelotFramework
 {
@@ -12,16 +15,16 @@ namespace CamelotFramework
 		setMax(Vector3(0.5f, 0.5f, 0.5f));
 	}
 
-	AABox::AABox(const AABox & rkBox)
+	AABox::AABox(const AABox& copy)
 		:mMinimum(Vector3::ZERO), mMaximum(Vector3::ONE)
 	{
-		setExtents( rkBox.mMinimum, rkBox.mMaximum );
+		setExtents(copy.mMinimum, copy.mMaximum);
 	}
 
 	AABox::AABox(const Vector3& min, const Vector3& max)
 		:mMinimum(Vector3::ZERO), mMaximum(Vector3::ONE)
 	{
-		setExtents( min, max );
+		setExtents(min, max);
 	}
 
 	AABox& AABox::operator=(const AABox& rhs)
@@ -31,7 +34,7 @@ namespace CamelotFramework
 		return *this;
 	}
 
-	void AABox::setExtents( const Vector3& min, const Vector3& max )
+	void AABox::setExtents(const Vector3& min, const Vector3& max)
 	{
         assert( (min.x <= max.x && min.y <= max.y && min.z <= max.z) &&
             "The minimum corner of the box must be less than or equal to maximum corner" );
@@ -40,6 +43,15 @@ namespace CamelotFramework
 		mMaximum = max;
 	}
 
+	void AABox::scale(const Vector3& s)
+	{
+		Vector3 center = getCenter();
+		Vector3 min = center + (mMinimum - center) * s;
+		Vector3 max = center + (mMaximum - center) * s;
+
+		setExtents(min, max);
+	}
+
 	Vector3 AABox::getCorner(CornerEnum cornerToGet) const
 	{
 		switch(cornerToGet)
@@ -65,7 +77,7 @@ namespace CamelotFramework
 		}
 	}
 
-	void AABox::merge( const AABox& rhs )
+	void AABox::merge(const AABox& rhs)
 	{
 		Vector3 min = mMinimum;
 		Vector3 max = mMaximum;
@@ -75,13 +87,13 @@ namespace CamelotFramework
 		setExtents(min, max);
 	}
 
-	void AABox::merge( const Vector3& point )
+	void AABox::merge(const Vector3& point)
 	{
 		mMaximum.ceil(point);
 		mMinimum.floor(point);
 	}
 
-	void AABox::transform( const Matrix4& matrix )
+	void AABox::transform(const Matrix4& matrix)
 	{
 		Vector3 oldMin, oldMax, currentCorner;
 
@@ -139,34 +151,13 @@ namespace CamelotFramework
 
 		Vector3 newCentre = m.transform3x4(centre);
 		Vector3 newHalfSize(
-			Math::Abs(m[0][0]) * halfSize.x + Math::Abs(m[0][1]) * halfSize.y + Math::Abs(m[0][2]) * halfSize.z, 
-			Math::Abs(m[1][0]) * halfSize.x + Math::Abs(m[1][1]) * halfSize.y + Math::Abs(m[1][2]) * halfSize.z,
-			Math::Abs(m[2][0]) * halfSize.x + Math::Abs(m[2][1]) * halfSize.y + Math::Abs(m[2][2]) * halfSize.z);
+			Math::abs(m[0][0]) * halfSize.x + Math::abs(m[0][1]) * halfSize.y + Math::abs(m[0][2]) * halfSize.z, 
+			Math::abs(m[1][0]) * halfSize.x + Math::abs(m[1][1]) * halfSize.y + Math::abs(m[1][2]) * halfSize.z,
+			Math::abs(m[2][0]) * halfSize.x + Math::abs(m[2][1]) * halfSize.y + Math::abs(m[2][2]) * halfSize.z);
 
 		setExtents(newCentre - newHalfSize, newCentre + newHalfSize);
 	}
 
-	bool AABox::intersects(const AABox& b2) const
-	{
-		// Use up to 6 separating planes
-		if (mMaximum.x < b2.mMinimum.x)
-			return false;
-		if (mMaximum.y < b2.mMinimum.y)
-			return false;
-		if (mMaximum.z < b2.mMinimum.z)
-			return false;
-
-		if (mMinimum.x > b2.mMaximum.x)
-			return false;
-		if (mMinimum.y > b2.mMaximum.y)
-			return false;
-		if (mMinimum.z > b2.mMaximum.z)
-			return false;
-
-		// otherwise, must be intersecting
-		return true;
-	}
-
 	AABox AABox::intersection(const AABox& b2) const
 	{
 		Vector3 intMin = mMinimum;
@@ -186,28 +177,56 @@ namespace CamelotFramework
         return AABox();
 	}
 
-	float AABox::volume(void) const
+	bool AABox::intersects(const AABox& b2) const
 	{
-		Vector3 diff = mMaximum - mMinimum;
-		return diff.x * diff.y * diff.z;
-	}
+		// Use up to 6 separating planes
+		if (mMaximum.x < b2.mMinimum.x)
+			return false;
+		if (mMaximum.y < b2.mMinimum.y)
+			return false;
+		if (mMaximum.z < b2.mMinimum.z)
+			return false;
 
-	void AABox::scale(const Vector3& s)
-	{
-		// NB assumes centered on origin
-		Vector3 min = mMinimum * s;
-		Vector3 max = mMaximum * s;
-		setExtents(min, max);
+		if (mMinimum.x > b2.mMaximum.x)
+			return false;
+		if (mMinimum.y > b2.mMaximum.y)
+			return false;
+		if (mMinimum.z > b2.mMaximum.z)
+			return false;
+
+		// Otherwise, must be intersecting
+		return true;
 	}
 
-	bool AABox::intersects(const Sphere& s) const
+	bool AABox::intersects(const Sphere& sphere) const
 	{
-		return Math::intersects(s, *this); 
+		// Use splitting planes
+		const Vector3& center = sphere.getCenter();
+		float radius = sphere.getRadius();
+		const Vector3& min = getMin();
+		const Vector3& max = getMax();
+
+		// Arvo's algorithm
+		float s, d = 0;
+		for (int i = 0; i < 3; ++i)
+		{
+			if (center.ptr()[i] < min.ptr()[i])
+			{
+				s = center.ptr()[i] - min.ptr()[i];
+				d += s * s; 
+			}
+			else if(center.ptr()[i] > max.ptr()[i])
+			{
+				s = center.ptr()[i] - max.ptr()[i];
+				d += s * s; 
+			}
+		}
+		return d <= radius * radius;
 	}
 
 	bool AABox::intersects(const Plane& p) const
 	{
-		return Math::intersects(p, *this);
+		return (p.getSide(*this) == Plane::BOTH_SIDE);
 	}
 
 	bool AABox::intersects(const Vector3& v) const
@@ -217,7 +236,209 @@ namespace CamelotFramework
 			v.z >= mMinimum.z  &&  v.z <= mMaximum.z);
 	}
 
-	Vector3 AABox::getCenter(void) const
+	std::pair<bool, float> AABox::intersects(const Ray& ray) const
+	{
+		float lowt = 0.0f;
+		float t;
+		bool hit = false;
+		Vector3 hitpoint;
+		const Vector3& min = getMin();
+		const Vector3& max = getMax();
+		const Vector3& rayorig = ray.getOrigin();
+		const Vector3& raydir = ray.getDirection();
+
+		// Check origin inside first
+		if ((rayorig.x > min.x && rayorig.y > min.y && rayorig.z > min.z) && (rayorig.x < max.x && rayorig.y < max.y && rayorig.z < max.z))
+		{
+			return std::pair<bool, float>(true, 0.0f);
+		}
+
+		// Check each face in turn, only check closest 3
+		// Min x
+		if (rayorig.x <= min.x && raydir.x > 0)
+		{
+			t = (min.x - rayorig.x) / raydir.x;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max x
+		if (rayorig.x >= max.x && raydir.x < 0)
+		{
+			t = (max.x - rayorig.x) / raydir.x;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Min y
+		if (rayorig.y <= min.y && raydir.y > 0)
+		{
+			t = (min.y - rayorig.y) / raydir.y;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max y
+		if (rayorig.y >= max.y && raydir.y < 0)
+		{
+			t = (max.y - rayorig.y) / raydir.y;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.z >= min.z && hitpoint.z <= max.z &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Min z
+		if (rayorig.z <= min.z && raydir.z > 0)
+		{
+			t = (min.z - rayorig.z) / raydir.z;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+		// Max z
+		if (rayorig.z >= max.z && raydir.z < 0)
+		{
+			t = (max.z - rayorig.z) / raydir.z;
+			if (t >= 0)
+			{
+				// Substitute t back into ray and check bounds and dist
+				hitpoint = rayorig + raydir * t;
+				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
+					hitpoint.y >= min.y && hitpoint.y <= max.y &&
+					(!hit || t < lowt))
+				{
+					hit = true;
+					lowt = t;
+				}
+			}
+		}
+
+		return std::pair<bool, float>(hit, lowt);
+
+	} 
+
+	bool AABox::intersects(const Ray& ray, float& d1, float& d2) const
+	{
+		const Vector3& min = getMin();
+		const Vector3& max = getMax();
+		const Vector3& rayorig = ray.getOrigin();
+		const Vector3& raydir = ray.getDirection();
+
+		Vector3 absDir;
+		absDir[0] = Math::abs(raydir[0]);
+		absDir[1] = Math::abs(raydir[1]);
+		absDir[2] = Math::abs(raydir[2]);
+
+		// Sort the axis, ensure check minimise floating error axis first
+		int imax = 0, imid = 1, imin = 2;
+		if (absDir[0] < absDir[2])
+		{
+			imax = 2;
+			imin = 0;
+		}
+		if (absDir[1] < absDir[imin])
+		{
+			imid = imin;
+			imin = 1;
+		}
+		else if (absDir[1] > absDir[imax])
+		{
+			imid = imax;
+			imax = 1;
+		}
+
+		float start = 0, end = Math::POS_INFINITY;
+
+#define _CALC_AXIS(i)                                       \
+	do {                                                    \
+	float denom = 1 / raydir[i];                         \
+	float newstart = (min[i] - rayorig[i]) * denom;      \
+	float newend = (max[i] - rayorig[i]) * denom;        \
+	if (newstart > newend) std::swap(newstart, newend); \
+	if (newstart > end || newend < start) return false; \
+	if (newstart > start) start = newstart;             \
+	if (newend < end) end = newend;                     \
+	} while(0)
+
+		// Check each axis in turn
+
+		_CALC_AXIS(imax);
+
+		if (absDir[imid] < std::numeric_limits<float>::epsilon())
+		{
+			// Parallel with middle and minimise axis, check bounds only
+			if (rayorig[imid] < min[imid] || rayorig[imid] > max[imid] ||
+				rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
+				return false;
+		}
+		else
+		{
+			_CALC_AXIS(imid);
+
+			if (absDir[imin] < std::numeric_limits<float>::epsilon())
+			{
+				// Parallel with minimise axis, check bounds only
+				if (rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
+					return false;
+			}
+			else
+			{
+				_CALC_AXIS(imin);
+			}
+		}
+#undef _CALC_AXIS
+
+		d1 = start;
+		d2 = end;
+
+		return true;
+	}
+
+	Vector3 AABox::getCenter() const
 	{
 		return Vector3(
 			(mMaximum.x + mMinimum.x) * 0.5f,
@@ -225,16 +446,27 @@ namespace CamelotFramework
 			(mMaximum.z + mMinimum.z) * 0.5f);
 	}
 
-	Vector3 AABox::getSize(void) const
+	Vector3 AABox::getSize() const
 	{
 		return mMaximum - mMinimum;
 	}
 
-	Vector3 AABox::getHalfSize(void) const
+	Vector3 AABox::getHalfSize() const
 	{
 		return (mMaximum - mMinimum) * 0.5;
 	}
 
+	float AABox::getRadius() const
+	{
+		return (mMaximum - mMinimum).length();
+	}
+
+	float AABox::getVolume() const
+	{
+		Vector3 diff = mMaximum - mMinimum;
+		return diff.x * diff.y * diff.z;
+	}
+
     bool AABox::contains(const Vector3& v) const
     {
         return mMinimum.x <= v.x && v.x <= mMaximum.x &&

+ 17 - 9
CamelotUtility/Include/CmAABox.h

@@ -32,20 +32,21 @@ namespace CamelotFramework
 		};
 
 		AABox();
-		AABox(const AABox & rkBox);
+		AABox(const AABox& copy);
 		AABox(const Vector3& min, const Vector3& max);
 
 		AABox& operator=(const AABox& rhs);
 
 		~AABox() { }
 
-		const Vector3& getMin(void) const { return mMinimum; }
-		const Vector3& getMax(void) const { return mMaximum; }
+		const Vector3& getMin() const { return mMinimum; }
+		const Vector3& getMax() const { return mMaximum; }
 
 		void setMin(const Vector3& vec) { mMinimum = vec; }
 		void setMax(const Vector3& vec) { mMaximum = vec; }
 
 		void setExtents(const Vector3& min, const Vector3& max);
+		void scale(const Vector3& s);
 
 		Vector3 getCorner(CornerEnum cornerToGet) const;
 
@@ -55,21 +56,28 @@ namespace CamelotFramework
 		void transform(const Matrix4& matrix);
 		void transformAffine(const Matrix4& matrix);
 
-		bool intersects(const AABox& b2) const;
-
 		AABox intersection(const AABox& b2) const;
 
-		float volume() const;
-
-		inline void scale(const Vector3& s);
-
+		bool intersects(const AABox& b2) const;
 		bool intersects(const Sphere& s) const;
 		bool intersects(const Plane& p) const;
 		bool intersects(const Vector3& v) const;
 
+        /**
+         * @brief	Ray / box intersection, returns boolean result and distance.
+         */
+        std::pair<bool, float> intersects(const Ray& ray) const;
+
+        /**
+         * @brief	Ray / box intersection, returns boolean result and near and far intersection distance.
+         */
+        bool intersects(const Ray& ray, float& d1, float& d2) const;
+
 		Vector3 getCenter() const;
 		Vector3 getSize() const;
 		Vector3 getHalfSize() const;
+		float getRadius() const;
+		float getVolume() const;
 
         bool contains(const Vector3& v) const;
         bool contains(const AABox& other) const;

+ 58 - 0
CamelotUtility/Include/CmDegree.h

@@ -0,0 +1,58 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+#include "CmRadian.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	Wrapper class which indicates a given angle value is in Degrees.
+	 * 			
+	 *	@note Degree values are interchangeable with Radian values, and conversions
+	 *	will be done automatically between them.
+	 */
+	class CM_UTILITY_EXPORT Degree
+	{
+		float mDeg; // if you get an error here - make sure to define/typedef 'float' first
+
+	public:
+		explicit Degree(float d = 0.0f) : mDeg(d) {}
+		Degree(const Radian& r);
+		Degree& operator= (const float& f) { mDeg = f; return *this; }
+		Degree& operator= (const Degree& d) { mDeg = d.mDeg; return *this; }
+		Degree& operator= (const Radian& r);
+
+		float valueDegrees() const { return mDeg; }
+		float valueRadians() const;
+
+		const Degree& operator+ () const { return *this; }
+		Degree operator+ (const Degree& d) const { return Degree (mDeg + d.mDeg); }
+		Degree operator+ (const Radian& r) const;
+		Degree& operator+= (const Degree& d) { mDeg += d.mDeg; return *this; }
+		Degree& operator+= (const Radian& r);
+		Degree operator- () const { return Degree(-mDeg); }
+		Degree operator- (const Degree& d) const { return Degree (mDeg - d.mDeg); }
+		Degree operator- (const Radian& r) const;
+		Degree& operator-= (const Degree& d) { mDeg -= d.mDeg; return *this; }
+		Degree& operator-= (const Radian& r);
+		Degree operator* (float f) const { return Degree (mDeg * f); }
+        Degree operator* (const Degree& f) const { return Degree (mDeg * f.mDeg); }
+		Degree& operator*= (float f) { mDeg *= f; return *this; }
+		Degree operator/ (float f) const { return Degree (mDeg / f); }
+		Degree& operator/= (float f) { mDeg /= f; return *this; }
+
+		friend Degree operator* (float lhs, const Degree& rhs) { return Degree(lhs * rhs.mDeg); }
+		friend Degree operator/ (float lhs, const Degree& rhs) { return Degree(lhs / rhs.mDeg); }
+		friend Degree operator+ (Degree& lhs, float rhs) { return Degree(lhs.mDeg + rhs); }
+		friend Degree operator+ (float lhs, const Degree& rhs) { return Degree(lhs + rhs.mDeg); }
+		friend Degree operator- (const Degree& lhs, float rhs) { return Degree(lhs.mDeg - rhs); }
+		friend Degree operator- (const float lhs, const Degree& rhs) { return Degree(lhs - rhs.mDeg); }
+
+		bool operator<  (const Degree& d) const { return mDeg <  d.mDeg; }
+		bool operator<= (const Degree& d) const { return mDeg <= d.mDeg; }
+		bool operator== (const Degree& d) const { return mDeg == d.mDeg; }
+		bool operator!= (const Degree& d) const { return mDeg != d.mDeg; }
+		bool operator>= (const Degree& d) const { return mDeg >= d.mDeg; }
+		bool operator>  (const Degree& d) const { return mDeg >  d.mDeg; }
+	};
+}

+ 59 - 588
CamelotUtility/Include/CmMath.h

@@ -25,633 +25,104 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 -----------------------------------------------------------------------------
 */
-#ifndef __Math_H__
-#define __Math_H__
+#pragma once
 
 #include "CmPrerequisitesUtil.h"
+#include "CmDegree.h"
+#include "CmRadian.h"
 
 namespace CamelotFramework
 {
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup Math
-	*  @{
-	*/
-	/** Wrapper class which indicates a given angle value is in Radians.
-    @remarks
-        Radian values are interchangeable with Degree values, and conversions
-        will be done automatically between them.
-    */
-	class Radian
-	{
-		float mRad;
-
-	public:
-		explicit Radian ( float r=0 ) : mRad(r) {}
-		Radian ( const Degree& d );
-		Radian& operator = ( const float& f ) { mRad = f; return *this; }
-		Radian& operator = ( const Radian& r ) { mRad = r.mRad; return *this; }
-		Radian& operator = ( const Degree& d );
-
-		float valueDegrees() const; // see bottom of this file
-		float valueRadians() const { return mRad; }
-		float valueAngleUnits() const;
-
-        const Radian& operator + () const { return *this; }
-		Radian operator + ( const Radian& r ) const { return Radian ( mRad + r.mRad ); }
-		Radian operator + ( const Degree& d ) const;
-		Radian& operator += ( const Radian& r ) { mRad += r.mRad; return *this; }
-		Radian& operator += ( const Degree& d );
-		Radian operator - () const { return Radian(-mRad); }
-		Radian operator - ( const Radian& r ) const { return Radian ( mRad - r.mRad ); }
-		Radian operator - ( const Degree& d ) const;
-		Radian& operator -= ( const Radian& r ) { mRad -= r.mRad; return *this; }
-		Radian& operator -= ( const Degree& d );
-		Radian operator * ( float f ) const { return Radian ( mRad * f ); }
-        Radian operator * ( const Radian& f ) const { return Radian ( mRad * f.mRad ); }
-		Radian& operator *= ( float f ) { mRad *= f; return *this; }
-		Radian operator / ( float f ) const { return Radian ( mRad / f ); }
-		Radian& operator /= ( float f ) { mRad /= f; return *this; }
-
-		bool operator <  ( const Radian& r ) const { return mRad <  r.mRad; }
-		bool operator <= ( const Radian& r ) const { return mRad <= r.mRad; }
-		bool operator == ( const Radian& r ) const { return mRad == r.mRad; }
-		bool operator != ( const Radian& r ) const { return mRad != r.mRad; }
-		bool operator >= ( const Radian& r ) const { return mRad >= r.mRad; }
-		bool operator >  ( const Radian& r ) const { return mRad >  r.mRad; }
-
-		inline CM_UTILITY_EXPORT friend std::ostream& operator <<
-			( std::ostream& o, const Radian& v )
-		{
-			o << "Radian(" << v.valueRadians() << ")";
-			return o;
-		}
-	};
-
-    /** Wrapper class which indicates a given angle value is in Degrees.
-    @remarks
-        Degree values are interchangeable with Radian values, and conversions
-        will be done automatically between them.
-    */
-	class Degree
-	{
-		float mDeg; // if you get an error here - make sure to define/typedef 'float' first
-
-	public:
-		explicit Degree ( float d=0 ) : mDeg(d) {}
-		Degree ( const Radian& r ) : mDeg(r.valueDegrees()) {}
-		Degree& operator = ( const float& f ) { mDeg = f; return *this; }
-		Degree& operator = ( const Degree& d ) { mDeg = d.mDeg; return *this; }
-		Degree& operator = ( const Radian& r ) { mDeg = r.valueDegrees(); return *this; }
-
-		float valueDegrees() const { return mDeg; }
-		float valueRadians() const; // see bottom of this file
-		float valueAngleUnits() const;
-
-		const Degree& operator + () const { return *this; }
-		Degree operator + ( const Degree& d ) const { return Degree ( mDeg + d.mDeg ); }
-		Degree operator + ( const Radian& r ) const { return Degree ( mDeg + r.valueDegrees() ); }
-		Degree& operator += ( const Degree& d ) { mDeg += d.mDeg; return *this; }
-		Degree& operator += ( const Radian& r ) { mDeg += r.valueDegrees(); return *this; }
-		Degree operator - () const { return Degree(-mDeg); }
-		Degree operator - ( const Degree& d ) const { return Degree ( mDeg - d.mDeg ); }
-		Degree operator - ( const Radian& r ) const { return Degree ( mDeg - r.valueDegrees() ); }
-		Degree& operator -= ( const Degree& d ) { mDeg -= d.mDeg; return *this; }
-		Degree& operator -= ( const Radian& r ) { mDeg -= r.valueDegrees(); return *this; }
-		Degree operator * ( float f ) const { return Degree ( mDeg * f ); }
-        Degree operator * ( const Degree& f ) const { return Degree ( mDeg * f.mDeg ); }
-		Degree& operator *= ( float f ) { mDeg *= f; return *this; }
-		Degree operator / ( float f ) const { return Degree ( mDeg / f ); }
-		Degree& operator /= ( float f ) { mDeg /= f; return *this; }
-
-		bool operator <  ( const Degree& d ) const { return mDeg <  d.mDeg; }
-		bool operator <= ( const Degree& d ) const { return mDeg <= d.mDeg; }
-		bool operator == ( const Degree& d ) const { return mDeg == d.mDeg; }
-		bool operator != ( const Degree& d ) const { return mDeg != d.mDeg; }
-		bool operator >= ( const Degree& d ) const { return mDeg >= d.mDeg; }
-		bool operator >  ( const Degree& d ) const { return mDeg >  d.mDeg; }
-
-		inline CM_UTILITY_EXPORT friend std::ostream& operator <<
-			( std::ostream& o, const Degree& v )
-		{
-			o << "Degree(" << v.valueDegrees() << ")";
-			return o;
-		}
-	};
-
-    /** Wrapper class which identifies a value as the currently default angle 
-        type, as defined by Math::setAngleUnit.
-    @remarks
-        Angle values will be automatically converted between radians and degrees,
-        as appropriate.
-    */
-	class Angle
-	{
-		float mAngle;
-	public:
-		explicit Angle ( float angle ) : mAngle(angle) {}
-		operator Radian() const;
-		operator Degree() const;
-	};
-
-	// these functions could not be defined within the class definition of class
-	// Radian because they required class Degree to be defined
-	inline Radian::Radian ( const Degree& d ) : mRad(d.valueRadians()) {
-	}
-	inline Radian& Radian::operator = ( const Degree& d ) {
-		mRad = d.valueRadians(); return *this;
-	}
-	inline Radian Radian::operator + ( const Degree& d ) const {
-		return Radian ( mRad + d.valueRadians() );
-	}
-	inline Radian& Radian::operator += ( const Degree& d ) {
-		mRad += d.valueRadians();
-		return *this;
-	}
-	inline Radian Radian::operator - ( const Degree& d ) const {
-		return Radian ( mRad - d.valueRadians() );
-	}
-	inline Radian& Radian::operator -= ( const Degree& d ) {
-		mRad -= d.valueRadians();
-		return *this;
-	}
-
-    /** Class to provide access to common mathematical functions.
-        @remarks
-            Most of the maths functions are aliased versions of the C runtime
-            library functions. They are aliased here to provide future
-            optimisation opportunities, either from faster RTLs or custom
-            math approximations.
-        @note
-            <br>This is based on MgcMath.h from
-            <a href="http://www.geometrictools.com/">Wild Magic</a>.
-    */
     class CM_UTILITY_EXPORT Math 
     {
-   public:
-       /** The angular units used by the API. This functionality is now deprecated in favor
-	       of discreet angular unit types ( see Degree and Radian above ). The only place
-		   this functionality is actually still used is when parsing files. Search for
-		   usage of the Angle class for those instances
-       */
-       enum AngleUnit
-       {
-           AU_DEGREE,
-           AU_RADIAN
-       };
-
-    protected:
-       // angle units used by the api
-       static AngleUnit msAngleUnit;
-
-        /// Size of the trig tables as determined by constructor.
-        static int mTrigTableSize;
-
-        /// Radian -> index factor value ( mTrigTableSize / 2 * PI )
-        static float mTrigTableFactor;
-        static float* mSinTable;
-        static float* mTanTable;
-
-        /** Private function to build trig tables.
-        */
-        void buildTrigTables();
-
-		static float SinTable (float fValue);
-		static float TanTable (float fValue);
     public:
-        /** Default constructor.
-            @param
-                trigTableSize Optional parameter to set the size of the
-                tables used to implement Sin, Cos, Tan
-        */
-        Math(unsigned int trigTableSize = 4096);
-
-        /** Default destructor.
-        */
-        ~Math();
-
-		static inline float Abs (float fValue) { return float(fabs(fValue)); }
-		static inline Degree Abs (const Degree& dValue) { return Degree(fabs(dValue.valueDegrees())); }
-		static inline Radian Abs (const Radian& rValue) { return Radian(fabs(rValue.valueRadians())); }
-		static Radian ACos (float fValue);
-		static Radian ASin (float fValue);
-		static inline Radian ATan (float fValue) { return Radian(atan(fValue)); }
-		static inline Radian ATan2 (float fY, float fX) { return Radian(atan2(fY,fX)); }
-		static inline float Ceil (float fValue) { return float(ceil(fValue)); }
-		static inline int CeilToInt (float fValue) { return int(ceil(fValue)); }
-		static inline float Round (float fValue) { return floor(fValue + 0.5f); }
-		static inline int RoundToInt (float fValue) { return int(floor(fValue + 0.5f)); }
-		static inline bool isNaN(float f)
-		{
-			// std::isnan() is C99, not supported by all compilers
-			// However NaN always fails this next test, no other number does.
-			return f != f;
-		}
-
-        /** Cosine function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-        static inline float Cos (const Radian& fValue, bool useTables = false) {
-			return (!useTables) ? float(cos(fValue.valueRadians())) : SinTable(fValue.valueRadians() + HALF_PI);
-		}
-        /** Cosine function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-        static inline float Cos (float fValue, bool useTables = false) {
-			return (!useTables) ? float(cos(fValue)) : SinTable(fValue + HALF_PI);
-		}
-
-		static inline float Exp (float fValue) { return float(exp(fValue)); }
+		static Radian acos(float val);
+		static Radian asin(float val);
+		static Radian atan(float val) { return Radian(std::atan(val)); }
+		static Radian tan2(float y, float x) { return Radian(std::atan2(y,x)); }
 
-		static inline float Floor (float fValue) { return float(floor(fValue)); }
+        static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
+        static float cos(float val) { return (float)std::cos(val); }
 
-		static inline int FloorToInt (float fValue) { return int(floor(fValue)); }
+        static float sin(const Radian& val) { return (float)std::sin(val.valueRadians()); }
+        static float sin(float val) { return (float)std::sin(val); }
 
-		static inline float Log (float fValue) { return float(log(fValue)); }
+		static float tan(const Radian& val) { return (float)std::tan(val.valueRadians()); }
+		static float tan(float val) { return (float)std::tan(val); }
 
-		/// Stored value of log(2) for frequent use
-		static const float LOG2;
+		static float sqrt(float val) { return (float)std::sqrt(val); }
+        static Radian sqrt(const Radian& val) { return Radian(std::sqrt(val.valueRadians())); }
+        static Degree sqrt(const Degree& val) { return Degree(std::sqrt(val.valueDegrees())); }
 
-		static inline float Log2 (float fValue) { return float(log(fValue)/LOG2); }
+		static float invSqrt(float val);
+		static float sqr(float val) { return val*val; }
 
-		static inline float LogN (float base, float fValue) { return float(log(fValue)/log(base)); }
+		static float pow(float base, float exponent) { return (float)std::pow(base, exponent); }
+		static float exp(float val) { return (float)std::exp(val); }
 
-		static inline float Pow (float fBase, float fExponent) { return float(pow(fBase,fExponent)); }
-
-        static float Sign (float fValue);
-		static inline Radian Sign ( const Radian& rValue )
-		{
-			return Radian(Sign(rValue.valueRadians()));
-		}
-		static inline Degree Sign ( const Degree& dValue )
-		{
-			return Degree(Sign(dValue.valueDegrees()));
-		}
+		static float log(float val) { return (float)std::log(val); }
+		static float log2(float val) { return (float)(std::log(val)/LOG2); }
+		static float logN(float base, float val) { return (float)(std::log(val)/std::log(base)); }
 
-        /** Sine function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-        static inline float Sin (const Radian& fValue, bool useTables = false) {
-			return (!useTables) ? float(sin(fValue.valueRadians())) : SinTable(fValue.valueRadians());
-		}
-        /** Sine function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-        static inline float Sin (float fValue, bool useTables = false) {
-			return (!useTables) ? float(sin(fValue)) : SinTable(fValue);
-		}
+		static float sign(float val);
+		static Radian sign(const Radian& val) { return Radian(sign(val.valueRadians())); }
+		static Degree sign(const Degree& val) { return Degree(sign(val.valueDegrees())); }
 
-		static inline float Sqr (float fValue) { return fValue*fValue; }
+		static float abs(float val) { return float(std::fabs(val)); }
+		static Degree abs(const Degree& val) { return Degree(std::fabs(val.valueDegrees())); }
+		static Radian abs(const Radian& val) { return Radian(std::fabs(val.valueRadians())); }
 
-		static inline float Sqrt (float fValue) { return float(sqrt(fValue)); }
+		static float ceil(float val) { return (float)std::ceil(val); }
+		static int ceilToInt(float val) { return (int)std::ceil(val); }
 
-        static inline Radian Sqrt (const Radian& fValue) { return Radian(sqrt(fValue.valueRadians())); }
+		static float round(float val) { return (float)std::floor(val + 0.5f); }
+		static int roundToInt(float val) { return (int)std::floor(val + 0.5f); }
 
-        static inline Degree Sqrt (const Degree& fValue) { return Degree(sqrt(fValue.valueDegrees())); }
+		static float floor(float val) { return (float)std::floor(val); }
+		static int floorToInt(float val) { return (int)std::floor(val); }
 
-        /** Inverse square root i.e. 1 / Sqrt(x), good for vector
-            normalisation.
-        */
-		static float InvSqrt(float fValue);
-
-        /** Tangent function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-		static inline float Tan (const Radian& fValue, bool useTables = false) {
-			return (!useTables) ? float(tan(fValue.valueRadians())) : TanTable(fValue.valueRadians());
-		}
-        /** Tangent function.
-            @param
-                fValue Angle in radians
-            @param
-                useTables If true, uses lookup tables rather than
-                calculation - faster but less accurate.
-        */
-		static inline float Tan (float fValue, bool useTables = false) {
-			return (!useTables) ? float(tan(fValue)) : TanTable(fValue);
-		}
-
-		static inline float DegreesToRadians(float degrees) { return degrees * fDeg2Rad; }
-        static inline float RadiansToDegrees(float radians) { return radians * fRad2Deg; }
-
-       /** These functions used to set the assumed angle units (radians or degrees) 
-            expected when using the Angle type.
-       @par
-            You can set this directly after creating a new Root, and also before/after resource creation,
-            depending on whether you want the change to affect resource files.
-       */
-       static void setAngleUnit(AngleUnit unit);
-       /** Get the unit being used for angles. */
-       static AngleUnit getAngleUnit(void);
-
-       /** Convert from the current AngleUnit to radians. */
-       static float AngleUnitsToRadians(float units);
-       /** Convert from radians to the current AngleUnit . */
-       static float RadiansToAngleUnits(float radians);
-       /** Convert from the current AngleUnit to degrees. */
-       static float AngleUnitsToDegrees(float units);
-       /** Convert from degrees to the current AngleUnit. */
-       static float DegreesToAngleUnits(float degrees);
-
-       /** Checks whether a given point is inside a triangle, in a
-            2-dimensional (Cartesian) space.
-            @remarks
-                The vertices of the triangle must be given in either
-                trigonometrical (anticlockwise) or inverse trigonometrical
-                (clockwise) order.
-            @param
-                p The point.
-            @param
-                a The triangle's first vertex.
-            @param
-                b The triangle's second vertex.
-            @param
-                c The triangle's third vertex.
-            @returns
-                If the point resides in the triangle, <b>true</b> is
-                returned.
-            @par
-                If the point is outside the triangle, <b>false</b> is
-                returned.
-        */
-        static bool pointInTri2D(const Vector2& p, const Vector2& a, 
-			const Vector2& b, const Vector2& c);
-
-       /** Checks whether a given 3D point is inside a triangle.
-       @remarks
-            The vertices of the triangle must be given in either
-            trigonometrical (anticlockwise) or inverse trigonometrical
-            (clockwise) order, and the point must be guaranteed to be in the
-			same plane as the triangle
-        @param
-            p The point.
-        @param
-            a The triangle's first vertex.
-        @param
-            b The triangle's second vertex.
-        @param
-            c The triangle's third vertex.
-		@param 
-			normal The triangle plane's normal (passed in rather than calculated
-				on demand since the caller may already have it)
-        @returns
-            If the point resides in the triangle, <b>true</b> is
-            returned.
-        @par
-            If the point is outside the triangle, <b>false</b> is
-            returned.
-        */
-        static bool pointInTri3D(const Vector3& p, const Vector3& a, 
-			const Vector3& b, const Vector3& c, const Vector3& normal);
-        /** Ray / plane intersection, returns boolean result and distance. */
-        static std::pair<bool, float> intersects(const Ray& ray, const Plane& plane);
-
-        /** Ray / sphere intersection, returns boolean result and distance. */
-        static std::pair<bool, float> intersects(const Ray& ray, const Sphere& sphere, 
-            bool discardInside = true);
-        
-        /** Ray / box intersection, returns boolean result and distance. */
-        static std::pair<bool, float> intersects(const Ray& ray, const AABox& box);
-
-        /** Ray / box intersection, returns boolean result and two intersection distance.
-        @param
-            ray The ray.
-        @param
-            box The box.
-        @param
-            d1 A real pointer to retrieve the near intersection distance
-                from the ray origin, maybe <b>null</b> which means don't care
-                about the near intersection distance.
-        @param
-            d2 A real pointer to retrieve the far intersection distance
-                from the ray origin, maybe <b>null</b> which means don't care
-                about the far intersection distance.
-        @returns
-            If the ray is intersects the box, <b>true</b> is returned, and
-            the near intersection distance is return by <i>d1</i>, the
-            far intersection distance is return by <i>d2</i>. Guarantee
-            <b>0</b> <= <i>d1</i> <= <i>d2</i>.
-        @par
-            If the ray isn't intersects the box, <b>false</b> is returned, and
-            <i>d1</i> and <i>d2</i> is unmodified.
-        */
-        static bool intersects(const Ray& ray, const AABox& box,
-            float* d1, float* d2);
-
-        /** Ray / triangle intersection, returns boolean result and distance.
-        @param
-            ray The ray.
-        @param
-            a The triangle's first vertex.
-        @param
-            b The triangle's second vertex.
-        @param
-            c The triangle's third vertex.
-		@param 
-			normal The triangle plane's normal (passed in rather than calculated
-				on demand since the caller may already have it), doesn't need
-                normalised since we don't care.
-        @param
-            positiveSide Intersect with "positive side" of the triangle
-        @param
-            negativeSide Intersect with "negative side" of the triangle
-        @returns
-            If the ray is intersects the triangle, a pair of <b>true</b> and the
-            distance between intersection point and ray origin returned.
-        @par
-            If the ray isn't intersects the triangle, a pair of <b>false</b> and
-            <b>0</b> returned.
-        */
-        static std::pair<bool, float> intersects(const Ray& ray, const Vector3& a,
-            const Vector3& b, const Vector3& c, const Vector3& normal,
-            bool positiveSide = true, bool negativeSide = true);
-
-        /** Ray / triangle intersection, returns boolean result and distance.
-        @param
-            ray The ray.
-        @param
-            a The triangle's first vertex.
-        @param
-            b The triangle's second vertex.
-        @param
-            c The triangle's third vertex.
-        @param
-            positiveSide Intersect with "positive side" of the triangle
-        @param
-            negativeSide Intersect with "negative side" of the triangle
-        @returns
-            If the ray is intersects the triangle, a pair of <b>true</b> and the
-            distance between intersection point and ray origin returned.
-        @par
-            If the ray isn't intersects the triangle, a pair of <b>false</b> and
-            <b>0</b> returned.
-        */
-        static std::pair<bool, float> intersects(const Ray& ray, const Vector3& a,
-            const Vector3& b, const Vector3& c,
-            bool positiveSide = true, bool negativeSide = true);
-
-        /** Sphere / box intersection test. */
-        static bool intersects(const Sphere& sphere, const AABox& box);
-
-        /** Plane / box intersection test. */
-        static bool intersects(const Plane& plane, const AABox& box);
-
-        /** Ray / convex plane list intersection test. 
-        @param ray The ray to test with
-        @param plaeList List of planes which form a convex volume
-        @param normalIsOutside Does the normal point outside the volume
-        */
-        static std::pair<bool, float> intersects(
-            const Ray& ray, const Vector<Plane>::type& planeList, 
-            bool normalIsOutside);
-        /** Ray / convex plane list intersection test. 
-        @param ray The ray to test with
-        @param plaeList List of planes which form a convex volume
-        @param normalIsOutside Does the normal point outside the volume
-        */
-        static std::pair<bool, float> intersects(
-            const Ray& ray, const List<Plane>::type& planeList, 
-            bool normalIsOutside);
-
-        /** Sphere / plane intersection test. 
-        @remarks NB just do a plane.getDistance(sphere.getCenter()) for more detail!
-        */
-        static bool intersects(const Sphere& sphere, const Plane& plane);
-
-        /** Compare 2 reals, using tolerance for inaccuracies.
-        */
-        static bool RealEqual(float a, float b,
-            float tolerance = std::numeric_limits<float>::epsilon());
-
-        /** Calculates the tangent space vector for a given set of positions / texture coords. */
-        static Vector3 calculateTangentSpaceVector(
-            const Vector3& position1, const Vector3& position2, const Vector3& position3,
-            float u1, float v1, float u2, float v2, float u3, float v3);
-
-        /** Build a reflection matrix for the passed in plane. */
-        static Matrix4 buildReflectionMatrix(const Plane& p);
-        /** Calculate a face normal, including the w component which is the offset from the origin. */
-        static Vector4 calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
-        /** Calculate a face normal, no w-information. */
-        static Vector3 calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
-        /** Calculate a face normal without normalize, including the w component which is the offset from the origin. */
-        static Vector4 calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
-        /** Calculate a face normal without normalize, no w-information. */
-        static Vector3 calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
-
-		/** Generates a value based on the Gaussian (normal) distribution function
-			with the given offset and scale parameters.
-		*/
-		static float gaussianDistribution(float x, float offset = 0.0f, float scale = 1.0f);
-
-		/** Clamp a value within an inclusive range. */
+		/**
+		 * @brief	Clamp a value within an inclusive range.
+		 */
 		template <typename T>
-		static T Clamp(T val, T minval, T maxval)
+		static T clamp(T val, T minval, T maxval)
 		{
 			assert (minval <= maxval && "Invalid clamp range");
 			return std::max(std::min(val, maxval), minval);
 		}
 
-		/** Clamp a value within an inclusive range. */
+		/**
+		 * @brief	Clamp a value within an inclusive range [0..1].
+		 */
 		template <typename T>
-		static T Clamp01(T val)
+		static T clamp01(T val)
 		{
 			return std::max(std::min(val, (T)1), (T)0);
 		}
 
-		static Matrix4 makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
-			const Matrix4* reflectMatrix = 0);
-
-		/** Get a bounding radius value from a bounding box. */
-		static float boundingRadiusFromAABB(const AABox& aabb);
+		static bool isNaN(float f)
+		{
+			return f != f;
+		}
 
+        /**
+         * @brief	Compare 2 floats, using tolerance for inaccuracies.
+         */
+        static bool approxEquals(float a, float b, float tolerance = std::numeric_limits<float>::epsilon());
 
+        /**
+         * @brief	Calculates the tangent space vector for a given set of positions / texture coords.
+         */
+        static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
+			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
 
         static const float POS_INFINITY;
         static const float NEG_INFINITY;
         static const float PI;
         static const float TWO_PI;
         static const float HALF_PI;
-		static const float fDeg2Rad;
-		static const float fRad2Deg;
-
+		static const float DEG2RAD;
+		static const float RAD2DEG;
+		static const float LOG2;
     };
-
-	// these functions must be defined down here, because they rely on the
-	// angle unit conversion functions in class Math:
-
-	inline float Radian::valueDegrees() const
-	{
-		return Math::RadiansToDegrees ( mRad );
-	}
-
-	inline float Radian::valueAngleUnits() const
-	{
-		return Math::RadiansToAngleUnits ( mRad );
-	}
-
-	inline float Degree::valueRadians() const
-	{
-		return Math::DegreesToRadians ( mDeg );
-	}
-
-	inline float Degree::valueAngleUnits() const
-	{
-		return Math::DegreesToAngleUnits ( mDeg );
-	}
-
-	inline Angle::operator Radian() const
-	{
-		return Radian(Math::AngleUnitsToRadians(mAngle));
-	}
-
-	inline Angle::operator Degree() const
-	{
-		return Degree(Math::AngleUnitsToDegrees(mAngle));
-	}
-
-	inline Radian operator * ( float a, const Radian& b )
-	{
-		return Radian ( a * b.valueRadians() );
-	}
-
-	inline Radian operator / ( float a, const Radian& b )
-	{
-		return Radian ( a / b.valueRadians() );
-	}
-
-	inline Degree operator * ( float a, const Degree& b )
-	{
-		return Degree ( a * b.valueDegrees() );
-	}
-
-	inline Degree operator / ( float a, const Degree& b )
-	{
-		return Degree ( a / b.valueDegrees() );
-	}
-	/** @} */
-	/** @} */
-
 }
-#endif

+ 6 - 1
CamelotUtility/Include/CmMatrix4.h

@@ -81,7 +81,7 @@ namespace CamelotFramework
         /**
          * @brief	Creates a 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
          */
-        Matrix4(const Matrix3& mat3)
+        explicit Matrix4(const Matrix3& mat3)
         {
 			m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2]; m[0][3] = 0.0f;
 			m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2]; m[1][3] = 0.0f;
@@ -398,6 +398,11 @@ namespace CamelotFramework
                 );
         }
 
+		/**
+		 * @brief	Creates a view matrix and applies optional reflection.
+		 */
+		void makeView(const Vector3& position, const Quaternion& orientation, const Matrix4* reflectMatrix = nullptr);
+
 		static const Matrix4 ZERO;
 		static const Matrix4 IDENTITY;
     };

+ 3 - 0
CamelotUtility/Include/CmPlane.h

@@ -141,6 +141,9 @@ namespace CamelotFramework {
         */
         float normalize(void);
 
+		/** Ray / plane intersection, returns boolean result and distance. */
+		std::pair<bool, float> intersects(const Ray& ray) const;
+
 		Vector3 normal;
         float d;
 

+ 58 - 0
CamelotUtility/Include/CmRadian.h

@@ -0,0 +1,58 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+#include "CmDegree.h"
+
+namespace CamelotFramework
+{
+	/**
+	 * @brief	Wrapper class which indicates a given angle value is in Radians.
+	 * 			
+	 *	@note Radian values are interchangeable with Degree values, and conversions
+	 *	will be done automatically between them.
+	 */
+	class CM_UTILITY_EXPORT Radian
+	{
+		float mRad;
+
+	public:
+		explicit Radian(float r = 0.0f) : mRad(r) {}
+		Radian(const Degree& d);
+		Radian& operator= (const float& f) { mRad = f; return *this; }
+		Radian& operator= (const Radian& r) { mRad = r.mRad; return *this; }
+		Radian& operator= (const Degree& d);
+
+		float valueDegrees() const;
+		float valueRadians() const { return mRad; }
+
+        const Radian& operator+ () const { return *this; }
+		Radian operator+ (const Radian& r) const { return Radian (mRad + r.mRad); }
+		Radian operator+ (const Degree& d) const;
+		Radian& operator+= (const Radian& r) { mRad += r.mRad; return *this; }
+		Radian& operator+= (const Degree& d);
+		Radian operator- () const { return Radian(-mRad); }
+		Radian operator- (const Radian& r) const { return Radian (mRad - r.mRad); }
+		Radian operator- (const Degree& d) const;
+		Radian& operator-= (const Radian& r) { mRad -= r.mRad; return *this; }
+		Radian& operator-= (const Degree& d);
+		Radian operator* (float f) const { return Radian (mRad * f); }
+        Radian operator* (const Radian& f) const { return Radian (mRad * f.mRad); }
+		Radian& operator*= (float f) { mRad *= f; return *this; }
+		Radian operator/ (float f) const { return Radian (mRad / f); }
+		Radian& operator/= (float f) { mRad /= f; return *this; }
+
+		friend Radian operator* (float lhs, const Radian& rhs) { return Radian(lhs * rhs.mRad); }
+		friend Radian operator/ (float lhs, const Radian& rhs) { return Radian(lhs / rhs.mRad); }
+		friend Radian operator+ (Radian& lhs, float rhs) { return Radian(lhs.mRad + rhs); }
+		friend Radian operator+ (float lhs, const Radian& rhs) { return Radian(lhs + rhs.mRad); }
+		friend Radian operator- (const Radian& lhs, float rhs) { return Radian(lhs.mRad - rhs); }
+		friend Radian operator- (const float lhs, const Radian& rhs) { return Radian(lhs - rhs.mRad); }
+
+		bool operator<  (const Radian& r) const { return mRad <  r.mRad; }
+		bool operator<= (const Radian& r) const { return mRad <= r.mRad; }
+		bool operator== (const Radian& r) const { return mRad == r.mRad; }
+		bool operator!= (const Radian& r) const { return mRad != r.mRad; }
+		bool operator>= (const Radian& r) const { return mRad >= r.mRad; }
+		bool operator>  (const Radian& r) const { return mRad >  r.mRad; }
+	};
+}

+ 33 - 12
CamelotUtility/Include/CmRay.h

@@ -78,30 +78,51 @@ namespace CamelotFramework {
 			indicate the distance along the ray at which it intersects. 
 			This can be converted to a point in space by calling getPoint().
 		*/
-		std::pair<bool, float> intersects(const Plane& p) const
-		{
-			return Math::intersects(*this, p);
-		}
+		std::pair<bool, float> intersects(const Plane& p) const;
+
 		/** Tests whether this ray intersects the given sphere. 
 		@returns A pair structure where the first element indicates whether
 			an intersection occurs, and if true, the second element will
 			indicate the distance along the ray at which it intersects. 
 			This can be converted to a point in space by calling getPoint().
 		*/
-		std::pair<bool, float> intersects(const Sphere& s) const
-		{
-			return Math::intersects(*this, s);
-		}
+		std::pair<bool, float> intersects(const Sphere& s) const;
+
 		/** Tests whether this ray intersects the given box. 
 		@returns A pair structure where the first element indicates whether
 			an intersection occurs, and if true, the second element will
 			indicate the distance along the ray at which it intersects. 
 			This can be converted to a point in space by calling getPoint().
 		*/
-		std::pair<bool, float> intersects(const AABox& box) const
-		{
-			return Math::intersects(*this, box);
-		}
+		std::pair<bool, float> intersects(const AABox& box) const;
+
+        /** Ray / triangle intersection, returns boolean result and distance.
+        @param
+            ray The ray.
+        @param
+            a The triangle's first vertex.
+        @param
+            b The triangle's second vertex.
+        @param
+            c The triangle's third vertex.
+		@param 
+			normal The triangle plane's normal (passed in rather than calculated
+				on demand since the caller may already have it), doesn't need
+                normalised since we don't care.
+        @param
+            positiveSide Intersect with "positive side" of the triangle
+        @param
+            negativeSide Intersect with "negative side" of the triangle
+        @returns
+            If the ray is intersects the triangle, a pair of <b>true</b> and the
+            distance between intersection point and ray origin returned.
+        @par
+            If the ray isn't intersects the triangle, a pair of <b>false</b> and
+            <b>0</b> returned.
+        */
+        std::pair<bool, float> intersects(const Vector3& a,
+            const Vector3& b, const Vector3& c, const Vector3& normal,
+            bool positiveSide = true, bool negativeSide = true) const;
 
     };
 	/** @} */

+ 8 - 11
CamelotUtility/Include/CmSphere.h

@@ -79,25 +79,22 @@ namespace CamelotFramework {
 		bool intersects(const Sphere& s) const
 		{
             return (s.mCenter - mCenter).squaredLength() <=
-                Math::Sqr(s.mRadius + mRadius);
+                Math::sqr(s.mRadius + mRadius);
 		}
 		/** Returns whether or not this sphere intersects a box. */
-		bool intersects(const AABox& box) const
-		{
-			return Math::intersects(*this, box);
-		}
+		bool intersects(const AABox& box) const;
+
 		/** Returns whether or not this sphere intersects a plane. */
-		bool intersects(const Plane& plane) const
-		{
-			return Math::intersects(*this, plane);
-		}
+		bool intersects(const Plane& plane) const;
+
 		/** Returns whether or not this sphere intersects a point. */
 		bool intersects(const Vector3& v) const
 		{
-            return ((v - mCenter).squaredLength() <= Math::Sqr(mRadius));
+            return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
 		}
-        
 
+		/** Ray / sphere intersection, returns boolean result and distance. */
+		std::pair<bool, float> intersects(const Ray& ray, bool discardInside = true) const;
     };
 	/** @} */
 	/** @} */

+ 3 - 3
CamelotUtility/Include/CmVector2.h

@@ -251,7 +251,7 @@ namespace CamelotFramework
          */
         float length() const
         {
-            return Math::Sqrt(x * x + y * y);
+            return Math::sqrt(x * x + y * y);
         }
 
         /**
@@ -291,7 +291,7 @@ namespace CamelotFramework
          */
         float normalize()
         {
-            float len = Math::Sqrt(x * x + y * y);
+            float len = Math::sqrt(x * x + y * y);
 
             // Will also work for zero-sized vectors, but will change nothing
             if (len > 1e-08)
@@ -372,7 +372,7 @@ namespace CamelotFramework
 
 		static Vector2 normalize(const Vector2& val)
 		{
-			float len = Math::Sqrt(val.x * val.x + val.y * val.y);
+			float len = Math::sqrt(val.x * val.x + val.y * val.y);
 
 			// Will also work for zero-sized vectors, but will change nothing
 			Vector2 normalizedVec;

+ 6 - 6
CamelotUtility/Include/CmVector3.h

@@ -262,7 +262,7 @@ namespace CamelotFramework
          */
         float length() const
         {
-            return Math::Sqrt(x * x + y * y + z * z);
+            return Math::sqrt(x * x + y * y + z * z);
         }
 
         /**
@@ -302,7 +302,7 @@ namespace CamelotFramework
          */
         float normalize()
         {
-            float len = Math::Sqrt(x * x + y * y + z * z);
+            float len = Math::sqrt(x * x + y * y + z * z);
 
             // Will also work for zero-sized vectors, but will change nothing
             if (len > 1e-08)
@@ -379,8 +379,8 @@ namespace CamelotFramework
 
 			float f = dot(dest) / lenProduct;
 
-			f = Math::Clamp(f, -1.0f, 1.0f);
-			return Math::ACos(f);
+			f = Math::clamp(f, -1.0f, 1.0f);
+			return Math::acos(f);
 
 		}
 
@@ -423,7 +423,7 @@ namespace CamelotFramework
 			}
 			else
 			{
-                float s = Math::Sqrt( (1+d)*2 );
+                float s = Math::sqrt( (1+d)*2 );
 	            float invs = 1 / s;
 
 				Vector3 c = v0.cross(v1);
@@ -474,7 +474,7 @@ namespace CamelotFramework
 
 		static Vector3 normalize(const Vector3& val)
 		{
-			float len = Math::Sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
+			float len = Math::sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
 
 			// Will also work for zero-sized vectors, but will change nothing
 			if (len > 1e-08)

+ 4 - 4
CamelotUtility/Source/CmColor.cpp

@@ -339,7 +339,7 @@ namespace CamelotFramework {
 
 		*brightness = vMax;
 
-		if (Math::RealEqual(delta, 0.0f, 1e-6f))
+		if (Math::approxEquals(delta, 0.0f, 1e-6f))
 		{
 			// grey
 			*hue = 0;
@@ -354,11 +354,11 @@ namespace CamelotFramework {
 			float deltaG = (((vMax - g) / 6.0f) + (delta / 2.0f)) / delta;
 			float deltaB = (((vMax - b) / 6.0f) + (delta / 2.0f)) / delta;
 
-			if (Math::RealEqual(r, vMax))
+			if (Math::approxEquals(r, vMax))
 				*hue = deltaB - deltaG;
-			else if (Math::RealEqual(g, vMax))
+			else if (Math::approxEquals(g, vMax))
 				*hue = 0.3333333f + deltaR - deltaB;
-			else if (Math::RealEqual(b, vMax)) 
+			else if (Math::approxEquals(b, vMax)) 
 				*hue = 0.6666667f + deltaG - deltaR;
 
 			if (*hue < 0.0f) 

+ 39 - 0
CamelotUtility/Source/CmDegree.cpp

@@ -0,0 +1,39 @@
+#include "CmDegree.h"
+#include "CmMath.h"
+
+namespace CamelotFramework
+{
+	Degree::Degree(const Radian& r) 
+		:mDeg(r.valueDegrees()) 
+	{ }
+
+	Degree& Degree::operator= (const Radian& r) 
+	{ 
+		mDeg = r.valueDegrees(); return *this; 
+	}
+
+	Degree Degree::operator+ (const Radian& r) const 
+	{ 
+		return Degree (mDeg + r.valueDegrees()); 
+	}
+
+	Degree& Degree::operator+= (const Radian& r) 
+	{ 
+		mDeg += r.valueDegrees(); return *this; 
+	}
+
+	Degree Degree::operator- (const Radian& r) const 
+	{ 
+		return Degree (mDeg - r.valueDegrees()); 
+	}
+
+	Degree& Degree::operator-= (const Radian& r) 
+	{ 
+		mDeg -= r.valueDegrees(); return *this; 
+	}
+
+	inline float Degree::valueRadians() const
+	{
+		return mDeg * Math::DEG2RAD;
+	}
+}

+ 61 - 867
CamelotUtility/Source/CmMath.cpp

@@ -38,101 +38,34 @@ namespace CamelotFramework
 {
     const float Math::POS_INFINITY = std::numeric_limits<float>::infinity();
     const float Math::NEG_INFINITY = -std::numeric_limits<float>::infinity();
-    const float Math::PI = float( 4.0 * atan( 1.0 ) );
-    const float Math::TWO_PI = float( 2.0 * PI );
-    const float Math::HALF_PI = float( 0.5 * PI );
-	const float Math::fDeg2Rad = PI / float(180.0);
-	const float Math::fRad2Deg = float(180.0) / PI;
-	const float Math::LOG2 = log(float(2.0));
+    const float Math::PI = (float)4.0f * std::atan(1.0f);
+    const float Math::TWO_PI = (float)(2.0f * PI);
+    const float Math::HALF_PI = (float)(0.5f * PI);
+	const float Math::DEG2RAD = PI / 180.0f;
+	const float Math::RAD2DEG = 180.0f / PI;
+	const float Math::LOG2 = std::log(2.0f);
 
-    int Math::mTrigTableSize;
-   Math::AngleUnit Math::msAngleUnit;
-
-    float  Math::mTrigTableFactor;
-    float *Math::mSinTable = NULL;
-    float *Math::mTanTable = NULL;
-
-    //-----------------------------------------------------------------------
-    Math::Math( unsigned int trigTableSize )
-    {
-        msAngleUnit = AU_DEGREE;
-
-        mTrigTableSize = trigTableSize;
-        mTrigTableFactor = mTrigTableSize / Math::TWO_PI;
-
-        mSinTable = (float*)malloc(sizeof(float) * mTrigTableSize);
-        mTanTable = (float*)malloc(sizeof(float) * mTrigTableSize);
-
-        buildTrigTables();
-    }
-
-    //-----------------------------------------------------------------------
-    Math::~Math()
-    {
-        free(mSinTable);
-        free(mTanTable);
-    }
-
-    //-----------------------------------------------------------------------
-    void Math::buildTrigTables(void)
-    {
-        // Build trig lookup tables
-        // Could get away with building only PI sized Sin table but simpler this 
-        // way. Who cares, it'll ony use an extra 8k of memory anyway and I like 
-        // simplicity.
-        float angle;
-        for (int i = 0; i < mTrigTableSize; ++i)
-        {
-            angle = Math::TWO_PI * i / mTrigTableSize;
-            mSinTable[i] = sin(angle);
-            mTanTable[i] = tan(angle);
-        }
-    }
-	//-----------------------------------------------------------------------	
-	float Math::SinTable (float fValue)
-    {
-        // Convert range to index values, wrap if required
-        int idx;
-        if (fValue >= 0)
-        {
-            idx = int(fValue * mTrigTableFactor) % mTrigTableSize;
-        }
-        else
-        {
-            idx = mTrigTableSize - (int(-fValue * mTrigTableFactor) % mTrigTableSize) - 1;
-        }
-
-        return mSinTable[idx];
-    }
-	//-----------------------------------------------------------------------
-	float Math::TanTable (float fValue)
-    {
-        // Convert range to index values, wrap if required
-		int idx = int(fValue *= mTrigTableFactor) % mTrigTableSize;
-		return mTanTable[idx];
-    }
-    //-----------------------------------------------------------------------
-    Radian Math::ACos (float fValue)
+    Radian Math::acos(float val)
     {
-        if ( -1.0 < fValue )
+        if (-1.0f < val)
         {
-            if ( fValue < 1.0 )
-                return Radian(acos(fValue));
+            if (val < 1.0f)
+                return Radian(std::acos(val));
             else
-                return Radian(0.0);
+                return Radian(0.0f);
         }
         else
         {
             return Radian(PI);
         }
     }
-    //-----------------------------------------------------------------------
-    Radian Math::ASin (float fValue)
+
+    Radian Math::asin(float val)
     {
-        if ( -1.0 < fValue )
+        if (-1.0f < val)
         {
-            if ( fValue < 1.0 )
-                return Radian(asin(fValue));
+            if (val < 1.0f)
+                return Radian(std::asin(val));
             else
                 return Radian(HALF_PI);
         }
@@ -141,166 +74,24 @@ namespace CamelotFramework
             return Radian(-HALF_PI);
         }
     }
-    //-----------------------------------------------------------------------
-    float Math::Sign (float fValue)
-    {
-        if ( fValue > 0.0 )
-            return 1.0;
-
-        if ( fValue < 0.0 )
-            return -1.0;
 
-        return 0.0;
-    }
-	//-----------------------------------------------------------------------
-	float Math::InvSqrt(float fValue)
-	{
-		return 1.0f/sqrt(fValue);
-	}
-   //-----------------------------------------------------------------------
-    void Math::setAngleUnit(Math::AngleUnit unit)
-   {
-       msAngleUnit = unit;
-   }
-   //-----------------------------------------------------------------------
-   Math::AngleUnit Math::getAngleUnit(void)
-   {
-       return msAngleUnit;
-   }
-    //-----------------------------------------------------------------------
-    float Math::AngleUnitsToRadians(float angleunits)
+    float Math::sign(float val)
     {
-       if (msAngleUnit == AU_DEGREE)
-           return angleunits * fDeg2Rad;
-       else
-           return angleunits;
-    }
-
-    //-----------------------------------------------------------------------
-    float Math::RadiansToAngleUnits(float radians)
-    {
-       if (msAngleUnit == AU_DEGREE)
-           return radians * fRad2Deg;
-       else
-           return radians;
-    }
+        if (val > 0.0f)
+            return 1.0f;
 
-    //-----------------------------------------------------------------------
-    float Math::AngleUnitsToDegrees(float angleunits)
-    {
-       if (msAngleUnit == AU_RADIAN)
-           return angleunits * fRad2Deg;
-       else
-           return angleunits;
-    }
+        if (val < 0.0f)
+            return -1.0f;
 
-    //-----------------------------------------------------------------------
-    float Math::DegreesToAngleUnits(float degrees)
-    {
-       if (msAngleUnit == AU_RADIAN)
-           return degrees * fDeg2Rad;
-       else
-           return degrees;
+        return 0.0f;
     }
 
-    //-----------------------------------------------------------------------
-	bool Math::pointInTri2D(const Vector2& p, const Vector2& a, 
-		const Vector2& b, const Vector2& c)
-    {
-		// Winding must be consistent from all edges for point to be inside
-		Vector2 v1, v2;
-		float dot[3];
-		bool zeroDot[3];
-
-		v1 = b - a;
-		v2 = p - a;
-
-		// Note we don't care about normalisation here since sign is all we need
-		// It means we don't have to worry about magnitude of cross products either
-		dot[0] = v1.cross(v2);
-		zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3f);
-
-
-		v1 = c - b;
-		v2 = p - b;
-
-		dot[1] = v1.cross(v2);
-		zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3f);
-
-		// Compare signs (ignore colinear / coincident points)
-		if(!zeroDot[0] && !zeroDot[1] 
-		&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
-		{
-			return false;
-		}
-
-		v1 = a - c;
-		v2 = p - c;
-
-		dot[2] = v1.cross(v2);
-		zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3f);
-		// Compare signs (ignore colinear / coincident points)
-		if((!zeroDot[0] && !zeroDot[2] 
-			&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
-			(!zeroDot[1] && !zeroDot[2] 
-			&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
-		{
-			return false;
-		}
-
-
-		return true;
-    }
-	//-----------------------------------------------------------------------
-	bool Math::pointInTri3D(const Vector3& p, const Vector3& a, 
-		const Vector3& b, const Vector3& c, const Vector3& normal)
+	float Math::invSqrt(float val)
 	{
-        // Winding must be consistent from all edges for point to be inside
-		Vector3 v1, v2;
-		float dot[3];
-		bool zeroDot[3];
-
-        v1 = b - a;
-        v2 = p - a;
-
-		// Note we don't care about normalisation here since sign is all we need
-		// It means we don't have to worry about magnitude of cross products either
-        dot[0] = v1.cross(v2).dot(normal);
-		zeroDot[0] = Math::RealEqual(dot[0], 0.0f, 1e-3f);
-
-
-        v1 = c - b;
-        v2 = p - b;
-
-		dot[1] = v1.cross(v2).dot(normal);
-		zeroDot[1] = Math::RealEqual(dot[1], 0.0f, 1e-3f);
-
-		// Compare signs (ignore colinear / coincident points)
-		if(!zeroDot[0] && !zeroDot[1] 
-			&& Math::Sign(dot[0]) != Math::Sign(dot[1]))
-		{
-            return false;
-		}
-
-        v1 = a - c;
-        v2 = p - c;
-
-		dot[2] = v1.cross(v2).dot(normal);
-		zeroDot[2] = Math::RealEqual(dot[2], 0.0f, 1e-3f);
-		// Compare signs (ignore colinear / coincident points)
-		if((!zeroDot[0] && !zeroDot[2] 
-			&& Math::Sign(dot[0]) != Math::Sign(dot[2])) ||
-			(!zeroDot[1] && !zeroDot[2] 
-			&& Math::Sign(dot[1]) != Math::Sign(dot[2])))
-		{
-			return false;
-		}
-
-
-        return true;
+		return 1.0f/sqrt(val);
 	}
-    //-----------------------------------------------------------------------
-    bool Math::RealEqual( float a, float b, float tolerance )
+
+    bool Math::approxEquals(float a, float b, float tolerance)
     {
         if (fabs(b-a) <= tolerance)
             return true;
@@ -308,638 +99,41 @@ namespace CamelotFramework
             return false;
     }
 
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, const Plane& plane)
-    {
-
-        float denom = plane.normal.dot(ray.getDirection());
-        if (Math::Abs(denom) < std::numeric_limits<float>::epsilon())
-        {
-            // Parallel
-            return std::pair<bool, float>(false, 0.0f);
-        }
-        else
-        {
-            float nom = plane.normal.dot(ray.getOrigin()) + plane.d;
-            float t = -(nom/denom);
-            return std::pair<bool, float>(t >= 0, t);
-        }
-        
-    }
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, 
-        const Vector<Plane>::type& planes, bool normalIsOutside)
-    {
-		List<Plane>::type planesList;
-		for (Vector<Plane>::type::const_iterator i = planes.begin(); i != planes.end(); ++i)
-		{
-			planesList.push_back(*i);
-		}
-		return intersects(ray, planesList, normalIsOutside);
-    }
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, 
-        const List<Plane>::type& planes, bool normalIsOutside)
-    {
-		List<Plane>::type::const_iterator planeit, planeitend;
-		planeitend = planes.end();
-		bool allInside = true;
-		std::pair<bool, float> ret;
-		std::pair<bool, float> end;
-		ret.first = false;
-		ret.second = 0.0f;
-		end.first = false;
-		end.second = 0;
-
-
-		// derive side
-		// NB we don't pass directly since that would require Plane::Side in 
-		// interface, which results in recursive includes since Math is so fundamental
-		Plane::Side outside = normalIsOutside ? Plane::POSITIVE_SIDE : Plane::NEGATIVE_SIDE;
-
-		for (planeit = planes.begin(); planeit != planeitend; ++planeit)
-		{
-			const Plane& plane = *planeit;
-			// is origin outside?
-			if (plane.getSide(ray.getOrigin()) == outside)
-			{
-				allInside = false;
-				// Test single plane
-				std::pair<bool, float> planeRes = 
-					ray.intersects(plane);
-				if (planeRes.first)
-				{
-					// Ok, we intersected
-					ret.first = true;
-					// Use the most distant result since convex volume
-					ret.second = std::max(ret.second, planeRes.second);
-				}
-				else
-				{
-					ret.first =false;
-					ret.second=0.0f;
-					return ret;
-				}
-			}
-			else
-			{
-				std::pair<bool, float> planeRes = 
-					ray.intersects(plane);
-				if (planeRes.first)
-				{
-					if( !end.first )
-					{
-						end.first = true;
-						end.second = planeRes.second;
-					}
-					else
-					{
-						end.second = std::min( planeRes.second, end.second );
-					}
-
-				}
-
-			}
-		}
-
-		if (allInside)
-		{
-			// Intersecting at 0 distance since inside the volume!
-			ret.first = true;
-			ret.second = 0.0f;
-			return ret;
-		}
-
-		if( end.first )
-		{
-			if( end.second < ret.second )
-			{
-				ret.first = false;
-				return ret;
-			}
-		}
-		return ret;
-    }
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, const Sphere& sphere, 
-        bool discardInside)
-    {
-        const Vector3& raydir = ray.getDirection();
-        // Adjust ray origin relative to sphere center
-        const Vector3& rayorig = ray.getOrigin() - sphere.getCenter();
-        float radius = sphere.getRadius();
-
-        // Check origin inside first
-        if (rayorig.squaredLength() <= radius*radius && discardInside)
-        {
-            return std::pair<bool, float>(true, 0.0f);
-        }
-
-        // Mmm, quadratics
-        // Build coeffs which can be used with std quadratic solver
-        // ie t = (-b +/- sqrt(b*b + 4ac)) / 2a
-        float a = raydir.dot(raydir);
-        float b = 2 * rayorig.dot(raydir);
-        float c = rayorig.dot(rayorig) - radius*radius;
-
-        // Calc determinant
-        float d = (b*b) - (4 * a * c);
-        if (d < 0)
-        {
-            // No intersection
-            return std::pair<bool, float>(false, 0.0f);
-        }
-        else
-        {
-            // BTW, if d=0 there is one intersection, if d > 0 there are 2
-            // But we only want the closest one, so that's ok, just use the 
-            // '-' version of the solver
-            float t = ( -b - Math::Sqrt(d) ) / (2 * a);
-            if (t < 0)
-                t = ( -b + Math::Sqrt(d) ) / (2 * a);
-            return std::pair<bool, float>(true, t);
-        }
-
-
-    }
-    //-----------------------------------------------------------------------
-	std::pair<bool, float> Math::intersects(const Ray& ray, const AABox& box)
-	{
-		float lowt = 0.0f;
-		float t;
-		bool hit = false;
-		Vector3 hitpoint;
-		const Vector3& min = box.getMin();
-		const Vector3& max = box.getMax();
-		const Vector3& rayorig = ray.getOrigin();
-		const Vector3& raydir = ray.getDirection();
-
-		// Check origin inside first
-		if ((rayorig.x > min.x && rayorig.y > min.y && rayorig.z > min.z) && (rayorig.x < max.x && rayorig.y < max.y && rayorig.z < max.z))
-		{
-			return std::pair<bool, float>(true, 0.0f);
-		}
-
-		// Check each face in turn, only check closest 3
-		// Min x
-		if (rayorig.x <= min.x && raydir.x > 0)
-		{
-			t = (min.x - rayorig.x) / raydir.x;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
-					hitpoint.z >= min.z && hitpoint.z <= max.z &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-		// Max x
-		if (rayorig.x >= max.x && raydir.x < 0)
-		{
-			t = (max.x - rayorig.x) / raydir.x;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.y >= min.y && hitpoint.y <= max.y &&
-					hitpoint.z >= min.z && hitpoint.z <= max.z &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-		// Min y
-		if (rayorig.y <= min.y && raydir.y > 0)
-		{
-			t = (min.y - rayorig.y) / raydir.y;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
-					hitpoint.z >= min.z && hitpoint.z <= max.z &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-		// Max y
-		if (rayorig.y >= max.y && raydir.y < 0)
-		{
-			t = (max.y - rayorig.y) / raydir.y;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
-					hitpoint.z >= min.z && hitpoint.z <= max.z &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-		// Min z
-		if (rayorig.z <= min.z && raydir.z > 0)
-		{
-			t = (min.z - rayorig.z) / raydir.z;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
-					hitpoint.y >= min.y && hitpoint.y <= max.y &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-		// Max z
-		if (rayorig.z >= max.z && raydir.z < 0)
-		{
-			t = (max.z - rayorig.z) / raydir.z;
-			if (t >= 0)
-			{
-				// Substitute t back into ray and check bounds and dist
-				hitpoint = rayorig + raydir * t;
-				if (hitpoint.x >= min.x && hitpoint.x <= max.x &&
-					hitpoint.y >= min.y && hitpoint.y <= max.y &&
-					(!hit || t < lowt))
-				{
-					hit = true;
-					lowt = t;
-				}
-			}
-		}
-
-		return std::pair<bool, float>(hit, lowt);
-
-	} 
-    //-----------------------------------------------------------------------
-    bool Math::intersects(const Ray& ray, const AABox& box,
-        float* d1, float* d2)
-    {
-        const Vector3& min = box.getMin();
-        const Vector3& max = box.getMax();
-        const Vector3& rayorig = ray.getOrigin();
-        const Vector3& raydir = ray.getDirection();
-
-        Vector3 absDir;
-        absDir[0] = Math::Abs(raydir[0]);
-        absDir[1] = Math::Abs(raydir[1]);
-        absDir[2] = Math::Abs(raydir[2]);
-
-        // Sort the axis, ensure check minimise floating error axis first
-        int imax = 0, imid = 1, imin = 2;
-        if (absDir[0] < absDir[2])
-        {
-            imax = 2;
-            imin = 0;
-        }
-        if (absDir[1] < absDir[imin])
-        {
-            imid = imin;
-            imin = 1;
-        }
-        else if (absDir[1] > absDir[imax])
-        {
-            imid = imax;
-            imax = 1;
-        }
-
-        float start = 0, end = Math::POS_INFINITY;
-
-#define _CALC_AXIS(i)                                       \
-    do {                                                    \
-        float denom = 1 / raydir[i];                         \
-        float newstart = (min[i] - rayorig[i]) * denom;      \
-        float newend = (max[i] - rayorig[i]) * denom;        \
-        if (newstart > newend) std::swap(newstart, newend); \
-        if (newstart > end || newend < start) return false; \
-        if (newstart > start) start = newstart;             \
-        if (newend < end) end = newend;                     \
-    } while(0)
-
-        // Check each axis in turn
-
-        _CALC_AXIS(imax);
-
-        if (absDir[imid] < std::numeric_limits<float>::epsilon())
-        {
-            // Parallel with middle and minimise axis, check bounds only
-            if (rayorig[imid] < min[imid] || rayorig[imid] > max[imid] ||
-                rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
-                return false;
-        }
-        else
-        {
-            _CALC_AXIS(imid);
-
-            if (absDir[imin] < std::numeric_limits<float>::epsilon())
-            {
-                // Parallel with minimise axis, check bounds only
-                if (rayorig[imin] < min[imin] || rayorig[imin] > max[imin])
-                    return false;
-            }
-            else
-            {
-                _CALC_AXIS(imin);
-            }
-        }
-#undef _CALC_AXIS
-
-        if (d1) *d1 = start;
-        if (d2) *d2 = end;
-
-        return true;
-    }
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, const Vector3& a,
-        const Vector3& b, const Vector3& c, const Vector3& normal,
-        bool positiveSide, bool negativeSide)
-    {
-        //
-        // Calculate intersection with plane.
-        //
-        float t;
-        {
-            float denom = normal.dot(ray.getDirection());
-
-            // Check intersect side
-            if (denom > + std::numeric_limits<float>::epsilon())
-            {
-                if (!negativeSide)
-                    return std::pair<bool, float>(false, 0.0f);
-            }
-            else if (denom < - std::numeric_limits<float>::epsilon())
-            {
-                if (!positiveSide)
-                    return std::pair<bool, float>(false, 0.0f);
-            }
-            else
-            {
-                // Parallel or triangle area is close to zero when
-                // the plane normal not normalised.
-                return std::pair<bool, float>(false, 0.0f);
-            }
-
-            t = normal.dot(a - ray.getOrigin()) / denom;
-
-            if (t < 0)
-            {
-                // Intersection is behind origin
-                return std::pair<bool, float>(false, 0.0f);
-            }
-        }
-
-        //
-        // Calculate the largest area projection plane in X, Y or Z.
-        //
-        size_t i0, i1;
-        {
-            float n0 = Math::Abs(normal[0]);
-            float n1 = Math::Abs(normal[1]);
-            float n2 = Math::Abs(normal[2]);
-
-            i0 = 1; i1 = 2;
-            if (n1 > n2)
-            {
-                if (n1 > n0) i0 = 0;
-            }
-            else
-            {
-                if (n2 > n0) i1 = 0;
-            }
-        }
-
-        //
-        // Check the intersection point is inside the triangle.
-        //
-        {
-            float u1 = b[i0] - a[i0];
-            float v1 = b[i1] - a[i1];
-            float u2 = c[i0] - a[i0];
-            float v2 = c[i1] - a[i1];
-            float u0 = t * ray.getDirection()[i0] + ray.getOrigin()[i0] - a[i0];
-            float v0 = t * ray.getDirection()[i1] + ray.getOrigin()[i1] - a[i1];
-
-            float alpha = u0 * v2 - u2 * v0;
-            float beta  = u1 * v0 - u0 * v1;
-            float area  = u1 * v2 - u2 * v1;
-
-            // epsilon to avoid float precision error
-            const float EPSILON = 1e-6f;
-
-            float tolerance = - EPSILON * area;
-
-            if (area > 0)
-            {
-                if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
-                    return std::pair<bool, float>(false, 0.0f);
-            }
-            else
-            {
-                if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
-                    return std::pair<bool, float>(false, 0.0f);
-            }
-        }
-
-        return std::pair<bool, float>(true, t);
-    }
-    //-----------------------------------------------------------------------
-    std::pair<bool, float> Math::intersects(const Ray& ray, const Vector3& a,
-        const Vector3& b, const Vector3& c,
-        bool positiveSide, bool negativeSide)
-    {
-        Vector3 normal = calculateBasicFaceNormalWithoutNormalize(a, b, c);
-        return intersects(ray, a, b, c, normal, positiveSide, negativeSide);
-    }
-    //-----------------------------------------------------------------------
-    bool Math::intersects(const Sphere& sphere, const AABox& box)
-    {
-        // Use splitting planes
-        const Vector3& center = sphere.getCenter();
-        float radius = sphere.getRadius();
-        const Vector3& min = box.getMin();
-        const Vector3& max = box.getMax();
-
-		// Arvo's algorithm
-		float s, d = 0;
-		for (int i = 0; i < 3; ++i)
-		{
-			if (center.ptr()[i] < min.ptr()[i])
-			{
-				s = center.ptr()[i] - min.ptr()[i];
-				d += s * s; 
-			}
-			else if(center.ptr()[i] > max.ptr()[i])
-			{
-				s = center.ptr()[i] - max.ptr()[i];
-				d += s * s; 
-			}
-		}
-		return d <= radius * radius;
-
-    }
-    //-----------------------------------------------------------------------
-    bool Math::intersects(const Plane& plane, const AABox& box)
-    {
-        return (plane.getSide(box) == Plane::BOTH_SIDE);
-    }
-    //-----------------------------------------------------------------------
-    bool Math::intersects(const Sphere& sphere, const Plane& plane)
-    {
-        return (
-            Math::Abs(plane.getDistance(sphere.getCenter()))
-            <= sphere.getRadius() );
-    }
-    //-----------------------------------------------------------------------
-    Vector3 Math::calculateTangentSpaceVector(
-        const Vector3& position1, const Vector3& position2, const Vector3& position3,
-        float u1, float v1, float u2, float v2, float u3, float v3)
-    {
-	    //side0 is the vector along one side of the triangle of vertices passed in, 
-	    //and side1 is the vector along another side. Taking the cross product of these returns the normal.
-	    Vector3 side0 = position1 - position2;
-	    Vector3 side1 = position3 - position1;
-	    //Calculate face normal
-	    Vector3 normal = side1.cross(side0);
-	    normal.normalize();
-	    //Now we use a formula to calculate the tangent. 
-	    float deltaV0 = v1 - v2;
-	    float deltaV1 = v3 - v1;
-	    Vector3 tangent = deltaV1 * side0 - deltaV0 * side1;
-	    tangent.normalize();
-	    //Calculate binormal
-	    float deltaU0 = u1 - u2;
-	    float deltaU1 = u3 - u1;
-	    Vector3 binormal = deltaU1 * side0 - deltaU0 * side1;
-	    binormal.normalize();
-	    //Now, we take the cross product of the tangents to get a vector which 
-	    //should point in the same direction as our normal calculated above. 
-	    //If it points in the opposite direction (the dot product between the normals is less than zero), 
-	    //then we need to reverse the s and t tangents. 
-	    //This is because the triangle has been mirrored when going from tangent space to object space.
-	    //reverse tangents if necessary
-	    Vector3 tangentCross = tangent.cross(binormal);
-	    if (tangentCross.dot(normal) < 0.0f)
-	    {
-		    tangent = -tangent;
-		    binormal = -binormal;
-	    }
-
-        return tangent;
-
-    }
-    //-----------------------------------------------------------------------
-    Matrix4 Math::buildReflectionMatrix(const Plane& p)
-    {
-        return Matrix4(
-            -2 * p.normal.x * p.normal.x + 1,   -2 * p.normal.x * p.normal.y,       -2 * p.normal.x * p.normal.z,       -2 * p.normal.x * p.d, 
-            -2 * p.normal.y * p.normal.x,       -2 * p.normal.y * p.normal.y + 1,   -2 * p.normal.y * p.normal.z,       -2 * p.normal.y * p.d, 
-            -2 * p.normal.z * p.normal.x,       -2 * p.normal.z * p.normal.y,       -2 * p.normal.z * p.normal.z + 1,   -2 * p.normal.z * p.d, 
-            0,                                  0,                                  0,                                  1);
-    }
-    //-----------------------------------------------------------------------
-    Vector4 Math::calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
-    {
-        Vector3 normal = calculateBasicFaceNormal(v1, v2, v3);
-        // Now set up the w (distance of tri from origin
-        return Vector4(normal.x, normal.y, normal.z, -(normal.dot(v1)));
-    }
-    //-----------------------------------------------------------------------
-    Vector3 Math::calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
-    {
-        Vector3 normal = (v2 - v1).cross(v3 - v1);
-        normal.normalize();
-        return normal;
-    }
-    //-----------------------------------------------------------------------
-    Vector4 Math::calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3)
-    {
-        Vector3 normal = calculateBasicFaceNormalWithoutNormalize(v1, v2, v3);
-        // Now set up the w (distance of tri from origin)
-        return Vector4(normal.x, normal.y, normal.z, -(normal.dot(v1)));
-    }
-    //-----------------------------------------------------------------------
-    Vector3 Math::calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3)
-    {
-        Vector3 normal = (v2 - v1).cross(v3 - v1);
-        return normal;
-    }
-	//-----------------------------------------------------------------------
-	float Math::gaussianDistribution(float x, float offset, float scale)
+	Vector3 Math::calculateTriTangent(const Vector3& position1, const Vector3& position2, 
+		const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3)
 	{
-		float nom = Math::Exp(
-			-Math::Sqr(x - offset) / (2 * Math::Sqr(scale)));
-		float denom = scale * Math::Sqrt(2 * Math::PI);
-
-		return nom / denom;
-
+		Vector3 side0 = position1 - position2;
+		Vector3 side1 = position3 - position1;
+
+		// Calculate face normal
+		Vector3 normal = side1.cross(side0);
+		normal.normalize();
+
+		// Now we use a formula to calculate the tangent. 
+		float deltaV0 = v1 - v2;
+		float deltaV1 = v3 - v1;
+		Vector3 tangent = deltaV1 * side0 - deltaV0 * side1;
+		tangent.normalize();
+
+		// Calculate binormal
+		float deltaU0 = u1 - u2;
+		float deltaU1 = u3 - u1;
+		Vector3 binormal = deltaU1 * side0 - deltaU0 * side1;
+		binormal.normalize();
+
+		// Now, we take the cross product of the tangents to get a vector which 
+		// should point in the same direction as our normal calculated above. 
+		// If it points in the opposite direction (the dot product between the normals is less than zero), 
+		// then we need to reverse the s and t tangents. 
+		// This is because the triangle has been mirrored when going from tangent space to object space.
+		// reverse tangents if necessary.
+		Vector3 tangentCross = tangent.cross(binormal);
+		if (tangentCross.dot(normal) < 0.0f)
+		{
+			tangent = -tangent;
+			binormal = -binormal;
+		}
+
+		return tangent;
 	}
-	//---------------------------------------------------------------------
-	Matrix4 Math::makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
-		const Matrix4* reflectMatrix)
-	{
-		Matrix4 viewMatrix;
-
-		// View matrix is:
-		//
-		//  [ Lx  Uy  Dz  Tx  ]
-		//  [ Lx  Uy  Dz  Ty  ]
-		//  [ Lx  Uy  Dz  Tz  ]
-		//  [ 0   0   0   1   ]
-		//
-		// Where T = -(Transposed(Rot) * Pos)
-
-		// This is most efficiently done using 3x3 Matrices
-		Matrix3 rot;
-		orientation.toRotationMatrix(rot);
-
-		// Make the translation relative to new axes
-		Matrix3 rotT = rot.transpose();
-		Vector3 trans = (-rotT).transform(position);
-
-		// Make final matrix
-		viewMatrix = Matrix4::IDENTITY;
-		viewMatrix = rotT; // fills upper 3x3
-		viewMatrix[0][3] = trans.x;
-		viewMatrix[1][3] = trans.y;
-		viewMatrix[2][3] = trans.z;
-
-		// Deal with reflections
-		if (reflectMatrix)
-		{
-			viewMatrix = viewMatrix * (*reflectMatrix);
-		}
-
-		return viewMatrix;
-
-	}
-	//---------------------------------------------------------------------
-	float Math::boundingRadiusFromAABB(const AABox& aabb)
-	{
-		Vector3 max = aabb.getMax();
-		Vector3 min = aabb.getMin();
-
-		Vector3 magnitude = max;
-		magnitude.ceil(-max);
-		magnitude.ceil(min);
-		magnitude.ceil(-min);
-
-		return magnitude.length();
-	}
-
 }

+ 61 - 61
CamelotUtility/Source/CmMatrix3.cpp

@@ -205,7 +205,7 @@ namespace CamelotFramework
 
         float det = m[0][0]*matInv[0][0] + m[0][1]*matInv[1][0] + m[0][2]*matInv[2][0];
 
-        if (Math::Abs(det) <= tolerance)
+        if (Math::abs(det) <= tolerance)
             return false;
 
         float invDet = 1.0f/det;
@@ -243,7 +243,7 @@ namespace CamelotFramework
         bool bIdentity;
 
         // Map first column to (*,0,0)
-        length = Math::Sqrt(matA[0][0]*matA[0][0] + matA[1][0]*matA[1][0] + matA[2][0]*matA[2][0]);
+        length = Math::sqrt(matA[0][0]*matA[0][0] + matA[1][0]*matA[1][0] + matA[2][0]*matA[2][0]);
         if (length > 0.0f)
         {
             sign = (matA[0][0] > 0.0f ? 1.0f : -1.0f);
@@ -279,7 +279,7 @@ namespace CamelotFramework
         }
 
         // Map first row to (*,*,0)
-        length = Math::Sqrt(matA[0][1]*matA[0][1]+matA[0][2]*matA[0][2]);
+        length = Math::sqrt(matA[0][1]*matA[0][1]+matA[0][2]*matA[0][2]);
         if ( length > 0.0 )
         {
             sign = (matA[0][1] > 0.0f ? 1.0f : -1.0f);
@@ -309,7 +309,7 @@ namespace CamelotFramework
         }
 
         // Map second column to (*,*,0)
-        length = Math::Sqrt(matA[1][1]*matA[1][1]+matA[2][1]*matA[2][1]);
+        length = Math::sqrt(matA[1][1]*matA[1][1]+matA[2][1]*matA[2][1]);
         if ( length > 0.0 )
         {
             sign = (matA[1][1] > 0.0f ? 1.0f : -1.0f);
@@ -356,14 +356,14 @@ namespace CamelotFramework
         float t12 = matA[1][1]*matA[1][2];
         float trace = f11+t22;
         float diff = f11-t22;
-        float discr = Math::Sqrt(diff*diff+4.0f*t12*t12);
+        float discr = Math::sqrt(diff*diff+4.0f*t12*t12);
         float root1 = 0.5f*(trace+discr);
         float root2 = 0.5f*(trace-discr);
 
         // Adjust right
-        float y = matA[0][0] - (Math::Abs(root1-t22) <= Math::Abs(root2-t22) ? root1 : root2);
+        float y = matA[0][0] - (Math::abs(root1-t22) <= Math::abs(root2-t22) ? root1 : root2);
         float z = matA[0][1];
-		float invLength = Math::InvSqrt(y*y+z*z);
+		float invLength = Math::invSqrt(y*y+z*z);
         float sin = z*invLength;
         float cos = -y*invLength;
 
@@ -386,7 +386,7 @@ namespace CamelotFramework
         // Adjust left
         y = matA[0][0];
         z = matA[1][0];
-        invLength = Math::InvSqrt(y*y+z*z);
+        invLength = Math::invSqrt(y*y+z*z);
         sin = z*invLength;
         cos = -y*invLength;
 
@@ -410,7 +410,7 @@ namespace CamelotFramework
         // Adjust right
         y = matA[0][1];
         z = matA[0][2];
-        invLength = Math::InvSqrt(y*y+z*z);
+        invLength = Math::invSqrt(y*y+z*z);
         sin = z*invLength;
         cos = -y*invLength;
 
@@ -433,7 +433,7 @@ namespace CamelotFramework
         // Adjust left
         y = matA[1][1];
         z = matA[2][1];
-        invLength = Math::InvSqrt(y*y+z*z);
+        invLength = Math::invSqrt(y*y+z*z);
         sin = z*invLength;
         cos = -y*invLength;
 
@@ -465,8 +465,8 @@ namespace CamelotFramework
             float sin0, cos0, tan0;
             float sin1, cos1, tan1;
 
-            bool test1 = (Math::Abs(mat[0][1]) <= SVD_EPSILON*(Math::Abs(mat[0][0])+Math::Abs(mat[1][1])));
-            bool test2 = (Math::Abs(mat[1][2]) <= SVD_EPSILON*(Math::Abs(mat[1][1])+Math::Abs(mat[2][2])));
+            bool test1 = (Math::abs(mat[0][1]) <= SVD_EPSILON*(Math::abs(mat[0][0])+Math::abs(mat[1][1])));
+            bool test2 = (Math::abs(mat[1][2]) <= SVD_EPSILON*(Math::abs(mat[1][1])+Math::abs(mat[2][2])));
 
             if (test1)
             {
@@ -481,8 +481,8 @@ namespace CamelotFramework
                 {
                     // 2x2 closed form factorization
                     tmp = (mat[1][1]*mat[1][1] - mat[2][2]*mat[2][2] + mat[1][2]*mat[1][2])/(mat[1][2]*mat[2][2]);
-                    tan0 = 0.5f*(tmp+Math::Sqrt(tmp*tmp + 4.0f));
-                    cos0 = Math::InvSqrt(1.0f+tan0*tan0);
+                    tan0 = 0.5f*(tmp+Math::sqrt(tmp*tmp + 4.0f));
+                    cos0 = Math::invSqrt(1.0f+tan0*tan0);
                     sin0 = tan0*cos0;
 
                     for (col = 0; col < 3; col++)
@@ -494,7 +494,7 @@ namespace CamelotFramework
                     }
 
                     tan1 = (mat[1][2]-mat[2][2]*tan0)/mat[1][1];
-                    cos1 = Math::InvSqrt(1.0f+tan1*tan1);
+                    cos1 = Math::invSqrt(1.0f+tan1*tan1);
                     sin1 = -tan1*cos1;
 
                     for (row = 0; row < 3; row++)
@@ -517,8 +517,8 @@ namespace CamelotFramework
                 {
                     // 2x2 closed form factorization
                     tmp = (mat[0][0]*mat[0][0] + mat[1][1]*mat[1][1] - mat[0][1]*mat[0][1])/(mat[0][1]*mat[1][1]);
-                    tan0 = 0.5f*(-tmp+Math::Sqrt(tmp*tmp + 4.0f));
-                    cos0 = Math::InvSqrt(1.0f+tan0*tan0);
+                    tan0 = 0.5f*(-tmp+Math::sqrt(tmp*tmp + 4.0f));
+                    cos0 = Math::invSqrt(1.0f+tan0*tan0);
                     sin0 = tan0*cos0;
 
                     for (col = 0; col < 3; col++)
@@ -530,7 +530,7 @@ namespace CamelotFramework
                     }
 
                     tan1 = (mat[0][1]-mat[1][1]*tan0)/mat[0][0];
-                    cos1 = Math::InvSqrt(1.0f+tan1*tan1);
+                    cos1 = Math::invSqrt(1.0f+tan1*tan1);
                     sin1 = -tan1*cos1;
 
                     for (row = 0; row < 3; row++)
@@ -568,7 +568,7 @@ namespace CamelotFramework
     void Matrix3::orthonormalize()
     {
         // Compute q0
-        float invLength = Math::InvSqrt(m[0][0]*m[0][0]+ m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+        float invLength = Math::invSqrt(m[0][0]*m[0][0]+ m[1][0]*m[1][0] + m[2][0]*m[2][0]);
 
         m[0][0] *= invLength;
         m[1][0] *= invLength;
@@ -581,7 +581,7 @@ namespace CamelotFramework
         m[1][1] -= dot0*m[1][0];
         m[2][1] -= dot0*m[2][0];
 
-        invLength = Math::InvSqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1] + m[2][1]*m[2][1]);
+        invLength = Math::invSqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1] + m[2][1]*m[2][1]);
 
         m[0][1] *= invLength;
         m[1][1] *= invLength;
@@ -595,7 +595,7 @@ namespace CamelotFramework
         m[1][2] -= dot0*m[1][0] + dot1*m[1][1];
         m[2][2] -= dot0*m[2][0] + dot1*m[2][1];
 
-        invLength = Math::InvSqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2] + m[2][2]*m[2][2]);
+        invLength = Math::invSqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2] + m[2][2]*m[2][2]);
 
         m[0][2] *= invLength;
         m[1][2] *= invLength;
@@ -605,7 +605,7 @@ namespace CamelotFramework
     void Matrix3::QDUDecomposition(Matrix3& matQ, Vector3& vecD, Vector3& vecU) const
     {
         // Build orthogonal matrix Q
-        float invLength = Math::InvSqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+        float invLength = Math::invSqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0] + m[2][0]*m[2][0]);
         matQ[0][0] = m[0][0]*invLength;
         matQ[1][0] = m[1][0]*invLength;
         matQ[2][0] = m[2][0]*invLength;
@@ -615,7 +615,7 @@ namespace CamelotFramework
         matQ[1][1] = m[1][1]-dot*matQ[1][0];
         matQ[2][1] = m[2][1]-dot*matQ[2][0];
 
-        invLength = Math::InvSqrt(matQ[0][1]*matQ[0][1] + matQ[1][1]*matQ[1][1] + matQ[2][1]*matQ[2][1]);
+        invLength = Math::invSqrt(matQ[0][1]*matQ[0][1] + matQ[1][1]*matQ[1][1] + matQ[2][1]*matQ[2][1]);
         matQ[0][1] *= invLength;
         matQ[1][1] *= invLength;
         matQ[2][1] *= invLength;
@@ -630,7 +630,7 @@ namespace CamelotFramework
         matQ[1][2] -= dot*matQ[1][1];
         matQ[2][2] -= dot*matQ[2][1];
 
-        invLength = Math::InvSqrt(matQ[0][2]*matQ[0][2] + matQ[1][2]*matQ[1][2] + matQ[2][2]*matQ[2][2]);
+        invLength = Math::invSqrt(matQ[0][2]*matQ[0][2] + matQ[1][2]*matQ[1][2] + matQ[2][2]*matQ[2][2]);
         matQ[0][2] *= invLength;
         matQ[1][2] *= invLength;
         matQ[2][2] *= invLength;
@@ -678,7 +678,7 @@ namespace CamelotFramework
     {
         float trace = m[0][0] + m[1][1] + m[2][2];
         float cos = 0.5f*(trace-1.0f);
-        radians = Math::ACos(cos);  // In [0, PI]
+        radians = Math::acos(cos);  // In [0, PI]
 
         if (radians > Radian(0.0f))
         {
@@ -699,7 +699,7 @@ namespace CamelotFramework
                     if (m[0][0] >= m[2][2])
                     {
                         // r00 is maximum diagonal term
-                        axis.x = 0.5f*Math::Sqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
+                        axis.x = 0.5f*Math::sqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
                         fHalfInverse = 0.5f/axis.x;
                         axis.y = fHalfInverse*m[0][1];
                         axis.z = fHalfInverse*m[0][2];
@@ -707,7 +707,7 @@ namespace CamelotFramework
                     else
                     {
                         // r22 is maximum diagonal term
-                        axis.z = 0.5f*Math::Sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
+                        axis.z = 0.5f*Math::sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
                         fHalfInverse = 0.5f/axis.z;
                         axis.x = fHalfInverse*m[0][2];
                         axis.y = fHalfInverse*m[1][2];
@@ -719,7 +719,7 @@ namespace CamelotFramework
                     if ( m[1][1] >= m[2][2] )
                     {
                         // r11 is maximum diagonal term
-                        axis.y = 0.5f*Math::Sqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
+                        axis.y = 0.5f*Math::sqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
                         fHalfInverse  = 0.5f/axis.y;
                         axis.x = fHalfInverse*m[0][1];
                         axis.z = fHalfInverse*m[1][2];
@@ -727,7 +727,7 @@ namespace CamelotFramework
                     else
                     {
                         // r22 is maximum diagonal term
-                        axis.z = 0.5f*Math::Sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
+                        axis.z = 0.5f*Math::sqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
                         fHalfInverse = 0.5f/axis.z;
                         axis.x = fHalfInverse*m[0][2];
                         axis.y = fHalfInverse*m[1][2];
@@ -747,8 +747,8 @@ namespace CamelotFramework
 
     void Matrix3::fromAxisAngle(const Vector3& axis, const Radian& angle)
     {
-        float cos = Math::Cos(angle);
-        float sin = Math::Sin(angle);
+        float cos = Math::cos(angle);
+        float sin = Math::sin(angle);
         float oneMinusCos = 1.0f-cos;
         float x2 = axis.x*axis.x;
         float y2 = axis.y*axis.y;
@@ -783,20 +783,20 @@ namespace CamelotFramework
 
     bool Matrix3::toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const
     {
-        xAngle = Radian(Math::ASin(m[0][2]));
+        xAngle = Radian(Math::asin(m[0][2]));
         if (xAngle < Radian(Math::HALF_PI))
         {
             if (xAngle > Radian(-Math::HALF_PI))
             {
-                yAngle = Math::ATan2(-m[1][2], m[2][2]);
-                zAngle = Math::ATan2(-m[0][1], m[0][0]);
+                yAngle = Math::tan2(-m[1][2], m[2][2]);
+                zAngle = Math::tan2(-m[0][1], m[0][0]);
 
                 return true;
             }
             else
             {
                 // WARNING.  Not a unique solution.
-                Radian angle = Math::ATan2(m[1][0],m[1][1]);
+                Radian angle = Math::tan2(m[1][0],m[1][1]);
                 zAngle = Radian(0.0f);  // Any angle works
                 yAngle = zAngle - angle;
 
@@ -806,7 +806,7 @@ namespace CamelotFramework
         else
         {
             // WARNING.  Not a unique solution.
-            Radian angle = Math::ATan2(m[1][0],m[1][1]);
+            Radian angle = Math::tan2(m[1][0],m[1][1]);
             zAngle = Radian(0.0f);  // Any angle works
             yAngle = angle - zAngle;
 
@@ -818,20 +818,20 @@ namespace CamelotFramework
 	{
 		const EulerAngleOrderData& l = EA_LOOKUP[(int)order];
 
-		xAngle = Radian(Math::ASin(l.sign * m[l.a][l.c]));
+		xAngle = Radian(Math::asin(l.sign * m[l.a][l.c]));
 		if (xAngle < Radian(Math::HALF_PI))
 		{
 			if (xAngle > Radian(-Math::HALF_PI))
 			{
-				yAngle = Math::ATan2(-l.sign * m[l.b][l.c], m[l.c][l.c]);
-				zAngle = Math::ATan2(-l.sign * m[l.a][l.b], m[l.a][l.a]);
+				yAngle = Math::tan2(-l.sign * m[l.b][l.c], m[l.c][l.c]);
+				zAngle = Math::tan2(-l.sign * m[l.a][l.b], m[l.a][l.a]);
 
 				return true;
 			}
 			else
 			{
 				// WARNING.  Not a unique solution.
-				Radian angle = Math::ATan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
+				Radian angle = Math::tan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
 				zAngle = Radian(0.0f);  // Any angle works
 				yAngle = zAngle - angle;
 
@@ -841,7 +841,7 @@ namespace CamelotFramework
 		else
 		{
 			// WARNING.  Not a unique solution.
-			Radian angle = Math::ATan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
+			Radian angle = Math::tan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
 			zAngle = Radian(0.0f);  // Any angle works
 			yAngle = angle - zAngle;
 
@@ -853,16 +853,16 @@ namespace CamelotFramework
     {
         float cos, sin;
 
-        cos = Math::Cos(yAngle);
-        sin = Math::Sin(yAngle);
+        cos = Math::cos(yAngle);
+        sin = Math::sin(yAngle);
         Matrix3 xMat(1.0f, 0.0f, 0.0f, 0.0f, cos, -sin, 0.0f, sin, cos);
 
-        cos = Math::Cos(xAngle);
-        sin = Math::Sin(xAngle);
+        cos = Math::cos(xAngle);
+        sin = Math::sin(xAngle);
         Matrix3 yMat(cos, 0.0f, sin, 0.0f, 1.0f, 0.0f, -sin, 0.0f, cos);
 
-        cos = Math::Cos(zAngle);
-        sin = Math::Sin(zAngle);
+        cos = Math::cos(zAngle);
+        sin = Math::sin(zAngle);
         Matrix3 zMat(cos,-sin, 0.0f, sin, cos, 0.0f, 0.0f, 0.0f, 1.0f);
 
         *this = xMat*(yMat*zMat);
@@ -875,16 +875,16 @@ namespace CamelotFramework
 		Matrix3 mats[3];
 		float cos, sin;
 
-		cos = Math::Cos(yAngle);
-		sin = Math::Sin(yAngle);
+		cos = Math::cos(yAngle);
+		sin = Math::sin(yAngle);
 		mats[0] = Matrix3(1.0f, 0.0f, 0.0f, 0.0f, cos, -sin, 0.0f, sin, cos);
 
-		cos = Math::Cos(xAngle);
-		sin = Math::Sin(xAngle);
+		cos = Math::cos(xAngle);
+		sin = Math::sin(xAngle);
 		mats[1] = Matrix3(cos, 0.0f, sin, 0.0f, 1.0f, 0.0f, -sin, 0.0f, cos);
 
-		cos = Math::Cos(zAngle);
-		sin = Math::Sin(zAngle);
+		cos = Math::cos(zAngle);
+		sin = Math::sin(zAngle);
 		mats[2] = Matrix3(cos,-sin, 0.0f, sin, cos, 0.0f, 0.0f, 0.0f, 1.0f);
 	
 		*this = mats[l.a]*(mats[l.b]*mats[l.c]);
@@ -909,9 +909,9 @@ namespace CamelotFramework
 
         diag[0] = fA;
         subDiag[2] = 0.0;
-        if (Math::Abs(fC) >= EPSILON)
+        if (Math::abs(fC) >= EPSILON)
         {
-            float fLength = Math::Sqrt(fB*fB+fC*fC);
+            float fLength = Math::sqrt(fB*fB+fC*fC);
             float fInvLength = 1.0f/fLength;
             fB *= fInvLength;
             fC *= fInvLength;
@@ -961,9 +961,9 @@ namespace CamelotFramework
                 int j;
                 for (j = i; j <= 1; j++)
                 {
-                    float sum = Math::Abs(diag[j]) + Math::Abs(diag[j+1]);
+                    float sum = Math::abs(diag[j]) + Math::abs(diag[j+1]);
 
-                    if (Math::Abs(subDiag[j]) + sum == sum)
+                    if (Math::abs(subDiag[j]) + sum == sum)
                         break;
                 }
 
@@ -971,7 +971,7 @@ namespace CamelotFramework
                     break;
 
                 float tmp0 = (diag[i+1]-diag[i])/(2.0f*subDiag[i]);
-                float tmp1 = Math::Sqrt(tmp0*tmp0+1.0f);
+                float tmp1 = Math::sqrt(tmp0*tmp0+1.0f);
 
                 if (tmp0 < 0.0f)
                     tmp0 = diag[j]-diag[i]+subDiag[i]/(tmp0-tmp1);
@@ -986,10 +986,10 @@ namespace CamelotFramework
                     float tmp3 = sin*subDiag[k];
                     float tmp4 = cos*subDiag[k];
 
-                    if (Math::Abs(tmp3) >= Math::Abs(tmp0))
+                    if (Math::abs(tmp3) >= Math::abs(tmp0))
                     {
                         cos = tmp0/tmp3;
-                        tmp1 = Math::Sqrt(cos*cos+1.0f);
+                        tmp1 = Math::sqrt(cos*cos+1.0f);
                         subDiag[k+1] = tmp3*tmp1;
                         sin = 1.0f/tmp1;
                         cos *= sin;
@@ -997,7 +997,7 @@ namespace CamelotFramework
                     else
                     {
                         sin = tmp3/tmp0;
-                        tmp1 = Math::Sqrt(sin*sin+1.0f);
+                        tmp1 = Math::sqrt(sin*sin+1.0f);
                         subDiag[k+1] = tmp0*tmp1;
                         cos = 1.0f/tmp1;
                         sin *= cos;

+ 32 - 0
CamelotUtility/Source/CmMatrix4.cpp

@@ -239,4 +239,36 @@ namespace CamelotFramework
 		rotation = Quaternion(matQ);
 		position = Vector3(m[0][3], m[1][3], m[2][3]);
 	}
+
+	void Matrix4::makeView(const Vector3& position, const Quaternion& orientation, const Matrix4* reflectMatrix)
+	{
+		// View matrix is:
+		//
+		//  [ Lx  Uy  Dz  Tx  ]
+		//  [ Lx  Uy  Dz  Ty  ]
+		//  [ Lx  Uy  Dz  Tz  ]
+		//  [ 0   0   0   1   ]
+		//
+		// Where T = -(Transposed(Rot) * Pos)
+
+		// This is most efficiently done using 3x3 Matrices
+		Matrix3 rot;
+		orientation.toRotationMatrix(rot);
+
+		// Make the translation relative to new axes
+		Matrix3 rotT = rot.transpose();
+		Vector3 trans = (-rotT).transform(position);
+
+		// Make final matrix
+		*this = Matrix4(rotT);
+		m[0][3] = trans.x;
+		m[1][3] = trans.y;
+		m[2][3] = trans.z;
+
+		// Deal with reflections
+		if (reflectMatrix)
+		{
+			*this = (*this) * (*reflectMatrix);
+		}
+	}
 }

+ 19 - 2
CamelotUtility/Source/CmPlane.cpp

@@ -28,7 +28,8 @@ THE SOFTWARE.
 
 #include "CmPlane.h"
 #include "CmMatrix3.h"
-#include "CmAABox.h" 
+#include "CmAABox.h"
+#include "CmRay.h"
 
 namespace CamelotFramework {
 	//-----------------------------------------------------------------------
@@ -98,7 +99,7 @@ namespace CamelotFramework {
 
         // Calculate the maximise allows absolute distance for
         // the distance between box centre and plane
-        float maxAbsDist = Math::Abs(normal.x * halfSize.x) + Math::Abs(normal.y * halfSize.y) + Math::Abs(normal.z * halfSize.z);
+        float maxAbsDist = Math::abs(normal.x * halfSize.x) + Math::abs(normal.y * halfSize.y) + Math::abs(normal.z * halfSize.z);
 
         if (dist < -maxAbsDist)
             return Plane::NEGATIVE_SIDE;
@@ -156,4 +157,20 @@ namespace CamelotFramework {
 
         return fLength;
     }
+
+	std::pair<bool, float> Plane::intersects(const Ray& ray) const
+	{
+		float denom = normal.dot(ray.getDirection());
+		if (Math::abs(denom) < std::numeric_limits<float>::epsilon())
+		{
+			// Parallel
+			return std::pair<bool, float>(false, 0.0f);
+		}
+		else
+		{
+			float nom = normal.dot(ray.getOrigin()) + d;
+			float t = -(nom/denom);
+			return std::pair<bool, float>(t >= 0, t);
+		}
+	}
 }

+ 13 - 13
CamelotUtility/Source/CmQuaternion.cpp

@@ -59,7 +59,7 @@ namespace CamelotFramework
         if (trace > 0.0f)
         {
             // |w| > 1/2, may as well choose w > 1/2
-            root = Math::Sqrt(trace + 1.0f);  // 2w
+            root = Math::sqrt(trace + 1.0f);  // 2w
             w = 0.5f*root;
             root = 0.5f/root;  // 1/(4w)
             x = (mat[2][1]-mat[1][2])*root;
@@ -81,7 +81,7 @@ namespace CamelotFramework
             size_t j = nextLookup[i];
             size_t k = nextLookup[j];
 
-            root = Math::Sqrt(mat[i][i]-mat[j][j]-mat[k][k] + 1.0f);
+            root = Math::sqrt(mat[i][i]-mat[j][j]-mat[k][k] + 1.0f);
 
             float* cmpntLookup[3] = { &x, &y, &z };
             *cmpntLookup[i] = 0.5f*root;
@@ -99,9 +99,9 @@ namespace CamelotFramework
     {
         // Assert:  axis[] is unit length
 
-        Radian fHalfAngle ( 0.5*angle );
-        float fSin = Math::Sin(fHalfAngle);
-        w = Math::Cos(fHalfAngle);
+        Radian fHalfAngle (0.5f*angle);
+        float fSin = Math::sin(fHalfAngle);
+        w = Math::cos(fHalfAngle);
         x = fSin*axis.x;
         y = fSin*axis.y;
         z = fSin*axis.z;
@@ -179,8 +179,8 @@ namespace CamelotFramework
 		float fSqrLength = x*x+y*y+z*z;
 		if ( fSqrLength > 0.0 )
 		{
-			angle = 2.0*Math::ACos(w);
-			float fInvLength = Math::InvSqrt(fSqrLength);
+			angle = 2.0*Math::acos(w);
+			float fInvLength = Math::invSqrt(fSqrLength);
 			axis.x = x*fInvLength;
 			axis.y = y*fInvLength;
 			axis.z = z*fInvLength;
@@ -344,14 +344,14 @@ namespace CamelotFramework
             quat = q;
         }
 
-        if (Math::Abs(cos) < 1 - EPSILON)
+        if (Math::abs(cos) < 1 - EPSILON)
         {
             // Standard case (slerp)
-            float sin = Math::Sqrt(1 - Math::Sqr(cos));
-            Radian angle = Math::ATan2(sin, cos);
+            float sin = Math::sqrt(1 - Math::sqr(cos));
+            Radian angle = Math::tan2(sin, cos);
             float invSin = 1.0f / sin;
-            float coeff0 = Math::Sin((1.0f - t) * angle) * invSin;
-            float coeff1 = Math::Sin(t * angle) * invSin;
+            float coeff0 = Math::sin((1.0f - t) * angle) * invSin;
+            float coeff1 = Math::sin(t * angle) * invSin;
             return coeff0 * p + coeff1 * quat;
         }
         else
@@ -373,7 +373,7 @@ namespace CamelotFramework
     float Quaternion::normalize()
     {
         float len = w*w+x*x+y*y+z*z;
-        float factor = 1.0f / Math::Sqrt(len);
+        float factor = 1.0f / Math::sqrt(len);
         *this = *this * factor;
         return len;
     }

+ 41 - 0
CamelotUtility/Source/CmRadian.cpp

@@ -0,0 +1,41 @@
+#include "CmRadian.h"
+#include "CmMath.h"
+
+namespace CamelotFramework
+{
+	inline Radian::Radian (const Degree& d) : mRad(d.valueRadians()) 
+	{ }
+
+	inline Radian& Radian::operator= (const Degree& d) 
+	{
+		mRad = d.valueRadians(); 
+		return *this;
+	}
+
+	inline Radian Radian::operator+ (const Degree& d) const 
+	{
+		return Radian (mRad + d.valueRadians());
+	}
+
+	inline Radian& Radian::operator+= (const Degree& d) 
+	{
+		mRad += d.valueRadians();
+		return *this;
+	}
+
+	inline Radian Radian::operator- (const Degree& d) const 
+	{
+		return Radian (mRad - d.valueRadians());
+	}
+
+	inline Radian& Radian::operator-= (const Degree& d) 
+	{
+		mRad -= d.valueRadians();
+		return *this;
+	}
+
+	inline float Radian::valueDegrees() const
+	{
+		return mRad * Math::RAD2DEG;
+	}
+}

+ 115 - 0
CamelotUtility/Source/CmRay.cpp

@@ -0,0 +1,115 @@
+#include "CmRay.h"
+#include "CmPlane.h"
+#include "CmSphere.h"
+#include "CmAABox.h"
+
+namespace CamelotFramework
+{
+	std::pair<bool, float> Ray::intersects(const Plane& p) const
+	{
+		return p.intersects(*this);
+	}
+
+	std::pair<bool, float> Ray::intersects(const Sphere& s) const
+	{
+		return s.intersects(*this);
+	}
+
+	std::pair<bool, float> Ray::intersects(const AABox& box) const
+	{
+		return box.intersects(*this);
+	}
+
+	std::pair<bool, float> Ray::intersects(const Vector3& a,
+		const Vector3& b, const Vector3& c, const Vector3& normal,
+		bool positiveSide, bool negativeSide) const
+	{
+		//
+		// Calculate intersection with plane.
+		//
+		float t;
+		{
+			float denom = normal.dot(getDirection());
+
+			// Check intersect side
+			if (denom > + std::numeric_limits<float>::epsilon())
+			{
+				if (!negativeSide)
+					return std::pair<bool, float>(false, 0.0f);
+			}
+			else if (denom < - std::numeric_limits<float>::epsilon())
+			{
+				if (!positiveSide)
+					return std::pair<bool, float>(false, 0.0f);
+			}
+			else
+			{
+				// Parallel or triangle area is close to zero when
+				// the plane normal not normalised.
+				return std::pair<bool, float>(false, 0.0f);
+			}
+
+			t = normal.dot(a - getOrigin()) / denom;
+
+			if (t < 0)
+			{
+				// Intersection is behind origin
+				return std::pair<bool, float>(false, 0.0f);
+			}
+		}
+
+		//
+		// Calculate the largest area projection plane in X, Y or Z.
+		//
+		size_t i0, i1;
+		{
+			float n0 = Math::abs(normal[0]);
+			float n1 = Math::abs(normal[1]);
+			float n2 = Math::abs(normal[2]);
+
+			i0 = 1; i1 = 2;
+			if (n1 > n2)
+			{
+				if (n1 > n0) i0 = 0;
+			}
+			else
+			{
+				if (n2 > n0) i1 = 0;
+			}
+		}
+
+		//
+		// Check the intersection point is inside the triangle.
+		//
+		{
+			float u1 = b[i0] - a[i0];
+			float v1 = b[i1] - a[i1];
+			float u2 = c[i0] - a[i0];
+			float v2 = c[i1] - a[i1];
+			float u0 = t * getDirection()[i0] + getOrigin()[i0] - a[i0];
+			float v0 = t * getDirection()[i1] + getOrigin()[i1] - a[i1];
+
+			float alpha = u0 * v2 - u2 * v0;
+			float beta  = u1 * v0 - u0 * v1;
+			float area  = u1 * v2 - u2 * v1;
+
+			// epsilon to avoid float precision error
+			const float EPSILON = 1e-6f;
+
+			float tolerance = - EPSILON * area;
+
+			if (area > 0)
+			{
+				if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
+					return std::pair<bool, float>(false, 0.0f);
+			}
+			else
+			{
+				if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
+					return std::pair<bool, float>(false, 0.0f);
+			}
+		}
+
+		return std::pair<bool, float>(true, t);
+	}
+}

+ 4 - 4
CamelotUtility/Source/CmRect.cpp

@@ -110,9 +110,9 @@ namespace CamelotFramework
 				maxY = verts[i].y;
 		}
 
-		x = Math::FloorToInt(minX);
-		y = Math::FloorToInt(minY);
-		width = Math::CeilToInt(maxX) - x;
-		height = Math::CeilToInt(maxY) - y;
+		x = Math::floorToInt(minX);
+		y = Math::floorToInt(minY);
+		width = Math::ceilToInt(maxX) - x;
+		height = Math::ceilToInt(maxY) - y;
 	}
 }

+ 56 - 0
CamelotUtility/Source/CmSphere.cpp

@@ -0,0 +1,56 @@
+#include "CmSphere.h"
+#include "CmRay.h"
+#include "CmPlane.h"
+#include "CmAABox.h"
+
+namespace CamelotFramework
+{
+	std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
+	{
+		const Vector3& raydir = ray.getDirection();
+		// Adjust ray origin relative to sphere center
+		const Vector3& rayorig = ray.getOrigin() - getCenter();
+		float radius = getRadius();
+
+		// Check origin inside first
+		if (rayorig.squaredLength() <= radius*radius && discardInside)
+		{
+			return std::pair<bool, float>(true, 0.0f);
+		}
+
+		// Mmm, quadratics
+		// Build coeffs which can be used with std quadratic solver
+		// ie t = (-b +/- sqrt(b*b + 4ac)) / 2a
+		float a = raydir.dot(raydir);
+		float b = 2 * rayorig.dot(raydir);
+		float c = rayorig.dot(rayorig) - radius*radius;
+
+		// Calc determinant
+		float d = (b*b) - (4 * a * c);
+		if (d < 0)
+		{
+			// No intersection
+			return std::pair<bool, float>(false, 0.0f);
+		}
+		else
+		{
+			// BTW, if d=0 there is one intersection, if d > 0 there are 2
+			// But we only want the closest one, so that's ok, just use the 
+			// '-' version of the solver
+			float t = ( -b - Math::sqrt(d) ) / (2 * a);
+			if (t < 0)
+				t = ( -b + Math::sqrt(d) ) / (2 * a);
+			return std::pair<bool, float>(true, t);
+		}
+	}
+
+	bool Sphere::intersects(const Plane& plane) const
+	{
+		return (Math::abs(plane.getDistance(getCenter())) <= getRadius());
+	}
+
+	bool Sphere::intersects(const AABox& box) const
+	{
+		return box.intersects(*this);
+	}
+}

+ 4 - 4
CamelotUtility/Source/CmString.cpp

@@ -178,13 +178,13 @@ namespace CamelotFramework
 	WString toWString(Radian val, unsigned short precision, 
 		unsigned short width, char fill, std::ios::fmtflags flags)
 	{
-		return toWString(val.valueAngleUnits(), precision, width, fill, flags);
+		return toWString(val.valueRadians(), precision, width, fill, flags);
 	}
 
 	WString toWString(Degree val, unsigned short precision, 
 		unsigned short width, char fill, std::ios::fmtflags flags)
 	{
-		return toWString(val.valueAngleUnits(), precision, width, fill, flags);
+		return toWString(val.valueDegrees(), precision, width, fill, flags);
 	}
 
 	WString toWString(int val, 
@@ -401,13 +401,13 @@ namespace CamelotFramework
 	String toString(Radian val, unsigned short precision, 
 		unsigned short width, char fill, std::ios::fmtflags flags)
 	{
-		return toString(val.valueAngleUnits(), precision, width, fill, flags);
+		return toString(val.valueRadians(), precision, width, fill, flags);
 	}
 
 	String toString(Degree val, unsigned short precision, 
 		unsigned short width, char fill, std::ios::fmtflags flags)
 	{
-		return toString(val.valueAngleUnits(), precision, width, fill, flags);
+		return toString(val.valueDegrees(), precision, width, fill, flags);
 	}
 
 	String toString(int val,