using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BauzoidNET
.math
{
public class Matrix4
{
public const int M11
= 0;
public const int M21
= 1;
public const int M31
= 2;
public const int M41
= 3;
public const int M12
= 4;
public const int M22
= 5;
public const int M32
= 6;
public const int M42
= 7;
public const int M13
= 8;
public const int M23
= 9;
public const int M33
= 10;
public const int M43
= 11;
public const int M14
= 12;
public const int M24
= 13;
public const int M34
= 14;
public const int M44
= 15;
public const int MATRIX_SIZE
= 4;
public float[] values
= new float[MATRIX_SIZE
*MATRIX_SIZE
];
public Matrix4
()
{
}
/** Copy constructor. */
public Matrix4
(Matrix4 b
)
{
for (int i
= 0; i
< values
.Length; i
++)
this.values[i
] = b
.values[i
];
}
public Matrix4
(float[] m
)
{
for (int i
= 0; i
< values
.Length; i
++)
this.values[i
] = m
[i
];
}
public float get
(int row,
int col
)
{
return values
[col
*MATRIX_SIZE
+ row
];
}
public void set
(int row,
int col,
float value
)
{
values
[col
*MATRIX_SIZE
+ row
] = value
;
}
public void zero
()
{
for (int i
= 0; i
< values
.Length; i
++)
values
[i
] = 0
.0f
;
}
public void identity
()
{
zero
();
values
[M11
] = 1
.0f
; values
[M22
] = 1
.0f
; values
[M33
] = 1
.0f
; values
[M44
] = 1
.0f
;
}
public bool equals
(Matrix4 other
)
{
for (int i
= 0; i
< values
.Length; i
++)
{
if (this.values[i
] != other
.values[i
])
return false;
}
return true;
}
public bool isSingular
()
{
float determinant
= getDeterminant
();
return ((float)Math
.Abs(determinant
) < MathUtil
.EPSILON);
}
public Matrix4 getTranspose
()
{
Matrix4 result
= new Matrix4
();
for (int row
= 0; row
< MATRIX_SIZE
; row
++)
{
for (int col
= 0; col
< MATRIX_SIZE
; col
++)
{
float v
= this.get(row, col
);
this.set(col, row, v
);
}
}
return result
;
}
public float getDeterminant
()
{
float result
=
values
[M14
] * values
[M23
] * values
[M32
] * values
[M41
] -
values
[M13
] * values
[M24
] * values
[M32
] * values
[M41
] -
values
[M14
] * values
[M22
] * values
[M33
] * values
[M41
] +
values
[M12
] * values
[M24
] * values
[M33
] * values
[M41
] +
values
[M13
] * values
[M22
] * values
[M34
] * values
[M41
] -
values
[M12
] * values
[M23
] * values
[M34
] * values
[M41
] -
values
[M14
] * values
[M23
] * values
[M31
] * values
[M42
] +
values
[M13
] * values
[M24
] * values
[M31
] * values
[M42
] +
values
[M14
] * values
[M21
] * values
[M33
] * values
[M42
] -
values
[M11
] * values
[M24
] * values
[M33
] * values
[M42
] -
values
[M13
] * values
[M21
] * values
[M34
] * values
[M42
] +
values
[M11
] * values
[M23
] * values
[M34
] * values
[M42
] +
values
[M14
] * values
[M22
] * values
[M31
] * values
[M43
] -
values
[M12
] * values
[M24
] * values
[M31
] * values
[M43
] -
values
[M14
] * values
[M21
] * values
[M32
] * values
[M43
] +
values
[M11
] * values
[M24
] * values
[M32
] * values
[M43
] +
values
[M12
] * values
[M21
] * values
[M34
] * values
[M43
] -
values
[M11
] * values
[M22
] * values
[M34
] * values
[M43
] -
values
[M13
] * values
[M22
] * values
[M31
] * values
[M44
] +
values
[M12
] * values
[M23
] * values
[M31
] * values
[M44
] +
values
[M13
] * values
[M21
] * values
[M32
] * values
[M44
] -
values
[M11
] * values
[M23
] * values
[M32
] * values
[M44
] -
values
[M12
] * values
[M21
] * values
[M33
] * values
[M44
] +
values
[M11
] * values
[M22
] * values
[M33
] * values
[M44
];
return result
;
}
public Matrix4 getInverse
()
{
Matrix4 result
= new Matrix4
();
float determinant
= getDeterminant
();
if (determinant
== 0
.0f
)
{
// singular matrix cannot be inverted
return this;
}
result
.values[M11
] = values
[M23
] * values
[M34
] * values
[M42
]
- values
[M24
] * values
[M33
] * values
[M42
]
+ values
[M24
] * values
[M32
] * values
[M43
]
- values
[M22
] * values
[M34
] * values
[M43
]
- values
[M23
] * values
[M32
] * values
[M44
]
+ values
[M22
] * values
[M33
] * values
[M44
];
result
.values[M12
] = values
[M14
] * values
[M33
] * values
[M42
]
- values
[M13
] * values
[M34
] * values
[M42
]
- values
[M14
] * values
[M32
] * values
[M43
]
+ values
[M12
] * values
[M34
] * values
[M43
]
+ values
[M13
] * values
[M32
] * values
[M44
]
- values
[M12
] * values
[M33
] * values
[M44
];
result
.values[M13
] = values
[M13
] * values
[M24
] * values
[M42
]
- values
[M14
] * values
[M23
] * values
[M42
]
+ values
[M14
] * values
[M22
] * values
[M43
]
- values
[M12
] * values
[M24
] * values
[M43
]
- values
[M13
] * values
[M22
] * values
[M44
]
+ values
[M12
] * values
[M23
] * values
[M44
];
result
.values[M14
] = values
[M14
] * values
[M23
] * values
[M32
]
- values
[M13
] * values
[M24
] * values
[M32
]
- values
[M14
] * values
[M22
] * values
[M33
]
+ values
[M12
] * values
[M24
] * values
[M33
]
+ values
[M13
] * values
[M22
] * values
[M34
]
- values
[M12
] * values
[M23
] * values
[M34
];
result
.values[M21
] = values
[M24
] * values
[M33
] * values
[M41
]
- values
[M23
] * values
[M34
] * values
[M41
]
- values
[M24
] * values
[M31
] * values
[M43
]
+ values
[M21
] * values
[M34
] * values
[M43
]
+ values
[M23
] * values
[M31
] * values
[M44
]
- values
[M21
] * values
[M33
] * values
[M44
];
result
.values[M22
] = values
[M13
] * values
[M34
] * values
[M41
]
- values
[M14
] * values
[M33
] * values
[M41
]
+ values
[M14
] * values
[M31
] * values
[M43
]
- values
[M11
] * values
[M34
] * values
[M43
]
- values
[M13
] * values
[M31
] * values
[M44
]
+ values
[M11
] * values
[M33
] * values
[M44
];
result
.values[M23
] = values
[M14
] * values
[M23
] * values
[M41
]
- values
[M13
] * values
[M24
] * values
[M41
]
- values
[M14
] * values
[M21
] * values
[M43
]
+ values
[M11
] * values
[M24
] * values
[M43
]
+ values
[M13
] * values
[M21
] * values
[M44
]
- values
[M11
] * values
[M23
] * values
[M44
];
result
.values[M24
] = values
[M13
] * values
[M24
] * values
[M31
]
- values
[M14
] * values
[M23
] * values
[M31
]
+ values
[M14
] * values
[M21
] * values
[M33
]
- values
[M11
] * values
[M24
] * values
[M33
]
- values
[M13
] * values
[M21
] * values
[M34
]
+ values
[M11
] * values
[M23
] * values
[M34
];
result
.values[M31
] = values
[M22
] * values
[M34
] * values
[M41
]
- values
[M24
] * values
[M32
] * values
[M41
]
+ values
[M24
] * values
[M31
] * values
[M42
]
- values
[M21
] * values
[M34
] * values
[M42
]
- values
[M22
] * values
[M31
] * values
[M44
]
+ values
[M21
] * values
[M32
] * values
[M44
];
result
.values[M32
] = values
[M14
] * values
[M32
] * values
[M41
]
- values
[M12
] * values
[M34
] * values
[M41
]
- values
[M14
] * values
[M31
] * values
[M42
]
+ values
[M11
] * values
[M34
] * values
[M42
]
+ values
[M12
] * values
[M31
] * values
[M44
]
- values
[M11
] * values
[M32
] * values
[M44
];
result
.values[M33
] = values
[M12
] * values
[M24
] * values
[M41
]
- values
[M14
] * values
[M22
] * values
[M41
]
+ values
[M14
] * values
[M21
] * values
[M42
]
- values
[M11
] * values
[M24
] * values
[M42
]
- values
[M12
] * values
[M21
] * values
[M44
]
+ values
[M11
] * values
[M22
] * values
[M44
];
result
.values[M34
] = values
[M14
] * values
[M22
] * values
[M31
]
- values
[M12
] * values
[M24
] * values
[M31
]
- values
[M14
] * values
[M21
] * values
[M32
]
+ values
[M11
] * values
[M24
] * values
[M32
]
+ values
[M12
] * values
[M21
] * values
[M34
]
- values
[M11
] * values
[M22
] * values
[M34
];
result
.values[M41
] = values
[M23
] * values
[M32
] * values
[M41
]
- values
[M22
] * values
[M33
] * values
[M41
]
- values
[M23
] * values
[M31
] * values
[M42
]
+ values
[M21
] * values
[M33
] * values
[M42
]
+ values
[M22
] * values
[M31
] * values
[M43
]
- values
[M21
] * values
[M32
] * values
[M43
];
result
.values[M42
] = values
[M12
] * values
[M33
] * values
[M41
]
- values
[M13
] * values
[M32
] * values
[M41
]
+ values
[M13
] * values
[M31
] * values
[M42
]
- values
[M11
] * values
[M33
] * values
[M42
]
- values
[M12
] * values
[M31
] * values
[M43
]
+ values
[M11
] * values
[M32
] * values
[M43
];
result
.values[M43
] = values
[M13
] * values
[M22
] * values
[M41
]
- values
[M12
] * values
[M23
] * values
[M41
]
- values
[M13
] * values
[M21
] * values
[M42
]
+ values
[M11
] * values
[M23
] * values
[M42
]
+ values
[M12
] * values
[M21
] * values
[M43
]
- values
[M11
] * values
[M22
] * values
[M43
];
result
.values[M44
] = values
[M12
] * values
[M23
] * values
[M31
]
- values
[M13
] * values
[M22
] * values
[M31
]
+ values
[M13
] * values
[M21
] * values
[M32
]
- values
[M11
] * values
[M23
] * values
[M32
]
- values
[M12
] * values
[M21
] * values
[M33
]
+ values
[M11
] * values
[M22
] * values
[M33
];
float multiply
= 1
.0f
/ determinant
;
for (int i
= 0; i
< values
.Length; i
++)
result
.values[i
] *= multiply
;
return result
;
}
public void copyTo
(Matrix4 target
)
{
for (int i
= 0; i
< values
.Length; i
++)
target
.values[i
] = this.values[i
];
}
public void copyFrom
(Matrix4 source
)
{
for (int i
= 0; i
< values
.Length; i
++)
this.values[i
] = source
.values[i
];
}
public void postMultiply
(Matrix4 v
)
{
multiply
(this,
this, v
);
}
public void preMultiply
(Matrix4 v
)
{
multiply
(this, v,
this);
}
static public void multiply
(Matrix4 result, Matrix4 a, Matrix4 b
)
{
float result11
= a
.values[M11
] * b
.values[M11
] + a
.values[M21
] * b
.values[M12
] + a
.values[M31
] * b
.values[M13
] + a
.values[M41
] * b
.values[M14
];
float result21
= a
.values[M11
] * b
.values[M21
] + a
.values[M21
] * b
.values[M22
] + a
.values[M31
] * b
.values[M23
] + a
.values[M41
] * b
.values[M24
];
float result31
= a
.values[M11
] * b
.values[M31
] + a
.values[M21
] * b
.values[M32
] + a
.values[M31
] * b
.values[M33
] + a
.values[M41
] * b
.values[M34
];
float result41
= a
.values[M11
] * b
.values[M41
] + a
.values[M21
] * b
.values[M42
] + a
.values[M31
] * b
.values[M43
] + a
.values[M41
] * b
.values[M44
];
float result12
= a
.values[M12
] * b
.values[M11
] + a
.values[M22
] * b
.values[M12
] + a
.values[M32
] * b
.values[M13
] + a
.values[M42
] * b
.values[M14
];
float result22
= a
.values[M12
] * b
.values[M21
] + a
.values[M22
] * b
.values[M22
] + a
.values[M32
] * b
.values[M23
] + a
.values[M42
] * b
.values[M24
];
float result32
= a
.values[M12
] * b
.values[M31
] + a
.values[M22
] * b
.values[M32
] + a
.values[M32
] * b
.values[M33
] + a
.values[M42
] * b
.values[M34
];
float result42
= a
.values[M12
] * b
.values[M41
] + a
.values[M22
] * b
.values[M42
] + a
.values[M32
] * b
.values[M43
] + a
.values[M42
] * b
.values[M44
];
float result13
= a
.values[M13
] * b
.values[M11
] + a
.values[M23
] * b
.values[M12
] + a
.values[M33
] * b
.values[M13
] + a
.values[M43
] * b
.values[M14
];
float result23
= a
.values[M13
] * b
.values[M21
] + a
.values[M23
] * b
.values[M22
] + a
.values[M33
] * b
.values[M23
] + a
.values[M43
] * b
.values[M24
];
float result33
= a
.values[M13
] * b
.values[M31
] + a
.values[M23
] * b
.values[M32
] + a
.values[M33
] * b
.values[M33
] + a
.values[M43
] * b
.values[M34
];
float result43
= a
.values[M13
] * b
.values[M41
] + a
.values[M23
] * b
.values[M42
] + a
.values[M33
] * b
.values[M43
] + a
.values[M43
] * b
.values[M44
];
float result14
= a
.values[M14
] * b
.values[M11
] + a
.values[M24
] * b
.values[M12
] + a
.values[M34
] * b
.values[M13
] + a
.values[M44
] * b
.values[M14
];
float result24
= a
.values[M14
] * b
.values[M21
] + a
.values[M24
] * b
.values[M22
] + a
.values[M34
] * b
.values[M23
] + a
.values[M44
] * b
.values[M24
];
float result34
= a
.values[M14
] * b
.values[M31
] + a
.values[M24
] * b
.values[M32
] + a
.values[M34
] * b
.values[M33
] + a
.values[M44
] * b
.values[M34
];
float result44
= a
.values[M14
] * b
.values[M41
] + a
.values[M24
] * b
.values[M42
] + a
.values[M34
] * b
.values[M43
] + a
.values[M44
] * b
.values[M44
];
result
.values[M11
] = result11
;
result
.values[M21
] = result21
;
result
.values[M31
] = result31
;
result
.values[M41
] = result41
;
result
.values[M12
] = result12
;
result
.values[M22
] = result22
;
result
.values[M32
] = result32
;
result
.values[M42
] = result42
;
result
.values[M13
] = result13
;
result
.values[M23
] = result23
;
result
.values[M33
] = result33
;
result
.values[M43
] = result43
;
result
.values[M14
] = result14
;
result
.values[M24
] = result24
;
result
.values[M34
] = result34
;
result
.values[M44
] = result44
;
}
static public Matrix4 multiply
(Matrix4 a, Matrix4 b
)
{
Matrix4 result
= new Matrix4
();
multiply
(result, a, b
);
return result
;
}
public void multiply
(Matrix4 other
)
{
Matrix4
.multiply(this,
this, other
);
}
static public Matrix4 createIdentity
()
{
return createScale
(1
.0f, 1
.0f, 1
.0f
);
}
static public Matrix4 createScale
(float sx,
float sy,
float sz
)
{
Matrix4 result
= new Matrix4
();
result
.setScale(sx, sy, sz
);
return result
;
}
static public Matrix4 createScale
(Vector3 scale
)
{
return createScale
(scale
.x, scale
.y, scale
.z);
}
static public Matrix4 createScale
(float s
)
{
return createScale
(s, s, s
);
}
public void setScale
(float sx,
float sy,
float sz
)
{
zero
();
this.values[M11
] = sx
;
this.values[M22
] = sy
;
this.values[M33
] = sz
;
this.values[M44
] = 1
.0f
;
}
public void setScale
(Vector3 scale
)
{
setScale
(scale
.x, scale
.y, scale
.z);
}
public void setScale
(float s
)
{
setScale
(s, s, s
);
}
static public Matrix4 createRotationX
(float degrees
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setRotationX(degrees
);
return matrix
;
}
public void setRotationX
(float degrees
)
{
float degreesrad
= MathUtil
.degToRad(degrees
);
float sinvalue
= (float)Math
.Sin(degreesrad
);
float cosvalue
= (float)Math
.Cos(degreesrad
);
this.identity();
this.values[M22
] = cosvalue
;
this.values[M32
] = -sinvalue
;
this.values[M23
] = sinvalue
;
this.values[M33
] = cosvalue
;
}
static public Matrix4 createRotationY
(float degrees
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setRotationY(degrees
);
return matrix
;
}
public void setRotationY
(float degrees
)
{
float degreesrad
= MathUtil
.degToRad(degrees
);
float sinvalue
= (float)Math
.Sin(degreesrad
);
float cosvalue
= (float)Math
.Cos(degreesrad
);
this.identity();
this.values[M11
] = cosvalue
;
this.values[M31
] = sinvalue
;
this.values[M13
] = -sinvalue
;
this.values[M33
] = cosvalue
;
}
static public Matrix4 createRotationZ
(float degrees
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setRotationZ(degrees
);
return matrix
;
}
public void setRotationZ
(float degrees
)
{
float degreesrad
= MathUtil
.degToRad(degrees
);
float sinvalue
= (float)Math
.Sin(degreesrad
);
float cosvalue
= (float)Math
.Cos(degreesrad
);
this.identity();
this.values[M11
] = cosvalue
;
this.values[M21
] = -sinvalue
;
this.values[M12
] = sinvalue
;
this.values[M22
] = cosvalue
;
}
static public Matrix4 createRotation
(Vector3 axis,
float degrees
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setRotation(axis, degrees
);
return matrix
;
}
public void setRotation
(Vector3 axis,
float degrees
)
{
float radangle
= MathUtil
.degToRad(degrees
);
float radcos
= (float)Math
.Cos(radangle
);
float radsin
= (float)Math
.Sin(radangle
);
this.identity();
this.values[M11
] = radcos
+ axis
.x * axis
.x * (1 - radcos
);
this.values[M21
] = axis
.z * radsin
+ axis
.y * axis
.x * (1 - radcos
);
this.values[M31
] = -axis
.y * radsin
+ axis
.z * axis
.x * (1 - radcos
);
this.values[M12
] = -axis
.z * radsin
+ axis
.x * axis
.y * (1 - radcos
);
this.values[M22
] = radcos
+ axis
.y * axis
.y * (1 - radcos
);
this.values[M32
] = axis
.x * radsin
+ axis
.z * axis
.y * (1 - radcos
);
this.values[M13
] = axis
.y * radsin
+ axis
.x * axis
.z * (1 - radcos
);
this.values[M23
] = -axis
.x * radsin
+ axis
.y * axis
.z * (1 - radcos
);
this.values[M33
] = radcos
+ axis
.z * axis
.z * (1 - radcos
);
this.values[M44
] = 1
.0f
;
}
static public Matrix4 createTranslation
(float x,
float y,
float z
)
{
Matrix4 result
= new Matrix4
();
result
.setTranslation(x, y, z
);
return result
;
}
static public Matrix4 createTranslation
(Vector3 translate
)
{
return createTranslation
(translate
.x, translate
.y, translate
.z);
}
public void setTranslation
(float x,
float y,
float z
)
{
this.values[M11
] = 1
.0f
; this.values[M21
] = 0
.0f
; this.values[M31
] = 0
.0f
; this.values[M41
] = 0
.0f
;
this.values[M12
] = 0
.0f
; this.values[M22
] = 1
.0f
; this.values[M32
] = 0
.0f
; this.values[M42
] = 0
.0f
;
this.values[M13
] = 0
.0f
; this.values[M23
] = 0
.0f
; this.values[M33
] = 1
.0f
; this.values[M43
] = 0
.0f
;
this.values[M14
] = x
; this.values[M24
] = y
; this.values[M34
] = z
; this.values[M44
] = 1
.0f
;
}
public void setTranslation
(Vector3 translate
)
{
setTranslation
(translate
.x, translate
.y, translate
.z);
}
static public Matrix4 createFromVectors
(Vector3 forward, Vector3 up, Vector3 right
)
{
forward
.normalize();
up
.normalize();
right
.normalize();
Matrix4 result
= new Matrix4
();
result
.setFromVectors(forward, up, right
);
return result
;
}
public void setFromVectors
(Vector3 forward, Vector3 up, Vector3 right
)
{
forward
.normalize();
up
.normalize();
right
.normalize();
identity
();
this.values[M11
] = right
.x;
this.values[M12
] = right
.y;
this.values[M13
] = right
.z;
this.values[M21
] = up
.x;
this.values[M22
] = up
.y;
this.values[M23
] = up
.z;
this.values[M31
] = -forward
.x;
this.values[M32
] = -forward
.y;
this.values[M33
] = -forward
.z;
this.values[M44
] = 1
.0f
;
}
static public Matrix4 createPerspective
(float fovDegreesY,
float aspect,
float zNear,
float zFar
)
{
Matrix4 result
= new Matrix4
();
result
.setPerspective(fovDegreesY, aspect, zNear, zFar
);
return result
;
}
public void setPerspective
(float fovDegreesY,
float aspect,
float zNear,
float zFar
)
{
float f
= 1
.0f
/ (float) Math
.Tan(fovDegreesY
* (Math
.PI / 360.0));
float rangeReciprocal
= 1
.0f
/ (zNear
- zFar
);
this.values[M11
] = f
/ aspect
;
this.values[M21
] = 0
.0f
;
this.values[M31
] = 0
.0f
;
this.values[M41
] = 0
.0f
;
this.values[M12
] = 0
.0f
;
this.values[M22
] = f
;
this.values[M32
] = 0
.0f
;
this.values[M42
] = 0
.0f
;
this.values[M13
] = 0
.0f
;
this.values[M23
] = 0
.0f
;
this.values[M33
] = (zFar
+ zNear
) * rangeReciprocal
;
this.values[M43
] = -1
.0f
;
this.values[M14
] = 0
.0f
;
this.values[M24
] = 0
.0f
;
this.values[M34
] = 2
.0f
* zFar
* zNear
* rangeReciprocal
;
this.values[M44
] = 0
.0f
;
}
static public Matrix4 createFrustum
(float left,
float right,
float bottom,
float top,
float near,
float far
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setFrustum(left, right, bottom, top, near, far
);
return matrix
;
}
public void setFrustum
(float left,
float right,
float bottom,
float top,
float near,
float far
)
{
if (left
== right
)
{
throw new ArgumentException
("left == right");
}
if (top
== bottom
)
{
throw new ArgumentException
("top == bottom");
}
if (near
== far
)
{
throw new ArgumentException
("near == far");
}
if (near
<= 0
.0f
)
{
throw new ArgumentException
("near <= 0.0f");
}
if (far
<= 0
.0f
)
{
throw new ArgumentException
("far <= 0.0f");
}
float r_width
= 1
.0f
/ (right
- left
);
float r_height
= 1
.0f
/ (top
- bottom
);
float r_depth
= 1
.0f
/ (near
- far
);
float x
= 2
.0f
* (near
* r_width
);
float y
= 2
.0f
* (near
* r_height
);
float A
= 2
.0f
* ((right
+ left
) * r_width
);
float B
= (top
+ bottom
) * r_height
;
float C
= (far
+ near
) * r_depth
;
float D
= 2
.0f
* (far
* near
* r_depth
);
this.values[M11
] = x
;
this.values[M21
] = 0
.0f
;
this.values[M31
] = 0
.0f
;
this.values[M41
] = 0
.0f
;
this.values[M12
] = 0
.0f
;
this.values[M22
] = y
;
this.values[M32
] = 0
.0f
;
this.values[M42
] = 0
.0f
;
this.values[M13
] = A
;
this.values[M23
] = B
;
this.values[M33
] = C
;
this.values[M43
] = -1
.0f
;
this.values[M14
] = 0
.0f
;
this.values[M24
] = 0
.0f
;
this.values[M34
] = D
;
this.values[M44
] = 0
.0f
;
}
static public Matrix4 createOrtho
(float left,
float right,
float bottom,
float top,
float near,
float far
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setOrtho(left, right, bottom, top, near, far
);
return matrix
;
}
public void setOrtho
(float left,
float right,
float bottom,
float top,
float near,
float far
)
{
if (left
== right
)
throw new ArgumentException
("left and right must not be identical!");
if (bottom
== top
)
throw new ArgumentException
("bottom and top must not be identical!");
if (near
== far
)
throw new ArgumentException
("near and far must not be identical!");
float r_width
= 1
.0f
/ (right
- left
);
float r_height
= 1
.0f
/ (top
- bottom
);
float r_depth
= 1
.0f
/ (far
- near
);
float x
= 2
.0f
* (r_width
);
float y
= 2
.0f
* (r_height
);
float z
= -2
.0f
* (r_depth
);
float tx
= -(right
+ left
) * r_width
;
float ty
= -(top
+ bottom
) * r_height
;
float tz
= -(far
+ near
) * r_depth
;
this.values[M11
] = x
; this.values[M21
] = 0
.0f
; this.values[M31
] = 0
.0f
; this.values[M41
] = 0
.0f
;
this.values[M12
] = 0
.0f
; this.values[M22
] = y
; this.values[M32
] = 0
.0f
; this.values[M42
] = 0
.0f
;
this.values[M13
] = 0
.0f
; this.values[M23
] = 0
.0f
; this.values[M33
] = z
; this.values[M43
] = 0
.0f
;
this.values[M14
] = tx
; this.values[M24
] = ty
; this.values[M34
] = tz
; this.values[M44
] = 1
.0f
;
}
static public Matrix4 createLookAt
(float eyeX,
float eyeY,
float eyeZ,
float centerX,
float centerY,
float centerZ,
float upX,
float upY,
float upZ
)
{
Matrix4 matrix
= new Matrix4
();
matrix
.setLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ
);
return matrix
;
}
public void setLookAt
(float eyeX,
float eyeY,
float eyeZ,
float centerX,
float centerY,
float centerZ,
float upX,
float upY,
float upZ
)
{
float fx
= centerX
- eyeX
;
float fy
= centerY
- eyeY
;
float fz
= centerZ
- eyeZ
;
// Normalize f
float rlf
= 1
.0f
/ Vector3
.length(fx, fy, fz
);
fx
*= rlf
;
fy
*= rlf
;
fz
*= rlf
;
// compute s = f x up (x means "cross product")
float sx
= fy
* upZ
- fz
* upY
;
float sy
= fz
* upX
- fx
* upZ
;
float sz
= fx
* upY
- fy
* upX
;
// and normalize s
float rls
= 1
.0f
/ Vector3
.length(sx, sy, sz
);
sx
*= rls
;
sy
*= rls
;
sz
*= rls
;
// compute u = s x f
float ux
= sy
* fz
- sz
* fy
;
float uy
= sz
* fx
- sx
* fz
;
float uz
= sx
* fy
- sy
* fx
;
this.values[M11
] = sx
;
this.values[M21
] = ux
;
this.values[M31
] = -fx
;
this.values[M41
] = 0
.0f
;
this.values[M12
] = sy
;
this.values[M22
] = uy
;
this.values[M32
] = -fy
;
this.values[M42
] = 0
.0f
;
this.values[M13
] = sz
;
this.values[M23
] = uz
;
this.values[M33
] = -fz
;
this.values[M43
] = 0
.0f
;
this.values[M14
] = 0
.0f
;
this.values[M24
] = 0
.0f
;
this.values[M34
] = 0
.0f
;
this.values[M44
] = 1
.0f
;
this.values[M14
] = this.values[M11
] * -eyeX
+ this.values[M12
] * -eyeY
+ this.values[M13
] * -eyeZ
+ this.values[M14
];
this.values[M24
] = this.values[M21
] * -eyeX
+ this.values[M22
] * -eyeY
+ this.values[M23
] * -eyeZ
+ this.values[M24
];
this.values[M34
] = this.values[M31
] * -eyeX
+ this.values[M32
] * -eyeY
+ this.values[M33
] * -eyeZ
+ this.values[M34
];
this.values[M44
] = this.values[M41
] * -eyeX
+ this.values[M42
] * -eyeY
+ this.values[M43
] * -eyeZ
+ this.values[M44
];
}
public Vector3 transform
(Vector3 vector
)
{
return new Vector3
(
values
[M11
] * vector
.x + values
[M21
] * vector
.y + values
[M31
] * vector
.z + values
[M41
],
values
[M12
] * vector
.x + values
[M22
] * vector
.y + values
[M32
] * vector
.z + values
[M42
],
values
[M13
] * vector
.x + values
[M23
] * vector
.y + values
[M33
] * vector
.z + values
[M43
]);
}
public Vector4 transform
(Vector4 vector
)
{
return new Vector4
(
values
[M11
] * vector
.x + values
[M21
] * vector
.y + values
[M31
] * vector
.z + values
[M41
] * vector
.w,
values
[M12
] * vector
.x + values
[M22
] * vector
.y + values
[M32
] * vector
.z + values
[M42
] * vector
.w,
values
[M13
] * vector
.x + values
[M23
] * vector
.y + values
[M33
] * vector
.z + values
[M43
] * vector
.w,
values
[M14
] * vector
.x + values
[M24
] * vector
.y + values
[M34
] * vector
.z + values
[M44
] * vector
.w);
}
static public void interpolate
(Matrix4 result, Matrix4 a, Matrix4 b,
float ratio
)
{
result
.values[M11
] = a
.values[M11
] + (b
.values[M11
] - a
.values[M11
]) * ratio
;
result
.values[M21
] = a
.values[M21
] + (b
.values[M21
] - a
.values[M21
]) * ratio
;
result
.values[M31
] = a
.values[M31
] + (b
.values[M31
] - a
.values[M31
]) * ratio
;
result
.values[M41
] = a
.values[M41
] + (b
.values[M41
] - a
.values[M41
]) * ratio
;
result
.values[M12
] = a
.values[M12
] + (b
.values[M12
] - a
.values[M12
]) * ratio
;
result
.values[M22
] = a
.values[M22
] + (b
.values[M22
] - a
.values[M22
]) * ratio
;
result
.values[M32
] = a
.values[M32
] + (b
.values[M32
] - a
.values[M32
]) * ratio
;
result
.values[M42
] = a
.values[M42
] + (b
.values[M42
] - a
.values[M42
]) * ratio
;
result
.values[M13
] = a
.values[M13
] + (b
.values[M13
] - a
.values[M13
]) * ratio
;
result
.values[M23
] = a
.values[M23
] + (b
.values[M23
] - a
.values[M23
]) * ratio
;
result
.values[M33
] = a
.values[M33
] + (b
.values[M33
] - a
.values[M33
]) * ratio
;
result
.values[M43
] = a
.values[M43
] + (b
.values[M43
] - a
.values[M43
]) * ratio
;
result
.values[M14
] = a
.values[M14
] + (b
.values[M14
] - a
.values[M14
]) * ratio
;
result
.values[M24
] = a
.values[M24
] + (b
.values[M24
] - a
.values[M24
]) * ratio
;
result
.values[M34
] = a
.values[M34
] + (b
.values[M34
] - a
.values[M34
]) * ratio
;
result
.values[M44
] = a
.values[M44
] + (b
.values[M44
] - a
.values[M44
]) * ratio
;
}
static public Matrix4 interpolate
(Matrix4 a, Matrix4 b,
float ratio
)
{
Matrix4 result
= createIdentity
();
interpolate
(result, a, b, ratio
);
return result
;
}
public Vector3 getForwardVector
()
{
Vector3 forward
= new Vector3
(-values
[M31
],
-values
[M32
],
-values
[M33
]);
forward
.normalize();
return forward
;
}
public Vector3 getUpVector
()
{
Vector3 up
= new Vector3
(values
[M21
], values
[M22
], values
[M23
]);
up
.normalize();
return up
;
}
public Vector3 getRightVector
()
{
Vector3 right
= new Vector3
(values
[M11
], values
[M12
], values
[M13
]);
right
.normalize();
return right
;
}
public float[] toGLMatrix
()
{
return values
;
}
public void fromGLMatrix
(float[] m
)
{
//values = m;
for (int i
= 0; i
< values
.Length; i
++)
values
[i
] = m
[i
];
}
// TODO: convert to C# equivalent
/*
public FloatBuffer toFloatBuffer()
{
FloatBuffer buffer = BufferUtils.newFloatBuffer(16);
BufferUtils.copy(values, buffer, values.length, 0);
return buffer;
}*/
}
}