public static CG_Matrix ViewSpace(ref Vector3Df Eye, ref Vector3Df Target, ref Vector3Df UpVector)
            {
                CG_Matrix result     = CG_Matrix.Zero();
                Vector3Df VDirection = (Target - Eye);

                VDirection = VDirection.UnitVector();


                Vector3Df RightDirection = Vector3Df.CrossProduct(ref VDirection, ref UpVector);

                RightDirection = RightDirection.UnitVector();
                Vector3Df UpDirection = Vector3Df.CrossProduct(ref RightDirection, ref VDirection);

                UpDirection = UpDirection.UnitVector();

                result.col[0][0] = RightDirection.X;
                result.col[1][0] = RightDirection.Y;
                result.col[2][0] = RightDirection.Z;

                result.col[0][1] = UpDirection.X;
                result.col[1][1] = UpDirection.Y;
                result.col[2][1] = UpDirection.Z;

                result.col[0][2] = -1 * VDirection.X;
                result.col[1][2] = -1 * VDirection.Y;
                result.col[2][2] = -1 * VDirection.Z;

                result.col[3][0] = -1 * Vector3Df.DotProduct(ref RightDirection, ref Eye);
                result.col[3][1] = -1 * Vector3Df.DotProduct(ref UpDirection, ref Eye);
                result.col[3][2] = Vector3Df.DotProduct(ref VDirection, ref Eye);

                result.col[3][3] = 1;

                return(result);
            }
            public static CG_Matrix PerspectiveProjection(float left,
                                                          float right,
                                                          float top,
                                                          float bottom,
                                                          float near,
                                                          float far)
            {
                float invRDiff = 1 / (right - left + float.Epsilon);
                float invUDiff = 1 / (top - bottom + float.Epsilon);
                float invDDiff = 1 / (far - near + float.Epsilon);

                CG_Matrix result = CG_Matrix.Zero();

                result.col[0][0] = 2 * near * invRDiff;

                result.col[1][1] = 2 * near * invUDiff;

                result.col[2][0] = (right + left) * invRDiff;
                result.col[2][1] = (top + bottom) * invUDiff;
                result.col[2][2] = -1 * (far + near) * invDDiff;
                result.col[2][3] = -1;

                result.col[3][2] = -2 * (far * near) * invDDiff;

                return(result);
            }
            public static CG_Matrix ScaleMatrix(ref Vector3Df Location, float Scale)
            {
                CG_Matrix result = new CG_Matrix(Scale);

                result.col[3][3] = 1;
                result.col[3][0] = Location.X;
                result.col[3][1] = Location.Y;
                result.col[3][2] = Location.Z;
                return(result);
            }
            public static CG_Matrix FromMattrix44(ref CG_Matrix Org)
            {
                CG_Matrix result = CG_Matrix.Zero();

                for (int c = 0; c < 4; c++)
                {
                    for (int r = 0; r < 4; r++)
                    {
                        result.col[c][r] = Org.col[c][r];
                    }
                }
                return(result);
            }
            public static CG_Matrix operator *(CG_Matrix lfs, CG_Matrix rhs)
            {
                CG_Matrix result = new CG_Matrix(0.0f);

                for (int r = 0; r < 4; r++)
                {
                    for (int c = 0; c < 4; c++)
                    {
                        for (int k = 0; k < 4; k++)
                        {
                            result.col[c][r] += lfs.col[k][r] * rhs.col[c][k];
                        }
                    }
                }
                return(result);
            }
            public static CG_Matrix ScaleMatrix(ref Vector3Df Location, ref Vector3Df Scale)
            {
                CG_Matrix result = CG_Matrix.Identity();

                //Matrix_33 M = Matrix_33.Zero();
                result.col[0][0] = Scale.X;
                result.col[1][1] = Scale.Y;
                result.col[2][2] = Scale.Z;

                result.col[3][3] = 1;
                result.col[3][0] = Location.X;
                result.col[3][1] = Location.Y;
                result.col[3][2] = Location.Z;

                return(result);
            }
            public static CG_Matrix Intialize(double[] List)
            {
                if (List.Length != 16)
                {
                    throw new ArgumentException("Initialization List != 16");
                }
                CG_Matrix result = CG_Matrix.Zero();

                for (int i = 0; i < List.Length; i++)
                {
                    int c = i / 4;
                    int r = i - (4 * c);
                    result.col[c][r] = (float)List[i];
                }
                return(result);
            }
            public static CG_Matrix OrthographicProjection(float left, float right, float top, float bottom, float near, float far)
            {
                float invRDiff = 1 / (right - left);
                float invUDiff = 1 / (top - bottom);
                float invDDiff = 1 / (far - near);

                CG_Matrix result = CG_Matrix.Zero();

                result.col[0][0] = 2 * invRDiff;
                result.col[3][0] = -1 * (right + left) * invRDiff;
                result.col[1][1] = 2 * invUDiff;
                result.col[3][1] = -1 * (top + bottom) * invUDiff;
                result.col[2][2] = -2 * invDDiff;
                result.col[3][2] = -1 * (far + near) * invDDiff;
                result.col[3][3] = 1;
                return(result);
            }
 public static CG_Matrix op_MultiplicationAssignment(CG_Matrix lfs, CG_Matrix rhs)
 {
     lfs = lfs * rhs;
     return(lfs);
 }
            public CG_Matrix Inverse()
            {
                CG_Matrix result = CG_Matrix.Identity();
                CG_Matrix Ref    = CG_Matrix.FromMattrix44(ref this);

                for (int colm = 0; colm < Ref.col.Length; colm++)
                {
                    for (int row = colm; row < Ref.col.Length; row++)
                    {
                        if (row == colm)
                        {
                            #region Create Diagnal with a magnitiude of 1
                            if (Ref.col[colm][row] == 0)
                            {
                                int  i      = row + 1;
                                bool Swaped = false;
                                while (i < 4)
                                {
                                    if (Ref.col[colm][i] != 0)
                                    {
                                        Ref.SwapRows(row, i);
                                        result.SwapRows(row, i);
                                        Swaped = true;
                                        break;
                                    }
                                }
                                if (!Swaped)
                                {
                                    throw new Exception("Non Invertable Matrix");
                                }
                            }
                            if (Ref.col[colm][row] != 1)
                            {
                                float nScale = -1 / Ref.col[colm][row];
                                Ref.ScaleRow(row, nScale);
                                result.ScaleRow(row, nScale);
                            }
                            #endregion
                        }
                        else
                        {
                            #region Deal with the lower triangle
                            if (Ref.col[colm][row] != 0)
                            {
                                float nScale = 1 / Ref.col[colm][row];
                                Ref.AddRows(row, colm, nScale);
                                result.AddRows(row, colm, nScale);
                            }
                            #endregion
                        }
                    }
                    for (int row = 0; row < colm; row++)
                    {
                        #region Deal with the Upper triangle
                        if (Ref.col[colm][row] != 0)
                        {
                            float nScale = -1 / Ref.col[colm][row];
                            Ref.AddRows(row, colm, nScale);
                            result.AddRows(row, colm, nScale);
                        }
                        #endregion
                    }
                }
                return(result);
            }