Last changed on Wednesday, 28th July; at 6:46pm (UTC+1)

Matrices

Matrices are really annoying me right now; I don't really understand them, and they're necessary for 3-dimensional game programming in XNA, a library for Direct X. I can use the built-in matrix class (just), but I felt I needed something more intuitive, so this is what I came up with:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;

namespace MyMatrix
{
    class MyMatrix
    {
        #region Private variables
        float[,] mMatrix;
        Vector3 mRot;
        Vector3 mScale;
        float fScale;
        #endregion

        ///
        /// Constructor for the MyMatrix class.
        ///

        public MyMatrix()
        {
            mMatrix = new float[4, 4];
            mRot = mScale = new Vector3(0, 0, 0);
            fScale = 0.0f;
        }

        #region Transformations

        ///
        /// Creates a rotation around all three axes.
        ///

        public Vector3 Rotation
        {
            get {return mRot;}
            set
            {
                float[,] XMat = new float[4, 4];
                float[,] YMat = new float[4, 4];
                float[,] ZMat = new float[4, 4];

                //The first expression in each mini-block ensures that the scale stays as 1 for the purposes of the rotation.

                XMat[0, 0] = 1;
                XMat[1, 1] = (float) Math.Cos(MathHelper.ToRadians(value.X));
                XMat[1, 2] = (float) Math.Sin(MathHelper.ToRadians(value.X));
                XMat[2, 1] = (float)-Math.Sin(MathHelper.ToRadians(value.X));
                XMat[2, 2] = (float) Math.Cos(MathHelper.ToRadians(value.X));

                YMat[1, 1] = 1;
                YMat[0, 0] = (float) Math.Cos(MathHelper.ToRadians(value.Y));
                YMat[0, 2] = (float) Math.Sin(MathHelper.ToRadians(value.Y));
                YMat[2, 0] = (float)-Math.Sin(MathHelper.ToRadians(value.Y));
                YMat[2, 2] = (float) Math.Cos(MathHelper.ToRadians(value.Y));

                ZMat[2, 2] = 1;
                ZMat[0, 0] = (float) Math.Cos(MathHelper.ToRadians(value.Z));
                ZMat[0, 1] = (float) Math.Sin(MathHelper.ToRadians(value.Z));
                ZMat[1, 0] = (float)-Math.Sin(MathHelper.ToRadians(value.Z));
                ZMat[1, 1] = (float) Math.Cos(MathHelper.ToRadians(value.Z));
                #region mMatrix += XMat*YMat*ZMat;
                mMatrix[0, 0] += XMat[0, 0] * YMat[0, 0] * ZMat[0, 0];
                mMatrix[0, 1] += XMat[0, 1] * YMat[0, 1] * ZMat[0, 1];
                mMatrix[0, 2] += XMat[0, 2] * YMat[0, 2] * ZMat[0, 2];

                mMatrix[1, 0] += XMat[1, 0] * YMat[1, 0] * ZMat[1, 0];
                mMatrix[1, 1] += XMat[1, 1] * YMat[1, 1] * ZMat[1, 1];
                mMatrix[1, 2] += XMat[1, 2] * YMat[1, 2] * ZMat[1, 2];

                mMatrix[2, 0] += XMat[2, 0] * YMat[2, 0] * ZMat[2, 0];
                mMatrix[2, 1] += XMat[2, 1] * YMat[2, 1] * ZMat[2, 1];
                mMatrix[2, 2] += XMat[2, 2] * YMat[2, 2] * ZMat[2, 2];
                #endregion
                mRot = value;
            }
        }

        ///
        /// Scales points relative to 0,0 on the grid using a vector
        ///

        public Vector3 Scale
        {
            get { return mScale; }
            set
            {
                mMatrix[0, 0] *= value.X;
                mMatrix[1, 1] *= value.Y;
                mMatrix[2, 2] *= value.Z;
            }
        }

        ///
        /// Scales in all directions by a certain amount.
        ///

        public float FScale
        {
            get {
                return fScale;
            }
            set {
                mMatrix[3, 3] = value;
                fScale = value;
            }
        }

        ///
        /// Moves the point by a certain amount in each direction, specified with a vector
        ///

        public Vector3 Translate
        {
            set
            {
                mMatrix[0, 3] += value.X;
                mMatrix[1, 3] += value.Y;
                mMatrix[2, 3] += value.Z;
            }
        }

        #endregion
        #region Operators used to apply the matrix to a Vector3

        static public Vector3 operator *(MyMatrix op1, Vector3 op2) {
            Vector3 tempVector;
            tempVector.X = ((op1.mMatrix[0, 0] * op2.X) + (op1.mMatrix[0, 1] * op2.Y) + (op1.mMatrix[0, 0] * op2.Z) + op1.mMatrix[0, 3]) / op1.mMatrix[3, 3];
            tempVector.Y = ((op1.mMatrix[1, 0] * op2.X) + (op1.mMatrix[1, 1] * op2.Y) + (op1.mMatrix[1, 0] * op2.Z) + op1.mMatrix[1, 3]) / op1.mMatrix[3, 3];
            tempVector.Z = ((op1.mMatrix[2, 0] * op2.X) + (op1.mMatrix[2, 1] * op2.Y) + (op1.mMatrix[2, 0] * op2.Z) + op1.mMatrix[2, 3]) / op1.mMatrix[3, 3];
            return tempVector;
        }

        static public Vector3 operator *(Vector3 op1, MyMatrix op2)
        {
            Vector3 tempVector;
            tempVector.X = ((op2.mMatrix[0, 0] * op1.X) + (op2.mMatrix[0, 1] * op1.Y) + (op2.mMatrix[0, 0] * op1.Z) + op2.mMatrix[0, 3]) / op2.mMatrix[3, 3];
            tempVector.Y = ((op2.mMatrix[1, 0] * op1.X) + (op2.mMatrix[1, 1] * op1.Y) + (op2.mMatrix[1, 0] * op1.Z) + op2.mMatrix[1, 3]) / op2.mMatrix[3, 3];
            tempVector.Z = ((op2.mMatrix[2, 0] * op1.X) + (op2.mMatrix[2, 1] * op1.Y) + (op2.mMatrix[2, 0] * op1.Z) + op2.mMatrix[2, 3]) / op2.mMatrix[3, 3];
            return tempVector;
        }

        #endregion
        #region Basic math operators for MyMatrix

        static public MyMatrix operator +(MyMatrix op1, MyMatrix op2)
        {
            MyMatrix TempMatrix;
            #region TempMatrix.mMatrix = op1.mMatrix + op2.mMatrix;

            TempMatrix.mMatrix[0, 0] = op1.mMatrix[0, 0] + op2.mMatrix[0, 0];
            TempMatrix.mMatrix[0, 1] = op1.mMatrix[0, 1] + op2.mMatrix[0, 1];
            TempMatrix.mMatrix[0, 2] = op1.mMatrix[0, 2] + op2.mMatrix[0, 2];
            TempMatrix.mMatrix[0, 3] = op1.mMatrix[0, 3] + op2.mMatrix[0, 3];

            TempMatrix.mMatrix[1, 0] = op1.mMatrix[1, 0] + op2.mMatrix[1, 0];
            TempMatrix.mMatrix[1, 1] = op1.mMatrix[1, 1] + op2.mMatrix[1, 1];
            TempMatrix.mMatrix[1, 2] = op1.mMatrix[1, 2] + op2.mMatrix[1, 2];
            TempMatrix.mMatrix[1, 3] = op1.mMatrix[1, 3] + op2.mMatrix[1, 3];

            TempMatrix.mMatrix[2, 0] = op1.mMatrix[2, 0] + op2.mMatrix[2, 0];
            TempMatrix.mMatrix[2, 1] = op1.mMatrix[2, 1] + op2.mMatrix[2, 1];
            TempMatrix.mMatrix[2, 2] = op1.mMatrix[2, 2] + op2.mMatrix[2, 2];
            TempMatrix.mMatrix[2, 3] = op1.mMatrix[2, 3] + op2.mMatrix[2, 3];

            #endregion
            return TempMatrix;
        }

        static public MyMatrix operator -(MyMatrix op1, MyMatrix op2)
        {
            MyMatrix TempMatrix;
            #region TempMatrix.mMatrix = op1.mMatrix - op2.mMatrix;

            TempMatrix.mMatrix[0, 0] = op1.mMatrix[0, 0] - op2.mMatrix[0, 0];
            TempMatrix.mMatrix[0, 1] = op1.mMatrix[0, 1] - op2.mMatrix[0, 1];
            TempMatrix.mMatrix[0, 2] = op1.mMatrix[0, 2] - op2.mMatrix[0, 2];
            TempMatrix.mMatrix[0, 3] = op1.mMatrix[0, 3] - op2.mMatrix[0, 3];

            TempMatrix.mMatrix[1, 0] = op1.mMatrix[1, 0] - op2.mMatrix[1, 0];
            TempMatrix.mMatrix[1, 1] = op1.mMatrix[1, 1] - op2.mMatrix[1, 1];
            TempMatrix.mMatrix[1, 2] = op1.mMatrix[1, 2] - op2.mMatrix[1, 2];
            TempMatrix.mMatrix[1, 3] = op1.mMatrix[1, 3] - op2.mMatrix[1, 3];

            TempMatrix.mMatrix[2, 0] = op1.mMatrix[2, 0] - op2.mMatrix[2, 0];
            TempMatrix.mMatrix[2, 1] = op1.mMatrix[2, 1] - op2.mMatrix[2, 1];
            TempMatrix.mMatrix[2, 2] = op1.mMatrix[2, 2] - op2.mMatrix[2, 2];
            TempMatrix.mMatrix[2, 3] = op1.mMatrix[2, 3] - op2.mMatrix[2, 3];

            #endregion
            return TempMatrix;
        }

        static public MyMatrix operator *(MyMatrix op1, MyMatrix op2)
        {
            MyMatrix TempMatrix;
            #region TempMatrix.mMatrix = op1.mMatrix * op2.mMatrix;

            TempMatrix.mMatrix[0, 0] = op1.mMatrix[0, 0] * op2.mMatrix[0, 0];
            TempMatrix.mMatrix[0, 1] = op1.mMatrix[0, 1] * op2.mMatrix[0, 1];
            TempMatrix.mMatrix[0, 2] = op1.mMatrix[0, 2] * op2.mMatrix[0, 2];
            TempMatrix.mMatrix[0, 3] = op1.mMatrix[0, 3] * op2.mMatrix[0, 3];

            TempMatrix.mMatrix[1, 0] = op1.mMatrix[1, 0] * op2.mMatrix[1, 0];
            TempMatrix.mMatrix[1, 1] = op1.mMatrix[1, 1] * op2.mMatrix[1, 1];
            TempMatrix.mMatrix[1, 2] = op1.mMatrix[1, 2] * op2.mMatrix[1, 2];
            TempMatrix.mMatrix[1, 3] = op1.mMatrix[1, 3] * op2.mMatrix[1, 3];

            TempMatrix.mMatrix[2, 0] = op1.mMatrix[2, 0] * op2.mMatrix[2, 0];
            TempMatrix.mMatrix[2, 1] = op1.mMatrix[2, 1] * op2.mMatrix[2, 1];
            TempMatrix.mMatrix[2, 2] = op1.mMatrix[2, 2] * op2.mMatrix[2, 2];
            TempMatrix.mMatrix[2, 3] = op1.mMatrix[2, 3] * op2.mMatrix[2, 3];

            #endregion
            return TempMatrix;
        }
        static public MyMatrix operator /(MyMatrix op1, MyMatrix op2)
        {
            MyMatrix TempMatrix;
            #region TempMatrix.mMatrix = op1.mMatrix / op2.mMatrix;

            TempMatrix.mMatrix[0, 0] = op1.mMatrix[0, 0] / op2.mMatrix[0, 0];
            TempMatrix.mMatrix[0, 1] = op1.mMatrix[0, 1] / op2.mMatrix[0, 1];
            TempMatrix.mMatrix[0, 2] = op1.mMatrix[0, 2] / op2.mMatrix[0, 2];
            TempMatrix.mMatrix[0, 3] = op1.mMatrix[0, 3] / op2.mMatrix[0, 3];

            TempMatrix.mMatrix[1, 0] = op1.mMatrix[1, 0] / op2.mMatrix[1, 0];
            TempMatrix.mMatrix[1, 1] = op1.mMatrix[1, 1] / op2.mMatrix[1, 1];
            TempMatrix.mMatrix[1, 2] = op1.mMatrix[1, 2] / op2.mMatrix[1, 2];
            TempMatrix.mMatrix[1, 3] = op1.mMatrix[1, 3] / op2.mMatrix[1, 3];

            TempMatrix.mMatrix[2, 0] = op1.mMatrix[2, 0] / op2.mMatrix[2, 0];
            TempMatrix.mMatrix[2, 1] = op1.mMatrix[2, 1] / op2.mMatrix[2, 1];
            TempMatrix.mMatrix[2, 2] = op1.mMatrix[2, 2] / op2.mMatrix[2, 2];
            TempMatrix.mMatrix[2, 3] = op1.mMatrix[2, 3] / op2.mMatrix[2, 3];

            #endregion
            return TempMatrix;
        }

        #endregion
    }

}