Commits

Amin67v  committed 01dcdc9

Wrapper updated

  • Participants
  • Parent commits dcd3cc6

Comments (0)

Files changed (21)

File DarkMotion/StateMachineView.cs

 
 		private float linePointdist(PointF ln1, PointF ln2, PointF pnt)
 		{
-			Vec2 v = new Vec2(ln1.X, ln1.Y);
-			Vec2 w = new Vec2(ln2.X, ln2.Y);
-			Vec2 p = new Vec2(pnt.X, pnt.Y);
-
-			float l2 = Vec2.SqrDistance(v, w);
-			if (l2 == 0.0)
-				return Vec2.Distance(p, v);
-			float t = Vec2.Dot(p - v, w - v) / l2;
-			if (t < 0.0)
-				return Vec2.Distance(p, v);
-			else if (t > 1.0)
-				return Vec2.Distance(p, w);
-			Vec2 projection = v + t * (w - v);
-			return Vec2.Distance(p, projection);
+			return MathUtil.LinePointDistance(Vec2.FromPointF(ln1), Vec2.FromPointF(ln2), Vec2.FromPointF(pnt));
 		}
 	}
 }

File SharpHammer/Camera.cs

+using System;
+using System.Runtime.InteropServices;
+
+namespace SharpHammer
+{
+	public class Camera
+	{
+		internal cam _cam;
+
+		private Camera()
+		{ }
+
+		public static Camera Create()
+		{
+			return Create(Vec4.Zero, Vec4.UnitZ);
+		}
+
+		public static Camera Create(Vec4 pos, Vec4 target)
+		{
+			Camera cam = new Camera();
+			NativeCalls.cam_init(ref cam._cam, ref pos, ref target, 0.1f, 1000f, (float)Math.PI * .3f);
+			return cam;
+		}
+
+	}
+
+	[StructLayout(LayoutKind.Sequential)]
+	internal struct cam
+	{
+		Quat rot;
+		Vec4 look;
+		Vec4 right;
+		Vec4 up;
+		Vec4 pos;
+
+		float fnear;
+		float ffar;
+		float fov;
+		float aspect;
+
+		float pitch_cur;
+		float yaw_cur;
+
+		UInt32 const_pitch;
+
+		float pitch_max;
+		float pitch_min;
+	}
+}

File SharpHammer/Config.cs

+using System;
+using System.IO;
+
+namespace SharpHammer
+{
+	public class Config : DisposableBase
+	{
+		internal IntPtr _params = IntPtr.Zero;
+
+		private Config()
+		{ }
+
+		public static Config FromFile(string path)
+		{
+			path = Path.GetFullPath(path);
+			if (!File.Exists(path))
+				throw new FileNotFoundException("Config file not found.", path);
+
+			Config cfg = new Config();
+			cfg._params = NativeCalls.app_load_config(path);
+			if (cfg._params == IntPtr.Zero)
+				throw new InvalidDataException("Invalid file format.");
+			return cfg;
+		}
+
+		public static Config Default
+		{
+			get 
+			{
+				Config cfg = new Config();
+				cfg._params = NativeCalls.app_defaultconfig();
+				return cfg;
+			}
+		}
+
+		protected override void OnDisposeUnmanaged()
+		{
+			if (_params != IntPtr.Zero)
+				NativeCalls.app_unload_config(_params);
+		}
+	}
+}

File SharpHammer/DisposableBase.cs

 {
 	public abstract class DisposableBase : IDisposable
 	{
-		private bool _disposed = false;
+		bool _disposed = false;
 
 		~DisposableBase()
 		{
-			Dispose();
+			//if (GetLogger() != null)
+			//	GetLogger().Warning("Dispose was not called explicitly on object of type : " + GetType().Name);
+			Dispose(false);
 		}
 
+		#region Methods
+		/// <summary>
+		/// Release all resources associated to this object.
+		/// </summary>
 		public void Dispose()
 		{
 			Dispose(true);
 			GC.SuppressFinalize(this);
 		}
 
-		protected abstract void OnDispose(bool managed);
+		protected virtual void OnDisposeManaged() { }
+
+		protected virtual void OnDisposeUnmanaged() { }
 
 		private void Dispose(bool disposing)
 		{
 			if (_disposed)
 				return;
 			_disposed = true;
+
+			// this order is important
 			if (disposing)
-				OnDispose(true);
-			OnDispose(false);
+				OnDisposeManaged();
+			OnDisposeUnmanaged();
 		}
+		#endregion
+
 	}
 }

File SharpHammer/Log.cs

+using System;
+using System.IO;
+
+namespace SharpHammer
+{
+	public static class Log
+	{
+
+		public static bool ConsoleOutput
+		{
+			get { return NativeCalls.log_isconsole() != 0u; }
+			set { NativeCalls.log_outputconsole(value ? 1u : 0u); }
+		}
+
+		public static void SetFileOutput(string path)
+		{
+			if (path == null || !File.Exists(path))
+				NativeCalls.log_outputfile(0u, "");
+			else
+				NativeCalls.log_outputfile(1u, path);	
+		}
+
+		public static bool GetFileOutput()
+		{
+			return NativeCalls.log_isconsole() != 0u;
+		}
+
+		public static void Print(LogType type, string text)
+		{
+			NativeCalls.log_print(type, text);
+		}
+	}
+
+	public enum LogType
+	{
+		Text = 0,
+		Error = 1,
+		Warning = 2,
+		Info = 3,
+		Load = 4
+	}
+
+}

File SharpHammer/MathUtil.cs

 				return max;
 			return value;
 		}
+
+		
+
+		/// <summary>
+		/// Finds nearest point on line (v,w) from point (p)
+		/// </summary>
+		public static Vec2 NearestPointOnLine(Vec2 v, Vec2 w, Vec2 p)
+		{
+			float l2 = Vec2.SqrDistance(v, w);
+			if (l2 == 0.0)
+				return v;
+			float t = Vec2.Dot(p - v, w - v) / l2;
+			if (t < 0.0)
+				return v;
+			else if (t > 1.0)
+				return w;
+			Vec2 projection = v + t * (w - v);
+			return projection;
+		}
+
+		/// <summary>
+		/// Finds min distance between line and point.
+		/// </summary>
+		public static float LinePointDistance(Vec2 v, Vec2 w, Vec2 p)
+		{
+			return Vec2.Distance(p, NearestPointOnLine(v, w, p));
+		}
 	}
 }

File SharpHammer/Matrix3.cs

+#region --- License ---
+/*
+Copyright (c) 2006 - 2008 The Open Toolkit library.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ */
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace SharpHammer
+{
+	/// <summary>
+	/// Represents a 3x3 matrix containing 3D rotation and scale.
+	/// </summary>
+	[Serializable]
+	[StructLayout(LayoutKind.Sequential)]
+	public struct Matrix3 : IEquatable<Matrix3>
+	{
+		#region Fields
+
+		/// <summary>
+		/// First row of the matrix.
+		/// </summary>
+		public Vec3 Row0;
+
+		/// <summary>
+		/// Second row of the matrix.
+		/// </summary>
+		public Vec3 Row1;
+
+		/// <summary>
+		/// Third row of the matrix.
+		/// </summary>
+		public Vec3 Row2;
+
+		/// <summary>
+		/// The identity matrix.
+		/// </summary>
+		public static readonly Matrix3 Identity = new Matrix3(Vec3.UnitX, Vec3.UnitY, Vec3.UnitZ);
+
+		/// <summary>
+		/// The zero matrix.
+		/// </summary>
+		public static readonly Matrix3 Zero = new Matrix3(Vec3.Zero, Vec3.Zero, Vec3.Zero);
+
+		#endregion
+
+		#region Constructors
+
+		/// <summary>
+		/// Constructs a new instance.
+		/// </summary>
+		/// <param name="row0">Top row of the matrix</param>
+		/// <param name="row1">Second row of the matrix</param>
+		/// <param name="row2">Bottom row of the matrix</param>
+		public Matrix3(Vec3 row0, Vec3 row1, Vec3 row2)
+		{
+			Row0 = row0;
+			Row1 = row1;
+			Row2 = row2;
+		}
+
+		/// <summary>
+		/// Constructs a new instance.
+		/// </summary>
+		/// <param name="m00">First item of the first row of the matrix.</param>
+		/// <param name="m01">Second item of the first row of the matrix.</param>
+		/// <param name="m02">Third item of the first row of the matrix.</param>
+		/// <param name="m10">First item of the second row of the matrix.</param>
+		/// <param name="m11">Second item of the second row of the matrix.</param>
+		/// <param name="m12">Third item of the second row of the matrix.</param>
+		/// <param name="m20">First item of the third row of the matrix.</param>
+		/// <param name="m21">Second item of the third row of the matrix.</param>
+		/// <param name="m22">Third item of the third row of the matrix.</param>
+		public Matrix3(
+			float m00, float m01, float m02,
+			float m10, float m11, float m12,
+			float m20, float m21, float m22)
+		{
+			Row0 = new Vec3(m00, m01, m02);
+			Row1 = new Vec3(m10, m11, m12);
+			Row2 = new Vec3(m20, m21, m22);
+		}
+
+		/// <summary>
+		/// Constructs a new instance.
+		/// </summary>
+		/// <param name="matrix">A Matrix4 to take the upper-left 3x3 from.</param>
+		public Matrix3(Matrix4 matrix)
+		{
+			Row0 = matrix.Row0.Xyz;
+			Row1 = matrix.Row1.Xyz;
+			Row2 = matrix.Row2.Xyz;
+		}
+
+		#endregion
+
+		#region Public Members
+
+		#region Properties
+
+		/// <summary>
+		/// Gets the determinant of this matrix.
+		/// </summary>
+		public float Determinant
+		{
+			get
+			{
+				float m11 = Row0.X, m12 = Row0.Y, m13 = Row0.Z,
+                m21 = Row1.X, m22 = Row1.Y, m23 = Row1.Z,
+                m31 = Row2.X, m32 = Row2.Y, m33 = Row2.Z;
+
+				return m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32
+					 - m13 * m22 * m31 - m11 * m23 * m32 - m12 * m21 * m33;
+			}
+		}
+
+		/// <summary>
+		/// Gets the first column of this matrix.
+		/// </summary>
+		public Vec3 Column0
+		{
+			get { return new Vec3(Row0.X, Row1.X, Row2.X); }
+		}
+
+		/// <summary>
+		/// Gets the second column of this matrix.
+		/// </summary>
+		public Vec3 Column1
+		{
+			get { return new Vec3(Row0.Y, Row1.Y, Row2.Y); }
+		}
+
+		/// <summary>
+		/// Gets the third column of this matrix.
+		/// </summary>
+		public Vec3 Column2
+		{
+			get { return new Vec3(Row0.Z, Row1.Z, Row2.Z); }
+		}
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 1 of this instance.
+		/// </summary>
+		public float M11 { get { return Row0.X; } set { Row0.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 2 of this instance.
+		/// </summary>
+		public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 3 of this instance.
+		/// </summary>
+		public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 1 of this instance.
+		/// </summary>
+		public float M21 { get { return Row1.X; } set { Row1.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 2 of this instance.
+		/// </summary>
+		public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 3 of this instance.
+		/// </summary>
+		public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 1 of this instance.
+		/// </summary>
+		public float M31 { get { return Row2.X; } set { Row2.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 2 of this instance.
+		/// </summary>
+		public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 3 of this instance.
+		/// </summary>
+		public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the values along the main diagonal of the matrix.
+		/// </summary>
+		public Vec3 Diagonal
+		{
+			get
+			{
+				return new Vec3(Row0.X, Row1.Y, Row2.Z);
+			}
+			set
+			{
+				Row0.X = value.X;
+				Row1.Y = value.Y;
+				Row2.Z = value.Z;
+			}
+		}
+
+		/// <summary>
+		/// Gets the trace of the matrix, the sum of the values along the diagonal.
+		/// </summary>
+		public float Trace { get { return Row0.X + Row1.Y + Row2.Z; } }
+
+		#endregion
+
+		#region Indexers
+
+		/// <summary>
+		/// Gets or sets the value at a specified row and column.
+		/// </summary>
+		public float this[int rowIndex, int columnIndex]
+		{
+			get
+			{
+				if (rowIndex == 0) return Row0[columnIndex];
+				else if (rowIndex == 1) return Row1[columnIndex];
+				else if (rowIndex == 2) return Row2[columnIndex];
+				throw new IndexOutOfRangeException("You tried to access this matrix at: (" + rowIndex + ", " + columnIndex + ")");
+			}
+			set
+			{
+				if (rowIndex == 0) Row0[columnIndex] = value;
+				else if (rowIndex == 1) Row1[columnIndex] = value;
+				else if (rowIndex == 2) Row2[columnIndex] = value;
+				else throw new IndexOutOfRangeException("You tried to set this matrix at: (" + rowIndex + ", " + columnIndex + ")");
+			}
+		}
+
+		#endregion
+
+		#region Instance
+
+		#region public void Invert()
+
+		/// <summary>
+		/// Converts this instance into its inverse.
+		/// </summary>
+		public void Invert()
+		{
+			this = Matrix3.Invert(this);
+		}
+
+		#endregion
+
+		#region public void Transpose()
+
+		/// <summary>
+		/// Converts this instance into its transpose.
+		/// </summary>
+		public void Transpose()
+		{
+			this = Matrix3.Transpose(this);
+		}
+
+		#endregion
+
+		/// <summary>
+		/// Returns a normalised copy of this instance.
+		/// </summary>
+		public Matrix3 Normalized()
+		{
+			Matrix3 m = this;
+			m.Normalize();
+			return m;
+		}
+
+		/// <summary>
+		/// Divides each element in the Matrix by the <see cref="Determinant"/>.
+		/// </summary>
+		public void Normalize()
+		{
+			var determinant = this.Determinant;
+			Row0 /= determinant;
+			Row1 /= determinant;
+			Row2 /= determinant;
+		}
+
+		/// <summary>
+		/// Returns an inverted copy of this instance.
+		/// </summary>
+		public Matrix3 Inverted()
+		{
+			Matrix3 m = this;
+			if (m.Determinant != 0)
+				m.Invert();
+			return m;
+		}
+
+		/// <summary>
+		/// Returns a copy of this Matrix3 without scale.
+		/// </summary>
+		public Matrix3 ClearScale()
+		{
+			Matrix3 m = this;
+			m.Row0 = m.Row0.Normalized();
+			m.Row1 = m.Row1.Normalized();
+			m.Row2 = m.Row2.Normalized();
+			return m;
+		}
+		/// <summary>
+		/// Returns a copy of this Matrix3 without rotation.
+		/// </summary>
+		public Matrix3 ClearRotation()
+		{
+			Matrix3 m = this;
+			m.Row0 = new Vec3(m.Row0.Length, 0, 0);
+			m.Row1 = new Vec3(0, m.Row1.Length, 0);
+			m.Row2 = new Vec3(0, 0, m.Row2.Length);
+			return m;
+		}
+
+		/// <summary>
+		/// Returns the scale component of this instance.
+		/// </summary>
+		public Vec3 ExtractScale() { return new Vec3(Row0.Length, Row1.Length, Row2.Length); }
+
+		/// <summary>
+		/// Returns the rotation component of this instance. Quite slow.
+		/// </summary>
+		/// <param name="row_normalise">Whether the method should row-normalise (i.e. remove scale from) the Matrix. Pass false if you know it's already normalised.</param>
+		public Quat ExtractRotation(bool row_normalise = true)
+		{
+			var row0 = Row0;
+			var row1 = Row1;
+			var row2 = Row2;
+
+			if (row_normalise) {
+				row0 = row0.Normalized();
+				row1 = row1.Normalized();
+				row2 = row2.Normalized();
+			}
+
+			// code below adapted from Blender
+
+			Quat q = new Quat();
+			double trace = 0.25 * (row0[0] + row1[1] + row2[2] + 1.0);
+
+			if (trace > 0) {
+				double sq = Math.Sqrt(trace);
+
+				q.W = (float)sq;
+				sq = 1.0 / (4.0 * sq);
+				q.X = (float)((row1[2] - row2[1]) * sq);
+				q.Y = (float)((row2[0] - row0[2]) * sq);
+				q.Z = (float)((row0[1] - row1[0]) * sq);
+			} else if (row0[0] > row1[1] && row0[0] > row2[2]) {
+				double sq = 2.0 * Math.Sqrt(1.0 + row0[0] - row1[1] - row2[2]);
+
+				q.X = (float)(0.25 * sq);
+				sq = 1.0 / sq;
+				q.W = (float)((row2[1] - row1[2]) * sq);
+				q.Y = (float)((row1[0] + row0[1]) * sq);
+				q.Z = (float)((row2[0] + row0[2]) * sq);
+			} else if (row1[1] > row2[2]) {
+				double sq = 2.0 * Math.Sqrt(1.0 + row1[1] - row0[0] - row2[2]);
+
+				q.Y = (float)(0.25 * sq);
+				sq = 1.0 / sq;
+				q.W = (float)((row2[0] - row0[2]) * sq);
+				q.X = (float)((row1[0] + row0[1]) * sq);
+				q.Z = (float)((row2[1] + row1[2]) * sq);
+			} else {
+				double sq = 2.0 * Math.Sqrt(1.0 + row2[2] - row0[0] - row1[1]);
+
+				q.Z = (float)(0.25 * sq);
+				sq = 1.0 / sq;
+				q.W = (float)((row1[0] - row0[1]) * sq);
+				q.X = (float)((row2[0] + row0[2]) * sq);
+				q.Y = (float)((row2[1] + row1[2]) * sq);
+			}
+
+			q.Normalize();
+			return q;
+		}
+
+		#endregion
+
+		#region Static
+
+		#region CreateFromAxisAngle
+
+		/// <summary>
+		/// Build a rotation matrix from the specified axis/angle rotation.
+		/// </summary>
+		/// <param name="axis">The axis to rotate about.</param>
+		/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
+		/// <param name="result">A matrix instance.</param>
+		public static void CreateFromAxisAngle(Vec3 axis, float angle, out Matrix3 result)
+		{
+			//normalize and create a local copy of the vector.
+			axis.Normalize();
+			float axisX = axis.X, axisY = axis.Y, axisZ = axis.Z;
+
+			//calculate angles
+			float cos = (float)System.Math.Cos(-angle);
+			float sin = (float)System.Math.Sin(-angle);
+			float t = 1.0f - cos;
+
+			//do the conversion math once
+			float tXX = t * axisX * axisX,
+            tXY = t * axisX * axisY,
+            tXZ = t * axisX * axisZ,
+            tYY = t * axisY * axisY,
+            tYZ = t * axisY * axisZ,
+            tZZ = t * axisZ * axisZ;
+
+			float sinX = sin * axisX,
+            sinY = sin * axisY,
+            sinZ = sin * axisZ;
+
+			result.Row0.X = tXX + cos;
+			result.Row0.Y = tXY - sinZ;
+			result.Row0.Z = tXZ + sinY;
+			result.Row1.X = tXY + sinZ;
+			result.Row1.Y = tYY + cos;
+			result.Row1.Z = tYZ - sinX;
+			result.Row2.X = tXZ - sinY;
+			result.Row2.Y = tYZ + sinX;
+			result.Row2.Z = tZZ + cos;
+		}
+
+		/// <summary>
+		/// Build a rotation matrix from the specified axis/angle rotation.
+		/// </summary>
+		/// <param name="axis">The axis to rotate about.</param>
+		/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
+		/// <returns>A matrix instance.</returns>
+		public static Matrix3 CreateFromAxisAngle(Vec3 axis, float angle)
+		{
+			Matrix3 result;
+			CreateFromAxisAngle(axis, angle, out result);
+			return result;
+		}
+
+		#endregion
+
+		#region CreateFromQuat
+
+		/// <summary>
+		/// Build a rotation matrix from the specified Quat.
+		/// </summary>
+		/// <param name="q">Quat to translate.</param>
+		/// <param name="result">Matrix result.</param>
+		public static void CreateFromQuat(ref Quat q, out Matrix3 result)
+		{
+			Vec3 axis;
+			float angle;
+			q.ToAxisAngle(out axis, out angle);
+			CreateFromAxisAngle(axis, angle, out result);
+		}
+
+		/// <summary>
+		/// Build a rotation matrix from the specified Quat.
+		/// </summary>
+		/// <param name="q">Quat to translate.</param>
+		/// <returns>A matrix instance.</returns>
+		public static Matrix3 CreateFromQuat(Quat q)
+		{
+			Matrix3 result;
+			CreateFromQuat(ref q, out result);
+			return result;
+		}
+
+		#endregion
+
+		#region CreateRotation[XYZ]
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the x-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <param name="result">The resulting Matrix3 instance.</param>
+		public static void CreateRotationX(float angle, out Matrix3 result)
+		{
+			float cos = (float)System.Math.Cos(angle);
+			float sin = (float)System.Math.Sin(angle);
+
+			result = Identity;
+			result.Row1.Y = cos;
+			result.Row1.Z = sin;
+			result.Row2.Y = -sin;
+			result.Row2.Z = cos;
+		}
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the x-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <returns>The resulting Matrix3 instance.</returns>
+		public static Matrix3 CreateRotationX(float angle)
+		{
+			Matrix3 result;
+			CreateRotationX(angle, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the y-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <param name="result">The resulting Matrix3 instance.</param>
+		public static void CreateRotationY(float angle, out Matrix3 result)
+		{
+			float cos = (float)System.Math.Cos(angle);
+			float sin = (float)System.Math.Sin(angle);
+
+			result = Identity;
+			result.Row0.X = cos;
+			result.Row0.Z = -sin;
+			result.Row2.X = sin;
+			result.Row2.Z = cos;
+		}
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the y-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <returns>The resulting Matrix3 instance.</returns>
+		public static Matrix3 CreateRotationY(float angle)
+		{
+			Matrix3 result;
+			CreateRotationY(angle, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the z-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <param name="result">The resulting Matrix3 instance.</param>
+		public static void CreateRotationZ(float angle, out Matrix3 result)
+		{
+			float cos = (float)System.Math.Cos(angle);
+			float sin = (float)System.Math.Sin(angle);
+
+			result = Identity;
+			result.Row0.X = cos;
+			result.Row0.Y = sin;
+			result.Row1.X = -sin;
+			result.Row1.Y = cos;
+		}
+
+		/// <summary>
+		/// Builds a rotation matrix for a rotation around the z-axis.
+		/// </summary>
+		/// <param name="angle">The counter-clockwise angle in radians.</param>
+		/// <returns>The resulting Matrix3 instance.</returns>
+		public static Matrix3 CreateRotationZ(float angle)
+		{
+			Matrix3 result;
+			CreateRotationZ(angle, out result);
+			return result;
+		}
+
+		#endregion
+
+		#region CreateScale
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="scale">Single scale factor for the x, y, and z axes.</param>
+		/// <returns>A scale matrix.</returns>
+		public static Matrix3 CreateScale(float scale)
+		{
+			Matrix3 result;
+			CreateScale(scale, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="scale">Scale factors for the x, y, and z axes.</param>
+		/// <returns>A scale matrix.</returns>
+		public static Matrix3 CreateScale(Vec3 scale)
+		{
+			Matrix3 result;
+			CreateScale(ref scale, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="x">Scale factor for the x axis.</param>
+		/// <param name="y">Scale factor for the y axis.</param>
+		/// <param name="z">Scale factor for the z axis.</param>
+		/// <returns>A scale matrix.</returns>
+		public static Matrix3 CreateScale(float x, float y, float z)
+		{
+			Matrix3 result;
+			CreateScale(x, y, z, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="scale">Single scale factor for the x, y, and z axes.</param>
+		/// <param name="result">A scale matrix.</param>
+		public static void CreateScale(float scale, out Matrix3 result)
+		{
+			result = Identity;
+			result.Row0.X = scale;
+			result.Row1.Y = scale;
+			result.Row2.Z = scale;
+		}
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="scale">Scale factors for the x, y, and z axes.</param>
+		/// <param name="result">A scale matrix.</param>
+		public static void CreateScale(ref Vec3 scale, out Matrix3 result)
+		{
+			result = Identity;
+			result.Row0.X = scale.X;
+			result.Row1.Y = scale.Y;
+			result.Row2.Z = scale.Z;
+		}
+
+		/// <summary>
+		/// Creates a scale matrix.
+		/// </summary>
+		/// <param name="x">Scale factor for the x axis.</param>
+		/// <param name="y">Scale factor for the y axis.</param>
+		/// <param name="z">Scale factor for the z axis.</param>
+		/// <param name="result">A scale matrix.</param>
+		public static void CreateScale(float x, float y, float z, out Matrix3 result)
+		{
+			result = Identity;
+			result.Row0.X = x;
+			result.Row1.Y = y;
+			result.Row2.Z = z;
+		}
+
+		#endregion
+
+		#region Multiply Functions
+
+		/// <summary>
+		/// Multiplies two instances.
+		/// </summary>
+		/// <param name="left">The left operand of the multiplication.</param>
+		/// <param name="right">The right operand of the multiplication.</param>
+		/// <returns>A new instance that is the result of the multiplication</returns>
+		public static Matrix3 Mult(Matrix3 left, Matrix3 right)
+		{
+			Matrix3 result;
+			Mult(ref left, ref right, out result);
+			return result;
+		}
+
+		/// <summary>
+		/// Multiplies two instances.
+		/// </summary>
+		/// <param name="left">The left operand of the multiplication.</param>
+		/// <param name="right">The right operand of the multiplication.</param>
+		/// <param name="result">A new instance that is the result of the multiplication</param>
+		public static void Mult(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
+		{
+			float   lM11 = left.Row0.X, lM12 = left.Row0.Y, lM13 = left.Row0.Z,
+            lM21 = left.Row1.X, lM22 = left.Row1.Y, lM23 = left.Row1.Z,
+            lM31 = left.Row2.X, lM32 = left.Row2.Y, lM33 = left.Row2.Z,
+            rM11 = right.Row0.X, rM12 = right.Row0.Y, rM13 = right.Row0.Z,
+            rM21 = right.Row1.X, rM22 = right.Row1.Y, rM23 = right.Row1.Z,
+            rM31 = right.Row2.X, rM32 = right.Row2.Y, rM33 = right.Row2.Z;
+
+			result.Row0.X = ((lM11 * rM11) + (lM12 * rM21)) + (lM13 * rM31);
+			result.Row0.Y = ((lM11 * rM12) + (lM12 * rM22)) + (lM13 * rM32);
+			result.Row0.Z = ((lM11 * rM13) + (lM12 * rM23)) + (lM13 * rM33);
+			result.Row1.X = ((lM21 * rM11) + (lM22 * rM21)) + (lM23 * rM31);
+			result.Row1.Y = ((lM21 * rM12) + (lM22 * rM22)) + (lM23 * rM32);
+			result.Row1.Z = ((lM21 * rM13) + (lM22 * rM23)) + (lM23 * rM33);
+			result.Row2.X = ((lM31 * rM11) + (lM32 * rM21)) + (lM33 * rM31);
+			result.Row2.Y = ((lM31 * rM12) + (lM32 * rM22)) + (lM33 * rM32);
+			result.Row2.Z = ((lM31 * rM13) + (lM32 * rM23)) + (lM33 * rM33);
+		}
+
+		#endregion
+
+		#region Invert Functions
+
+		/// <summary>
+		/// Calculate the inverse of the given matrix
+		/// </summary>
+		/// <param name="mat">The matrix to invert</param>
+		/// <param name="result">The inverse of the given matrix if it has one, or the input if it is singular</param>
+		/// <exception cref="InvalidOperationException">Thrown if the Matrix3 is singular.</exception>
+		public static void Invert(ref Matrix3 mat, out Matrix3 result)
+		{
+			int[] colIdx = { 0, 0, 0 };
+			int[] rowIdx = { 0, 0, 0 };
+			int[] pivotIdx = { -1, -1, -1 };
+
+			float[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z},
+                {mat.Row1.X, mat.Row1.Y, mat.Row1.Z},
+                {mat.Row2.X, mat.Row2.Y, mat.Row2.Z}};
+
+			int icol = 0;
+			int irow = 0;
+			for (int i = 0; i < 3; i++) {
+				float maxPivot = 0.0f;
+				for (int j = 0; j < 3; j++) {
+					if (pivotIdx[j] != 0) {
+						for (int k = 0; k < 3; ++k) {
+							if (pivotIdx[k] == -1) {
+								float absVal = System.Math.Abs(inverse[j, k]);
+								if (absVal > maxPivot) {
+									maxPivot = absVal;
+									irow = j;
+									icol = k;
+								}
+							} else if (pivotIdx[k] > 0) {
+								result = mat;
+								return;
+							}
+						}
+					}
+				}
+
+				++(pivotIdx[icol]);
+
+				if (irow != icol) {
+					for (int k = 0; k < 3; ++k) {
+						float f = inverse[irow, k];
+						inverse[irow, k] = inverse[icol, k];
+						inverse[icol, k] = f;
+					}
+				}
+
+				rowIdx[i] = irow;
+				colIdx[i] = icol;
+
+				float pivot = inverse[icol, icol];
+
+				if (pivot == 0.0f) {
+					throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
+				}
+
+				float oneOverPivot = 1.0f / pivot;
+				inverse[icol, icol] = 1.0f;
+				for (int k = 0; k < 3; ++k)
+					inverse[icol, k] *= oneOverPivot;
+
+				for (int j = 0; j < 3; ++j) {
+					if (icol != j) {
+						float f = inverse[j, icol];
+						inverse[j, icol] = 0.0f;
+						for (int k = 0; k < 3; ++k)
+							inverse[j, k] -= inverse[icol, k] * f;
+					}
+				}
+			}
+
+			for (int j = 2; j >= 0; --j) {
+				int ir = rowIdx[j];
+				int ic = colIdx[j];
+				for (int k = 0; k < 3; ++k) {
+					float f = inverse[k, ir];
+					inverse[k, ir] = inverse[k, ic];
+					inverse[k, ic] = f;
+				}
+			}
+
+			result.Row0.X = inverse[0, 0];
+			result.Row0.Y = inverse[0, 1];
+			result.Row0.Z = inverse[0, 2];
+			result.Row1.X = inverse[1, 0];
+			result.Row1.Y = inverse[1, 1];
+			result.Row1.Z = inverse[1, 2];
+			result.Row2.X = inverse[2, 0];
+			result.Row2.Y = inverse[2, 1];
+			result.Row2.Z = inverse[2, 2];
+		}
+
+		/// <summary>
+		/// Calculate the inverse of the given matrix
+		/// </summary>
+		/// <param name="mat">The matrix to invert</param>
+		/// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
+		/// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
+		public static Matrix3 Invert(Matrix3 mat)
+		{
+			Matrix3 result;
+			Invert(ref mat, out result);
+			return result;
+		}
+
+		#endregion
+
+		#region Transpose
+
+		/// <summary>
+		/// Calculate the transpose of the given matrix
+		/// </summary>
+		/// <param name="mat">The matrix to transpose</param>
+		/// <returns>The transpose of the given matrix</returns>
+		public static Matrix3 Transpose(Matrix3 mat)
+		{
+			return new Matrix3(mat.Column0, mat.Column1, mat.Column2);
+		}
+
+		/// <summary>
+		/// Calculate the transpose of the given matrix
+		/// </summary>
+		/// <param name="mat">The matrix to transpose</param>
+		/// <param name="result">The result of the calculation</param>
+		public static void Transpose(ref Matrix3 mat, out Matrix3 result)
+		{
+			result.Row0.X = mat.Row0.X;
+			result.Row0.Y = mat.Row1.X;
+			result.Row0.Z = mat.Row2.X;
+			result.Row1.X = mat.Row0.Y;
+			result.Row1.Y = mat.Row1.Y;
+			result.Row1.Z = mat.Row2.Y;
+			result.Row2.X = mat.Row0.Z;
+			result.Row2.Y = mat.Row1.Z;
+			result.Row2.Z = mat.Row2.Z;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region Operators
+
+		/// <summary>
+		/// Matrix multiplication
+		/// </summary>
+		/// <param name="left">left-hand operand</param>
+		/// <param name="right">right-hand operand</param>
+		/// <returns>A new Matrix3d which holds the result of the multiplication</returns>
+		public static Matrix3 operator *(Matrix3 left, Matrix3 right)
+		{
+			return Matrix3.Mult(left, right);
+		}
+
+		/// <summary>
+		/// Compares two instances for equality.
+		/// </summary>
+		/// <param name="left">The first instance.</param>
+		/// <param name="right">The second instance.</param>
+		/// <returns>True, if left equals right; false otherwise.</returns>
+		public static bool operator ==(Matrix3 left, Matrix3 right)
+		{
+			return left.Equals(right);
+		}
+
+		/// <summary>
+		/// Compares two instances for inequality.
+		/// </summary>
+		/// <param name="left">The first instance.</param>
+		/// <param name="right">The second instance.</param>
+		/// <returns>True, if left does not equal right; false otherwise.</returns>
+		public static bool operator !=(Matrix3 left, Matrix3 right)
+		{
+			return !left.Equals(right);
+		}
+
+		#endregion
+
+		#region Overrides
+
+		#region public override string ToString()
+
+		/// <summary>
+		/// Returns a System.String that represents the current Matrix3d.
+		/// </summary>
+		/// <returns>The string representation of the matrix.</returns>
+		public override string ToString()
+		{
+			return String.Format("{0}\n{1}\n{2}", Row0, Row1, Row2);
+		}
+
+		#endregion
+
+		#region public override int GetHashCode()
+
+		/// <summary>
+		/// Returns the hashcode for this instance.
+		/// </summary>
+		/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
+		public override int GetHashCode()
+		{
+			return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
+		}
+
+		#endregion
+
+		#region public override bool Equals(object obj)
+
+		/// <summary>
+		/// Indicates whether this instance and a specified object are equal.
+		/// </summary>
+		/// <param name="obj">The object to compare to.</param>
+		/// <returns>True if the instances are equal; false otherwise.</returns>
+		public override bool Equals(object obj)
+		{
+			if (!(obj is Matrix3))
+				return false;
+
+			return this.Equals((Matrix3)obj);
+		}
+
+		#endregion
+
+		#endregion
+
+		#endregion
+
+		#region IEquatable<Matrix3> Members
+
+		/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
+		/// <param name="other">A matrix to compare with this matrix.</param>
+		/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
+		public bool Equals(Matrix3 other)
+		{
+			return
+				Row0 == other.Row0 &&
+					Row1 == other.Row1 &&
+					Row2 == other.Row2;
+		}
+
+		#endregion
+	}
+}

File SharpHammer/Matrix4.cs

-using System;
+#region --- License ---
+/*
+Copyright (c) 2006 - 2008 The Open Toolkit library.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ */
+#endregion
+
+using System;
 using System.Runtime.InteropServices;
 
 namespace SharpHammer
 {
+	/// <summary>
+	/// Represents a 4x4 matrix containing 3D rotation, scale, transform, and projection.
+	/// </summary>
+	/// <seealso cref="Matrix4d"/>
+	[Serializable]
 	[StructLayout(LayoutKind.Sequential)]
-	public struct Matrix4
+	public struct Matrix4 : IEquatable<Matrix4>
 	{
-		public Matrix4(float m11, float m21, float m31, float m41,
-					   float m12, float m22, float m32, float m42,
-					   float m13, float m23, float m33, float m43,
-					   float m14, float m24, float m34, float m44)
+		#region Fields
+
+		/// <summary>
+		/// Top row of the matrix.
+		/// </summary>
+		public Vec4 Row0;
+
+		/// <summary>
+		/// 2nd row of the matrix.
+		/// </summary>
+		public Vec4 Row1;
+
+		/// <summary>
+		/// 3rd row of the matrix.
+		/// </summary>
+		public Vec4 Row2;
+
+		/// <summary>
+		/// Bottom row of the matrix.
+		/// </summary>
+		public Vec4 Row3;
+
+		/// <summary>
+		/// The identity matrix.
+		/// </summary>
+		public static readonly Matrix4 Identity = new Matrix4(Vec4.UnitX, Vec4.UnitY, Vec4.UnitZ, Vec4.UnitW);
+
+		/// <summary>
+		/// The zero matrix.
+		/// </summary>
+		public static readonly Matrix4 Zero = new Matrix4(Vec4.Zero, Vec4.Zero, Vec4.Zero, Vec4.Zero);
+
+		#endregion
+
+		#region Constructors
+
+		/// <summary>
+		/// Constructs a new instance.
+		/// </summary>
+		/// <param name="row0">Top row of the matrix.</param>
+		/// <param name="row1">Second row of the matrix.</param>
+		/// <param name="row2">Third row of the matrix.</param>
+		/// <param name="row3">Bottom row of the matrix.</param>
+		public Matrix4(Vec4 row0, Vec4 row1, Vec4 row2, Vec4 row3)
 		{
-			Column1.X = m11;
-			Column2.X = m21;
-			Column3.X = m31;
-			Column4.X = m41;
-			Column1.Y = m12;
-			Column2.Y = m22;
-			Column3.Y = m32;
-			Column4.Y = m42;
-			Column1.Z = m13;
-			Column2.Z = m23;
-			Column3.Z = m33;
-			Column4.Z = m43;
-			Column1.W = m14;
-			Column2.W = m24;
-			Column3.W = m34;
-			Column4.W = m44;
-		}
-
-		public Matrix4(Vec4 column1, Vec4 column2, Vec4 column3, Vec4 column4)
-		{
-			this.Column1 = column1;
-			this.Column2 = column2;
-			this.Column3 = column3;
-			this.Column4 = column4;
-		}
-
-		public Matrix4(Matrix4 other)
-		{
-			this = other;
+			Row0 = row0;
+			Row1 = row1;
+			Row2 = row2;
+			Row3 = row3;
 		}
 
 		/// <summary>
-		/// Transpose this matrix.
+		/// Constructs a new instance.
 		/// </summary>
-		///
-		public void Transpose()
+		/// <param name="m00">First item of the first row of the matrix.</param>
+		/// <param name="m01">Second item of the first row of the matrix.</param>
+		/// <param name="m02">Third item of the first row of the matrix.</param>
+		/// <param name="m03">Fourth item of the first row of the matrix.</param>
+		/// <param name="m10">First item of the second row of the matrix.</param>
+		/// <param name="m11">Second item of the second row of the matrix.</param>
+		/// <param name="m12">Third item of the second row of the matrix.</param>
+		/// <param name="m13">Fourth item of the second row of the matrix.</param>
+		/// <param name="m20">First item of the third row of the matrix.</param>
+		/// <param name="m21">Second item of the third row of the matrix.</param>
+		/// <param name="m22">Third item of the third row of the matrix.</param>
+		/// <param name="m23">First item of the third row of the matrix.</param>
+		/// <param name="m30">Fourth item of the fourth row of the matrix.</param>
+		/// <param name="m31">Second item of the fourth row of the matrix.</param>
+		/// <param name="m32">Third item of the fourth row of the matrix.</param>
+		/// <param name="m33">Fourth item of the fourth row of the matrix.</param>
+		public Matrix4(
+			float m00, float m01, float m02, float m03,
+			float m10, float m11, float m12, float m13,
+			float m20, float m21, float m22, float m23,
+			float m30, float m31, float m32, float m33)
 		{
-			Matrix4 tmp = this;
-			Column1 = tmp.Row1;
-			Column2 = tmp.Row2;
-			Column3 = tmp.Row3;
-			Column4 = tmp.Row4;
+			Row0 = new Vec4(m00, m01, m02, m03);
+			Row1 = new Vec4(m10, m11, m12, m13);
+			Row2 = new Vec4(m20, m21, m22, m23);
+			Row3 = new Vec4(m30, m31, m32, m33);
 		}
 
-		/// <summary>
-		/// Invert this Matrix4.
-		/// </summary>
-		public void Invert()
-		{
-			this = Inverse;
-		}
+		#endregion
 
-		public override string ToString()
-		{
-			return base.ToString();
-		}
+		#region Public Members
+
+		#region Properties
 
 		/// <summary>
-		/// Multiply two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <returns></returns>
-		public static Matrix4 Multiply(ref Matrix4 a, ref Matrix4 b)
-		{
-			Matrix4 r;
-			Multiply(ref a, ref b, out r);
-			return r;
-		}
-
-		/// <summary>
-		/// Multiply two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <param name="r"></param>
-		public static void Multiply(ref Matrix4 a, ref Matrix4 b, out Matrix4 r)
-		{
-			float
-				am11 = a.M11, am21 = a.M21, am31 = a.M31, am41 = a.M41,
-				am12 = a.M12, am22 = a.M22, am32 = a.M32, am42 = a.M42,
-				am13 = a.M13, am23 = a.M23, am33 = a.M33, am43 = a.M43,
-				am14 = a.M14, am24 = a.M24, am34 = a.M34, am44 = a.M44,
-
-				bm11 = b.M11, bm21 = b.M21, bm31 = b.M31, bm41 = b.M41,
-				bm12 = b.M12, bm22 = b.M22, bm32 = b.M32, bm42 = b.M42,
-				bm13 = b.M13, bm23 = b.M23, bm33 = b.M33, bm43 = b.M43,
-				bm14 = b.M14, bm24 = b.M24, bm34 = b.M34, bm44 = b.M44;
-
-			r.Column1.X = am11 * bm11 + am21 * bm12 + am31 * bm13 + am41 * bm14; // M11
-			r.Column2.X = am11 * bm21 + am21 * bm22 + am31 * bm23 + am41 * bm24; // M21
-			r.Column3.X = am11 * bm31 + am21 * bm32 + am31 * bm33 + am41 * bm34; // M31
-			r.Column4.X = am11 * bm41 + am21 * bm42 + am31 * bm43 + am41 * bm44; // M41
-
-			r.Column1.Y = am12 * bm11 + am22 * bm12 + am32 * bm13 + am42 * bm14; // M12
-			r.Column2.Y = am12 * bm21 + am22 * bm22 + am32 * bm23 + am42 * bm24; // M22
-			r.Column3.Y = am12 * bm31 + am22 * bm32 + am32 * bm33 + am42 * bm34; // M32
-			r.Column4.Y = am12 * bm41 + am22 * bm42 + am32 * bm43 + am42 * bm44; // M42
-
-			r.Column1.Z = am13 * bm11 + am23 * bm12 + am33 * bm13 + am43 * bm14; // M13
-			r.Column2.Z = am13 * bm21 + am23 * bm22 + am33 * bm23 + am43 * bm24; // M23
-			r.Column3.Z = am13 * bm31 + am23 * bm32 + am33 * bm33 + am43 * bm34; // M33
-			r.Column4.Z = am13 * bm41 + am23 * bm42 + am33 * bm43 + am43 * bm44; // M43
-
-			r.Column1.W = am14 * bm11 + am24 * bm12 + am34 * bm13 + am44 * bm14; // M14
-			r.Column2.W = am14 * bm21 + am24 * bm22 + am34 * bm23 + am44 * bm24; // M24
-			r.Column3.W = am14 * bm31 + am24 * bm32 + am34 * bm33 + am44 * bm34; // M34
-			r.Column4.W = am14 * bm41 + am24 * bm42 + am34 * bm43 + am44 * bm44;  // M44
-		}
-
-		/// <summary>
-		/// Multiply matrix by a scalar.
-		/// </summary>
-		/// <param name="mat"></param>
-		/// <param name="f"></param>
-		/// <param name="r"></param>
-		public static void Multiply(ref Matrix4 mat, float f, out Matrix4 r)
-		{
-			r.Column1.X = mat.Column1.X * f;
-			r.Column1.Y = mat.Column1.Y * f;
-			r.Column1.Z = mat.Column1.Z * f;
-			r.Column1.W = mat.Column1.W * f;
-			r.Column2.X = mat.Column2.X * f;
-			r.Column2.Y = mat.Column2.Y * f;
-			r.Column2.Z = mat.Column2.Z * f;
-			r.Column2.W = mat.Column2.W * f;
-			r.Column3.X = mat.Column3.X * f;
-			r.Column3.Y = mat.Column3.Y * f;
-			r.Column3.Z = mat.Column3.Z * f;
-			r.Column3.W = mat.Column3.W * f;
-			r.Column4.X = mat.Column4.X * f;
-			r.Column4.Y = mat.Column4.Y * f;
-			r.Column4.Z = mat.Column4.Z * f;
-			r.Column4.W = mat.Column4.W * f;
-		}
-
-		/// <summary>
-		/// Multiply matrix by a scalar.
-		/// </summary>
-		/// <param name="mat"></param>
-		/// <param name="f"></param>
-		/// <returns></returns>
-		public static Matrix4 Multiply(ref Matrix4 mat, float f)
-		{
-			Matrix4 r;
-			Multiply(ref mat, f, out r);
-			return r;
-		}
-
-		/// <summary>
-		/// Multiply two 4x3 matrices (assumes row 4 to be 0,0,0,1 ).
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <returns></returns>
-		public static Matrix4 Multiply4x3(ref Matrix4 a, ref Matrix4 b)
-		{
-			Matrix4 r;
-			Multiply4x3(ref a, ref b, out r);
-			return r;
-		}
-
-		/// <summary>
-		/// Multiply two 4x3 matrices (assumes row 4 to be 0,0,0,1 ).
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <param name="r"></param>
-		public static void Multiply4x3(ref Matrix4 a, ref Matrix4 b, out Matrix4 r)
-		{
-			float
-				am11 = a.M11, am21 = a.M21, am31 = a.M31, am41 = a.M41,
-				am12 = a.M12, am22 = a.M22, am32 = a.M32, am42 = a.M42,
-				am13 = a.M13, am23 = a.M23, am33 = a.M33, am43 = a.M43,
-				am14 = a.M14, am24 = a.M24, am34 = a.M34, am44 = a.M44,
-
-				bm11 = b.M11, bm21 = b.M21, bm31 = b.M31, bm41 = b.M41,
-				bm12 = b.M12, bm22 = b.M22, bm32 = b.M32, bm42 = b.M42,
-				bm13 = b.M13, bm23 = b.M23, bm33 = b.M33, bm43 = b.M43;
-
-			r.Column1.X = am11 * bm11 + am21 * bm12 + am31 * bm13; // M11
-			r.Column2.X = am11 * bm21 + am21 * bm22 + am31 * bm23; // M21
-			r.Column3.X = am11 * bm31 + am21 * bm32 + am31 * bm33; // M31
-			r.Column4.X = am11 * bm41 + am21 * bm42 + am31 * bm43 + am41; // M41
-
-			r.Column1.Y = am12 * bm11 + am22 * bm12 + am32 * bm13; // M12
-			r.Column2.Y = am12 * bm21 + am22 * bm22 + am32 * bm23; // M22
-			r.Column3.Y = am12 * bm31 + am22 * bm32 + am32 * bm33; // M32
-			r.Column4.Y = am12 * bm41 + am22 * bm42 + am32 * bm43 + am42; // M42
-
-			r.Column1.Z = am13 * bm11 + am23 * bm12 + am33 * bm13; // M13
-			r.Column2.Z = am13 * bm21 + am23 * bm22 + am33 * bm23; // M23
-			r.Column3.Z = am13 * bm31 + am23 * bm32 + am33 * bm33; // M33
-			r.Column4.Z = am13 * bm41 + am23 * bm42 + am33 * bm43 + am43; // M43
-
-			r.Column1.W = 0; // M14
-			r.Column2.W = 0; // M24
-			r.Column3.W = 0; // M34
-			r.Column4.W = 1;  // M44
-		}
-
-		/// <summary>
-		/// Add two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <param name="r"></param>
-		public static void Add(ref Matrix4 a, ref Matrix4 b, ref Matrix4 r)
-		{
-			r.Column1.X = a.Column1.X + b.Column1.X;
-			r.Column1.Y = a.Column1.Y + b.Column1.Y;
-			r.Column1.Z = a.Column1.Z + b.Column1.Z;
-			r.Column1.W = a.Column1.W + b.Column1.W;
-
-			r.Column2.X = a.Column2.X + b.Column2.X;
-			r.Column2.Y = a.Column2.Y + b.Column2.Y;
-			r.Column2.Z = a.Column2.Z + b.Column2.Z;
-			r.Column2.W = a.Column2.W + b.Column2.W;
-
-			r.Column3.X = a.Column3.X + b.Column3.X;
-			r.Column3.Y = a.Column3.Y + b.Column3.Y;
-			r.Column3.Z = a.Column3.Z + b.Column3.Z;
-			r.Column3.W = a.Column3.W + b.Column3.W;
-
-			r.Column4.X = a.Column4.X + b.Column4.X;
-			r.Column4.Y = a.Column4.Y + b.Column4.Y;
-			r.Column4.Z = a.Column4.Z + b.Column4.Z;
-			r.Column4.W = a.Column4.W + b.Column4.W;
-		}
-
-		/// <summary>
-		/// Add two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <returns></returns>
-		public static Matrix4 Add(ref Matrix4 a, ref Matrix4 b)
-		{
-			Matrix4 r = Matrix4.Identity;
-			Add(ref a, ref b, ref r);
-			return r;
-		}
-
-		/// <summary>
-		/// Subtract two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <param name="r"></param>
-		public static void Subtract(ref Matrix4 a, ref Matrix4 b, out Matrix4 r)
-		{
-			r.Column1.X = a.Column1.X - b.Column1.X;
-			r.Column1.Y = a.Column1.Y - b.Column1.Y;
-			r.Column1.Z = a.Column1.Z - b.Column1.Z;
-			r.Column1.W = a.Column1.W - b.Column1.W;
-
-			r.Column2.X = a.Column2.X - b.Column2.X;
-			r.Column2.Y = a.Column2.Y - b.Column2.Y;
-			r.Column2.Z = a.Column2.Z - b.Column2.Z;
-			r.Column2.W = a.Column2.W - b.Column2.W;
-
-			r.Column3.X = a.Column3.X - b.Column3.X;
-			r.Column3.Y = a.Column3.Y - b.Column3.Y;
-			r.Column3.Z = a.Column3.Z - b.Column3.Z;
-			r.Column3.W = a.Column3.W - b.Column3.W;
-
-			r.Column4.X = a.Column4.X - b.Column4.X;
-			r.Column4.Y = a.Column4.Y - b.Column4.Y;
-			r.Column4.Z = a.Column4.Z - b.Column4.Z;
-			r.Column4.W = a.Column4.W - b.Column4.W;
-		}
-
-		/// <summary>
-		/// Subtract two matrices.
-		/// </summary>
-		/// <param name="a"></param>
-		/// <param name="b"></param>
-		/// <returns></returns>
-		public static Matrix4 Subtract(ref Matrix4 a, ref Matrix4 b)
-		{
-			Matrix4 r;
-			Subtract(ref a, ref b, out r);
-			return r;
-		}
-
-		/// <summary>
-		/// Item at column 1 and row 1
-		/// </summary>
-		public float M11
-		{
-			get
-			{
-				return Column1.X;
-			}
-			set
-			{
-				Column1.X = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 1 and row 2
-		/// </summary>
-		public float M12
-		{
-			get
-			{
-				return Column1.Y;
-			}
-			set
-			{
-				Column1.Y = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 1 and row 3
-		/// </summary>
-		public float M13
-		{
-			get
-			{
-				return Column1.Z;
-			}
-			set
-			{
-				Column1.Z = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 1 and row 4
-		/// </summary>
-		public float M14
-		{
-			get
-			{
-				return Column1.W;
-			}
-			set
-			{
-				Column1.W = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 2 and row 1
-		/// </summary>
-		public float M21
-		{
-			get
-			{
-				return Column2.X;
-			}
-			set
-			{
-				Column2.X = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 2 and row 2
-		/// </summary>
-		public float M22
-		{
-			get
-			{
-				return Column2.Y;
-			}
-			set
-			{
-				Column2.Y = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 2 and row 3
-		/// </summary>
-		public float M23
-		{
-			get
-			{
-				return Column2.Z;
-			}
-			set
-			{
-				Column2.Z = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 2 and row 4
-		/// </summary>
-		public float M24
-		{
-			get
-			{
-				return Column2.W;
-			}
-			set
-			{
-				Column2.W = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 3 and row 1
-		/// </summary>
-		public float M31
-		{
-			get
-			{
-				return Column3.X;
-			}
-			set
-			{
-				Column3.X = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 3 and row 2
-		/// </summary>
-		public float M32
-		{
-			get
-			{
-				return Column3.Y;
-			}
-			set
-			{
-				Column3.Y = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 3 and row 3
-		/// </summary>
-		public float M33
-		{
-			get
-			{
-				return Column3.Z;
-			}
-			set
-			{
-				Column3.Z = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 3 and row 4
-		/// </summary>
-		public float M34
-		{
-			get
-			{
-				return Column3.W;
-			}
-			set
-			{
-				Column3.W = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 4 and row 1
-		/// </summary>
-		public float M41
-		{
-			get
-			{
-				return Column4.X;
-			}
-			set
-			{
-				Column4.X = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 4 and row 2
-		/// </summary>
-		public float M42
-		{
-			get
-			{
-				return Column4.Y;
-			}
-			set
-			{
-				Column4.Y = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 4 and row 3
-		/// </summary>
-		public float M43
-		{
-			get
-			{
-				return Column4.Z;
-			}
-			set
-			{
-				Column4.Z = value;
-			}
-		}
-
-		/// <summary>
-		/// Item at column 4 and row 4
-		/// </summary>
-		public float M44
-		{
-			get
-			{
-				return Column4.W;
-			}
-			set
-			{
-				Column4.W = value;
-			}
-		}
-
-		/// <summary>
-		/// Gets determinant of this matrix.
+		/// Gets the determinant of this matrix.
 		/// </summary>
 		public float Determinant
 		{
 			get
 			{
-				float m12 = M12, m22 = M22, m32 = M32, m42 = M42,
-					  m13 = M13, m23 = M23, m33 = M33, m43 = M43,
-					  m14 = M14, m24 = M24, m34 = M34, m44 = M44;
+				float m11 = Row0.X, m12 = Row0.Y, m13 = Row0.Z, m14 = Row0.W,
+					  m21 = Row1.X, m22 = Row1.Y, m23 = Row1.Z, m24 = Row1.W,
+					  m31 = Row2.X, m32 = Row2.Y, m33 = Row2.Z, m34 = Row2.W,
+					  m41 = Row3.X, m42 = Row3.Y, m43 = Row3.Z, m44 = Row3.W;
 
-				float a = m33 * m44 - m43 * m34;
-				float b = m13 * m44 - m43 * m14;
-				float c = m23 * m44 - m43 * m24;
-				float d = m13 * m24 - m23 * m14;
-				float e = m13 * m34 - m33 * m14;
-				float f = m23 * m34 - m33 * m24;
-
-				float ac = m22 * a - m32 * c + m42 * f;
-				float bc = m12 * a - m32 * b + m42 * e;
-				float cc = m12 * c - m22 * b + m42 * d;
-				float dc = m12 * f - m22 * e + m32 * d;
-
-				ac *= M11;
-				bc *= M21;
-				cc *= M31;
-				dc *= M41;
-
-				return ac - bc + cc - dc;
+				return
+					m11 * m22 * m33 * m44 - m11 * m22 * m34 * m43 + m11 * m23 * m34 * m42 - m11 * m23 * m32 * m44
+				  + m11 * m24 * m32 * m43 - m11 * m24 * m33 * m42 - m12 * m23 * m34 * m41 + m12 * m23 * m31 * m44
+				  - m12 * m24 * m31 * m43 + m12 * m24 * m33 * m41 - m12 * m21 * m33 * m44 + m12 * m21 * m34 * m43
+				  + m13 * m24 * m31 * m42 - m13 * m24 * m32 * m41 + m13 * m21 * m32 * m44 - m13 * m21 * m34 * m42
+				  + m13 * m22 * m34 * m41 - m13 * m22 * m31 * m44 - m14 * m21 * m32 * m43 + m14 * m21 * m33 * m42
+				  - m14 * m22 * m33 * m41 + m14 * m22 * m31 * m43 - m14 * m23 * m31 * m42 + m14 * m23 * m32 * m41;
 			}
 		}
 
 		/// <summary>
-		/// Gets determinant of this matrix. (assumes row 4 to be 0,0,0,1 ).
+		/// Gets the first column of this matrix.
 		/// </summary>
-		public float Determinant4x3
+		public Vec4 Column0
+		{
+			get { return new Vec4(Row0.X, Row1.X, Row2.X, Row3.X); }
+			set { Row0.X = value.X; Row1.X = value.Y; Row2.X = value.Z; Row3.X = value.W; }
+		}
+
+		/// <summary>
+		/// Gets the second column of this matrix.
+		/// </summary>
+		public Vec4 Column1
+		{
+			get { return new Vec4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
+			set { Row0.Y = value.X; Row1.Y = value.Y; Row2.Y = value.Z; Row3.Y = value.W; }
+		}
+
+		/// <summary>
+		/// Gets the third column of this matrix.
+		/// </summary>
+		public Vec4 Column2
+		{
+			get { return new Vec4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
+			set { Row0.Z = value.X; Row1.Z = value.Y; Row2.Z = value.Z; Row3.Z = value.W; }
+		}
+
+		/// <summary>
+		/// Gets the fourth column of this matrix.
+		/// </summary>
+		public Vec4 Column3
+		{
+			get { return new Vec4(Row0.W, Row1.W, Row2.W, Row3.W); }
+			set { Row0.W = value.X; Row1.W = value.Y; Row2.W = value.Z; Row3.W = value.W; }
+		}
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 1 of this instance.
+		/// </summary>
+		public float M11 { get { return Row0.X; } set { Row0.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 2 of this instance.
+		/// </summary>
+		public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 3 of this instance.
+		/// </summary>
+		public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 1, column 4 of this instance.
+		/// </summary>
+		public float M14 { get { return Row0.W; } set { Row0.W = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 1 of this instance.
+		/// </summary>
+		public float M21 { get { return Row1.X; } set { Row1.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 2 of this instance.
+		/// </summary>
+		public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 3 of this instance.
+		/// </summary>
+		public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 2, column 4 of this instance.
+		/// </summary>
+		public float M24 { get { return Row1.W; } set { Row1.W = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 1 of this instance.
+		/// </summary>
+		public float M31 { get { return Row2.X; } set { Row2.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 2 of this instance.
+		/// </summary>
+		public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 3 of this instance.
+		/// </summary>
+		public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 3, column 4 of this instance.
+		/// </summary>
+		public float M34 { get { return Row2.W; } set { Row2.W = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 4, column 1 of this instance.
+		/// </summary>
+		public float M41 { get { return Row3.X; } set { Row3.X = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 4, column 2 of this instance.
+		/// </summary>
+		public float M42 { get { return Row3.Y; } set { Row3.Y = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 4, column 3 of this instance.
+		/// </summary>
+		public float M43 { get { return Row3.Z; } set { Row3.Z = value; } }
+
+		/// <summary>
+		/// Gets or sets the value at row 4, column 4 of this instance.
+		/// </summary>
+		public float M44 { get { return Row3.W; } set { Row3.W = value; } }
+
+		/// <summary>
+		/// Gets or sets the values along the main diagonal of the matrix.
+		/// </summary>
+		public Vec4 Diagonal
 		{
 			get
 			{
-				float m12 = M12, m13 = M13,
-					  m22 = M22, m23 = M23,
-					  m32 = M32, m33 = M33;
-
-				float ac = M11 * (m22 * m33 - m32 * m23);
-				float bc = M21 * (m12 * m33 - m32 * m13);
-				float cc = M31 * (m12 * m23 - m22 * m13);
-				return ac - bc + cc;
+				return new Vec4(Row0.X, Row1.Y, Row2.Z, Row3.W);
+			}
+			set
+			{
+				Row0.X = value.X;
+				Row1.Y = value.Y;
+				Row2.Z = value.Z;
+				Row3.W = value.W;
 			}
 		}
 
 		/// <summary>
-		/// Gets inverse of this Matrix4.
+		/// Gets the trace of the matrix, the sum of the values along the diagonal.
 		/// </summary>
-		public Matrix4 Inverse
+		public float Trace { get { return Row0.X + Row1.Y + Row2.Z + Row3.W; } }
+
+		#endregion
+
+		#region Indexers
+
+		/// <summary>
+		/// Gets or sets the value at a specified row and column.
+		/// </summary>
+		public float this[int rowIndex, int columnIndex]
 		{
 			get
 			{
-				float m11 = M11, m21 = M21, m31 = M31, m41 = M41,
-					  m12 = M12, m22 = M22, m32 = M32, m42 = M42,
-					  m13 = M13, m23 = M23, m33 = M33, m43 = M43,
-					  m14 = M14, m24 = M24, m34 = M34, m44 = M44;
-
-				float s0 = m11 * m22 - m12 * m21;
-				float s1 = m11 * m32 - m12 * m31;
-				float s2 = m11 * m42 - m12 * m41;
-				float s3 = m21 * m32 - m22 * m31;
-				float s4 = m21 * m42 - m22 * m41;
-				float s5 = m31 * m42 - m32 * m41;
-
-				float c5 = m33 * m44 - m34 * m43;
-				float c4 = m23 * m44 - m24 - m43;
-				float c3 = m23 * m34 - m24 * m33;
-				float c2 = m13 * m44 - m14 * m43;
-				float c1 = m13 * m34 - m14 * m33;
-				float c0 = m13 * m24 - m14 * m23;
-
-				float det = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
-
-				if ((float)Math.Abs(det) < .000000001f)
-					throw new InvalidOperationException("Matrix is not invertible.");
-
-				float invdet = 1 / det;
-
-				Matrix4 r;
-				r.Column1.X = (m22 * c5 - m32 * c4 + m42 * c3) * invdet;
-				r.Column2.X = (-m21 * c5 + m31 * c4 - m41 * c3) * invdet;
-				r.Column3.X = (m24 * s5 - m34 * s4 + m44 * s3) * invdet;
-				r.Column4.X = (-m23 * s5 + m33 * s4 - m43 * s3) * invdet;
-
-				r.Column1.Y = (-m12 * c5 + m32 * c2 - m42 * c1) * invdet;
-				r.Column2.Y = (m11 * c5 - m31 * c2 + m41 * c1) * invdet;
-				r.Column3.Y = (-m14 * s5 + m34 * s2 - m44 * s1) * invdet;
-				r.Column4.Y = (m13 * s5 - m33 * s2 + m43 * s1) * invdet;
-
-				r.Column1.Z = (m12 * c4 - m22 * c2 + m42 * c0) * invdet;
-				r.Column2.Z = (-m11 * c4 + m21 * c2 - m41 * c0) * invdet;
-				r.Column3.Z = (m14 * s4 - m24 * s2 + m44 * s0) * invdet;
-				r.Column4.Z = (-m13 * s4 + m23 * s2 - m43 * s0) * invdet;
-
-				r.Column1.W = (-m12 * c3 + m22 * c1 - m32 * c0) * invdet;
-				r.Column2.W = (m11 * c3 - m21 * c1 + m31 * c0) * invdet;
-				r.Column3.W = (-m14 * s3 + m24 * s1 - m34 * s0) * invdet;
-				r.Column4.W = (m13 * s3 - m23 * s1 + m33 * s0) * invdet;
-
-				return r;
+				if (rowIndex == 0) return Row0[columnIndex];
+				else if (rowIndex == 1) return Row1[columnIndex];
+				else if (rowIndex == 2) return Row2[columnIndex];
+				else if (rowIndex == 3) return Row3[columnIndex];
+				throw new IndexOutOfRangeException("You tried to access this matrix at: (" + rowIndex + ", " + columnIndex + ")");
+			}
+			set
+			{
+				if (rowIndex == 0) Row0[columnIndex] = value;
+				else if (rowIndex == 1) Row1[columnIndex] = value;
+				else if (rowIndex == 2) Row2[columnIndex] = value;
+				else if (rowIndex == 3) Row3[columnIndex] = value;
+				else throw new IndexOutOfRangeException("You tried to set this matrix at: (" + rowIndex + ", " + columnIndex + ")");
 			}
 		}
 
-		public Vec4 Row1
+		#endregion
+
+		#region Instance
+
+		#region public void Invert()
+
+		/// <summary>
+		/// Converts this instance into its inverse.
+		/// </summary>
+		public void Invert()
 		{
-			get
-			{
-				return new Vec4(Column1.X, Column2.X, Column3.X, Column4.X);
-			}