Create matrix from array. This is a convenient way to deal with arrays of "classic" layout: the storage order in an array should be row-major
Check if matrix represents affine transformation
Adjugate and cofactor matrices
Adjugate and cofactor matrices
Determinant (of upper-left 3x3 portion for 4x4 matrices)
Row/column manipulations
Rotate a vector by the inverse 3x3 upper-left portion of the matrix
Inverse of a matrix
Invert
Check if matrix represents affine transformation
Return true if matrix is singular
Negative matrix
Matrix + Matrix
Matrix - Matrix
Matrix * Matrix
Matrix * T
Multiply column vector by the matrix
Multiply column 3D vector by the affine 4x4 matrix
Compare two matrices.
T = Matrix[i, j]
T = Matrixindex Indices start with 0
Matrix[i, j] = T
Matrixindex = T Indices start with 0
Matrix += Matrix
Matrix -= Matrix
Matrix *= Matrix
Matrix *= T
Matrix4x4!(T)index1..index2 = T
Matrix[] = T
Rotate a vector by the 3x3 upper-left portion of the matrix
Set to identity
Convert to string
Transpose
Return the transposed matrix
Matrix elements
1 auto m1 = matrixf( 2 1, 2, 0, 6, 3 4, 6, 3, 1, 4 2, 7, 8, 2, 5 0, 5, 2, 1 6 ); 7 auto m2 = matrixf( 8 0, 3, 7, 1, 9 1, 0, 2, 5, 10 1, 9, 2, 6, 11 5, 2, 0, 0 12 ); 13 assert(m1 * m2 == matrixf( 14 32, 15, 11, 11, 15 14, 41, 46, 52, 16 25, 82, 44, 85, 17 12, 20, 14, 37) 18 ); 19 20 auto m3 = Matrix4f.identity; 21 assert(m3 == matrixf( 22 1, 0, 0, 0, 23 0, 1, 0, 0, 24 0, 0, 1, 0, 25 0, 0, 0, 1) 26 ); 27 28 m3[12] = 1; 29 m3.a24 = 2; 30 m3.a34 = 3; 31 m3[1..4] = 0; 32 33 assert(m3[12] == 1); 34 35 assert(m1.determinant3x3 == -25); 36 assert(m1.determinant == 567); 37 38 assert(m1.singular == false); 39 40 assert(m1.affine == false); 41 42 assert(m1.transposed == matrixf( 43 1, 4, 2, 0, 44 2, 6, 7, 5, 45 0, 3, 8, 2, 46 6, 1, 2, 1) 47 ); 48 49 auto m4 = matrixf( 50 0, 3, 2, 51 1, 0, 8, 52 0, 1, 0 53 ); 54 55 assert(m4.inverse == matrixf( 56 -4, 1, 12, 57 -0, 0, 1, 58 0.5, 0, -1.5) 59 ); 60 61 assert(m1.adjugate == matrixf( 62 7, 148, -16, -158, 63 -14, 28, -49, 154, 64 -14, -53, 113, -89, 65 98, -34, 19, -25) 66 ); 67 68 assert(m1.cofactor == matrixf( 69 7, -14, -14, 98, 70 148, 28, -53, -34, 71 -16, -49, 113, 19, 72 -158, 154, -89, -25) 73 ); 74 75 m1.transpose(); 76 assert(m1 == matrixf( 77 1, 4, 2, 0, 78 2, 6, 7, 5, 79 0, 3, 8, 2, 80 6, 1, 2, 1) 81 ); 82 83 Matrix2f m5; 84 m5[] = 1.0f; 85 m5 += matrixf( 86 2, 2, 87 2, 2 88 ); 89 m5 *= m5; 90 assert(m5 == matrixf( 91 18, 18, 92 18, 18) 93 ); 94 95 m5 = m5 - m5; 96 assert(m5 == Matrix2f.zero); 97 98 Matrix2f m6 = matrixf( 99 2, 2, 100 2, 2 101 ); 102 m6 = m6 * m6; 103 m6 = m6 * 2; 104 m6 *= 2; 105 assert(m6 == matrixf( 106 32, 32, 107 32, 32) 108 ); 109 assert(m6.determinant == 0); 110 111 Matrix3f m7 = matrixf( 112 3, 3, 3, 113 3, 3, 3, 114 3, 3, 3 115 ); 116 m7 = m7 * m7; 117 assert(m7 == matrixf( 118 27, 27, 27, 119 27, 27, 27, 120 27, 27, 27) 121 ); 122 123 Matrix2f m8 = matrixf( 124 1, 0, 125 0, 1 126 ); 127 m8.invert(); 128 assert(m8 == matrixf( 129 1, 0, 130 0, 1) 131 ); 132 assert(m8.negative == matrixf( 133 -1, 0, 134 0, -1) 135 ); 136 137 auto m9 = matrixf( 138 1, 0, 0, 2, 139 0, 1, 0, 3, 140 0, 0, 1, 4, 141 0, 0, 0, 1 142 ); 143 assert(m9.affine == true); 144 assert(m9.inverse == matrixf( 145 1, 0, 0, -2, 146 0, 1, 0, -3, 147 0, 0, 1, -4, 148 0, 0, 0, 1) 149 ); 150 151 bool isAlmostZero3(Vector3f v) 152 { 153 float e = 0.002f; 154 return abs(v.x) < e && 155 abs(v.y) < e && 156 abs(v.z) < e; 157 } 158 159 Vector3f v1 = Vector3f(1, 0, 0); 160 v1 = v1 * matrixf( 161 1, 0, 0, 2, 162 0, 1, 0, 3, 163 0, 0, 1, 4, 164 0, 0, 0, 1 165 ); 166 assert(v1 == Vector3f(3, 3, 4)); 167 168 Vector3f v2 = Vector3f(0, 1, 0); 169 const float a1 = PI * 0.5f; 170 v2 = matrixf( 171 1, 0, 0, 0, 172 0, cos(a1), -sin(a1), 0, 173 0, sin(a1), cos(a1), 0, 174 0, 0, 0, 1 175 ).rotate(v2); 176 assert(isAlmostZero3(v2 - Vector3f(0, 0, 1))); 177 178 Vector3f v3 = Vector3f(0, 1, 0); 179 v3 = matrixf( 180 1, 0, 0, 0, 181 0, cos(a1), -sin(a1), 0, 182 0, sin(a1), cos(a1), 0, 183 0, 0, 0, 1 184 ).invRotate(v3); 185 assert(isAlmostZero3(v3 - Vector3f(0, 0, -1))); 186 187 auto m10 = matrixf( 188 1, 2, 3, 189 3, 2, 1, 190 2, 3, 1 191 ); 192 193 Vector3f r0 = m10.getRow(0); 194 assert(isAlmostZero3(r0 - Vector3f(1, 2, 3))); 195 196 Vector3f c0 = m10.getColumn(0); 197 assert(isAlmostZero3(c0 - Vector3f(1, 3, 2))); 198 199 m10.setRow(2, Vector3f(1, 1, 1)); 200 Vector3f r2 = m10.getRow(2); 201 assert(isAlmostZero3(r2 - Vector3f(1, 1, 1))); 202 203 m10.setColumn(2, Vector3f(1, 1, 1)); 204 Vector3f c2 = m10.getColumn(2); 205 assert(isAlmostZero3(c2 - Vector3f(1, 1, 1))); 206 207 m10.swapRows(0, 1); 208 Vector3f r1 = m10.getRow(1); 209 assert(isAlmostZero3(r1 - Vector3f(1, 2, 1))); 210 211 m10.swapColumns(1, 2); 212 Vector3f c1 = m10.getColumn(1); 213 assert(isAlmostZero3(c1 - Vector3f(1, 1, 1))); 214 215 Matrix2f m11 = matrixf( 216 2, 1, 217 2, 1 218 ); 219 assert(m11.adjugate == matrixf( 220 1, -1, 221 -2, 2) 222 ); 223 assert(m11.cofactor == matrixf( 224 1, -2, 225 -1, 2) 226 ); 227 assert(m11.flatten == [2, 1, 2, 1]); 228 229 assert(m11.elements("a") == "T a11;T a21;T a12;T a22;"); 230 231 Matrix!(float, 1) m12 = matrixf(1); 232 assert(m12.determinant == 1); 233 assert(m12.inverse == matrixf(1)); 234 assert(m12.adjugate == matrixf(1)); 235 assert(m12.cofactor == matrixf(1));
Square (NxN) matrix.
Implementation notes:
- The storage order is column-major.
- Affine vector of 4x4 matrix is in the 4th column (as in OpenGL).
- Elements are stored in a fixed manner, so it is impossible to change matrix size once it's created.
- Actual data is allocated as a static array, so no references, no GC touching. When you pass a Matrix by value, it will be safely copied.
- This implementation is not perfect (as for now) for dealing with really big matrices, but ideal for smaller ones, e.g. those which are meant to be manipulated in real-time (in game engines, rendering pipelines etc).