| 1 | /** | 
|---|
| 2 | * Copyright (c) 2006-2023 LOVE Development Team | 
|---|
| 3 | * | 
|---|
| 4 | * This software is provided 'as-is', without any express or implied | 
|---|
| 5 | * warranty.  In no event will the authors be held liable for any damages | 
|---|
| 6 | * arising from the use of this software. | 
|---|
| 7 | * | 
|---|
| 8 | * Permission is granted to anyone to use this software for any purpose, | 
|---|
| 9 | * including commercial applications, and to alter it and redistribute it | 
|---|
| 10 | * freely, subject to the following restrictions: | 
|---|
| 11 | * | 
|---|
| 12 | * 1. The origin of this software must not be misrepresented; you must not | 
|---|
| 13 | *    claim that you wrote the original software. If you use this software | 
|---|
| 14 | *    in a product, an acknowledgment in the product documentation would be | 
|---|
| 15 | *    appreciated but is not required. | 
|---|
| 16 | * 2. Altered source versions must be plainly marked as such, and must not be | 
|---|
| 17 | *    misrepresented as being the original software. | 
|---|
| 18 | * 3. This notice may not be removed or altered from any source distribution. | 
|---|
| 19 | **/ | 
|---|
| 20 |  | 
|---|
| 21 | #include "Matrix.h" | 
|---|
| 22 | #include "common/config.h" | 
|---|
| 23 |  | 
|---|
| 24 | // STD | 
|---|
| 25 | #include <cstring> // memcpy | 
|---|
| 26 | #include <cmath> | 
|---|
| 27 |  | 
|---|
| 28 | #if defined(LOVE_SIMD_SSE) | 
|---|
| 29 | #include <xmmintrin.h> | 
|---|
| 30 | #endif | 
|---|
| 31 |  | 
|---|
| 32 | #if defined(LOVE_SIMD_NEON) | 
|---|
| 33 | #include <arm_neon.h> | 
|---|
| 34 | #endif | 
|---|
| 35 |  | 
|---|
| 36 | namespace love | 
|---|
| 37 | { | 
|---|
| 38 |  | 
|---|
| 39 | //                 | e0 e4 e8  e12 | | 
|---|
| 40 | //                 | e1 e5 e9  e13 | | 
|---|
| 41 | //                 | e2 e6 e10 e14 | | 
|---|
| 42 | //                 | e3 e7 e11 e15 | | 
|---|
| 43 | // | e0 e4 e8  e12 | | 
|---|
| 44 | // | e1 e5 e9  e13 | | 
|---|
| 45 | // | e2 e6 e10 e14 | | 
|---|
| 46 | // | e3 e7 e11 e15 | | 
|---|
| 47 |  | 
|---|
| 48 | void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, float t[16]) | 
|---|
| 49 | { | 
|---|
| 50 | #if defined(LOVE_SIMD_SSE) | 
|---|
| 51 |  | 
|---|
| 52 | // We can't guarantee 16-bit alignment (e.g. for heap-allocated Matrix4 | 
|---|
| 53 | // objects) so we use unaligned loads and stores. | 
|---|
| 54 | __m128 col1 = _mm_loadu_ps(&a.e[0]); | 
|---|
| 55 | __m128 col2 = _mm_loadu_ps(&a.e[4]); | 
|---|
| 56 | __m128 col3 = _mm_loadu_ps(&a.e[8]); | 
|---|
| 57 | __m128 col4 = _mm_loadu_ps(&a.e[12]); | 
|---|
| 58 |  | 
|---|
| 59 | for (int i = 0; i < 4; i++) | 
|---|
| 60 | { | 
|---|
| 61 | __m128 brod1 = _mm_set1_ps(b.e[4*i + 0]); | 
|---|
| 62 | __m128 brod2 = _mm_set1_ps(b.e[4*i + 1]); | 
|---|
| 63 | __m128 brod3 = _mm_set1_ps(b.e[4*i + 2]); | 
|---|
| 64 | __m128 brod4 = _mm_set1_ps(b.e[4*i + 3]); | 
|---|
| 65 |  | 
|---|
| 66 | __m128 col = _mm_add_ps( | 
|---|
| 67 | _mm_add_ps(_mm_mul_ps(brod1, col1), _mm_mul_ps(brod2, col2)), | 
|---|
| 68 | _mm_add_ps(_mm_mul_ps(brod3, col3), _mm_mul_ps(brod4, col4)) | 
|---|
| 69 | ); | 
|---|
| 70 |  | 
|---|
| 71 | _mm_storeu_ps(&t[4*i], col); | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | #elif defined(LOVE_SIMD_NEON) | 
|---|
| 75 |  | 
|---|
| 76 | float32x4_t cola1 = vld1q_f32(&a.e[0]); | 
|---|
| 77 | float32x4_t cola2 = vld1q_f32(&a.e[4]); | 
|---|
| 78 | float32x4_t cola3 = vld1q_f32(&a.e[8]); | 
|---|
| 79 | float32x4_t cola4 = vld1q_f32(&a.e[12]); | 
|---|
| 80 |  | 
|---|
| 81 | float32x4_t col1 = vmulq_n_f32(cola1, b.e[0]); | 
|---|
| 82 | col1 = vmlaq_n_f32(col1, cola2, b.e[1]); | 
|---|
| 83 | col1 = vmlaq_n_f32(col1, cola3, b.e[2]); | 
|---|
| 84 | col1 = vmlaq_n_f32(col1, cola4, b.e[3]); | 
|---|
| 85 |  | 
|---|
| 86 | float32x4_t col2 = vmulq_n_f32(cola1, b.e[4]); | 
|---|
| 87 | col2 = vmlaq_n_f32(col2, cola2, b.e[5]); | 
|---|
| 88 | col2 = vmlaq_n_f32(col2, cola3, b.e[6]); | 
|---|
| 89 | col2 = vmlaq_n_f32(col2, cola4, b.e[7]); | 
|---|
| 90 |  | 
|---|
| 91 | float32x4_t col3 = vmulq_n_f32(cola1, b.e[8]); | 
|---|
| 92 | col3 = vmlaq_n_f32(col3, cola2, b.e[9]); | 
|---|
| 93 | col3 = vmlaq_n_f32(col3, cola3, b.e[10]); | 
|---|
| 94 | col3 = vmlaq_n_f32(col3, cola4, b.e[11]); | 
|---|
| 95 |  | 
|---|
| 96 | float32x4_t col4 = vmulq_n_f32(cola1, b.e[12]); | 
|---|
| 97 | col4 = vmlaq_n_f32(col4, cola2, b.e[13]); | 
|---|
| 98 | col4 = vmlaq_n_f32(col4, cola3, b.e[14]); | 
|---|
| 99 | col4 = vmlaq_n_f32(col4, cola4, b.e[15]); | 
|---|
| 100 |  | 
|---|
| 101 | vst1q_f32(&t[0], col1); | 
|---|
| 102 | vst1q_f32(&t[4], col2); | 
|---|
| 103 | vst1q_f32(&t[8], col3); | 
|---|
| 104 | vst1q_f32(&t[12], col4); | 
|---|
| 105 |  | 
|---|
| 106 | #else | 
|---|
| 107 |  | 
|---|
| 108 | t[0]  = (a.e[0]*b.e[0])  + (a.e[4]*b.e[1])  + (a.e[8]*b.e[2])  + (a.e[12]*b.e[3]); | 
|---|
| 109 | t[4]  = (a.e[0]*b.e[4])  + (a.e[4]*b.e[5])  + (a.e[8]*b.e[6])  + (a.e[12]*b.e[7]); | 
|---|
| 110 | t[8]  = (a.e[0]*b.e[8])  + (a.e[4]*b.e[9])  + (a.e[8]*b.e[10]) + (a.e[12]*b.e[11]); | 
|---|
| 111 | t[12] = (a.e[0]*b.e[12]) + (a.e[4]*b.e[13]) + (a.e[8]*b.e[14]) + (a.e[12]*b.e[15]); | 
|---|
| 112 |  | 
|---|
| 113 | t[1]  = (a.e[1]*b.e[0])  + (a.e[5]*b.e[1])  + (a.e[9]*b.e[2])  + (a.e[13]*b.e[3]); | 
|---|
| 114 | t[5]  = (a.e[1]*b.e[4])  + (a.e[5]*b.e[5])  + (a.e[9]*b.e[6])  + (a.e[13]*b.e[7]); | 
|---|
| 115 | t[9]  = (a.e[1]*b.e[8])  + (a.e[5]*b.e[9])  + (a.e[9]*b.e[10]) + (a.e[13]*b.e[11]); | 
|---|
| 116 | t[13] = (a.e[1]*b.e[12]) + (a.e[5]*b.e[13]) + (a.e[9]*b.e[14]) + (a.e[13]*b.e[15]); | 
|---|
| 117 |  | 
|---|
| 118 | t[2]  = (a.e[2]*b.e[0])  + (a.e[6]*b.e[1])  + (a.e[10]*b.e[2])  + (a.e[14]*b.e[3]); | 
|---|
| 119 | t[6]  = (a.e[2]*b.e[4])  + (a.e[6]*b.e[5])  + (a.e[10]*b.e[6])  + (a.e[14]*b.e[7]); | 
|---|
| 120 | t[10] = (a.e[2]*b.e[8])  + (a.e[6]*b.e[9])  + (a.e[10]*b.e[10]) + (a.e[14]*b.e[11]); | 
|---|
| 121 | t[14] = (a.e[2]*b.e[12]) + (a.e[6]*b.e[13]) + (a.e[10]*b.e[14]) + (a.e[14]*b.e[15]); | 
|---|
| 122 |  | 
|---|
| 123 | t[3]  = (a.e[3]*b.e[0])  + (a.e[7]*b.e[1])  + (a.e[11]*b.e[2])  + (a.e[15]*b.e[3]); | 
|---|
| 124 | t[7]  = (a.e[3]*b.e[4])  + (a.e[7]*b.e[5])  + (a.e[11]*b.e[6])  + (a.e[15]*b.e[7]); | 
|---|
| 125 | t[11] = (a.e[3]*b.e[8])  + (a.e[7]*b.e[9])  + (a.e[11]*b.e[10]) + (a.e[15]*b.e[11]); | 
|---|
| 126 | t[15] = (a.e[3]*b.e[12]) + (a.e[7]*b.e[13]) + (a.e[11]*b.e[14]) + (a.e[15]*b.e[15]); | 
|---|
| 127 |  | 
|---|
| 128 | #endif | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, Matrix4 &t) | 
|---|
| 132 | { | 
|---|
| 133 | multiply(a, b, t.e); | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | // | e0 e4 e8  e12 | | 
|---|
| 137 | // | e1 e5 e9  e13 | | 
|---|
| 138 | // | e2 e6 e10 e14 | | 
|---|
| 139 | // | e3 e7 e11 e15 | | 
|---|
| 140 |  | 
|---|
| 141 | Matrix4::Matrix4() | 
|---|
| 142 | { | 
|---|
| 143 | setIdentity(); | 
|---|
| 144 | } | 
|---|
| 145 |  | 
|---|
| 146 |  | 
|---|
| 147 | Matrix4::Matrix4(const float elements[16]) | 
|---|
| 148 | { | 
|---|
| 149 | memcpy(e, elements, sizeof(float) * 16); | 
|---|
| 150 | } | 
|---|
| 151 |  | 
|---|
| 152 | Matrix4::Matrix4(float t00, float t10, float t01, float t11, float x, float y) | 
|---|
| 153 | { | 
|---|
| 154 | setRawTransformation(t00, t10, t01, t11, x, y); | 
|---|
| 155 | } | 
|---|
| 156 |  | 
|---|
| 157 | Matrix4::Matrix4(const Matrix4 &a, const Matrix4 &b) | 
|---|
| 158 | { | 
|---|
| 159 | multiply(a, b, e); | 
|---|
| 160 | } | 
|---|
| 161 |  | 
|---|
| 162 | Matrix4::Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) | 
|---|
| 163 | { | 
|---|
| 164 | setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | Matrix4 Matrix4::operator * (const Matrix4 &m) const | 
|---|
| 168 | { | 
|---|
| 169 | return Matrix4(*this, m); | 
|---|
| 170 | } | 
|---|
| 171 |  | 
|---|
| 172 | void Matrix4::operator *= (const Matrix4 &m) | 
|---|
| 173 | { | 
|---|
| 174 | float t[16]; | 
|---|
| 175 | multiply(*this, m, t); | 
|---|
| 176 | memcpy(this->e, t, sizeof(float)*16); | 
|---|
| 177 | } | 
|---|
| 178 |  | 
|---|
| 179 | const float *Matrix4::getElements() const | 
|---|
| 180 | { | 
|---|
| 181 | return e; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | void Matrix4::setIdentity() | 
|---|
| 185 | { | 
|---|
| 186 | memset(e, 0, sizeof(float)*16); | 
|---|
| 187 | e[15] = e[10] = e[5] = e[0] = 1; | 
|---|
| 188 | } | 
|---|
| 189 |  | 
|---|
| 190 | void Matrix4::setTranslation(float x, float y) | 
|---|
| 191 | { | 
|---|
| 192 | setIdentity(); | 
|---|
| 193 | e[12] = x; | 
|---|
| 194 | e[13] = y; | 
|---|
| 195 | } | 
|---|
| 196 |  | 
|---|
| 197 | void Matrix4::setRotation(float rad) | 
|---|
| 198 | { | 
|---|
| 199 | setIdentity(); | 
|---|
| 200 | float c = cosf(rad), s = sinf(rad); | 
|---|
| 201 | e[0] = c; | 
|---|
| 202 | e[4] = -s; | 
|---|
| 203 | e[1] = s; | 
|---|
| 204 | e[5] = c; | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | void Matrix4::setScale(float sx, float sy) | 
|---|
| 208 | { | 
|---|
| 209 | setIdentity(); | 
|---|
| 210 | e[0] = sx; | 
|---|
| 211 | e[5] = sy; | 
|---|
| 212 | } | 
|---|
| 213 |  | 
|---|
| 214 | void Matrix4::setShear(float kx, float ky) | 
|---|
| 215 | { | 
|---|
| 216 | setIdentity(); | 
|---|
| 217 | e[1] = ky; | 
|---|
| 218 | e[4] = kx; | 
|---|
| 219 | } | 
|---|
| 220 |  | 
|---|
| 221 | void Matrix4::getApproximateScale(float &sx, float &sy) const | 
|---|
| 222 | { | 
|---|
| 223 | sx = sqrtf(e[0] * e[0] + e[4] * e[4]); | 
|---|
| 224 | sy = sqrtf(e[1] * e[1] + e[5] * e[5]); | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | void Matrix4::setRawTransformation(float t00, float t10, float t01, float t11, float x, float y) | 
|---|
| 228 | { | 
|---|
| 229 | memset(e, 0, sizeof(float)*16); // zero out matrix | 
|---|
| 230 | e[10] = e[15] = 1.0f; | 
|---|
| 231 | e[0] = t00; | 
|---|
| 232 | e[1] = t10; | 
|---|
| 233 | e[4] = t01; | 
|---|
| 234 | e[5] = t11; | 
|---|
| 235 | e[12] = x; | 
|---|
| 236 | e[13] = y; | 
|---|
| 237 | } | 
|---|
| 238 |  | 
|---|
| 239 | void Matrix4::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) | 
|---|
| 240 | { | 
|---|
| 241 | memset(e, 0, sizeof(float)*16); // zero out matrix | 
|---|
| 242 | float c = cosf(angle), s = sinf(angle); | 
|---|
| 243 | // matrix multiplication carried out on paper: | 
|---|
| 244 | // |1     x| |c -s    | |sx       | | 1 ky    | |1     -ox| | 
|---|
| 245 | // |  1   y| |s  c    | |   sy    | |kx  1    | |  1   -oy| | 
|---|
| 246 | // |    1  | |     1  | |      1  | |      1  | |    1    | | 
|---|
| 247 | // |      1| |       1| |        1| |        1| |       1 | | 
|---|
| 248 | //   move      rotate      scale       skew       origin | 
|---|
| 249 | e[10] = e[15] = 1.0f; | 
|---|
| 250 | e[0]  = c * sx - ky * s * sy; // = a | 
|---|
| 251 | e[1]  = s * sx + ky * c * sy; // = b | 
|---|
| 252 | e[4]  = kx * c * sx - s * sy; // = c | 
|---|
| 253 | e[5]  = kx * s * sx + c * sy; // = d | 
|---|
| 254 | e[12] = x - ox * e[0] - oy * e[4]; | 
|---|
| 255 | e[13] = y - ox * e[1] - oy * e[5]; | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | void Matrix4::translate(float x, float y) | 
|---|
| 259 | { | 
|---|
| 260 | Matrix4 t; | 
|---|
| 261 | t.setTranslation(x, y); | 
|---|
| 262 | this->operator *=(t); | 
|---|
| 263 | } | 
|---|
| 264 |  | 
|---|
| 265 | void Matrix4::rotate(float rad) | 
|---|
| 266 | { | 
|---|
| 267 | Matrix4 t; | 
|---|
| 268 | t.setRotation(rad); | 
|---|
| 269 | this->operator *=(t); | 
|---|
| 270 | } | 
|---|
| 271 |  | 
|---|
| 272 | void Matrix4::scale(float sx, float sy) | 
|---|
| 273 | { | 
|---|
| 274 | Matrix4 t; | 
|---|
| 275 | t.setScale(sx, sy); | 
|---|
| 276 | this->operator *=(t); | 
|---|
| 277 | } | 
|---|
| 278 |  | 
|---|
| 279 | void Matrix4::shear(float kx, float ky) | 
|---|
| 280 | { | 
|---|
| 281 | Matrix4 t; | 
|---|
| 282 | t.setShear(kx,ky); | 
|---|
| 283 | this->operator *=(t); | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | bool Matrix4::isAffine2DTransform() const | 
|---|
| 287 | { | 
|---|
| 288 | return fabsf(e[2] + e[3] + e[6] + e[7] + e[8] + e[9] + e[11] + e[14]) < 0.00001f | 
|---|
| 289 | && fabsf(e[10] + e[15] - 2.0f) < 0.00001f; | 
|---|
| 290 | } | 
|---|
| 291 |  | 
|---|
| 292 | Matrix4 Matrix4::inverse() const | 
|---|
| 293 | { | 
|---|
| 294 | Matrix4 inv; | 
|---|
| 295 |  | 
|---|
| 296 | inv.e[0] = e[5]  * e[10] * e[15] - | 
|---|
| 297 | e[5]  * e[11] * e[14] - | 
|---|
| 298 | e[9]  * e[6]  * e[15] + | 
|---|
| 299 | e[9]  * e[7]  * e[14] + | 
|---|
| 300 | e[13] * e[6]  * e[11] - | 
|---|
| 301 | e[13] * e[7]  * e[10]; | 
|---|
| 302 |  | 
|---|
| 303 | inv.e[4] = -e[4]  * e[10] * e[15] + | 
|---|
| 304 | e[4]  * e[11] * e[14] + | 
|---|
| 305 | e[8]  * e[6]  * e[15] - | 
|---|
| 306 | e[8]  * e[7]  * e[14] - | 
|---|
| 307 | e[12] * e[6]  * e[11] + | 
|---|
| 308 | e[12] * e[7]  * e[10]; | 
|---|
| 309 |  | 
|---|
| 310 | inv.e[8] = e[4]  * e[9]  * e[15] - | 
|---|
| 311 | e[4]  * e[11] * e[13] - | 
|---|
| 312 | e[8]  * e[5]  * e[15] + | 
|---|
| 313 | e[8]  * e[7]  * e[13] + | 
|---|
| 314 | e[12] * e[5]  * e[11] - | 
|---|
| 315 | e[12] * e[7]  * e[9]; | 
|---|
| 316 |  | 
|---|
| 317 | inv.e[12] = -e[4]  * e[9]  * e[14] + | 
|---|
| 318 | e[4]  * e[10] * e[13] + | 
|---|
| 319 | e[8]  * e[5]  * e[14] - | 
|---|
| 320 | e[8]  * e[6]  * e[13] - | 
|---|
| 321 | e[12] * e[5]  * e[10] + | 
|---|
| 322 | e[12] * e[6]  * e[9]; | 
|---|
| 323 |  | 
|---|
| 324 | inv.e[1] = -e[1]  * e[10] * e[15] + | 
|---|
| 325 | e[1]  * e[11] * e[14] + | 
|---|
| 326 | e[9]  * e[2]  * e[15] - | 
|---|
| 327 | e[9]  * e[3]  * e[14] - | 
|---|
| 328 | e[13] * e[2]  * e[11] + | 
|---|
| 329 | e[13] * e[3]  * e[10]; | 
|---|
| 330 |  | 
|---|
| 331 | inv.e[5] = e[0]  * e[10] * e[15] - | 
|---|
| 332 | e[0]  * e[11] * e[14] - | 
|---|
| 333 | e[8]  * e[2]  * e[15] + | 
|---|
| 334 | e[8]  * e[3]  * e[14] + | 
|---|
| 335 | e[12] * e[2]  * e[11] - | 
|---|
| 336 | e[12] * e[3]  * e[10]; | 
|---|
| 337 |  | 
|---|
| 338 | inv.e[9] = -e[0]  * e[9]  * e[15] + | 
|---|
| 339 | e[0]  * e[11] * e[13] + | 
|---|
| 340 | e[8]  * e[1]  * e[15] - | 
|---|
| 341 | e[8]  * e[3]  * e[13] - | 
|---|
| 342 | e[12] * e[1]  * e[11] + | 
|---|
| 343 | e[12] * e[3]  * e[9]; | 
|---|
| 344 |  | 
|---|
| 345 | inv.e[13] = e[0]  * e[9]  * e[14] - | 
|---|
| 346 | e[0]  * e[10] * e[13] - | 
|---|
| 347 | e[8]  * e[1]  * e[14] + | 
|---|
| 348 | e[8]  * e[2]  * e[13] + | 
|---|
| 349 | e[12] * e[1]  * e[10] - | 
|---|
| 350 | e[12] * e[2]  * e[9]; | 
|---|
| 351 |  | 
|---|
| 352 | inv.e[2] = e[1]  * e[6] * e[15] - | 
|---|
| 353 | e[1]  * e[7] * e[14] - | 
|---|
| 354 | e[5]  * e[2] * e[15] + | 
|---|
| 355 | e[5]  * e[3] * e[14] + | 
|---|
| 356 | e[13] * e[2] * e[7] - | 
|---|
| 357 | e[13] * e[3] * e[6]; | 
|---|
| 358 |  | 
|---|
| 359 | inv.e[6] = -e[0]  * e[6] * e[15] + | 
|---|
| 360 | e[0]  * e[7] * e[14] + | 
|---|
| 361 | e[4]  * e[2] * e[15] - | 
|---|
| 362 | e[4]  * e[3] * e[14] - | 
|---|
| 363 | e[12] * e[2] * e[7] + | 
|---|
| 364 | e[12] * e[3] * e[6]; | 
|---|
| 365 |  | 
|---|
| 366 | inv.e[10] = e[0]  * e[5] * e[15] - | 
|---|
| 367 | e[0]  * e[7] * e[13] - | 
|---|
| 368 | e[4]  * e[1] * e[15] + | 
|---|
| 369 | e[4]  * e[3] * e[13] + | 
|---|
| 370 | e[12] * e[1] * e[7] - | 
|---|
| 371 | e[12] * e[3] * e[5]; | 
|---|
| 372 |  | 
|---|
| 373 | inv.e[14] = -e[0]  * e[5] * e[14] + | 
|---|
| 374 | e[0]  * e[6] * e[13] + | 
|---|
| 375 | e[4]  * e[1] * e[14] - | 
|---|
| 376 | e[4]  * e[2] * e[13] - | 
|---|
| 377 | e[12] * e[1] * e[6] + | 
|---|
| 378 | e[12] * e[2] * e[5]; | 
|---|
| 379 |  | 
|---|
| 380 | inv.e[3] = -e[1] * e[6] * e[11] + | 
|---|
| 381 | e[1] * e[7] * e[10] + | 
|---|
| 382 | e[5] * e[2] * e[11] - | 
|---|
| 383 | e[5] * e[3] * e[10] - | 
|---|
| 384 | e[9] * e[2] * e[7] + | 
|---|
| 385 | e[9] * e[3] * e[6]; | 
|---|
| 386 |  | 
|---|
| 387 | inv.e[7] = e[0] * e[6] * e[11] - | 
|---|
| 388 | e[0] * e[7] * e[10] - | 
|---|
| 389 | e[4] * e[2] * e[11] + | 
|---|
| 390 | e[4] * e[3] * e[10] + | 
|---|
| 391 | e[8] * e[2] * e[7] - | 
|---|
| 392 | e[8] * e[3] * e[6]; | 
|---|
| 393 |  | 
|---|
| 394 | inv.e[11] = -e[0] * e[5] * e[11] + | 
|---|
| 395 | e[0] * e[7] * e[9] + | 
|---|
| 396 | e[4] * e[1] * e[11] - | 
|---|
| 397 | e[4] * e[3] * e[9] - | 
|---|
| 398 | e[8] * e[1] * e[7] + | 
|---|
| 399 | e[8] * e[3] * e[5]; | 
|---|
| 400 |  | 
|---|
| 401 | inv.e[15] = e[0] * e[5] * e[10] - | 
|---|
| 402 | e[0] * e[6] * e[9] - | 
|---|
| 403 | e[4] * e[1] * e[10] + | 
|---|
| 404 | e[4] * e[2] * e[9] + | 
|---|
| 405 | e[8] * e[1] * e[6] - | 
|---|
| 406 | e[8] * e[2] * e[5]; | 
|---|
| 407 |  | 
|---|
| 408 | float det = e[0] * inv.e[0] + e[1] * inv.e[4] + e[2] * inv.e[8] + e[3] * inv.e[12]; | 
|---|
| 409 |  | 
|---|
| 410 | float invdet = 1.0f / det; | 
|---|
| 411 |  | 
|---|
| 412 | for (int i = 0; i < 16; i++) | 
|---|
| 413 | inv.e[i] *= invdet; | 
|---|
| 414 |  | 
|---|
| 415 | return inv; | 
|---|
| 416 | } | 
|---|
| 417 |  | 
|---|
| 418 | Matrix4 Matrix4::ortho(float left, float right, float bottom, float top, float near, float far) | 
|---|
| 419 | { | 
|---|
| 420 | Matrix4 m; | 
|---|
| 421 |  | 
|---|
| 422 | m.e[0] = 2.0f / (right - left); | 
|---|
| 423 | m.e[5] = 2.0f / (top - bottom); | 
|---|
| 424 | m.e[10] = -2.0f / (far - near); | 
|---|
| 425 |  | 
|---|
| 426 | m.e[12] = -(right + left) / (right - left); | 
|---|
| 427 | m.e[13] = -(top + bottom) / (top - bottom); | 
|---|
| 428 | m.e[14] = -(far + near) / (far - near); | 
|---|
| 429 |  | 
|---|
| 430 | return m; | 
|---|
| 431 | } | 
|---|
| 432 |  | 
|---|
| 433 | /** | 
|---|
| 434 | * | e0 e3 e6 | | 
|---|
| 435 | * | e1 e4 e7 | | 
|---|
| 436 | * | e2 e5 e8 | | 
|---|
| 437 | **/ | 
|---|
| 438 | Matrix3::Matrix3() | 
|---|
| 439 | { | 
|---|
| 440 | setIdentity(); | 
|---|
| 441 | } | 
|---|
| 442 |  | 
|---|
| 443 | Matrix3::Matrix3(const Matrix4 &mat4) | 
|---|
| 444 | { | 
|---|
| 445 | const float *mat4elems = mat4.getElements(); | 
|---|
| 446 |  | 
|---|
| 447 | // Column 0. | 
|---|
| 448 | e[0] = mat4elems[0]; | 
|---|
| 449 | e[1] = mat4elems[1]; | 
|---|
| 450 | e[2] = mat4elems[2]; | 
|---|
| 451 |  | 
|---|
| 452 | // Column 1. | 
|---|
| 453 | e[3] = mat4elems[4]; | 
|---|
| 454 | e[4] = mat4elems[5]; | 
|---|
| 455 | e[5] = mat4elems[6]; | 
|---|
| 456 |  | 
|---|
| 457 | // Column 2. | 
|---|
| 458 | e[6] = mat4elems[8]; | 
|---|
| 459 | e[7] = mat4elems[9]; | 
|---|
| 460 | e[8] = mat4elems[10]; | 
|---|
| 461 | } | 
|---|
| 462 |  | 
|---|
| 463 | Matrix3::Matrix3(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) | 
|---|
| 464 | { | 
|---|
| 465 | setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); | 
|---|
| 466 | } | 
|---|
| 467 |  | 
|---|
| 468 | Matrix3::~Matrix3() | 
|---|
| 469 | { | 
|---|
| 470 | } | 
|---|
| 471 |  | 
|---|
| 472 | void Matrix3::setIdentity() | 
|---|
| 473 | { | 
|---|
| 474 | memset(e, 0, sizeof(float) * 9); | 
|---|
| 475 | e[8] = e[4] = e[0] = 1.0f; | 
|---|
| 476 | } | 
|---|
| 477 |  | 
|---|
| 478 | Matrix3 Matrix3::operator * (const love::Matrix3 &m) const | 
|---|
| 479 | { | 
|---|
| 480 | Matrix3 t; | 
|---|
| 481 |  | 
|---|
| 482 | t.e[0] = (e[0]*m.e[0]) + (e[3]*m.e[1]) + (e[6]*m.e[2]); | 
|---|
| 483 | t.e[3] = (e[0]*m.e[3]) + (e[3]*m.e[4]) + (e[6]*m.e[5]); | 
|---|
| 484 | t.e[6] = (e[0]*m.e[6]) + (e[3]*m.e[7]) + (e[6]*m.e[8]); | 
|---|
| 485 |  | 
|---|
| 486 | t.e[1] = (e[1]*m.e[0]) + (e[4]*m.e[1]) + (e[7]*m.e[2]); | 
|---|
| 487 | t.e[4] = (e[1]*m.e[3]) + (e[4]*m.e[4]) + (e[7]*m.e[5]); | 
|---|
| 488 | t.e[7] = (e[1]*m.e[6]) + (e[4]*m.e[7]) + (e[7]*m.e[8]); | 
|---|
| 489 |  | 
|---|
| 490 | t.e[2] = (e[2]*m.e[0]) + (e[5]*m.e[1]) + (e[8]*m.e[2]); | 
|---|
| 491 | t.e[5] = (e[2]*m.e[3]) + (e[5]*m.e[4]) + (e[8]*m.e[5]); | 
|---|
| 492 | t.e[8] = (e[2]*m.e[6]) + (e[5]*m.e[7]) + (e[8]*m.e[8]); | 
|---|
| 493 |  | 
|---|
| 494 | return t; | 
|---|
| 495 | } | 
|---|
| 496 |  | 
|---|
| 497 | void Matrix3::operator *= (const Matrix3 &m) | 
|---|
| 498 | { | 
|---|
| 499 | Matrix3 t = (*this) * m; | 
|---|
| 500 | memcpy(e, t.e, sizeof(float) * 9); | 
|---|
| 501 | } | 
|---|
| 502 |  | 
|---|
| 503 | const float *Matrix3::getElements() const | 
|---|
| 504 | { | 
|---|
| 505 | return e; | 
|---|
| 506 | } | 
|---|
| 507 |  | 
|---|
| 508 | Matrix3 Matrix3::transposedInverse() const | 
|---|
| 509 | { | 
|---|
| 510 | // e0 e3 e6 | 
|---|
| 511 | // e1 e4 e7 | 
|---|
| 512 | // e2 e5 e8 | 
|---|
| 513 |  | 
|---|
| 514 | float det = e[0] * (e[4]*e[8] - e[7]*e[5]) | 
|---|
| 515 | - e[1] * (e[3]*e[8] - e[5]*e[6]) | 
|---|
| 516 | + e[2] * (e[3]*e[7] - e[4]*e[6]); | 
|---|
| 517 |  | 
|---|
| 518 | float invdet = 1.0f / det; | 
|---|
| 519 |  | 
|---|
| 520 | Matrix3 m; | 
|---|
| 521 |  | 
|---|
| 522 | m.e[0] =  invdet * (e[4]*e[8] - e[7]*e[5]); | 
|---|
| 523 | m.e[3] = -invdet * (e[1]*e[8] - e[2]*e[7]); | 
|---|
| 524 | m.e[6] =  invdet * (e[1]*e[5] - e[2]*e[4]); | 
|---|
| 525 | m.e[1] = -invdet * (e[3]*e[8] - e[5]*e[6]); | 
|---|
| 526 | m.e[4] =  invdet * (e[0]*e[8] - e[2]*e[6]); | 
|---|
| 527 | m.e[7] = -invdet * (e[0]*e[5] - e[3]*e[2]); | 
|---|
| 528 | m.e[2] =  invdet * (e[3]*e[7] - e[6]*e[4]); | 
|---|
| 529 | m.e[5] = -invdet * (e[0]*e[7] - e[6]*e[1]); | 
|---|
| 530 | m.e[8] =  invdet * (e[0]*e[4] - e[3]*e[1]); | 
|---|
| 531 |  | 
|---|
| 532 | return m; | 
|---|
| 533 | } | 
|---|
| 534 |  | 
|---|
| 535 | void Matrix3::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) | 
|---|
| 536 | { | 
|---|
| 537 | float c = cosf(angle), s = sinf(angle); | 
|---|
| 538 | // matrix multiplication carried out on paper: | 
|---|
| 539 | // |1    x| |c -s  | |sx     | | 1 ky  | |1   -ox| | 
|---|
| 540 | // |  1  y| |s  c  | |   sy  | |kx  1  | |  1 -oy| | 
|---|
| 541 | // |     1| |     1| |      1| |      1| |     1 | | 
|---|
| 542 | //   move    rotate    scale     skew      origin | 
|---|
| 543 | e[0] = c * sx - ky * s * sy; // = a | 
|---|
| 544 | e[1] = s * sx + ky * c * sy; // = b | 
|---|
| 545 | e[3] = kx * c * sx - s * sy; // = c | 
|---|
| 546 | e[4] = kx * s * sx + c * sy; // = d | 
|---|
| 547 | e[6] = x - ox * e[0] - oy * e[3]; | 
|---|
| 548 | e[7] = y - ox * e[1] - oy * e[4]; | 
|---|
| 549 |  | 
|---|
| 550 | e[2] = e[5] = 0.0f; | 
|---|
| 551 | e[8] = 1.0f; | 
|---|
| 552 | } | 
|---|
| 553 |  | 
|---|
| 554 | } // love | 
|---|
| 555 |  | 
|---|