public void TransformNormalize(Matrix3 m)
 {
     float[] result = m.VectorMultiply (new float[4] { X, Y, Z, W });
     X = result [0] / result [3];
     Y = result [1] / result [3];
     Z = result [2];
     W = 1;
 }
 public Point3[] CircleCoordinates(float y)
 {
     Point3[] pts = new Point3[30];
     Matrix3 m = new Matrix3 ();
     for (int i = 0; i < pts.Length; i++) {
         pts [i] = m.Cylindrical (r, i * 360 / (pts.Length - 1), y);
     }
     return pts;
 }
 // Multiply two matrices together:
 public static Matrix3 operator *(Matrix3 m1, Matrix3 m2)
 {
     Matrix3 result = new Matrix3 ();
     for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
             float element = 0;
             for (int k = 0; k < 4; k++) {
                 element += m1.M [i, k] * m2.M [k, j];
             }
             result.M [i, j] = element;
         }
     }
     return result;
 }
 // Axonometric projection matrix:
 public static Matrix3 Axonometric(float alpha, float beta)
 {
     Matrix3 result = new Matrix3 ();
     float sna = (float)Math.Sin (alpha * Math.PI / 180);
     float cna = (float)Math.Cos (alpha * Math.PI / 180);
     float snb = (float)Math.Sin (beta * Math.PI / 180);
     float cnb = (float)Math.Cos (beta * Math.PI / 180);
     result.M [0, 0] = cnb;
     result.M [0, 2] = snb;
     result.M [1, 0] = sna * snb;
     result.M [1, 1] = cna;
     result.M [1, 2] = -sna * cnb;
     result.M [2, 2] = 0;
     return result;
 }
 // Oblique projection matrix:
 public static Matrix3 Oblique(float alpha, float theta)
 {
     Matrix3 result = new Matrix3 ();
     float ta = (float)Math.Tan (alpha * Math.PI / 180);
     float snt = (float)Math.Sin (theta * Math.PI / 180);
     float cnt = (float)Math.Cos (theta * Math.PI / 180);
     result.M [0, 2] = -cnt / ta;
     result.M [1, 2] = -snt / ta;
     result.M [2, 2] = 0;
     return result;
 }
 // Front view projection matrix:
 public static Matrix3 FrontView()
 {
     Matrix3 result = new Matrix3 ();
     result.M [2, 2] = 0;
     return result;
 }
 // Create a translation matrix
 public static Matrix3 Translate3(float dx, float dy, float dz)
 {
     Matrix3 result = new Matrix3 ();
     result.M [0, 3] = dx;
     result.M [1, 3] = dy;
     result.M [2, 3] = dz;
     return result;
 }
 // Top view projection matrix:
 public static Matrix3 TopView()
 {
     Matrix3 result = new Matrix3 ();
     result.M [1, 1] = 0;
     result.M [2, 2] = 0;
     result.M [1, 2] = -1;
     return result;
 }
 // Side view projection matrix:
 public static Matrix3 SideView()
 {
     Matrix3 result = new Matrix3 ();
     result.M [0, 0] = 0;
     result.M [2, 2] = 0;
     result.M [0, 2] = -1;
     return result;
 }
 // Create a scaling matrix:
 public static Matrix3 Scale3(float sx, float sy, float sz)
 {
     Matrix3 result = new Matrix3 ();
     result.M [0, 0] = sx;
     result.M [1, 1] = sy;
     result.M [2, 2] = sz;
     return result;
 }
 // Create a rotation matrix around the z axis:
 public static Matrix3 Rotate3Z(float theta)
 {
     theta = theta * (float)Math.PI / 180.0f;
     float sn = (float)Math.Sin (theta);
     float cn = (float)Math.Cos (theta);
     Matrix3 result = new Matrix3 ();
     result.M [0, 0] = cn;
     result.M [0, 1] = -sn;
     result.M [1, 0] = sn;
     result.M [1, 1] = cn;
     return result;
 }
 // Perspective projection matrix:
 public static Matrix3 Perspective(float d)
 {
     Matrix3 result = new Matrix3 ();
     result.M [3, 2] = -1 / d;
     return result;
 }