# Matrix

(Difference between revisions)

## Description

This snippet is my matrix class. I use this class when I can't get Unity's internal rotation and 3D math functions to do exactly what I want. It's pretty easy to use and the functions are discreet.

## Usage

Below are some basic usage patterns to get you going and to let you see how the class works.

• Rotate Around Yaw - Rotate an object around it's Y axis.
```Matrix mat = new Matrix();
mat *= Matrix.RotateY( 15.0f );

object.transform.position = mat.TransformVector( object.transform.position );
</csharp>

If you wanted to, this could be done in less code.  For example:

<syntaxhighlight lang="csharp">Matrix mat = Matrix.RotateY( 15.0f );

object.transform.position = mat.TransformVector( object.transform.position );
</csharp>

Or even:

<syntaxhighlight lang="csharp">object.transform.position = Matrix.RotateY( 15.0f ).TransformVector( object.transform.position );
</csharp>

* '''Rotate Around Pitch And Yaw''' - Rotate an object around both it's X and Y axes.

<syntaxhighlight lang="csharp">Matrix mat = new Matrix();
mat *= Matrix.RotateY( 15.0f );
mat *= Matrix.RotateX( 45.0f );

object.transform.position = mat.TransformVector( object.transform.position );
</csharp>

You can easily chain matrix commands together, so the above could be done like this:

<syntaxhighlight lang="csharp">Matrix mat = new Matrix();
mat *= Matrix.RotateY( 15.0f ) * Matrix.RotateX( 45.0f );

object.transform.position = mat.TransformVector( object.transform.position );
</csharp>

That doesn't sacrifice a lot of readability and makes for cleaner looking code.

* '''Scale And Translate''' - Scale an object around it's local coordinate space and move to a location.

<syntaxhighlight lang="csharp">Matrix mat = new Matrix();
mat *= Matrix.Scale( 2.0f );
mat *= Matrix.Translate( 64.0f, 0.0f, 0.0f );

object.transform.position = mat.TransformVector( object.transform.position );
</csharp>

== Optimizations ==

If this class becomes a bottleneck for you, you're using it too much.  But seriously, one easy optimization to the above code examples is to skip the initial "new Matrix()" line.  That creates a brand new identity matrix and returns it to you.  If you're immediately going to start calling functions that change the matrix you might as well just start with those and save that step.  For example, you could change this:

<syntaxhighlight lang="csharp">Matrix mat = new Matrix();
mat *= Matrix.Scale( 2.0f );
mat *= Matrix.Translate( 64.0f, 0.0f, 0.0f );
</csharp>

Into this:

<syntaxhighlight lang="csharp">Matrix mat = Matrix.Scale( 2.0f );
mat *= Matrix.Translate( 64.0f, 0.0f, 0.0f );
</csharp>

And save yourself the object creation line.

== Summary ==

So it should be pretty clear how it works.  The basic pattern to follow is: Create a matrix object, stack operations into it (''translations, rotation, scaling''), and then use that matrix to transform Vector3 objects.

== History ==
* Article submitted (4/7/2007)

== C# - Matrix.cs ==
<syntaxhighlight lang="csharp">using UnityEngine;
using System.Collections;

public class Matrix : MonoBehaviour
{
public float[] m;

public Matrix()
{
}

// Loads this matrix with an identity matrix

{
m = new float[ 16 ];

for( int x = 0 ; x < 16 ; ++x )
{
m[ x ] = 0;
}

m [ 0 ] = 1;
m [ 5 ] = 1;
m [ 10 ] = 1;
m [ 15 ] = 1;
}

// Returns a translation matrix along the XYZ axes

public static Matrix Translate( float _X, float _Y, float _Z )
{
Matrix wk = new Matrix();

wk.m [ 12 ] = _X;
wk.m [ 13 ] = _Y;
wk.m [ 14 ] = _Z;

return wk;
}

// Returns a rotation matrix around the X axis

public static Matrix RotateX( float _Degree )
{
Matrix wk = new Matrix();

if( _Degree == 0 )
{
return wk;
}

float C = Mathf.Cos( _Degree * Mathf.Deg2Rad );
float S = Mathf.Sin( _Degree * Mathf.Deg2Rad );

wk.m [ 5 ] = C;
wk.m [ 6 ] = S;
wk.m [ 9 ] = -S;
wk.m [ 10 ] = C;

return wk;
}

// Returns a rotation matrix around the Y axis

public static Matrix RotateY( float _Degree )
{
Matrix wk = new Matrix();

if( _Degree == 0 )
{
return wk;
}

float C = Mathf.Cos( _Degree * Mathf.Deg2Rad );
float S = Mathf.Sin( _Degree * Mathf.Deg2Rad );

wk.m [ 0 ] = C;
wk.m [ 2 ] = -S;
wk.m [ 8 ] = S;
wk.m [ 10 ] = C;

return wk;
}

// Returns a rotation matrix around the Z axis

public static Matrix RotateZ( float _Degree )
{
Matrix wk = new Matrix();

if( _Degree == 0 )
{
return wk;
}

float C = Mathf.Cos( _Degree * Mathf.Deg2Rad );
float S = Mathf.Sin( _Degree * Mathf.Deg2Rad );

wk.m [ 0 ] = C;
wk.m [ 1 ] = S;
wk.m [ 4 ] = -S;
wk.m [ 5 ] = C;

return wk;
}

// Returns a scale matrix uniformly scaled on the XYZ axes

public static Matrix Scale( float _In )
{
return Matrix.Scale3D( _In, _In, _In );
}

// Returns a scale matrix scaled on the XYZ axes

public static Matrix Scale3D( float _X, float _Y, float _Z )
{
Matrix wk = new Matrix();

wk.m [ 0 ] = _X;
wk.m [ 5 ] = _Y;
wk.m [ 10 ] = _Z;

return wk;
}

// Transforms a vector with this matrix

public Vector3 TransformVector( Vector3 _V )
{
Vector3 vtx = new Vector3(0,0,0);

vtx.x = ( _V.x * m [ 0 ] ) + ( _V.y * m [ 4 ] ) + ( _V.z * m [ 8 ] ) + m [ 12 ];
vtx.y = ( _V.x * m [ 1 ] ) + ( _V.y * m [ 5 ] ) + ( _V.z * m [ 9 ] ) + m [ 13 ];
vtx.z = ( _V.x * m [ 2 ] ) + ( _V.y * m [ 6 ] ) + ( _V.z * m [ 10 ] ) + m [ 14 ];

return vtx;
}

public static Matrix operator *( Matrix _A, Matrix _B )
{
Matrix wk = new Matrix();

wk.m [ 0 ] = _A.m [ 0 ] * _B.m [ 0 ] + _A.m [ 4 ] * _B.m [ 1 ] + _A.m [ 8 ] * _B.m [ 2 ] + _A.m [ 12 ] * _B.m [ 3 ];
wk.m [ 4 ] = _A.m [ 0 ] * _B.m [ 4 ] + _A.m [ 4 ] * _B.m [ 5 ] + _A.m [ 8 ] * _B.m [ 6 ] + _A.m [ 12 ] * _B.m [ 7 ];
wk.m [ 8 ] = _A.m [ 0 ] * _B.m [ 8 ] + _A.m [ 4 ] * _B.m [ 9 ] + _A.m [ 8 ] * _B.m [ 10 ] + _A.m [ 12 ] * _B.m [ 11 ];
wk.m [ 12 ] = _A.m [ 0 ] * _B.m [ 12 ] + _A.m [ 4 ] * _B.m [ 13 ] + _A.m [ 8 ] * _B.m [ 14 ] + _A.m [ 12 ] * _B.m [ 15 ];

wk.m [ 1 ] = _A.m [ 1 ] * _B.m [ 0 ] + _A.m [ 5 ] * _B.m [ 1 ] + _A.m [ 9 ] * _B.m [ 2 ] + _A.m [ 13 ] * _B.m [ 3 ];
wk.m [ 5 ] = _A.m [ 1 ] * _B.m [ 4 ] + _A.m [ 5 ] * _B.m [ 5 ] + _A.m [ 9 ] * _B.m [ 6 ] + _A.m [ 13 ] * _B.m [ 7 ];
wk.m [ 9 ] = _A.m [ 1 ] * _B.m [ 8 ] + _A.m [ 5 ] * _B.m [ 9 ] + _A.m [ 9 ] * _B.m [ 10 ] + _A.m [ 13 ] * _B.m [ 11 ];
wk.m [ 13 ] = _A.m [ 1 ] * _B.m [ 12 ] + _A.m [ 5 ] * _B.m [ 13 ] + _A.m [ 9 ] * _B.m [ 14 ] + _A.m [ 13 ] * _B.m [ 15 ];

wk.m [ 2 ] = _A.m [ 2 ] * _B.m [ 0 ] + _A.m [ 6 ] * _B.m [ 1 ] + _A.m [ 10 ] * _B.m [ 2 ] + _A.m [ 14 ] * _B.m [ 3 ];
wk.m [ 6 ] = _A.m [ 2 ] * _B.m [ 4 ] + _A.m [ 6 ] * _B.m [ 5 ] + _A.m [ 10 ] * _B.m [ 6 ] + _A.m [ 14 ] * _B.m [ 7 ];
wk.m [ 10 ] = _A.m [ 2 ] * _B.m [ 8 ] + _A.m [ 6 ] * _B.m [ 9 ] + _A.m [ 10 ] * _B.m [ 10 ] + _A.m [ 14 ] * _B.m [ 11 ];
wk.m [ 14 ] = _A.m [ 2 ] * _B.m [ 12 ] + _A.m [ 6 ] * _B.m [ 13 ] + _A.m [ 10 ] * _B.m [ 14 ] + _A.m [ 14 ] * _B.m [ 15 ];

wk.m [ 3 ] = _A.m [ 3 ] * _B.m [ 0 ] + _A.m [ 7 ] * _B.m [ 1 ] + _A.m [ 11 ] * _B.m [ 2 ] + _A.m [ 15 ] * _B.m [ 3 ];
wk.m [ 7 ] = _A.m [ 3 ] * _B.m [ 4 ] + _A.m [ 7 ] * _B.m [ 5 ] + _A.m [ 11 ] * _B.m [ 6 ] + _A.m [ 15 ] * _B.m [ 7 ];
wk.m [ 11 ] = _A.m [ 3 ] * _B.m [ 8 ] + _A.m [ 7 ] * _B.m [ 9 ] + _A.m [ 11 ] * _B.m [ 10 ] + _A.m [ 15 ] * _B.m [ 11 ];
wk.m [ 15 ] = _A.m [ 3 ] * _B.m [ 12 ] + _A.m [ 7 ] * _B.m [ 13 ] + _A.m [ 11 ] * _B.m [ 14 ] + _A.m [ 15 ] * _B.m [ 15 ];

return wk;
}
}
</csharp>```