Matrix

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removing all content from page)
m (Reverted edits by Joseph05408 (Talk); changed back to last version by Willem)
Line 1: Line 1:
 +
[[Category: Concepts]]
 +
[[Category: Math]]
 +
[[Category: C Sharp]]
 +
== 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.
 +
 +
<csharp>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:
 +
 +
<csharp>Matrix mat = Matrix.RotateY( 15.0f );
 +
 +
object.transform.position = mat.TransformVector( object.transform.position );
 +
</csharp>
 +
 +
Or even:
 +
 +
<csharp>object.transform.position = Matrix.RotateY( 15.0f ).TransformVector( object.transform.position );
 +
</csharp>
 +
 +
It all depends on what your code readability tolerance is.
 +
 +
* '''Rotate Around Pitch And Yaw''' - Rotate an object around both it's X and Y axes.
 +
 +
<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:
 +
 +
<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.
 +
 +
<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:
 +
 +
<csharp>Matrix mat = new Matrix();
 +
mat *= Matrix.Scale( 2.0f );
 +
mat *= Matrix.Translate( 64.0f, 0.0f, 0.0f );
 +
</csharp>
 +
 +
Into this:
 +
 +
<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 ==
 +
<csharp>using UnityEngine;
 +
using System.Collections;
 +
 +
public class Matrix : MonoBehaviour
 +
{
 +
    public float[] m;
 +
 +
    public Matrix()
 +
    { 
 +
        LoadIdentity();
 +
    } 
 +
 +
    // Loads this matrix with an identity matrix
 +
 +
    public void LoadIdentity()
 +
    {
 +
        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;
 +
    }
 +
 +
    // Overloaded operators
 +
 +
    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>

Revision as of 19:04, 19 October 2009

Contents

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.

<csharp>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:

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

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

Or even:

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

It all depends on what your code readability tolerance is.

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

<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:

<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.

<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:

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

Into this:

<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

<csharp>using UnityEngine; using System.Collections;

public class Matrix : MonoBehaviour {

   public float[] m;
   public Matrix()
   {   
       LoadIdentity();
   }   
   // Loads this matrix with an identity matrix
   public void LoadIdentity()
   {
       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;
   }
   // Overloaded operators
   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>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox