//////////////////////////////////////////////////////////////////////////////
/// \file CooneyMath.h
///
/// Contains declarations and definitions for linear-algebra and geometric
/// operations.
///
/// Core Declarations:
/// Vec2 - 2 length vector
/// Vec3 - 3 length vector
/// Vec4 - 4 length vector
/// Mat2 - 2x2 matrix
/// Mat3 - 3x3 matrix
/// Mat4 - 4x4 matrix
///________________
///////////////////
/// Paradigms
///
/// - Fast
/// - Safe
/// - User-Friendly
///
///________________
/// Class styles
///
/// Classes are as lightweight as they can be while still being user friendly.
/// Most functions that operate on the classes(vectors/matrixes) are contained
/// in the pseudo-global file namespace. Only necessary functionality is defined
/// within the class (constructors primarily).
///
/// No Implicit Conversion.
/// There is no implicit/automatic conversion between class types(Ex: Vec2->Vec3).
/// Explicit conversions exist.
/// Ex: Vec3 = ToVector3(Vector4()); // drops the 4th member.
///
///________________
/// Function styles
///
/// Generally, there may be up to three 'flavors' of each function. Example:
///
/// 1- Mat2 Transpose2(const Mat2 &a)
///
/// 2- Mat2& Transpose2(const Mat2 &a, Mat2 &out)
///
/// 3- Mat2& MakeTranpose2(Mat2 &a)
///
/// 1- This version creates a new matrix, does an operation (tranposes) and returns the new matrix.
/// This version does not manipulate the original matrix.
///
/// 2- This version does an operation(tranposes) on a and then puts it into the non-constant out.
/// This version does not manipulate the original matrix or create a new matrix. The out parameter
/// should never been the same as the input parameter. The intention of this function format
/// is to reduce overhead by putting data in already constructed structures. However, The benefits
/// are eliminated when any compiler optimizations are enabled.
///
/// 3- This version creates a temporary matrix (internally), does the operation(tranposes),
/// and then copies the temporary matrix to the original matrix.
/// This version overwrites the original matrix.
///
/// Part of the idea is that a function will never manipulate the source parameters unless hinted
/// so by the name 'Make'. The versions in which an output parameter is specified are intended
/// to speed up the operation. In testing, this does help, but ONLY if there is no compiler
/// optimization. Compiler optimization generally smooths out the small differences presented.
///
///________________
/// Use of inline
///
/// Almost everything is declared as inline. The intention is that speed is vastly more useful
/// in a graphics/physics/simulations math library than size. Using this mathematics library will
/// probably cause your program to expand in size. It'll be much faster than if we had to bounce
/// around doing all this matrix/vector/physics math.
///
/// As such compilers don't like putting inline code in source files(cpp). This also allows the
/// library to be easily portable.
///
/// When compiling for debug, inline often won't be compiled as inline. This
/// could cause your debug testing to SLOW down (tremendously).
/// 
///________________
///////////////////
/// Modified
/// September 22, 2006 Teal J Wilkes & Stephen T Cooney (Prototyped)
/// August 07, 2007 Stephen Timothy Cooney (Rewritten)
/// September 8, 2007 Stephen Timothy Cooney (Continuation of Rewrite)
/// December 16, 2007 Stephen Timothy Cooney (Continuation of Reqrite, SHRPMath.h)
/// January 16, 2009 Stephen Timothy Cooney (Reformatted, CooneyMath.h)
/// February 4, 2009 Stephen Timothy Cooney (merged CooneyMathConstants... fixed Inverse and Row orient bugs)
/// February 27, 2009 Stephen Timothy Cooney (Making math classes more user friendly, adding better constructors and operators) (about time...)
/// February 28, 2009 Stephen Timothy Cooney (fixed Mult bugs and added binary operators (ex: MatA * MatB))
/// March 29, 2009 Stephen Timothy Cooney (fixed inverse/rotate/translate bugs (wowsa!) Added Cofactor Matrixes
/// October 2009, Stephen Timothy Cooney (Adding a lot of geometric mathematics, ray/plane/sphere/aabb)
/// November 17, 2009 Stephen Timothy Cooney (removed CPP file, header only for ease of use)
/// November 19, 2009 Stephen Timothy Cooney (updating commenting/formatting for doxygen)
/// November 26, 2009 Stephen Timothy Cooney (continued commenting/formatting for doxygen)
/// January 10, 2010 Stephen Timothy Cooney (completed commenting/formatting core code for doxygen)
//////////////////////////////////////////////////////////////////////////////
#ifndef COONEYMATH_H
#define COONEYMATH_H

#include <cmath>
#include <assert.h>
#include <stdlib.h>

#ifndef FORCE_INLINE
#ifdef _WINDOWS
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE inline
#endif
#endif

#ifndef uint
typedef unsigned int uint;
#endif

//_______________________________________
/////////////////////////////////////////
// Section: Math-System defines/constants

// If you want to be really fast, you can do some of the operations with macros
// Most of the macros that do operations require a semicolon(;) at the end. This is
// so that the macros can be strung together with other operations
// ex: COONEY_MATH_SIN(3.14f);

#define COONEY_MATH_ROW_MAJOR			0 ///<1(true, DirectX) or 0(false, OpenGL) (rearranges the matrixes to mirror the systems)
#define COONEY_MATH_EPSILON				0.001f

#define COONEY_MATH_PI			3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f
#define COONEY_MATH_PI_HALF		(COONEY_MATH_PI/2.0f) ///< TODO: Unoptimal? I think I saw the compiler bakes this...
#define COONEY_MATH_PI_TWO		(COONEY_MATH_PI*2.0f) ///< TODO: Unoptimal? "

#define COONEY_MATH_WRAP_FLOAT(max,wrap_value) (wrap_value>=max?wrap_value-max:wrap_value)

#define COONEY_MATH_SIN(radians) sinf(radians)
#define COONEY_MATH_COS(radians) cosf(radians)
#define COONEY_MATH_ASIN(fSin) asinf(fSin)
#define COONEY_MATH_ACOS(fCos) acosf(fCos)
#define COONEY_MATH_POW(a, power) powf(a,power)
#define COONEY_MATH_EXP(exp) expf(exp)
#define COONEY_MATH_LOG(log) logf(log)
#define COONEY_MATH_SQRT(a) sqrtf(a)
#define COONEY_MATH_ABSF(a) fabsf(a)
#define COONEY_MATH_ABS(a) abs(a)

#define COONEY_MATH_MATRIX2_DET(e00, e01, e10, e11) ((e00)*(e11)-(e01)*(e10))
#define COONEY_MATH_MATRIX3_DET(e00, e01, e02, e10, e11, e12, e20, e21, e22) (((e00)*COONEY_MATH_MATRIX2_DET(e11,e12,e21,e22))-((e01)*COONEY_MATH_MATRIX2_DET(e10,e12,e20,e22))+((e02)*COONEY_MATH_MATRIX2_DET(e10,e11,e20,e21)))
#define COONEY_MATH_MATRIX4_DET(e00, e01, e02, e03, e10, e11, e12, e13, e20, e21, e22, e23, e30, e31, e32, e33) (((e00)*COONEY_MATH_MATRIX3_DET(e11,e12,e13,e21,e22,e23,e31,e32,e33))-((e01)*COONEY_MATH_MATRIX3_DET(e10,e12,e13,e20,e22,e23,e30,e32,e33))+((e02)*COONEY_MATH_MATRIX3_DET(e10,e11,e13,e20,e21,e23,e30,e31,e33))-((e03)*COONEY_MATH_MATRIX3_DET(e10,e11,e12,e20,e21,e22,e30,e31,e32)))

#define COONEY_MATH_ISPOWER2(a) (((a) & -(a))==(a))
#define COONEY_MATH_MIN(a,b) (((a) < (b))?(a):(b))
#define COONEY_MATH_MAX(a,b) (((a) > (b))?(a):(b))
#define COONEY_MATH_SWAP(var_type,a,b) {var_type varTemp = a; a = b; b = varTemp;}
#define COONEY_MATH_SWAPQUICK(a,b,temp) {temp=(a);a=b;b=temp;}
#define COONEY_MATH_RAND_FLOAT(min, max)	(((rand() / (float)RAND_MAX) * ((max) - (min))) + (min))
#define COONEY_MATH_DEGREES_TO_RADIANS(degrees) ((degrees)*(COONEY_MATH_PI/180.0f))
#define COONEY_MATH_RADIANS_TO_DEGREES(radians) ((radians)*(180.0f/COONEY_MATH_PI))

namespace Cooney
{
	namespace Math
	{
		//___________________________
		/////////////////////////////
		// Section: Basic Mathematics
		
		/// Determines the orientation of matrixes in memory. If it is row major,
		/// rows are strung in memory before columns. DirectX is considered row
		/// major whereas OpenGL is considered column major.
		const bool		isRowMajor								= COONEY_MATH_ROW_MAJOR;
		
		/// An extremely generic description of small. Used in multiple places but primarily
		/// useful for collision tests and physics code. Most linear-algebra math does not
		/// require an epsilon to worry about.
		const float		epsilon									= COONEY_MATH_EPSILON;
		
		/// Geometric Pi, useful for rotational mathematics.
		const float		pi										= COONEY_MATH_PI;
		
		/// Half of geometric Pi.
		const float		halfPi									= COONEY_MATH_PI_HALF;
		
		/// Twice geometric Pi.
		const float		twoPi									= COONEY_MATH_PI_TWO;
		
		/// Is the number(a) a power of two?
		FORCE_INLINE bool	IsPowerOfTwo(const int a)						{ return COONEY_MATH_ISPOWER2(a); };
		/// Return the greater of the two floats.
		FORCE_INLINE float	Max(const float a,const float b)					{ return COONEY_MATH_MAX(a,b); }		
		/// Return the greater of the two integers.
		FORCE_INLINE int	Max(const int a,const int b)						{ return COONEY_MATH_MAX(a,b); }
		/// Return the greater of the two unsigned integers.
		FORCE_INLINE uint	Max(const uint a,const uint b)						{ return COONEY_MATH_MAX(a,b); }
		/// Return the lesser of the two floats.
		FORCE_INLINE float	Min(const float a,const float b)					{ return COONEY_MATH_MIN(a,b); }
		/// Return the lesser of the two integers.
		FORCE_INLINE int	Min(const int a,const int b)						{ return COONEY_MATH_MIN(a,b); }
		/// Return the lesser of the two integers.
		FORCE_INLINE uint	Min(const uint a,const uint b)						{ return COONEY_MATH_MIN(a,b); }
		/// Swap a and b into each other.
		FORCE_INLINE void	Swap(float& a, float& b)				{ COONEY_MATH_SWAP(float,a,b);}
		/// Swap a and b into each other and use a passed in reference for the intermediary
		FORCE_INLINE void	SwapQuick(float& a,float& b,float& temp){ COONEY_MATH_SWAPQUICK(a,b,temp);}
		/// Return a random float between min and max.
		FORCE_INLINE float	RandFloat(const float min, const float max)			{ return COONEY_MATH_RAND_FLOAT(min,max);}
		/// Convert degrees to radians.
		FORCE_INLINE float	DegreesToRadians(const float fDegrees)	{ return COONEY_MATH_DEGREES_TO_RADIANS(fDegrees); }
		/// Convert radians to degrees.
		FORCE_INLINE float	RadiansToDegrees(const float fRadians)	{ return COONEY_MATH_RADIANS_TO_DEGREES(fRadians); }
		/// wraps the value around between zero and max. This will not loop, it will only do one wrap.
		FORCE_INLINE float WrapUp(const float max, const float wrap_value) {return COONEY_MATH_WRAP_FLOAT(max,wrap_value);}
		/// wrap the value around until it fits within min and max.
		FORCE_INLINE float Wrap(const float min, const float max, float wrap_value)
		{
			// loop through and 'wrap' the value until it fits within min and max.
			while(true)
			{
				if(wrap_value < min){wrap_value = max + (wrap_value-min);continue;}
				else if(wrap_value >= max){wrap_value = min + (wrap_value-max);continue;}
				else{return wrap_value;}
			}
			return wrap_value;
		}
		
		/// Sine of a radian value.
		FORCE_INLINE float Sin(const float fRad) {return COONEY_MATH_SIN(fRad);}
		/// Cosine of a radian value.
		FORCE_INLINE float Cos(const float fRad) {return COONEY_MATH_COS(fRad);}
		/// Sine of a value in degrees.
		FORCE_INLINE float SinDeg(const float fDeg) {return COONEY_MATH_SIN(COONEY_MATH_DEGREES_TO_RADIANS(Wrap(0.0f,360.0f,fDeg)));}
		/// Cosine of a value in degrees.
		FORCE_INLINE float CosDeg(const float fDeg) {return COONEY_MATH_COS(COONEY_MATH_DEGREES_TO_RADIANS(Wrap(0.0f,360.0f,fDeg)));}
		/// ArcSine that returns in radians.
		FORCE_INLINE float ASin(const float fSin) {return COONEY_MATH_ASIN(fSin);}
		/// ArcCosine that returns in radians.
		FORCE_INLINE float ACos(const float fCos) {return COONEY_MATH_ACOS(fCos);}
		/// ArcSine that returns in degrees(slower than radians).
		FORCE_INLINE float ASinDeg(const float fSin) {return COONEY_MATH_RADIANS_TO_DEGREES(COONEY_MATH_ASIN(fSin));}
		/// ArcCosine that returns in degrees(slower than radians).
		FORCE_INLINE float ACosDeg(const float fCos) {return COONEY_MATH_RADIANS_TO_DEGREES(COONEY_MATH_ACOS(fCos));}
		/// Return a to the power 'power'.
		FORCE_INLINE float Pow(const float a, const float power) {return COONEY_MATH_POW(a,power);}
		/// Return e(base of natural logarithm) to the power 'expo'.
		FORCE_INLINE float Exp(const float expo) {return COONEY_MATH_EXP(expo);}
		/// Find the logaritmic value of 'log'.
		FORCE_INLINE float Log(const float log) {return COONEY_MATH_LOG(log);}
		/// Return the square root.
		FORCE_INLINE float Sqrt(const float a) {return COONEY_MATH_SQRT(a);}
		/// Return the absolute value of the float.
		FORCE_INLINE float Abs(const float a) {return COONEY_MATH_ABSF(a);}
		/// Return the absolute value of the int.
		FORCE_INLINE int	Abs(const int a) {return COONEY_MATH_ABS(a);}
		
		//_____________________________________
		///////////////////////////////////////
		// Section: Vector & Matrix Mathematics

		//_______________________
		// Prototype declarations
		// comments and explanations located at the function/class definitions.
		
		class Mat2;
		class Mat3;
		class Mat4;
		class Vec2;
		class Vec3;
		class Vec4;

		FORCE_INLINE Mat2 Matrix2(float e00, float e01, float e10, float e11);
		FORCE_INLINE Mat2 Matrix2(float *elements4);
		FORCE_INLINE Mat3 Matrix3(float e00, float e01, float e02, float e10, float e11, float e12, float e20, float e21, float e22);
		FORCE_INLINE Mat3 Matrix3(float *elements9);
		FORCE_INLINE Mat4 Matrix4(float e00, float e01, float e02, float e03, float e10, float e11, float e12, float e13, float e20, float e21, float e22, float e23, float e30, float e31, float e32, float e33);
		FORCE_INLINE Mat4 Matrix4(float *elements16);
		FORCE_INLINE Vec2 Vector2(float x, float y);
		FORCE_INLINE Vec2 Vector2(float *elements2);
		FORCE_INLINE Vec3 Vector3(float x, float y, float z);
		FORCE_INLINE Vec3 Vector3(float *elements3);
		FORCE_INLINE Vec4 Vector4(float x, float y, float z, float w);
		FORCE_INLINE Vec4 Vector4(float *elements4);
		FORCE_INLINE Mat2& Matrix2(float e00, float e01, float e10, float e11, Mat2 &out);
		FORCE_INLINE Mat2& Matrix2(float *elements4, Mat2 &out);
		FORCE_INLINE Mat3& Matrix3(float e00, float e01, float e02, float e10, float e11, float e12, float e20, float e21, float e22, Mat3 &out);
		FORCE_INLINE Mat3& Matrix3(float *elements9, Mat3 &out);
		FORCE_INLINE Mat4& Matrix4(float e00, float e01, float e02, float e03, float e10, float e11, float e12, float e13, float e20, float e21, float e22, float e23, float e30, float e31, float e32, float e33, Mat4 &out);
		FORCE_INLINE Mat4& Matrix4(float *elements16, Mat4 &out);
		FORCE_INLINE Vec2& Vector2(float x, float y, Vec2 &out);
		FORCE_INLINE Vec2& Vector2(float *elements2, Vec2 &out);
		FORCE_INLINE Vec3& Vector3(float x, float y, float z, Vec3 &out);
		FORCE_INLINE Vec3& Vector3(float *elements3, Vec3 &out);
		FORCE_INLINE Vec4& Vector4(float x, float y, float z, float w, Vec4 &out);
		FORCE_INLINE Vec4& Vector4(float *elements4, Vec4 &out);
		//
		FORCE_INLINE Mat2& MakeZero2(Mat2 &a);
		FORCE_INLINE Mat3& MakeZero3(Mat3 &a);
		FORCE_INLINE Mat4& MakeZero4(Mat4 &a);
		FORCE_INLINE Vec2& MakeZero2(Vec2 &a);
		FORCE_INLINE Vec3& MakeZero3(Vec3 &a);
		FORCE_INLINE Vec4& MakeZero4(Vec4 &a);
		//
		FORCE_INLINE Mat2& MakeIdentity2(Mat2 &a);
		FORCE_INLINE Mat3& MakeIdentity3(Mat3 &a);
		FORCE_INLINE Mat4& MakeIdentity4(Mat4 &a);
		//
		FORCE_INLINE Vec2 AxisX2(const Mat2 &a);
		FORCE_INLINE Vec2 AxisY2(const Mat2 &a);
		FORCE_INLINE Vec3 AxisX3(const Mat3 &a);
		FORCE_INLINE Vec3 AxisY3(const Mat3 &a);
		FORCE_INLINE Vec3 AxisZ3(const Mat3 &a);
		FORCE_INLINE Vec4 AxisX4(const Mat4 &a);
		FORCE_INLINE Vec4 AxisY4(const Mat4 &a);
		FORCE_INLINE Vec4 AxisZ4(const Mat4 &a);
		FORCE_INLINE Vec4 AxisW4(const Mat4 &a);
		FORCE_INLINE Vec4 AxisTranslation4(const Mat4 &a);
		FORCE_INLINE Vec2& AxisX2(const Mat2 &a, Vec2 &out);
		FORCE_INLINE Vec2& AxisY2(const Mat2 &a, Vec2 &out);
		FORCE_INLINE Vec3& AxisX3(const Mat3 &a, Vec3 &out);
		FORCE_INLINE Vec3& AxisY3(const Mat3 &a, Vec3 &out);
		FORCE_INLINE Vec3& AxisZ3(const Mat3 &a, Vec3 &out);
		FORCE_INLINE Vec4& AxisX4(const Mat4 &a, Vec4 &out);
		FORCE_INLINE Vec4& AxisY4(const Mat4 &a, Vec4 &out);
		FORCE_INLINE Vec4& AxisZ4(const Mat4 &a, Vec4 &out);
		FORCE_INLINE Vec4& AxisW4(const Mat4 &a, Vec4 &out);
		FORCE_INLINE Vec4& AxisTranslation4(const Mat4 &a, Vec4 &out);
		//
		FORCE_INLINE Mat2 Transpose2(const Mat2 &a);
		FORCE_INLINE Mat3 Transpose3(const Mat3 &a);
		FORCE_INLINE Mat4 Transpose4(const Mat4 &a);
		FORCE_INLINE Mat2& Transpose2(const Mat2 &a,Mat2 &out);
		FORCE_INLINE Mat3& Transpose3(const Mat3 &a,Mat2 &out);
		FORCE_INLINE Mat4& Transpose4(const Mat4 &a,Mat2 &out);
		FORCE_INLINE Mat2& MakeTranspose2(Mat2 &a);
		FORCE_INLINE Mat3& MakeTranspose3(Mat3 &a);
		FORCE_INLINE Mat4& MakeTranspose4(Mat4 &a);
		//
		FORCE_INLINE Mat2 Scalar2(const Vec2 &scalar);
		FORCE_INLINE Mat3 Scalar3(const Vec3 &scalar);
		FORCE_INLINE Mat4 Scalar4(const Vec3 &scalar);
		FORCE_INLINE Mat2& Scalar2(const Vec2 &scalar, Mat2 &out);
		FORCE_INLINE Mat3& Scalar3(const Vec3 &scalar, Mat3 &out);
		FORCE_INLINE Mat4& Scalar4(const Vec3 &scalar, Mat4 &out);
		//
		FORCE_INLINE Mat2 Rotational2(const float radians);
		FORCE_INLINE Mat3 Rotational3(const Vec3 &axis, const float radians);
		FORCE_INLINE Mat3 Rotational3(const float radiansx, const float radiansy, const float radiansz);
		FORCE_INLINE Mat3 RotationalX3(const float radians);
		FORCE_INLINE Mat3 RotationalY3(const float radians);
		FORCE_INLINE Mat3 RotationalZ3(const float radians);
		FORCE_INLINE Mat4 Rotational4(const Vec3 &axis, const float radians);
		FORCE_INLINE Mat4 Rotational4(const float radiansx, const float radiansy, const float radiansz);
		FORCE_INLINE Mat4 RotationalX4(const float radians);
		FORCE_INLINE Mat4 RotationalY4(const float radians);
		FORCE_INLINE Mat4 RotationalZ4(const float radians);
		FORCE_INLINE Mat2& Rotational2(const float radians, Mat2 &out);
		FORCE_INLINE Mat3& Rotational3(const Vec3 &axis, const float radians, Mat3 &out);
		FORCE_INLINE Mat3& Rotational3(const float radiansx, const float radiansy, const float radiansz, Mat3& out);
		FORCE_INLINE Mat3& RotationalX3(const float radians, Mat3 &out);
		FORCE_INLINE Mat3& RotationalY3(const float radians, Mat3 &out);
		FORCE_INLINE Mat3& RotationalZ3(const float radians, Mat3 &out);
		FORCE_INLINE Mat4& Rotational4(const Vec3 &axis, const float radians, Mat4 &out);
		FORCE_INLINE Mat4& Rotational4(const float radiansx, const float radiansy, const float radiansz, Mat4 &out);
		FORCE_INLINE Mat4& RotationalX4(const float radians, Mat4 &out);
		FORCE_INLINE Mat4& RotationalY4(const float radians, Mat4 &out);
		FORCE_INLINE Mat4& RotationalZ4(const float radians, Mat4 &out);
		//
		FORCE_INLINE Mat3 Translational3(const Vec2 &translation);
		FORCE_INLINE Mat4 Translational4(const Vec3 &translation);
		FORCE_INLINE Mat3& Translational3(const Vec2 &translation, Mat3 &out);
		FORCE_INLINE Mat4& Translational4(const Vec3 &translation, Mat4 &out);
		//
		FORCE_INLINE float Determinant2(const Mat2 &a);
		FORCE_INLINE float Determinant3(const Mat3 &a);
		FORCE_INLINE float Determinant4(const Mat4 &a);
		//
		FORCE_INLINE Mat2 Cofactor2(const Mat2 &a);
		FORCE_INLINE Mat3 Cofactor3(const Mat3 &a);
		FORCE_INLINE Mat4 Cofactor4(const Mat4 &a);
		FORCE_INLINE Mat2& Cofactor2(const Mat2 &a, Mat2 &out);
		FORCE_INLINE Mat3& Cofactor3(const Mat3 &a, Mat3 &out);
		FORCE_INLINE Mat4& Cofactor4(const Mat4 &a, Mat4 &out);
		FORCE_INLINE Mat2& MakeCofactor2(Mat2 &a_out);
		FORCE_INLINE Mat3& MakeCofactor3(Mat3 &a_out);
		FORCE_INLINE Mat4& MakeCofactor4(Mat4 &a_out);
		//
		FORCE_INLINE Mat2 Inverse2(const Mat2 &a);
		FORCE_INLINE Mat3 Inverse3(const Mat3 &a);
		FORCE_INLINE Mat4 Inverse4(const Mat4 &a);
		FORCE_INLINE Mat2& Inverse2(const Mat2 &a,Mat2 &out);
		FORCE_INLINE Mat3& Inverse3(const Mat3 &a,Mat2 &out);
		FORCE_INLINE Mat4& Inverse4(const Mat4 &a,Mat2 &out);
		FORCE_INLINE Mat2& MakeInverse2(Mat2 &a);
		FORCE_INLINE Mat3& MakeInverse3(Mat3 &a);
		FORCE_INLINE Mat4& MakeInverse4(Mat4 &a);
		//
		FORCE_INLINE Vec2 Cross2(const Vec2 &a);
		FORCE_INLINE Vec3 Cross3(const Vec3 &a,const Vec3 &b);
		FORCE_INLINE Vec4 Cross4(const Vec4 &a, const Vec4 &b, const Vec4 &c);
		FORCE_INLINE Vec2& Cross2(const Vec2 &a, Vec2 &out);
		FORCE_INLINE Vec3& Cross3(const Vec3 &a,const Vec3 &b, Vec3 &out);
		FORCE_INLINE Vec4& Cross4(const Vec4 &a, const Vec4 &b, const Vec4 &c, Vec4 &out);
		FORCE_INLINE Vec2& MakeCross2(Vec2 &a_out);
		FORCE_INLINE Vec3& MakeCross3(Vec3 &a_out,const Vec3 &b);
		FORCE_INLINE Vec4& MakeCross4(Vec4 &a_out, const Vec4 &b, const Vec4 &c);
		//
		FORCE_INLINE Mat2 Add2(const Mat2 &a,const Mat2 &b);
		FORCE_INLINE Mat3 Add3(const Mat3 &a,const Mat3 &b);
		FORCE_INLINE Mat4 Add4(const Mat4 &a,const Mat4 &b);
		FORCE_INLINE Vec2 Add2(const Vec2 &a,const Vec2 &b);
		FORCE_INLINE Vec3 Add3(const Vec3 &a,const Vec3 &b);
		FORCE_INLINE Vec4 Add4(const Vec4 &a,const Vec4 &b);
		FORCE_INLINE Mat2& Add2(const Mat2 &a,const Mat2 &b,Mat2 &out);
		FORCE_INLINE Mat3& Add3(const Mat3 &a,const Mat3 &b,Mat3 &out);
		FORCE_INLINE Mat4& Add4(const Mat4 &a,const Mat4 &b,Mat4 &out);
		FORCE_INLINE Vec2& Add2(const Vec2 &a,const Vec2 &b,Vec2 &out);
		FORCE_INLINE Vec3& Add3(const Vec3 &a,const Vec3 &b,Vec3 &out);
		FORCE_INLINE Vec4& Add4(const Vec4 &a,const Vec4 &b,Vec4 &out);
		FORCE_INLINE Mat2& MakeAdd2(Mat2 &a_out,const Mat2 &b);
		FORCE_INLINE Mat3& MakeAdd3(Mat3 &a_out,const Mat3 &b);
		FORCE_INLINE Mat4& MakeAdd4(Mat4 &a_out,const Mat4 &b);
		FORCE_INLINE Vec2& MakeAdd2(Vec2 &a_out,const Vec2 &b);
		FORCE_INLINE Vec3& MakeAdd3(Vec3 &a_out,const Vec3 &b);
		FORCE_INLINE Vec4& MakeAdd4(Vec4 &a_out,const Vec4 &b);
		FORCE_INLINE Mat2 operator +(const Mat2 &a, const Mat2 &b);
		FORCE_INLINE Mat3 operator +(const Mat3 &a, const Mat3 &b);
		FORCE_INLINE Mat4 operator +(const Mat4 &a, const Mat4 &b);
		FORCE_INLINE Vec2 operator +(const Vec2 &a, const Vec2 &b);
		FORCE_INLINE Vec3 operator +(const Vec3 &a, const Vec3 &b);
		FORCE_INLINE Vec4 operator +(const Vec4 &a, const Vec4 &b);
		FORCE_INLINE Mat2& operator +=(Mat2 &a, const Mat2 &b);
		FORCE_INLINE Mat3& operator +=(Mat3 &a, const Mat3 &b);
		FORCE_INLINE Mat4& operator +=(Mat4 &a, const Mat4 &b);
		FORCE_INLINE Vec2& operator +=(Vec2 &a, const Vec2 &b);
		FORCE_INLINE Vec3& operator +=(Vec3 &a, const Vec3 &b);
		FORCE_INLINE Vec4& operator +=(Vec4 &a, const Vec4 &b);
		//
		FORCE_INLINE Mat2 Sub2(const Mat2 &a,const Mat2 &b);
		FORCE_INLINE Mat3 Sub3(const Mat3 &a,const Mat3 &b);
		FORCE_INLINE Mat4 Sub4(const Mat4 &a,const Mat4 &b);
		FORCE_INLINE Vec2 Sub2(const Vec2 &a,const Vec2 &b);
		FORCE_INLINE Vec3 Sub3(const Vec3 &a,const Vec3 &b);
		FORCE_INLINE Vec4 Sub4(const Vec4 &a,const Vec4 &b);
		FORCE_INLINE Mat2& Sub2(const Mat2 &a,const Mat2 &b,Mat2 &out);
		FORCE_INLINE Mat3& Sub3(const Mat3 &a,const Mat3 &b,Mat3 &out);
		FORCE_INLINE Mat4& Sub4(const Mat4 &a,const Mat4 &b,Mat4 &out);
		FORCE_INLINE Vec2& Sub2(const Vec2 &a,const Vec2 &b,Vec2 &out);
		FORCE_INLINE Vec3& Sub3(const Vec3 &a,const Vec3 &b,Vec3 &out);
		FORCE_INLINE Vec4& Sub4(const Vec4 &a,const Vec4 &b,Vec4 &out);
		FORCE_INLINE Mat2& MakeSub2(Mat2 &a_out,const Mat2 &b);
		FORCE_INLINE Mat3& MakeSub3(Mat3 &a_out,const Mat3 &b);
		FORCE_INLINE Mat4& MakeSub4(Mat4 &a_out,const Mat4 &b);
		FORCE_INLINE Vec2& MakeSub2(Vec2 &a_out,const Vec2 &b);
		FORCE_INLINE Vec3& MakeSub3(Vec3 &a_out,const Vec3 &b);
		FORCE_INLINE Vec4& MakeSub4(Vec4 &a_out,const Vec4 &b);
		FORCE_INLINE Mat2 operator -(const Mat2 &a, const Mat2 &b);
		FORCE_INLINE Mat3 operator -(const Mat3 &a, const Mat3 &b);
		FORCE_INLINE Mat4 operator -(const Mat4 &a, const Mat4 &b);
		FORCE_INLINE Vec2 operator -(const Vec2 &a, const Vec2 &b);
		FORCE_INLINE Vec3 operator -(const Vec3 &a, const Vec3 &b);
		FORCE_INLINE Vec4 operator -(const Vec4 &a, const Vec4 &b);
		FORCE_INLINE Mat2& operator -=(Mat2 &a, const Mat2 &b);
		FORCE_INLINE Mat3& operator -=(Mat3 &a, const Mat3 &b);
		FORCE_INLINE Mat4& operator -=(Mat4 &a, const Mat4 &b);
		FORCE_INLINE Vec2& operator -=(Vec2 &a, const Vec2 &b);
		FORCE_INLINE Vec3& operator -=(Vec3 &a, const Vec3 &b);
		FORCE_INLINE Vec4& operator -=(Vec4 &a, const Vec4 &b);
		//
		FORCE_INLINE float Dot2(const Vec2 &a, const Vec2 &b);
		FORCE_INLINE float Dot3(const Vec3 &a, const Vec3 &b);
		FORCE_INLINE float Dot4(const Vec4 &a, const Vec4 &b);
		FORCE_INLINE float Dot2(const Vec2 &a, const Vec2 &b, float &out);
		FORCE_INLINE float Dot3(const Vec3 &a, const Vec3 &b, float &out);
		FORCE_INLINE float Dot4(const Vec4 &a, const Vec4 &b, float &out);
		//
		FORCE_INLINE float Mag2(const Vec2 &a);
		FORCE_INLINE float Mag3(const Vec3 &a);
		FORCE_INLINE float Mag4(const Vec4 &a);
		FORCE_INLINE float Mag2(const Vec2 &a, float &out);
		FORCE_INLINE float Mag3(const Vec3 &a, float &out);
		FORCE_INLINE float Mag4(const Vec4 &a, float &out);
		FORCE_INLINE float MagSquared2(const Vec2 &a);
		FORCE_INLINE float MagSquared3(const Vec3 &a);
		FORCE_INLINE float MagSquared4(const Vec4 &a);
		FORCE_INLINE float MagSquared2(const Vec2 &a, float &out);
		FORCE_INLINE float MagSquared3(const Vec3 &a, float &out);
		FORCE_INLINE float MagSquared4(const Vec4 &a, float &out);
		//
		FORCE_INLINE Vec3 Barycentric2(const Vec2 &point, const Vec2 &a, const Vec2 &b, const Vec2 &c);
		FORCE_INLINE Vec3 Barycentric2(const Vec2 &point, const Vec2 &a, const Vec2 &b, const Vec2 &c, Vec3 &bary_out);
		FORCE_INLINE Vec3 Barycentric3(const Vec3 &point, const Vec3 &a, const Vec3 &b, const Vec3 &c);
		FORCE_INLINE Vec3 Barycentric3(const Vec3 &point, const Vec3 &a, const Vec3 &b, const Vec3 &c, Vec3 &bary_out);
		//
		FORCE_INLINE Vec2 Normalized2(const Vec2& a);
		FORCE_INLINE Vec3 Normalized3(const Vec3& a);
		FORCE_INLINE Vec4 Normalized4(const Vec4& a);
		FORCE_INLINE Vec2& Normalized2(const Vec2& a, Vec2& out);
		FORCE_INLINE Vec3& Normalized3(const Vec3& a, Vec3& out);
		FORCE_INLINE Vec4& Normalized4(const Vec4& a, Vec4& out);
		FORCE_INLINE Vec2& MakeNormalized2(Vec2& a_out);
		FORCE_INLINE Vec3& MakeNormalized3(Vec3& a_out);
		FORCE_INLINE Vec4& MakeNormalized4(Vec4& a_out);
		//
		FORCE_INLINE Mat2 OrthoNormalized2(const Mat2& a);
		FORCE_INLINE Mat3 OrthoNormalized3(const Mat3& a);
		FORCE_INLINE Mat4 OrthoNormalized4(const Mat4& a);
		FORCE_INLINE Mat2& OrthoNormalized2(const Mat2& a, Mat2& out);
		FORCE_INLINE Mat3& OrthoNormalized3(const Mat3& a, Mat3& out);
		FORCE_INLINE Mat4& OrthoNormalized4(const Mat4& a, Mat4& out);
		FORCE_INLINE Mat2& MakeOrthoNormalized2(Mat2& a_out);
		FORCE_INLINE Mat3& MakeOrthoNormalized3(Mat3& a_out);
		FORCE_INLINE Mat4& MakeOrthoNormalized4(Mat4& a_out);
		//
		FORCE_INLINE Mat2 ScalarMult2(const Mat2& a, const float& scalar);
		FORCE_INLINE Mat3 ScalarMult3(const Mat3& a, const float& scalar);
		FORCE_INLINE Mat4 ScalarMult4(const Mat4& a, const float& scalar);
		FORCE_INLINE Vec2 ScalarMult2(const Vec2& a, const float& scalar);
		FORCE_INLINE Vec3 ScalarMult3(const Vec3& a, const float& scalar);
		FORCE_INLINE Vec4 ScalarMult4(const Vec4& a, const float& scalar);
		FORCE_INLINE Mat2& ScalarMult2(const Mat2& a, const float& scalar, Mat2& out);
		FORCE_INLINE Mat3& ScalarMult3(const Mat3& a, const float& scalar, Mat3& out);
		FORCE_INLINE Mat4& ScalarMult4(const Mat4& a, const float& scalar, Mat4& out);
		FORCE_INLINE Vec2& ScalarMult2(const Vec2& a, const float& scalar, Vec2& out);
		FORCE_INLINE Vec3& ScalarMult3(const Vec3& a, const float& scalar, Vec3& out);
		FORCE_INLINE Vec4& ScalarMult4(const Vec4& a, const float& scalar, Vec4& out);
		FORCE_INLINE Mat2& MakeScalarMult2(Mat2& a_out, const float& scalar);
		FORCE_INLINE Mat3& MakeScalarMult3(Mat3& a_out, const float& scalar);
		FORCE_INLINE Mat4& MakeScalarMult4(Mat4& a_out, const float& scalar);
		FORCE_INLINE Vec2& MakeScalarMult2(Vec2& a_out, const float& scalar);
		FORCE_INLINE Vec3& MakeScalarMult3(Vec3& a_out, const float& scalar);
		FORCE_INLINE Vec4& MakeScalarMult4(Vec4& a_out, const float& scalar);
		FORCE_INLINE Mat2 operator *(const Mat2& a, const float scalar);
		FORCE_INLINE Mat2 operator *(const float scalar, const Mat2& a);
		FORCE_INLINE Mat3 operator *(const Mat3& a, const float scalar);
		FORCE_INLINE Mat3 operator *(const float scalar, const Mat3& a);
		FORCE_INLINE Mat4 operator *(const Mat4& a, const float scalar);
		FORCE_INLINE Mat4 operator *(const float scalar, const Mat4& a);
		FORCE_INLINE Vec2 operator *(const Vec2& a, const float scalar);
		FORCE_INLINE Vec2 operator *(const float scalar, const Vec2& a);
		FORCE_INLINE Vec3 operator *(const Vec3& a, const float scalar);
		FORCE_INLINE Vec3 operator *(const float scalar, const Vec3& a);
		FORCE_INLINE Vec4 operator *(const Vec4& a, const float scalar);
		FORCE_INLINE Vec4 operator *(const float scalar, const Vec4& a);
		FORCE_INLINE Mat2& operator *=(Mat2& a, const float scalar);
		FORCE_INLINE Mat3& operator *=(Mat3& a, const float scalar);
		FORCE_INLINE Mat4& operator *=(Mat4& a, const float scalar);
		FORCE_INLINE Vec2& operator *=(Vec2& a, const float scalar);
		FORCE_INLINE Vec3& operator *=(Vec3& a, const float scalar);
		FORCE_INLINE Vec4& operator *=(Vec4& a, const float scalar);
		//
		FORCE_INLINE Mat2 ScalarDiv2(const Mat2& a, const float& scalar);
		FORCE_INLINE Mat3 ScalarDiv3(const Mat3& a, const float& scalar);
		FORCE_INLINE Mat4 ScalarDiv4(const Mat4& a, const float& scalar);
		FORCE_INLINE Vec2 ScalarDiv2(const Vec2& a, const float& scalar);
		FORCE_INLINE Vec3 ScalarDiv3(const Vec3& a, const float& scalar);
		FORCE_INLINE Vec4 ScalarDiv4(const Vec4& a, const float& scalar);
		FORCE_INLINE Mat2& ScalarDiv2(const Mat2& a, const float& scalar, Mat2& out);
		FORCE_INLINE Mat3& ScalarDiv3(const Mat3& a, const float& scalar, Mat3& out);
		FORCE_INLINE Mat4& ScalarDiv4(const Mat4& a, const float& scalar, Mat4& out);
		FORCE_INLINE Vec2& ScalarDiv2(const Vec2& a, const float& scalar, Vec2& out);
		FORCE_INLINE Vec3& ScalarDiv3(const Vec3& a, const float& scalar, Vec3& out);
		FORCE_INLINE Vec4& ScalarDiv4(const Vec4& a, const float& scalar, Vec4& out);
		FORCE_INLINE Mat2& MakeScalarDiv2(Mat2& a_out, const float& scalar);
		FORCE_INLINE Mat3& MakeScalarDiv3(Mat3& a_out, const float& scalar);
		FORCE_INLINE Mat4& MakeScalarDiv4(Mat4& a_out, const float& scalar);
		FORCE_INLINE Vec2& MakeScalarDiv2(Vec2& a_out, const float& scalar);
		FORCE_INLINE Vec3& MakeScalarDiv3(Vec3& a_out, const float& scalar);
		FORCE_INLINE Vec4& MakeScalarDiv4(Vec4& a_out, const float& scalar);
		FORCE_INLINE Mat2 operator /(const Mat2& a, const float scalar);
		FORCE_INLINE Mat3 operator /(const Mat3& a, const float scalar);
		FORCE_INLINE Mat4 operator /(const Mat4& a, const float scalar);
		FORCE_INLINE Vec2 operator /(const Vec2& a, const float scalar);
		FORCE_INLINE Vec3 operator /(const Vec3& a, const float scalar);
		FORCE_INLINE Vec4 operator /(const Vec4& a, const float scalar);
		FORCE_INLINE Mat2& operator /=(Mat2& a, const float scalar);
		FORCE_INLINE Mat3& operator /=(Mat3& a, const float scalar);
		FORCE_INLINE Mat4& operator /=(Mat4& a, const float scalar);
		FORCE_INLINE Vec2& operator /=(Vec2& a, const float scalar);
		FORCE_INLINE Vec3& operator /=(Vec3& a, const float scalar);
		FORCE_INLINE Vec4& operator /=(Vec4& a, const float scalar);
		//
		FORCE_INLINE Mat2 Mult2(const Mat2& a,const Mat2& b);
		FORCE_INLINE Mat3 Mult3(const Mat3& a,const Mat3& b);
		FORCE_INLINE Mat4 Mult4(const Mat4& a,const Mat4& b);
		FORCE_INLINE Vec2 Mult2(const Mat2& a,const Vec2& b);
		FORCE_INLINE Vec3 Mult3(const Mat3& a,const Vec3& b);
		FORCE_INLINE Vec4 Mult4(const Mat4& a,const Vec4& b);
		FORCE_INLINE Mat2& Mult2(const Mat2& a,const Mat2& b,Mat2& out);
		FORCE_INLINE Mat3& Mult3(const Mat3& a,const Mat3& b,Mat3& out);
		FORCE_INLINE Mat4& Mult4(const Mat4& a,const Mat4& b,Mat4& out);
		FORCE_INLINE Vec2& Mult2(const Mat2& a,const Vec2& b,Vec2& out);
		FORCE_INLINE Vec3& Mult3(const Mat3& a,const Vec3& b,Vec3& out);
		FORCE_INLINE Vec4& Mult4(const Mat4& a,const Vec4& b,Vec4& out);
		FORCE_INLINE Mat2& MakeMult2(Mat2& a_out,const Mat2& b);
		FORCE_INLINE Mat3& MakeMult3(Mat3& a_out,const Mat3& b);
		FORCE_INLINE Mat4& MakeMult4(Mat4& a_out,const Mat4& b);
		FORCE_INLINE Mat2 operator *(const Mat2& a, const Mat2& b);
		FORCE_INLINE Mat3 operator *(const Mat3& a, const Mat3& b);
		FORCE_INLINE Mat4 operator *(const Mat4& a, const Mat4& b);
		FORCE_INLINE Vec2 operator *(const Mat2& a, const Vec2& b);
		FORCE_INLINE Vec3 operator *(const Mat3& a, const Vec3& b);
		FORCE_INLINE Vec4 operator *(const Mat4& a, const Vec4& b);
		FORCE_INLINE Mat2& operator *=(Mat2& a, const Mat2& b);
		FORCE_INLINE Mat3& operator *=(Mat3& a, const Mat3& b);
		FORCE_INLINE Mat4& operator *=(Mat4& a, const Mat4& b);
		//
		FORCE_INLINE Mat2& ToMatrix2(const Mat3& a, Mat2& out);
		FORCE_INLINE Mat2& ToMatrix2(const Mat4& a, Mat2& out);
		FORCE_INLINE Mat3& ToMatrix3(const Mat2& a, Mat3& out);
		FORCE_INLINE Mat3& ToMatrix3(const Mat4& a, Mat3& out);
		FORCE_INLINE Mat4& ToMatrix4(const Mat2& a, Mat4& out);
		FORCE_INLINE Mat4& ToMatrix4(const Mat3& a, Mat4& out);
		FORCE_INLINE Mat2 ToMatrix2(const Mat3& a);
		FORCE_INLINE Mat2 ToMatrix2(const Mat4& a);
		FORCE_INLINE Mat3 ToMatrix3(const Mat2& a);
		FORCE_INLINE Mat3 ToMatrix3(const Mat4& a);
		FORCE_INLINE Mat4 ToMatrix4(const Mat2& a);
		FORCE_INLINE Mat4 ToMatrix4(const Mat3& a);
		//
		FORCE_INLINE Vec2& ToVector2(const Vec3& a, Vec2& out);
		FORCE_INLINE Vec2& ToVector2(const Vec4& a, Vec2& out);
		FORCE_INLINE Vec3& ToVector3(const Vec2& a, Vec3& out, const float z);
		FORCE_INLINE Vec3& ToVector3(const Vec4& a, Vec3& out);
		FORCE_INLINE Vec4& ToVector4(const Vec2& a, Vec4& out, const float z, const float w);
		FORCE_INLINE Vec4& ToVector4(const Vec3& a, Vec4& out, const float w);
		FORCE_INLINE Vec2 ToVector2(const Vec3& a);
		FORCE_INLINE Vec2 ToVector2(const Vec4& a);
		FORCE_INLINE Vec3 ToVector3(const Vec2& a, const float z);
		FORCE_INLINE Vec3 ToVector3(const Vec4& a);
		FORCE_INLINE Vec4 ToVector4(const Vec2& a, const float z, const float w);
		FORCE_INLINE Vec4 ToVector4(const Vec3& a, const float w);
		//
		FORCE_INLINE bool operator ==(const Mat2& a, const Mat2& b);
		FORCE_INLINE bool operator ==(const Mat3& a, const Mat3& b);
		FORCE_INLINE bool operator ==(const Mat4& a, const Mat4& b);
		FORCE_INLINE bool operator ==(const Vec2& a, const Vec2& b);
		FORCE_INLINE bool operator ==(const Vec3& a, const Vec3& b);
		FORCE_INLINE bool operator ==(const Vec4& a, const Vec4& b);
		FORCE_INLINE bool operator !=(const Mat2& a, const Mat2& b);
		FORCE_INLINE bool operator !=(const Mat3& a, const Mat3& b);
		FORCE_INLINE bool operator !=(const Mat4& a, const Mat4& b);
		FORCE_INLINE bool operator !=(const Vec2& a, const Vec2& b);
		FORCE_INLINE bool operator !=(const Vec3& a, const Vec3& b);
		FORCE_INLINE bool operator !=(const Vec4& a, const Vec4& b);
		
		//______________________________________________
		// End prototype declarations, begin definition.

#ifdef _WINDOWS
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a 2x2 matrix useful in linear-algebra/geometry.
		/// Most operations useful on and for the Mat2 class are defined
		/// globally. See all in CooneyMath.h.
		class Mat2
		{
		public:
			/// Union maps the elements array to the list of e**
			/// variables. Elements is a shallow description of
			/// the matrix while the e** variables represent mappings
			/// that remain the same even when the row orientation
			/// changes due to COONEY_MATH_ROW_MAJOR.
			union
			{
				float elements[4];
				struct  
				{
#if COONEY_MATH_ROW_MAJOR
					float	e00, e01,
							e10, e11;
#else
					float	e00, e10,
							e01, e11;
#endif //#if COONEY_MATH_ROW_ORIENT
				};
			};

			/// Makes an identity matrix by default.
			FORCE_INLINE				Mat2(){MakeIdentity2(*this);};
			FORCE_INLINE				~Mat2(){};
			
			FORCE_INLINE				Mat2(const Mat2& a){e00=a.e00;e01=a.e01;e10=a.e10;e11=a.e11;}
			FORCE_INLINE				Mat2(float el00, float el01, float el10, float el11)
			{
				e00=el00;
				e01=el01;
				e10=el10;
				e11=el11;
			}
			FORCE_INLINE				Mat2(float* elements4)
			{
				elements[0]=elements4[0];
				elements[1]=elements4[1];
				elements[2]=elements4[2];
				elements[3]=elements4[3];
			}
			FORCE_INLINE Mat2&			operator=(const Mat2& a){e00=a.e00;e01=a.e01;e10=a.e10;e11=a.e11;return *this;}

			/// Returns the number of elements that the matrix contains.
			FORCE_INLINE int			Elements() const	{return 4;}
			
			/// Returns a direct pointer to the elements. It's not recommended to act
			/// on the pointer directly since the organization may change due to row
			/// orientation.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
		};
#ifdef _WINDOWS
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a 3x3 matrix useful in linear-algebra/geometry.
		/// Most operations useful on and for the Mat3 class are defined
		/// globally. See all in CooneyMath.h.
		class Mat3
		{
		public:
			/// Union maps the elements array to the list of e**
			/// variables. Elements is a shallow description of
			/// the matrix while the e** variables represent mappings
			/// that remain the same even when the row orientation
			/// changes due to COONEY_MATH_ROW_MAJOR.
			union
			{
				float elements[9];
				struct  
				{
#if COONEY_MATH_ROW_MAJOR
					float	e00, e01, e02,
							e10, e11, e12,
							e20, e21, e22;
#else
					float	e00, e10, e20,
							e01, e11, e21,
							e02, e12, e22;
#endif //#if COONEY_MATH_ROW_ORIENT
				};
			};
			
			/// Constructs the identity matrix by default.
			FORCE_INLINE				Mat3(){MakeIdentity3(*this);};
			FORCE_INLINE				~Mat3(){};

			FORCE_INLINE				Mat3(const Mat3& a){e00=a.e00;e01=a.e01;e02=a.e02;e10=a.e10;e11=a.e11;e12=a.e12;e20=a.e20;e21=a.e21;e22=a.e22;}
			FORCE_INLINE				Mat3(float el00, float el01, float el02, float el10, float el11, float el12, float el20, float el21, float el22)
			{
				e00=el00;
				e01=el01;
				e02=el02;
				e10=el10;
				e11=el11;
				e12=el12;
				e20=el20;
				e21=el21;
				e22=el22;
			};
			FORCE_INLINE				Mat3(float* elements9)
			{
				elements[0]=elements9[0];
				elements[1]=elements9[1];
				elements[2]=elements9[2];
				elements[3]=elements9[3];
				elements[4]=elements9[4];
				elements[5]=elements9[5];
				elements[6]=elements9[6];
				elements[7]=elements9[7];
				elements[8]=elements9[8];
			}
			FORCE_INLINE Mat3&			operator=(const Mat3& a){e00=a.e00;e01=a.e01;e02=a.e02;e10=a.e10;e11=a.e11;e12=a.e12;e20=a.e20;e21=a.e21;e22=a.e22;return *this;}

			/// Returns the number of elements in the matrix (9 here).
			FORCE_INLINE int			Elements() const	{return 9;}
			
			/// Returns a direct pointer to the elements. It's not recommended to act
			/// on the pointer directly since the organization may change due to row
			/// orientation.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
		};
#ifdef _WINDOWS
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a 4x4 matrix useful in linear-algebra/geometry.
		/// Most operations useful on and for the Mat4 class are defined
		/// globally. See all in CooneyMath.h.
		class Mat4
		{
		public:
			/// Union maps the elements array to the list of e**
			/// variables. Elements is a shallow description of
			/// the matrix while the e** variables represent mappings
			/// that remain the same even when the row orientation
			/// changes due to COONEY_MATH_ROW_MAJOR.
			union
			{
				float elements[16];
				struct  
				{
#if COONEY_MATH_ROW_MAJOR
					float	e00, e01, e02, e03,
							e10, e11, e12, e13,
							e20, e21, e22, e23,
							e30, e31, e32, e33;
#else
					float	e00, e10, e20, e30,
							e01, e11, e21, e31,
							e02, e12, e22, e32,
							e03, e13, e23, e33;
#endif //#if COONEY_MATH_ROW_MAJOR
				};
			};
			
			/// Constructs an identity matrix by default.
			FORCE_INLINE				Mat4(){MakeIdentity4(*this);};
			FORCE_INLINE				~Mat4(){};

			FORCE_INLINE				Mat4(const Mat4& a){e00=a.e00;e01=a.e01;e02=a.e02;e03=a.e03;e10=a.e10;e11=a.e11;e12=a.e12;e13=a.e13;e20=a.e20;e21=a.e21;e22=a.e22;e23=a.e23;e30=a.e30;e31=a.e31;e32=a.e32;e33=a.e33;}
			FORCE_INLINE				Mat4(float el00, float el01, float el02, float el03, float el10, float el11, float el12, float el13, float el20, float el21, float el22, float el23, float el30, float el31, float el32, float el33)
			{
				e00=el00;
				e01=el01;
				e02=el02;
				e03=el03;
				e10=el10;
				e11=el11;
				e12=el12;
				e13=el13;
				e20=el20;
				e21=el21;
				e22=el22;
				e23=el23;
				e30=el30;
				e31=el31;
				e32=el32;
				e33=el33;
			}
			FORCE_INLINE				Mat4(float* elements16)
			{
				elements[0]=elements16[0];
				elements[1]=elements16[1];
				elements[2]=elements16[2];
				elements[3]=elements16[3];
				elements[4]=elements16[4];
				elements[5]=elements16[5];
				elements[6]=elements16[6];
				elements[7]=elements16[7];
				elements[8]=elements16[8];
				elements[9]=elements16[9];
				elements[10]=elements16[10];
				elements[11]=elements16[11];
				elements[12]=elements16[12];
				elements[13]=elements16[13];
				elements[14]=elements16[14];
				elements[15]=elements16[15];
			}
			FORCE_INLINE Mat4&			operator=(const Mat4& a){e00=a.e00;e01=a.e01;e02=a.e02;e03=a.e03;e10=a.e10;e11=a.e11;e12=a.e12;e13=a.e13;e20=a.e20;e21=a.e21;	e22=a.e22;e23=a.e23;e30=a.e30;e31=a.e31;e32=a.e32;e33=a.e33;return *this;}

			/// Returns then number of elements in the matrix (16 in this case).
			FORCE_INLINE int			Elements() const	{return 16;}
			
			/// Returns a direct pointer to the elements. It's not recommended to act
			/// on the pointer directly since the organization may change due to row
			/// orientation.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access the elements of the matrix by their indexes. This is not recommended
			/// since the organization of the matrix may change due to the row orientation.
			/// This could hinder portable code. Access via e** variables is safer.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
		};
#ifdef _WINDOWS
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a vector with 2 elements for linear-algebra/geometry.
		/// Most operations useful for the Vec2 class are defined globally. See all in CooneyMath.h.
		class Vec2
		{
		public:
			/// Union links an array of elements to different interpretations
			/// of a vector that may be useful for computer graphics/physics/simulation.
			union
			{
				float elements[2];
				struct 
				{
					float	x,y;
				};
				struct
				{
					float	r,g;
				};
				struct
				{
					float	_u,_v; // _ because xyz can have a w, overlapping
				};
			};
			
			FORCE_INLINE				Vec2(){MakeZero2(*this);};
			FORCE_INLINE				~Vec2(){};

			FORCE_INLINE				Vec2(const Vec2& a){x=a.x;y=a.y;}
			FORCE_INLINE				Vec2(const float ex, const float ey){x = ex;y = ey;}
			FORCE_INLINE				Vec2(float* elements2){x = elements2[0];y = elements2[1];}
			FORCE_INLINE Vec2&			operator=(const Vec2& a){x=a.x;y=a.y;return *this;}

			/// Returns the number of elements in the vector (2).
			FORCE_INLINE int			Elements() const	{return 2;}
			
			/// Returns a pointer to the first element in the vector.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access an element of the vector directly.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access an element of the vector directly.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
			
			friend FORCE_INLINE Vec2 operator-(const Vec2 &);
		};
		/// Memberwise negate the vector.
		FORCE_INLINE Vec2 operator-(const Vec2 &vec)
		{
			return Vector2(-vec.x, -vec.y);
		}
#ifdef _WINDOWS
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a vector with 3 elements for linear-algebra/geometry.
		/// Most operations useful for the Vec3 class are defined globally. See all in CooneyMath.h.
		class Vec3
		{
		public:
			/// Union links an array of elements to different interpretations
			/// of a vector that may be useful for computer graphics/physics/simulation.
			union
			{
				float elements[3];
				struct 
				{
					float	x,y,z;
				};
				struct
				{
					float	r,g,b;
				};
				struct
				{
					float	_u,_v,_w; // _w because xyz can have a w
				};
			};
			
			FORCE_INLINE				Vec3(){MakeZero3(*this);};
			FORCE_INLINE				~Vec3(){};

			FORCE_INLINE				Vec3(const Vec3& a){x=a.x;y=a.y;z=a.z;}
			FORCE_INLINE				Vec3(const float ex, const float ey, const float ez){x = ex;y = ey;z = ez;}
			FORCE_INLINE				Vec3(float* elements3){x = elements3[0];y = elements3[1];z = elements3[2];}
			FORCE_INLINE Vec3&			operator=(const Vec3& a){x=a.x;y=a.y;z=a.z;return *this;}

			/// Returns the number of elements in the vector (2).
			FORCE_INLINE int			Elements() const	{return 3;}
			
			/// Returns a pointer to the first element in the vector.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access the vector's elements directly.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access the vector's elements directly.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
			
			friend FORCE_INLINE Vec3 operator-(const Vec3 &);
		};
		/// Memberwise negate the vector.
		FORCE_INLINE Vec3 operator-(const Vec3 &vec)
		{
			return Vector3(-vec.x, -vec.y, -vec.z);
		}
#ifdef _WINDOWS
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
#endif
		/// Describes a vector with 3 elements for linear-algebra/geometry.
		/// Most operations useful for the Vec3 class are defined globally. See all in CooneyMath.h.
		class Vec4
		{
		public:
			/// Union links an array of elements to different interpretations
			/// of a vector that may be useful for computer graphics/physics/simulation.
			union
			{
				float elements[4];
				struct 
				{
					float	x,y,z,w;
				};
				struct
				{
					float	r,g,b,a;
				};
				struct
				{
					float _u,_v,_w,_x; // using _ because of overlap.
				};
			};
			
			FORCE_INLINE				Vec4(){MakeZero4(*this);};
			FORCE_INLINE				~Vec4(){};

			FORCE_INLINE				Vec4(const Vec4& a){x=a.x;y=a.y;z=a.z;w=a.w;}
			FORCE_INLINE				Vec4(float ex, float ey, float ez, float ew){x = ex;y = ey;z = ez;w = ew;}
			FORCE_INLINE				Vec4(float* elements4){x = elements4[0];y = elements4[1];z = elements4[2];w = elements4[3];}
			FORCE_INLINE Vec4&			operator=(const Vec4& a){x=a.x;y=a.y;z=a.z;w=a.w;return *this;}

			/// Returns the number of elements in the vector (4).
			FORCE_INLINE int			Elements() const	{return 4;}
			
			/// Returns a pointer to the first element in the vector.
			FORCE_INLINE float*			Ref() const			{return (float*)elements;}
			
			/// Access elements of the vector directly.
			FORCE_INLINE float&			operator[](const uint index) {return elements[index];}
			
			/// Access elements of the vector directly.
			FORCE_INLINE float			operator[](const uint index) const {return elements[index];}
			
			friend FORCE_INLINE Vec4 operator-(const Vec4 &);
		};
		/// Memberwise negate the vector.
		FORCE_INLINE Vec4 operator-(const Vec4 &vec)
		{
			return Vector4(-vec.x, -vec.y, -vec.z, -vec.w);
		}
#ifdef _WINDOWS
#pragma pack(pop)
#endif

		/// Constructor, takes individual members as initializer parameters.
		FORCE_INLINE Mat2 Matrix2(float e00, float e01, float e10, float e11)
		{
			Mat2 out;
			out.e00=e00;
			out.e01=e01;
			out.e10=e10;
			out.e11=e11;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array(size of 4).
		FORCE_INLINE Mat2 Matrix2(float *elements4)
		{
			Mat2 out;
			out.elements[0]=elements4[0];
			out.elements[1]=elements4[1];
			out.elements[2]=elements4[2];
			out.elements[3]=elements4[3];
			return out;
		}
		/// Constructor, takes individual members as initializer parameters.
		FORCE_INLINE Mat3 Matrix3(float e00, float e01, float e02, float e10, float e11, float e12, float e20, float e21, float e22)
		{
			Mat3 out;
			out.e00=e00;
			out.e01=e01;
			out.e02=e02;
			out.e10=e10;
			out.e11=e11;
			out.e12=e12;
			out.e20=e20;
			out.e21=e21;
			out.e22=e22;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array(size of 9).
		FORCE_INLINE Mat3 Matrix3(float *elements9)
		{
			Mat3 out;
			out.elements[0]=elements9[0];
			out.elements[1]=elements9[1];
			out.elements[2]=elements9[2];
			out.elements[3]=elements9[3];
			out.elements[4]=elements9[4];
			out.elements[5]=elements9[5];
			out.elements[6]=elements9[6];
			out.elements[7]=elements9[7];
			out.elements[8]=elements9[8];
			return out;
		}
		/// Constructor, takes individual members as initializer parameters.
		FORCE_INLINE Mat4 Matrix4(float e00, float e01, float e02, float e03, float e10, float e11, float e12, float e13, float e20, float e21, float e22, float e23, float e30, float e31, float e32, float e33)
		{
			Mat4 out;
			out.e00=e00;
			out.e01=e01;
			out.e02=e02;
			out.e03=e03;
			out.e10=e10;
			out.e11=e11;
			out.e12=e12;
			out.e13=e13;
			out.e20=e20;
			out.e21=e21;
			out.e22=e22;
			out.e23=e23;
			out.e30=e30;	
			out.e31=e31;
			out.e32=e32;
			out.e33=e33;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array(size of 16).
		FORCE_INLINE Mat4 Matrix4(float *elements16)
		{
			Mat4 out;
			out.elements[0]=elements16[0];
			out.elements[1]=elements16[1];
			out.elements[2]=elements16[2];
			out.elements[3]=elements16[3];
			out.elements[4]=elements16[4];
			out.elements[5]=elements16[5];
			out.elements[6]=elements16[6];
			out.elements[7]=elements16[7];
			out.elements[8]=elements16[8];
			out.elements[9]=elements16[9];
			out.elements[10]=elements16[10];
			out.elements[11]=elements16[11];
			out.elements[12]=elements16[12];
			out.elements[13]=elements16[13];
			out.elements[14]=elements16[14];
			out.elements[15]=elements16[15];
			return out;
		}
		/// Constructor, takes individual members as initializer parameters(x,y).
		FORCE_INLINE Vec2 Vector2(float x, float y)
		{
			Vec2 out;
			out.x = x;
			out.y = y;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array (size of 2).
		FORCE_INLINE Vec2 Vector2(float *elements2)
		{
			Vec2 out;
			out.x = elements2[0];
			out.y = elements2[1];
			return out;
		}
		/// Constructor, takes individual members as initializer parameters(x,y,z).
		FORCE_INLINE Vec3 Vector3(float x, float y, float z)
		{
			Vec3 out;
			out.x = x;
			out.y = y;
			out.z = z;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array (size of 3).
		FORCE_INLINE Vec3 Vector3(float *elements3)
		{
			Vec3 out;
			out.x = elements3[0];
			out.y = elements3[1];
			out.z = elements3[2];
			return out;
		}
		/// Constructor, takes individual members as initializer parameters(x,y,z,w).
		FORCE_INLINE Vec4 Vector4(float x, float y, float z, float w)
		{
			Vec4 out;
			out.x = x;
			out.y = y;
			out.z = z;
			out.w = w;
			return out;
		}
		/// Constructor, takes a pointer to an array that maps
		/// directly to the member element array(size of 4).
		FORCE_INLINE Vec4 Vector4(float *elements4)
		{
			Vec4 out;
			out.x = elements4[0];
			out.y = elements4[1];
			out.z = elements4[2];
			out.w = elements4[3];
			return out;
		}
		/// Constructor, takes individual members as parameters and a Mat2 to fill.
		FORCE_INLINE Mat2& Matrix2(float e00, float e01, float e10, float e11, Mat2 &out)
		{
			out.e00=e00;
			out.e01=e01;
			out.e10=e10;
			out.e11=e11;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 4) and a Mat2.
		FORCE_INLINE Mat2& Matrix2(float *elements4, Mat2 &out)
		{
			out.elements[0]=elements4[0];
			out.elements[1]=elements4[1];
			out.elements[2]=elements4[2];
			out.elements[3]=elements4[3];
			return out;
		}
		/// Constructor, takes individual members as parameters and a Mat3 to fill.
		FORCE_INLINE Mat3& Matrix3(float e00, float e01, float e02, float e10, float e11, float e12, float e20, float e21, float e22, Mat3 &out)
		{
			out.e00=e00;
			out.e01=e01;
			out.e02=e02;
			out.e10=e10;
			out.e11=e11;
			out.e12=e12;
			out.e20=e20;
			out.e21=e21;
			out.e22=e22;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 9) and a Mat3 to fill.
		FORCE_INLINE Mat3& Matrix3(float *elements9, Mat3 &out)
		{
			out.elements[0]=elements9[0];
			out.elements[1]=elements9[1];
			out.elements[2]=elements9[2];
			out.elements[3]=elements9[3];
			out.elements[4]=elements9[4];
			out.elements[5]=elements9[5];
			out.elements[6]=elements9[6];
			out.elements[7]=elements9[7];
			out.elements[8]=elements9[8];
			return out;
		}
		/// Constructor, takes individual members as parameters and a Mat4 to fill.
		FORCE_INLINE Mat4& Matrix4(float e00, float e01, float e02, float e03, float e10, float e11, float e12, float e13, float e20, float e21, float e22, float e23, float e30, float e31, float e32, float e33, Mat4 &out)
		{
			out.e00=e00;
			out.e01=e01;
			out.e02=e02;
			out.e03=e03;
			out.e10=e10;
			out.e11=e11;
			out.e12=e12;
			out.e13=e13;
			out.e20=e20;
			out.e21=e21;
			out.e22=e22;
			out.e23=e23;
			out.e30=e30;
			out.e31=e31;
			out.e32=e32;
			out.e33=e33;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 16) and a Mat4 to fill.
		FORCE_INLINE Mat4& Matrix4(float *elements16, Mat4 &out)
		{
			out.elements[0]=elements16[0];
			out.elements[1]=elements16[1];
			out.elements[2]=elements16[2];
			out.elements[3]=elements16[3];
			out.elements[4]=elements16[4];
			out.elements[5]=elements16[5];
			out.elements[6]=elements16[6];
			out.elements[7]=elements16[7];
			out.elements[8]=elements16[8];
			out.elements[9]=elements16[9];
			out.elements[10]=elements16[10];
			out.elements[11]=elements16[11];
			out.elements[12]=elements16[12];
			out.elements[13]=elements16[13];
			out.elements[14]=elements16[14];
			out.elements[15]=elements16[15];
			return out;
		}
		/// Constructor, takes individual members as parameters(x,y) and a Vec2 to fill.
		FORCE_INLINE Vec2& Vector2(float x, float y, Vec2 &out)
		{
			out.x = x;
			out.y = y;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 2) and a Vec2 to fill.
		FORCE_INLINE Vec2& Vector2(float *elements2, Vec2 &out)
		{
			out.x = elements2[0];
			out.y = elements2[1];
			return out;
		}
		/// Constructor, takes individual members as parameters(x,y,z) and a Vec3 to fill.
		FORCE_INLINE Vec3& Vector3(float x, float y, float z, Vec3 &out)
		{
			out.x = x;
			out.y = y;
			out.z = z;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 3) and a Vec3 to fill.
		FORCE_INLINE Vec3& Vector3(float *elements3, Vec3 &out)
		{
			out.x = elements3[0];
			out.y = elements3[1];
			out.z = elements3[2];
			return out;
		}
		/// Constructor, takes individual members as parameters(x,y,z,w) and a Vec4 to fill.
		FORCE_INLINE Vec4& Vector4(float x, float y, float z, float w, Vec4 &out)
		{
			out.x = x;
			out.y = y;
			out.z = z;
			out.w = w;
			return out;
		}
		/// Constructor, takes an array as initialization parameters(size of 4) and a Vec4 to fill.
		FORCE_INLINE Vec4& Vector4(float *elements4, Vec4 &out)
		{
			out.x = elements4[0];
			out.y = elements4[1];
			out.z = elements4[2];
			out.w = elements4[3];
			return out;
		}
		//
		/// Zero out all of the members in a Mat2.
		FORCE_INLINE Mat2& MakeZero2(Mat2 &a)
		{
			a.e00=a.e01=a.e10=a.e11=0.0f;
			return a;
		}
		/// Zero out all of the members in a Mat3.
		FORCE_INLINE Mat3& MakeZero3(Mat3 &a)
		{
			a.e00=a.e01=a.e02=a.e10=a.e11=a.e12=a.e20=a.e21=a.e22=0.0f;
			return a;
		}
		/// Zero out all of the members in a Mat4.
		FORCE_INLINE Mat4& MakeZero4(Mat4 &a)
		{
			a.e00=a.e01=a.e02=a.e03=a.e10=a.e11=a.e12=a.e13=a.e20=a.e21=a.e22=a.e23=a.e30=a.e31=a.e32=a.e33=0.0f;
			return a;
		}
		/// Zero out all of the members in a Vec2.
		FORCE_INLINE Vec2& MakeZero2(Vec2 &a)
		{
			a.x=a.y=0.0f;
			return a;
		}
		/// Zero out all of the members in a Vec3.
		FORCE_INLINE Vec3& MakeZero3(Vec3 &a)
		{
			a.x=a.y=a.z=0.0f;
			return a;
		}
		/// Zero out all of the members in a Vec4.
		FORCE_INLINE Vec4& MakeZero4(Vec4 &a)
		{
			a.x=a.y=a.z=a.w=0.0f;
			return a;
		}
		//
		/// Set the matrix to its identity form.
		/// [1 0]
		/// [0 1]
		FORCE_INLINE Mat2& MakeIdentity2(Mat2 &a)
		{
			a.e00=a.e11=1.0f;
			a.e01=a.e10=0.0f;
			return a;
		}
		/// Set the matrix to its identity form.
		/// [1 0 0]
		/// [0 1 0]
		/// [0 0 1]
		FORCE_INLINE Mat3& MakeIdentity3(Mat3 &a)
		{
			a.e00=a.e11=a.e22=1.0f;
			a.e01=a.e02=a.e10=a.e12=a.e20=a.e21=0.0f;
			return a;
		}
		/// Set the matrix to its identity form.
		/// [1 0 0 0]
		/// [0 1 0 0]
		/// [0 0 1 0]
		/// [0 0 0 1]
		FORCE_INLINE Mat4& MakeIdentity4(Mat4 &a)
		{
			a.e00=a.e11=a.e22=a.e33=1.0f;
			a.e01=a.e02=a.e03=a.e10=a.e12=a.e13=a.e20=a.e21=a.e23=a.e30=a.e31=a.e32=0.0f;
			return a;
		}
		//
		/// Return a Vec2 containing the x dimension.
		FORCE_INLINE Vec2 AxisX2(const Mat2 &a)
		{
			Vec2 out;
			out.x = a.e00;
			out.y = a.e01;
			return out;
		}
		/// Return a Vec2 containing the y dimension.
		FORCE_INLINE Vec2 AxisY2(const Mat2 &a)
		{
			Vec2 out;
			out.x = a.e10;
			out.y = a.e11;
			return out;
		}
		/// Return a Vec3 containing the x dimension.
		FORCE_INLINE Vec3 AxisX3(const Mat3 &a)
		{
			Vec3 out;
			out.x = a.e00;
			out.y = a.e01;
			out.z = a.e02;
			return out;
		}
		/// Return a Vec3 containing the y dimension.
		FORCE_INLINE Vec3 AxisY3(const Mat3 &a)
		{
			Vec3 out;
			out.x = a.e10;
			out.y = a.e11;
			out.z = a.e12;
			return out;
		}
		/// Return a Vec3 containing the z dimension.
		FORCE_INLINE Vec3 AxisZ3(const Mat3 &a)
		{
			Vec3 out;
			out.x = a.e20;
			out.y = a.e21;
			out.z = a.e22;
			return out;
		}
		/// Return a Vec4 containing the x dimension.
		FORCE_INLINE Vec4 AxisX4(const Mat4 &a)
		{
			Vec4 out;
			out.x = a.e00;
			out.y = a.e01;
			out.z = a.e02;
			out.w = a.e03;
			return out;
		}
		/// Return a Vec4 containing the y dimension.
		FORCE_INLINE Vec4 AxisY4(const Mat4 &a)
		{
			Vec4 out;
			out.x = a.e10;
			out.y = a.e11;
			out.z = a.e12;
			out.w = a.e13;
			return out;
		}
		/// Return a Vec4 containing the z dimension.
		FORCE_INLINE Vec4 AxisZ4(const Mat4 &a)
		{
			Vec4 out;
			out.x = a.e20;
			out.y = a.e21;
			out.z = a.e22;
			out.w = a.e23;
			return out;
		}
		/// Return a Vec4 containing the w dimension.
		FORCE_INLINE Vec4 AxisW4(const Mat4 &a)
		{
			Vec4 out;
			out.x = a.e30;
			out.y = a.e31;
			out.z = a.e32;
			out.w = a.e33;
			return out;
		}
		/// Return a Vec4 containing the homogenous translational parameters.
		FORCE_INLINE Vec4 AxisTranslation4(const Mat4 &a)
		{
			Vec4 out;
			out.x = a.e03;
			out.y = a.e13;
			out.z = a.e23;
			out.w = a.e33;
			return out;
		}
		/// Fills a Vec2 with the x dimension from the matrix.
		FORCE_INLINE Vec2& AxisX2(const Mat2 &a, Vec2 &out)
		{
			out.x = a.e00;
			out.y = a.e01;
			return out;
		}
		/// Fills a Vec2 with the y dimension from the matrix.
		FORCE_INLINE Vec2& AxisY2(const Mat2 &a, Vec2 &out)
		{
			out.x = a.e10;
			out.y = a.e11;
			return out;
		}
		/// Fills a Vec3 with the x dimension from the matrix.
		FORCE_INLINE Vec3& AxisX3(const Mat3 &a, Vec3 &out)
		{
			out.x = a.e00;
			out.y = a.e01;
			out.z = a.e02;
			return out;
		}
		/// Fills a Vec3 with the y dimension from the matrix.
		FORCE_INLINE Vec3& AxisY3(const Mat3 &a, Vec3 &out)
		{
			out.x = a.e10;
			out.y = a.e11;
			out.z = a.e12;
			return out;
		}
		/// Fills a Vec3 with the z dimension from the matrix.
		FORCE_INLINE Vec3& AxisZ3(const Mat3 &a, Vec3 &out)
		{
			out.x = a.e20;
			out.y = a.e21;
			out.z = a.e22;
			return out;
		}
		/// Fills a Vec4 with the x dimension from the matrix.
		FORCE_INLINE Vec4& AxisX4(const Mat4 &a, Vec4 &out)
		{
			out.x = a.e00;
			out.y = a.e01;
			out.z = a.e02;
			out.w = a.e03;
			return out;
		}
		/// Fills a Vec4 with the y dimension from the matrix.
		FORCE_INLINE Vec4& AxisY4(const Mat4 &a, Vec4 &out)
		{
			out.x = a.e10;
			out.y = a.e11;
			out.z = a.e12;
			out.w = a.e13;
			return out;
		}
		/// Fills a Vec4 with the z dimension from the matrix.
		FORCE_INLINE Vec4& AxisZ4(const Mat4 &a, Vec4 &out)
		{
			out.x = a.e20;
			out.y = a.e21;
			out.z = a.e22;
			out.w = a.e23;
			return out;
		}
		/// Fills a Vec4 with the w dimension from the matrix.
		FORCE_INLINE Vec4& AxisW4(const Mat4 &a, Vec4 &out)
		{
			out.x = a.e30;
			out.y = a.e31;
			out.z = a.e32;
			out.w = a.e33;
			return out;
		}
		/// Fills a Vec4 with the homogenous translational component from the matrix.
		FORCE_INLINE Vec4& AxisTranslation4(const Mat4 &a, Vec4 &out)
		{
			out.x = a.e03;
			out.y = a.e13;
			out.z = a.e23;
			out.w = a.e33;
			return out;
		}
		//
		/// Return a transposed version of a Mat2.
		FORCE_INLINE Mat2 Transpose2(const Mat2 & a)
		{
			Mat2 out;
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e10 = a.e01;
			out.e11 = a.e11;
			return out;
		}
		/// Return a transposed version of a Mat3.
		FORCE_INLINE Mat3 Transpose3(const Mat3 & a)
		{
			Mat3 out;
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e02 = a.e20;
			out.e10 = a.e01;
			out.e11 = a.e11;
			out.e12 = a.e21;
			out.e20 = a.e02;
			out.e21 = a.e12;
			out.e22 = a.e22;
			return out;
		}
		/// Return a transposed version of a Mat4.
		FORCE_INLINE Mat4 Transpose4(const Mat4 & a)
		{
			Mat4 out;
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e02 = a.e20;
			out.e03 = a.e30;
			out.e10 = a.e01;
			out.e11 = a.e11;
			out.e12 = a.e21;
			out.e13 = a.e31;
			out.e20 = a.e02;
			out.e21 = a.e12;
			out.e22 = a.e22;
			out.e23 = a.e32;
			out.e30 = a.e03;
			out.e31 = a.e13;
			out.e32 = a.e23;
			out.e33 = a.e33;
			return out;
		}
		/// Fill a Mat2 with the transpose of another Mat2.
		/// The out matrix should not be the same as the in
		/// matrix.
		FORCE_INLINE Mat2& Transpose2(const Mat2 &a,Mat2 &out)
		{
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e10 = a.e01;
			out.e11 = a.e11;
			return out;
		}
		/// Fill a Mat3 with the transpose of another Mat3.
		/// The out matrix should not be the same as the in
		/// matrix.
		FORCE_INLINE Mat3& Transpose3(const Mat3 &a,Mat3 &out)
		{
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e02 = a.e20;
			out.e10 = a.e01;
			out.e11 = a.e11;
			out.e12 = a.e21;
			out.e20 = a.e02;
			out.e21 = a.e12;
			out.e22 = a.e22;
			return out;
		}
		/// Fill a Mat4 with the transpose of another Mat4.
		/// The out matrix should not be the same as the in
		/// matrix.
		FORCE_INLINE Mat4& Transpose4(const Mat4 &a,Mat4 &out)
		{
			out.e00 = a.e00;
			out.e01 = a.e10;
			out.e02 = a.e20;
			out.e03 = a.e30;
			out.e10 = a.e01;
			out.e11 = a.e11;
			out.e12 = a.e21;
			out.e13 = a.e31;
			out.e20 = a.e02;
			out.e21 = a.e12;
			out.e22 = a.e22;
			out.e23 = a.e32;
			out.e30 = a.e03;
			out.e31 = a.e13;
			out.e32 = a.e23;
			out.e33 = a.e33;
			return out;
		}
		/// Transpose a Mat2 and store it in the original matrix.
		FORCE_INLINE Mat2& MakeTranspose2(Mat2 &a)
		{
			Swap(a.e01,a.e10);
			return a;
		}
		/// Transpose a Mat3 and store it in the original matrix.
		FORCE_INLINE Mat3& MakeTranspose3(Mat3 &a)
		{
			float tmp;
			SwapQuick(a.e01,a.e10,tmp);
			SwapQuick(a.e02,a.e20,tmp);
			SwapQuick(a.e12,a.e21,tmp);
			return a;
		}
		/// Transpose a Mat4 and store it in the original matrix.
		FORCE_INLINE Mat4& MakeTranspose4(Mat4 &a)
		{
			float tmp;
			SwapQuick(a.e01,a.e10,tmp);
			SwapQuick(a.e02,a.e20,tmp);
			SwapQuick(a.e03,a.e30,tmp);
			SwapQuick(a.e12,a.e21,tmp);
			SwapQuick(a.e13,a.e31,tmp);
			SwapQuick(a.e23,a.e32,tmp);
			return a;
		}
		//
		/// Create a scalar Mat2 transformation.
		/// Configuration is as such:
		/// [scalar.x, 0]
		/// [0, scalar.y]
		FORCE_INLINE Mat2 Scalar2(const Vec2 &scalar)
		{
			Mat2 out;
			out.e00=scalar.x;
			out.e01=out.e10=0.0f;
			out.e11=scalar.y;
			return out;
		}
		/// Create a scalar Mat3 transformation.
		/// Configuration is as such:
		/// [scalar.x, 0, 0]
		/// [0, scalar.y, 0]
		/// [0, 0, scalar.z]
		FORCE_INLINE Mat3 Scalar3(const Vec3 &scalar)
		{
			Mat3 out;
			out.e00=scalar.x;
			out.e01=out.e02=out.e10=0.0f;
			out.e11=scalar.y;
			out.e12=out.e20=out.e21=0.0f;
			out.e22=scalar.z;
			return out;
		}
		/// Create a scalar Mat4 transformation.
		/// Configuration is as such:
		/// [scalar.x, 0, 0, 0]
		/// [0, scalar.y, 0, 0]
		/// [0, 0, scalar.z, 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4 Scalar4(const Vec3 &scalar)
		{
			Mat4 out;
			out.e00=scalar.x;
			out.e01=out.e02=out.e03=out.e10=0.0f;
			out.e11=scalar.y;
			out.e12=out.e13=out.e20=out.e21=0.0f;
			out.e22=scalar.z;
			out.e23=out.e30=out.e31=out.e32=0.0f;
			out.e33=1.0f;
			return out;
		}
		/// Create a scalar transformation and put it in a Mat2.
		/// Configuration is as such:
		/// [scalar.x, 0]
		/// [0, scalar.y]
		FORCE_INLINE Mat2& Scalar2(const Vec2 &scalar, Mat2 &out)
		{
			out.e00=scalar.x;
			out.e01=out.e10=0.0f;
			out.e11=scalar.y;
			return out;
		}
		/// Create a scalar transformation and put it in a Mat3.
		/// Configuration is as such:
		/// [scalar.x, 0, 0]
		/// [0, scalar.y, 0]
		/// [0, 0, scalar.z]
		FORCE_INLINE Mat3& Scalar3(const Vec3 &scalar, Mat3 &out)
		{
			out.e00=scalar.x;
			out.e01=out.e02=out.e10=0.0f;
			out.e11=scalar.y;
			out.e12=out.e20=out.e21=0.0f;
			out.e22=scalar.z;
			return out;
		}
		/// Create a scalar transformation and put it in a Mat4.
		/// Configuration is as such:
		/// [scalar.x, 0, 0, 0]
		/// [0, scalar.y, 0, 0]
		/// [0, 0, scalar.z, 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4& Scalar4(const Vec3 &scalar, Mat4 &out)
		{
			out.e00=scalar.x;
			out.e01=out.e02=out.e03=out.e10=0.0f;
			out.e11=scalar.y;
			out.e12=out.e13=out.e20=out.e21=0.0f;
			out.e22=scalar.z;
			out.e23=out.e30=out.e31=out.e32=0.0f;
			out.e33=1.0f;
			return out;
		}
		//
		/// Create a 2D(Mat2) rotational transformation.
		/// Configuration is as such:
		/// Each [] represents a row (not column as you may be used to).
		/// [cos(rad), -sin(rad)]
		/// [sin(rad), cos(rad)]
		FORCE_INLINE Mat2 Rotational2(const float radians)
		{
			Mat2 out;
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		/// Create a rotational transformation about an axis(Mat3).
		/// TODO: fully document how this transformation is set up.
		FORCE_INLINE Mat3 Rotational3(const Vec3 &axis, const float radians)
		{
			float cosrad = Cos(radians), sinrad = Sin(radians);
			Mat3 out;
			MakeIdentity3(out);
			out.e00 = cosrad+((1.0f-cosrad)*(axis.x*axis.x));
			out.e01 = ((1-cosrad)*(axis.x*axis.y))-(sinrad*axis.z);
			out.e02 = ((1-cosrad)*(axis.x*axis.z))+(sinrad*axis.y);
			out.e10 = ((1-cosrad)*(axis.y*axis.x))+(sinrad*axis.z);
			out.e11 = cosrad+((1.0f-cosrad)*(axis.y*axis.y));
			out.e12 = ((1-cosrad)*(axis.y*axis.z))-(sinrad*axis.x);
			out.e20 = ((1-cosrad)*(axis.z*axis.x))-(sinrad*axis.y);
			out.e21 = ((1-cosrad)*(axis.z*axis.y))+(sinrad*axis.x);
			out.e22 = cosrad+((1.0f-cosrad)*(axis.z*axis.z));
			return out;
		}
		/// Create a 3D(Mat3) rotational transformation about the x y and z axis.
		/// The order of operations is Roll -> Pitch -> Yaw (similar to how an aircraft
		/// measures rotation). Basically, just automates the calls to RotationalX3,
		/// RotationalY3, RotationalZ3.
		FORCE_INLINE Mat3 Rotational3(const float radiansx, const float radiansy, const float radiansz)
		{
			return RotationalY3(radiansy) * RotationalX3(radiansx) * RotationalZ3(radiansz);
		}
		/// Create a 3D(Mat3) rotation around the X axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0]
		/// [0, cos(rad), -sin(rad)]
		/// [0, sin(rad), cos(rad)]
		FORCE_INLINE Mat3 RotationalX3(const float radians)
		{
			Mat3 out;
			MakeIdentity3(out);
			out.e11 = Cos(radians);
			out.e12 = -Sin(radians);
			out.e21 = Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Create a 3D(Mat3) rotation around the Y axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), 0, sin(rad)]
		/// [0, 1, 0]
		/// [-sin(rad), 0, cos(rad)]
		FORCE_INLINE Mat3 RotationalY3(const float radians)
		{
			Mat3 out;
			MakeIdentity3(out);
			out.e00 = Cos(radians);
			out.e02 = Sin(radians);
			out.e20 = -Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Create a 3D(Mat3) rotation around the Z axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), -sin(rad), 0]
		/// [sin(rad), cos(rad), 0]
		/// [0, 0, 1]
		FORCE_INLINE Mat3 RotationalZ3(const float radians)
		{
			Mat3 out;
			MakeIdentity3(out);
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		/// Create a 3D(Mat4) rotation around an axis.
		/// TODO: Properly document axis-radian rotation transformations.
		FORCE_INLINE Mat4 Rotational4(const Vec3 &axis, const float radians)
		{
			float cosrad = Cos(radians), sinrad = Sin(radians);
			Mat4 out;
			MakeIdentity4(out);
			out.e00 = cosrad+((1.0f-cosrad)*(axis.x*axis.x));
			out.e01 = ((1-cosrad)*(axis.x*axis.y))-(sinrad*axis.z);
			out.e02 = ((1-cosrad)*(axis.x*axis.z))+(sinrad*axis.y);
			out.e10 = ((1-cosrad)*(axis.y*axis.x))+(sinrad*axis.z);
			out.e11 = cosrad+((1.0f-cosrad)*(axis.y*axis.y));
			out.e12 = ((1-cosrad)*(axis.y*axis.z))-(sinrad*axis.x);
			out.e20 = ((1-cosrad)*(axis.z*axis.x))-(sinrad*axis.y);
			out.e21 = ((1-cosrad)*(axis.z*axis.y))+(sinrad*axis.x);
			out.e22 = cosrad+((1.0f-cosrad)*(axis.z*axis.z));
			return out;
		}
		/// Create a 3D(Mat4) rotation around the x y and z axis.
		/// The order of operations is Roll -> Pitch -> Yaw (similar
		/// in order to how an aircraft measures rotation).
		/// Basically, just calls RotationalX4, RotationalY4 and
		/// RotationalZ4.
		FORCE_INLINE Mat4 Rotational4(const float radiansx, const float radiansy, const float radiansz)
		{
			return (RotationalY4(radiansy) * RotationalX4(radiansx) * RotationalZ4(radiansz));
		}
		/// Create a 3D(Mat4) rotation around the x axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0, 0]
		/// [0, cos(rad), -sin(rad), 0]
		/// [0, sin(rad), cos(rad), 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4 RotationalX4(const float radians)
		{
			Mat4 out;
			MakeIdentity4(out);
			out.e11 = Cos(radians);
			out.e12 = -Sin(radians);
			out.e21 = Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Create a 3D(Mat4) rotation around the y axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), 0, sin(rad), 0]
		/// [0, 1, 0, 0]
		/// [-sin(rad), 0, cos(rad), 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4 RotationalY4(const float radians)
		{
			Mat4 out;
			MakeIdentity4(out);
			out.e00 = Cos(radians);
			out.e02 = Sin(radians);
			out.e20 = -Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Create a 3D(Mat4) rotation around the z axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), -sin(rad), 0, 0]
		/// [sin(rad), cos(rad), 0, 0]
		/// [0, 0, 1, 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4 RotationalZ4(const float radians)
		{
			Mat4 out;
			MakeIdentity4(out);
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		/// Fill a Mat2 with a 2D rotation.
		/// Configuration is as such:
		/// each [] represents a row (not a column as you may be used to).
		/// [cos(rad), -sin(rad)]
		/// [sin(rad), cos(rad)]
		FORCE_INLINE Mat2& Rotational2(const float radians, Mat2 &out)
		{
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		/// Fill a Mat3 with a 3D rotation about an axis.
		/// TODO: Accurately document angle/axis rotations.
		FORCE_INLINE Mat3& Rotational3(const Vec3 &axis, const float radians, Mat3 &out)
		{
			float cosrad = Cos(radians), sinrad = Sin(radians);
			MakeIdentity3(out);
			out.e00 = cosrad+((1.0f-cosrad)*(axis.x*axis.x));
			out.e01 = ((1-cosrad)*(axis.x*axis.y))-(sinrad*axis.z);
			out.e02 = ((1-cosrad)*(axis.x*axis.z))+(sinrad*axis.y);
			out.e10 = ((1-cosrad)*(axis.y*axis.x))+(sinrad*axis.z);
			out.e11 = cosrad+((1.0f-cosrad)*(axis.y*axis.y));
			out.e12 = ((1-cosrad)*(axis.y*axis.z))-(sinrad*axis.x);
			out.e20 = ((1-cosrad)*(axis.z*axis.x))-(sinrad*axis.y);
			out.e21 = ((1-cosrad)*(axis.z*axis.y))+(sinrad*axis.x);
			out.e22 = cosrad+((1.0f-cosrad)*(axis.z*axis.z));
			return out;
		}
		/// Fill a Mat3 with a rotation around the x y and z axis(seperately).
		/// The order of operations is Roll -> Pitch -> Yaw (similar to how an aircraft
		/// measures rotation). Basically, just automates the calls to RotationalX3,
		/// RotationalY3, RotationalZ3.
		FORCE_INLINE Mat3& Rotational3(const float radiansx, const float radiansy, const float radiansz, Mat3& out)
		{
			return (out = RotationalY3(radiansy) * RotationalX3(radiansx) * RotationalZ3(radiansz));
		}
		/// Fill a Mat3 with a 3D rotation around the X axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0]
		/// [0, cos(rad), -sin(rad)]
		/// [0, sin(rad), cos(rad)]
		FORCE_INLINE Mat3& RotationalX3(const float radians, Mat3 &out)
		{
			MakeIdentity3(out);
			out.e11 = Cos(radians);
			out.e12 = -Sin(radians);
			out.e21 = Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Fill a Mat3 with a 3D rotation about the Y axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), 0, sin(rad)]
		/// [0, 1, 0]
		/// [-sin(rad), 0, cos(rad)]
		FORCE_INLINE Mat3& RotationalY3(const float radians, Mat3 &out)
		{
			MakeIdentity3(out);
			out.e00 = Cos(radians);
			out.e02 = Sin(radians);
			out.e20 = -Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Fill a Mat3 with a 3D rotation around the Z axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), -sin(rad), 0]
		/// [sin(rad), cos(rad), 0]
		/// [0, 0, 1]
		FORCE_INLINE Mat3& RotationalZ3(const float radians, Mat3 &out)
		{
			MakeIdentity3(out);
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		/// Fill a Mat4 with a 3D rotation about an axis.
		/// TODO: Accurately document angle-axis rotational matrixes.
		FORCE_INLINE Mat4& Rotational4(const Vec3 &axis, const float radians, Mat4 &out)
		{
			float cosrad = Cos(radians), sinrad = Sin(radians);
			MakeIdentity4(out);
			out.e00 = cosrad+((1.0f-cosrad)*(axis.x*axis.x));
			out.e01 = ((1-cosrad)*(axis.x*axis.y))-(sinrad*axis.z);
			out.e02 = ((1-cosrad)*(axis.x*axis.z))+(sinrad*axis.y);
			out.e10 = ((1-cosrad)*(axis.y*axis.x))+(sinrad*axis.z);
			out.e11 = cosrad+((1.0f-cosrad)*(axis.y*axis.y));
			out.e12 = ((1-cosrad)*(axis.y*axis.z))-(sinrad*axis.x);
			out.e20 = ((1-cosrad)*(axis.z*axis.x))-(sinrad*axis.y);
			out.e21 = ((1-cosrad)*(axis.z*axis.y))+(sinrad*axis.x);
			out.e22 = cosrad+((1.0f-cosrad)*(axis.z*axis.z));
			return out;
		}
		/// Fill a Mat4 with a 3D rotation about the x y and z axis(seperately).
		/// The order of operations is Roll -> Pitch -> Yaw (similar to how an aircraft
		/// measures rotation). Basically, just automates the calls to RotationalX4,
		/// RotationalY4, RotationalZ4.
		FORCE_INLINE Mat4& Rotational4(const float radiansx, const float radiansy, const float radiansz, Mat4 &out)
		{
			return (out = RotationalY4(radiansy) * RotationalX4(radiansx) * RotationalZ4(radiansz));
		}
		/// Fill a Mat4 with a 3D rotation around the X axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0, 0]
		/// [0, cos(rad), -sin(rad), 0]
		/// [0, sin(rad), cos(rad), 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4& RotationalX4(const float radians, Mat4 &out)
		{
			MakeIdentity4(out);
			out.e11 = Cos(radians);
			out.e12 = -Sin(radians);
			out.e21 = Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Fill a Mat4 with a 3D rotation around the Y axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), 0, sin(rad), 0]
		/// [0, 1, 0, 0]
		/// [-sin(rad), 0, cos(rad), 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4& RotationalY4(const float radians, Mat4 &out)
		{
			MakeIdentity4(out);
			out.e00 = Cos(radians);
			out.e02 = Sin(radians);
			out.e20 = -Sin(radians);
			out.e22 = Cos(radians);
			return out;
		}
		/// Fill a Mat4 with a 3D rotation around the Z axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [cos(rad), -sin(rad), 0, 0]
		/// [sin(rad), cos(rad), 0, 0]
		/// [0, 0, 1, 0]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4& RotationalZ4(const float radians, Mat4 &out)
		{
			MakeIdentity4(out);
			out.e00 = Cos(radians);
			out.e01 = -Sin(radians);
			out.e10 = Sin(radians);
			out.e11 = Cos(radians);
			return out;
		}
		//
		/// Create a 2D(Mat3) translational matrix along the x and y.
		/// A little different than most translational matrixes.
		/// This is useful if the 3rd dimension is treated as a
		/// homogenous layer. This would allow translation along
		/// the x & y axis (but not the z).
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, translation.x]
		/// [0, 1, translation.y]
		/// [0, 0, 1]
		FORCE_INLINE Mat3 Translational3(const Vec2 &translation)
		{
			Mat3 out;
			MakeIdentity3(out);
			out.e02 = translation.x;
			out.e12 = translation.y;
			return out;
		}
		/// Create a 3D(Mat4) translational matrix along the x y and z axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0, translation.x]
		/// [0, 1, 0, translation.y]
		/// [0, 0, 1, translation.z]
		/// [0, 0, 0, 1]
		FORCE_INLINE Mat4 Translational4(const Vec3 &translation)
		{
			Mat4 out;
			MakeIdentity4(out);
			out.e03 = translation.x;
			out.e13 = translation.y;
			out.e23 = translation.z;
			return out;
		}
		/// Fill a Mat2 with a translational matrix along the x and y axis.
		/// A little different than most translational matrixes.
		/// This is useful if the 3rd dimension is treated as a
		/// homogenous layer. This would allow translation along
		/// the x & y axis (but not the z).
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, translation.x]
		/// [0, 1, translation.y]
		/// [0, 0, 1]		
		FORCE_INLINE Mat3& Translational3(const Vec2 &translation, Mat3 &out)
		{
			MakeIdentity3(out);
			out.e02 = translation.x;
			out.e12 = translation.y;
			return out;
		}
		/// Fill a Mat3 with a translational matrix along the x and y axis.
		/// Configuration is as such:
		/// Each [] represents a row (not a column as you may be used to).
		/// [1, 0, 0, translation.x]
		/// [0, 1, 0, translation.y]
		/// [0, 0, 1, translation.z]
		/// [0, 0, 0, 1]s
		FORCE_INLINE Mat4& Translational4(const Vec3 &translation, Mat4 &out)
		{
			MakeIdentity4(out);
			out.e03 = translation.x;
			out.e13 = translation.y;
			out.e23 = translation.z;
			return out;
		}
		//
		/// Determine the determinant of a Mat2.
		/// Determinant of a 2x2 is simple:
		/// det = e00*e11 - e01*e10
		FORCE_INLINE float Determinant2(const Mat2 &a)
		{
			return COONEY_MATH_MATRIX2_DET(a.e00,a.e01,a.e10,a.e11);
		}
		/// Determine the determinant of a Mat3.
		/// determinant of a mat3 is fairly simple and basically
		/// just built upon the determinants of minors.
		/// For a 3x3 it's still fairly simple:
		/// det = e00 * det(e11, e12, e21, e22) - e01 * det(e10, e12, e20, e22) + e02 * det(e10, e11, e20, e21)
		FORCE_INLINE float Determinant3(const Mat3 &a)
		{
			return COONEY_MATH_MATRIX3_DET(a.e00,a.e01,a.e02,a.e10,a.e11,a.e12,a.e20,a.e21,a.e22);
		}
		/// Determine the determinant of a Mat4.
		/// For a 4x4 it's similar to how the 3x3 determinant
		/// built on a series of 2x2 determinants.
		/// Construction is as such:
		/// det = e00 * det(e00's minor) - e01 * det(e01's minor) + e02 * det(e02's minor) - e03 * det(e03's minor)
		FORCE_INLINE float Determinant4(const Mat4 &a)
		{
			return COONEY_MATH_MATRIX4_DET(a.e00,a.e01,a.e02,a.e03,a.e10,a.e11,a.e12,a.e13,a.e20,a.e21,a.e22,a.e23,a.e30,a.e31,a.e32,a.e33);
		}
		//
		/// Create a cofactor Mat2 based on an input matrix.
		/// Cofactor's are basically constructions of signed minor
		/// determinants. 2x2 matrixes are really simple here since the
		/// minors in a 2x2 matrix are just one value. (the sign of the 
		/// minor can be easily found if i + j of each component is even(positive)
		/// or odd(negative)).
		FORCE_INLINE Mat2 Cofactor2(const Mat2 &a)
		{
			Mat2 out;
			out.e00 = a.e11;
			out.e01 = -a.e10;
			out.e10 = -a.e01;
			out.e11 = a.e00;
			return out;
		}
		/// Create a cofactor Mat3 based on an input matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// For this it's simple, take a matrix member at (i,j) and
		/// find its signed minor's determinant. (the sign of the minor
		/// can be easily found if i + j of each component is even(positive)
		/// or odd(negative)).
		FORCE_INLINE Mat3 Cofactor3(const Mat3 &a)
		{
			Mat3 out;
			out.e00 = COONEY_MATH_MATRIX2_DET(a.e11, a.e12, a.e21, a.e22);
			out.e01 = -COONEY_MATH_MATRIX2_DET(a.e10, a.e12, a.e20, a.e22);
			out.e02 = COONEY_MATH_MATRIX2_DET(a.e10, a.e11, a.e20, a.e21);
			out.e10 = -COONEY_MATH_MATRIX2_DET(a.e01, a.e02, a.e21, a.e22);
			out.e11 = COONEY_MATH_MATRIX2_DET(a.e00, a.e02, a.e20, a.e22);
			out.e12 = -COONEY_MATH_MATRIX2_DET(a.e00, a.e01, a.e20, a.e21);
			out.e20 = COONEY_MATH_MATRIX2_DET(a.e01, a.e02, a.e11, a.e12);
			out.e21 = -COONEY_MATH_MATRIX2_DET(a.e00, a.e02, a.e10, a.e12);
			out.e22 = COONEY_MATH_MATRIX2_DET(a.e00, a.e01, a.e10, a.e11);
			return out;
		}
		/// Create a cofactor Mat4 based on an input matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// All we need to do to construct one is take a matrix
		/// component at i,j and find it's signed minor's determinant.
		/// (the sign of the minor can be easily found if i + j of each
		/// component is even(positive) or odd(negative)).
		FORCE_INLINE Mat4 Cofactor4(const Mat4 &a)
		{
			Mat4 out;
			out.e00 = COONEY_MATH_MATRIX3_DET(a.e11, a.e12, a.e13, a.e21, a.e22, a.e23, a.e31, a.e32, a.e33);
			out.e01 = -COONEY_MATH_MATRIX3_DET(a.e10, a.e12, a.e13, a.e20, a.e22, a.e23, a.e30, a.e32, a.e33);
			out.e02 = COONEY_MATH_MATRIX3_DET(a.e10, a.e11, a.e13, a.e20, a.e21, a.e23, a.e30, a.e31, a.e33);
			out.e03 = -COONEY_MATH_MATRIX3_DET(a.e10, a.e11, a.e12, a.e20, a.e21, a.e22, a.e30, a.e31, a.e32);
			out.e10 = -COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e21, a.e22, a.e23, a.e31, a.e32, a.e33);
			out.e11 = COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e20, a.e22, a.e23, a.e30, a.e32, a.e33);
			out.e12 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e20, a.e21, a.e23, a.e30, a.e31, a.e33);
			out.e13 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e20, a.e21, a.e22, a.e30, a.e31, a.e32);
			out.e20 = COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e11, a.e12, a.e13, a.e31, a.e32, a.e33);
			out.e21 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e10, a.e12, a.e13, a.e30, a.e32, a.e33);
			out.e22 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e10, a.e11, a.e13, a.e30, a.e31, a.e33);
			out.e23 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e10, a.e11, a.e12, a.e30, a.e31, a.e32);
			out.e30 = -COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e11, a.e12, a.e13, a.e21, a.e22, a.e23);
			out.e31 = COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e10, a.e12, a.e13, a.e20, a.e22, a.e23);
			out.e32 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e10, a.e11, a.e13, a.e20, a.e21, a.e23);
			out.e33 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e10, a.e11, a.e12, a.e20, a.e21, a.e22);
			return out;
		}
		/// Fill a Mat2 with a cofactor matrix based on an input matrix.
		/// Cofactor's are basically constructions of signed minor
		/// determinants. 2x2 matrixes are really simple here since the
		/// minors in a 2x2 matrix are just one value. (the sign of the 
		/// minor can be easily found if i + j of each component is even(positive)
		/// or odd(negative)).
		FORCE_INLINE Mat2& Cofactor2(const Mat2 &a, Mat2 &out)
		{
			out.e00 = a.e11;
			out.e01 = -a.e10;
			out.e10 = -a.e01;
			out.e11 = a.e00;
			return out;
		}
		/// Fill a Mat3 with a cofactor matrix based on an input matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// For this it's simple, take a matrix member at (i,j) and
		/// find its signed minor's determinant. (the sign of the minor
		/// can be easily found if i + j of each component is even(positive)
		/// or odd(negative)).
		FORCE_INLINE Mat3& Cofactor3(const Mat3 &a, Mat3 &out)
		{
			out.e00 = COONEY_MATH_MATRIX2_DET(a.e11, a.e12, a.e21, a.e22);
			out.e01 = -COONEY_MATH_MATRIX2_DET(a.e10, a.e12, a.e20, a.e22);
			out.e02 = COONEY_MATH_MATRIX2_DET(a.e10, a.e11, a.e20, a.e21);
			out.e10 = -COONEY_MATH_MATRIX2_DET(a.e01, a.e02, a.e21, a.e22);
			out.e11 = COONEY_MATH_MATRIX2_DET(a.e00, a.e02, a.e20, a.e22);
			out.e12 = -COONEY_MATH_MATRIX2_DET(a.e00, a.e01, a.e20, a.e21);
			out.e20 = COONEY_MATH_MATRIX2_DET(a.e01, a.e02, a.e11, a.e12);
			out.e21 = -COONEY_MATH_MATRIX2_DET(a.e00, a.e02, a.e10, a.e12);
			out.e22 = COONEY_MATH_MATRIX2_DET(a.e00, a.e01, a.e10, a.e11);
			return out;
		}
		/// Fill a Mat4 withe a cofactor matrix based on an input matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// All we need to do to construct one is take a matrix
		/// component at i,j and find it's signed minor's determinant.
		/// (the sign of the minor can be easily found if i + j of each
		/// component is even(positive) or odd(negative)).
		FORCE_INLINE Mat4& Cofactor4(const Mat4 &a, Mat4 &out)
		{
			out.e00 = COONEY_MATH_MATRIX3_DET(a.e11, a.e12, a.e13, a.e21, a.e22, a.e23, a.e31, a.e32, a.e33);
			out.e01 = -COONEY_MATH_MATRIX3_DET(a.e10, a.e12, a.e13, a.e20, a.e22, a.e23, a.e30, a.e32, a.e33);
			out.e02 = COONEY_MATH_MATRIX3_DET(a.e10, a.e11, a.e13, a.e20, a.e21, a.e23, a.e30, a.e31, a.e33);
			out.e03 = -COONEY_MATH_MATRIX3_DET(a.e10, a.e11, a.e12, a.e20, a.e21, a.e22, a.e30, a.e31, a.e32);
			out.e10 = -COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e21, a.e22, a.e23, a.e31, a.e32, a.e33);
			out.e11 = COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e20, a.e22, a.e23, a.e30, a.e32, a.e33);
			out.e12 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e20, a.e21, a.e23, a.e30, a.e31, a.e33);
			out.e13 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e20, a.e21, a.e22, a.e30, a.e31, a.e32);
			out.e20 = COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e11, a.e12, a.e13, a.e31, a.e32, a.e33);
			out.e21 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e10, a.e12, a.e13, a.e30, a.e32, a.e33);
			out.e22 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e10, a.e11, a.e13, a.e30, a.e31, a.e33);
			out.e23 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e10, a.e11, a.e12, a.e30, a.e31, a.e32);
			out.e30 = -COONEY_MATH_MATRIX3_DET(a.e01, a.e02, a.e03, a.e11, a.e12, a.e13, a.e21, a.e22, a.e23);
			out.e31 = COONEY_MATH_MATRIX3_DET(a.e00, a.e02, a.e03, a.e10, a.e12, a.e13, a.e20, a.e22, a.e23);
			out.e32 = -COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e03, a.e10, a.e11, a.e13, a.e20, a.e21, a.e23);
			out.e33 = COONEY_MATH_MATRIX3_DET(a.e00, a.e01, a.e02, a.e10, a.e11, a.e12, a.e20, a.e21, a.e22);
			return out;
		}
		/// Set an input Mat2 to its cofactor matrix.
		/// Cofactor's are basically constructions of signed minor
		/// determinants. 2x2 matrixes are really simple here since the
		/// minors in a 2x2 matrix are just one value. (the sign of the 
		/// minor can be easily found if i + j of each component is even(positive)
		/// or odd(negative)).
		FORCE_INLINE Mat2& MakeCofactor2(Mat2 &a_out)
		{
			Mat2 out;
			out.e00 = a_out.e11;
			out.e01 = -a_out.e10;
			out.e10 = -a_out.e01;
			out.e11 = a_out.e00;
			return (a_out = out);
		}
		/// Set an input Mat3 to its cofactor matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// All we need to do to construct one is take a matrix
		/// component at i,j and find it's signed minor's determinant.
		/// (the sign of the minor can be easily found if i + j of each
		/// component is even(positive) or odd(negative)).
		FORCE_INLINE Mat3& MakeCofactor3(Mat3 &a_out)
		{
			Mat3 out;
			out.e00 = COONEY_MATH_MATRIX2_DET(a_out.e11, a_out.e12, a_out.e21, a_out.e22);
			out.e01 = -COONEY_MATH_MATRIX2_DET(a_out.e10, a_out.e12, a_out.e20, a_out.e22);
			out.e02 = COONEY_MATH_MATRIX2_DET(a_out.e10, a_out.e11, a_out.e20, a_out.e21);
			out.e10 = -COONEY_MATH_MATRIX2_DET(a_out.e01, a_out.e02, a_out.e21, a_out.e22);
			out.e11 = COONEY_MATH_MATRIX2_DET(a_out.e00, a_out.e02, a_out.e20, a_out.e22);
			out.e12 = -COONEY_MATH_MATRIX2_DET(a_out.e00, a_out.e01, a_out.e20, a_out.e21);
			out.e20 = COONEY_MATH_MATRIX2_DET(a_out.e01, a_out.e02, a_out.e11, a_out.e12);
			out.e21 = -COONEY_MATH_MATRIX2_DET(a_out.e00, a_out.e02, a_out.e10, a_out.e12);
			out.e22 = COONEY_MATH_MATRIX2_DET(a_out.e00, a_out.e01, a_out.e10, a_out.e11);
			return (a_out = out);
		}
		/// Set an input Mat4 to its cofactor matrix.
		/// Cofactor matrixes are constructions of minor determinants.
		/// All we need to do to construct one is take a matrix  
		/// component at i,j and find it's signed minor's determinant.
		/// (the sign of the minor can be easily found if i + j of each
		/// component is even(positive) or odd(negative)).
		FORCE_INLINE Mat4& MakeCofactor4(Mat4 &a_out)
		{
			Mat4 out;
			out.e00 = COONEY_MATH_MATRIX3_DET(a_out.e11, a_out.e12, a_out.e13, a_out.e21, a_out.e22, a_out.e23, a_out.e31, a_out.e32, a_out.e33);
			out.e01 = -COONEY_MATH_MATRIX3_DET(a_out.e10, a_out.e12, a_out.e13, a_out.e20, a_out.e22, a_out.e23, a_out.e30, a_out.e32, a_out.e33);
			out.e02 = COONEY_MATH_MATRIX3_DET(a_out.e10, a_out.e11, a_out.e13, a_out.e20, a_out.e21, a_out.e23, a_out.e30, a_out.e31, a_out.e33);
			out.e03 = -COONEY_MATH_MATRIX3_DET(a_out.e10, a_out.e11, a_out.e12, a_out.e20, a_out.e21, a_out.e22, a_out.e30, a_out.e31, a_out.e32);
			out.e10 = -COONEY_MATH_MATRIX3_DET(a_out.e01, a_out.e02, a_out.e03, a_out.e21, a_out.e22, a_out.e23, a_out.e31, a_out.e32, a_out.e33);
			out.e11 = COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e02, a_out.e03, a_out.e20, a_out.e22, a_out.e23, a_out.e30, a_out.e32, a_out.e33);
			out.e12 = -COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e03, a_out.e20, a_out.e21, a_out.e23, a_out.e30, a_out.e31, a_out.e33);
			out.e13 = COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e02, a_out.e20, a_out.e21, a_out.e22, a_out.e30, a_out.e31, a_out.e32);
			out.e20 = COONEY_MATH_MATRIX3_DET(a_out.e01, a_out.e02, a_out.e03, a_out.e11, a_out.e12, a_out.e13, a_out.e31, a_out.e32, a_out.e33);
			out.e21 = -COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e02, a_out.e03, a_out.e10, a_out.e12, a_out.e13, a_out.e30, a_out.e32, a_out.e33);
			out.e22 = COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e03, a_out.e10, a_out.e11, a_out.e13, a_out.e30, a_out.e31, a_out.e33);
			out.e23 = -COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e02, a_out.e10, a_out.e11, a_out.e12, a_out.e30, a_out.e31, a_out.e32);
			out.e30 = -COONEY_MATH_MATRIX3_DET(a_out.e01, a_out.e02, a_out.e03, a_out.e11, a_out.e12, a_out.e13, a_out.e21, a_out.e22, a_out.e23);
			out.e31 = COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e02, a_out.e03, a_out.e10, a_out.e12, a_out.e13, a_out.e20, a_out.e22, a_out.e23);
			out.e32 = -COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e03, a_out.e10, a_out.e11, a_out.e13, a_out.e20, a_out.e21, a_out.e23);
			out.e33 = COONEY_MATH_MATRIX3_DET(a_out.e00, a_out.e01, a_out.e02, a_out.e10, a_out.e11, a_out.e12, a_out.e20, a_out.e21, a_out.e22);
			return (a_out = out);
		}
		//
		/// Return the inverse of a Mat2.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat2 Inverse2(const Mat2 &a)
		{
			Mat2 out;
			
			float fDet = Determinant2(a);
			if(fDet==0)
				return out;
			
			Mat2 adjugate = Transpose2(Cofactor2(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Return the inverse of a Mat3.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat3 Inverse3(const Mat3 &a)
		{
			Mat3 out;
			
			float fDet = Determinant3(a);
			if(fDet==0)
				return out;
			
			Mat3 adjugate = Transpose3(Cofactor3(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Return the inverse of a Mat3.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat4 Inverse4(const Mat4 &a)
		{
			Mat4 out;
			
			float fDet = Determinant4(a);
			if(fDet==0)
				return out;
			
			Mat4 adjugate = Transpose4(Cofactor4(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Fill a Mat2 with the inverse of a matrix.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat2& Inverse2(const Mat2 &a,Mat2 &out)
		{
			float fDet = Determinant2(a);
			if(fDet==0)
				return out;
			
			Mat2 adjugate = Transpose2(Cofactor2(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Fill a Mat3 with the inverse of a matrix.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat3& Inverse3(const Mat3 &a,Mat3 &out)
		{
			float fDet = Determinant3(a);
			if(fDet==0)
				return out;
			
			Mat3 adjugate = Transpose3(Cofactor3(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Fill a Mat4 with the inverse of a matrix.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat4& Inverse4(const Mat4 &a,Mat4& out)
		{
			float fDet = Determinant4(a);
			if(fDet==0)
				return out;
			
			Mat4 adjugate = Transpose4(Cofactor4(a));
			out = adjugate / fDet;
			
			return out;
		}
		/// Set an input Mat2 to its inverse.
		/// The inverse represents a matrix that does essentially the opposite
		/// of the original matrix. Such that AB = BA = Identity (Assuming B
		/// is the inverse of A).
		/// The inverse can be defined as:
		/// inv(A) = tranpose(cofactor(A))/determinant(A)
		FORCE_INLINE Mat2& MakeInverse2(Mat2 &a)
		{
			Mat2 out;
			
			float fDet = Determinant2(a);
			if(fDet==0)
				return MakeIdentity2(a);
			
			Mat2 adjugate =