github.com/xlab/linmath@v0.0.0-20220922225318-40b6290c3b40/linmath.go (about) 1 package linmath 2 3 type Mat4x4 [4]Vec4 4 5 func (m *Mat4x4) Fill(d float32) { 6 for i := 0; i < 4; i++ { 7 for j := 0; j < 4; j++ { 8 m[i][j] = d 9 } 10 } 11 } 12 13 func (m *Mat4x4) Identity() { 14 for i := 0; i < 4; i++ { 15 for j := 0; j < 4; j++ { 16 if i == j { 17 m[i][j] = 1 18 } else { 19 m[i][j] = 0 20 } 21 } 22 } 23 } 24 25 func (m *Mat4x4) Dup(n *Mat4x4) { 26 for i := 0; i < 4; i++ { 27 for j := 0; j < 4; j++ { 28 m[i][j] = n[i][j] 29 } 30 } 31 } 32 33 func (r *Vec4) Mat4x4Row(m *Mat4x4, i int) { 34 for k := 0; k < 4; k++ { 35 r[k] = m[k][i] 36 } 37 } 38 39 func (r *Vec4) Mat4x4Col(m *Mat4x4, i int) { 40 for k := 0; k < 4; k++ { 41 r[k] = m[i][k] 42 } 43 } 44 45 func (m *Mat4x4) Transpose(n *Mat4x4) { 46 for i := 0; i < 4; i++ { 47 for j := 0; j < 4; j++ { 48 m[i][j] = n[j][i] 49 } 50 } 51 } 52 53 func (m *Mat4x4) Add(a, b *Mat4x4) { 54 for i := 0; i < 4; i++ { 55 m[i].Add(&a[i], &b[i]) 56 } 57 } 58 59 func (m *Mat4x4) Sub(a, b *Mat4x4) { 60 for i := 0; i < 4; i++ { 61 m[i].Sub(&a[i], &b[i]) 62 } 63 } 64 65 func (m *Mat4x4) Scale(a *Mat4x4, k float32) { 66 for i := 0; i < 4; i++ { 67 m[i].Scale(&a[i], k) 68 } 69 } 70 71 func (m *Mat4x4) ScaleAniso(a *Mat4x4, x, y, z float32) { 72 m[0].Scale(&a[0], x) 73 m[1].Scale(&a[1], y) 74 m[2].Scale(&a[2], z) 75 for i := 0; i < 4; i++ { 76 m[3][i] = a[3][i] 77 } 78 } 79 80 func (m *Mat4x4) Mult(a, b *Mat4x4) { 81 var temp = new(Mat4x4) 82 83 for c := 0; c < 4; c++ { 84 for r := 0; r < 4; r++ { 85 temp[c][r] = 0 86 for k := 0; k < 4; k++ { 87 temp[c][r] += a[k][r] * b[c][k] 88 } 89 } 90 } 91 92 m.Dup(temp) 93 } 94 95 func (r *Vec4) Mat4x4MultVec4(m *Mat4x4, v Vec4) { 96 for j := 0; j < 4; j++ { 97 r[j] = 0 98 for i := 0; i < 4; i++ { 99 r[j] += m[i][j] * v[i] 100 } 101 } 102 } 103 104 func (m *Mat4x4) Translate(x, y, z float32) { 105 m.Identity() 106 m[3][0] = x 107 m[3][1] = y 108 m[3][2] = z 109 } 110 111 func (m *Mat4x4) TranslateInPlace(x, y, z float32) { 112 var t = &Vec4{x, y, z, 0} 113 var r = new(Vec4) 114 for i := 0; i < 4; i++ { 115 r.Mat4x4Row(m, i) 116 m[3][i] += Vec4MultInner(r, t) 117 } 118 } 119 120 func (m *Mat4x4) FromVec3MultOuter(a, b *Vec3) { 121 for i := 0; i < 4; i++ { 122 for j := 0; j < 4; j++ { 123 if i < 3 && j < 3 { 124 m[i][j] = a[i] * b[j] 125 } else { 126 m[i][j] = 0 127 } 128 } 129 } 130 } 131 132 func (r *Mat4x4) Rotate(m *Mat4x4, x, y, z, angle float32) { 133 var s = sinf(angle) 134 var c = cosf(angle) 135 var u = &Vec3{x, y, z} 136 137 if u.Len() > 1e-4 { 138 u.Norm(u) 139 var T = new(Mat4x4) 140 T.FromVec3MultOuter(u, u) 141 142 var S = &Mat4x4{ 143 {0, u[2], -u[1], 0}, 144 {-u[2], 0, u[0], 0}, 145 {u[1], -u[0], 0, 0}, 146 {0, 0, 0, 0}, 147 } 148 S.Scale(S, s) 149 150 var C = new(Mat4x4) 151 C.Identity() 152 C.Sub(C, T) 153 154 C.Scale(C, c) 155 156 T.Add(T, C) 157 T.Add(T, S) 158 159 T[3][3] = 1 160 r.Mult(m, T) 161 } else { 162 r.Dup(m) 163 } 164 } 165 166 func (q *Mat4x4) RotateX(m *Mat4x4, angle float32) { 167 var s = sinf(angle) 168 var c = cosf(angle) 169 var R = &Mat4x4{ 170 {1, 0, 0, 0}, 171 {0, c, s, 0}, 172 {0, -s, c, 0}, 173 {0, 0, 0, 1}, 174 } 175 q.Mult(m, R) 176 } 177 178 func (q *Mat4x4) RotateY(m *Mat4x4, angle float32) { 179 var s = sinf(angle) 180 var c = cosf(angle) 181 var R = &Mat4x4{ 182 {c, 0, s, 0}, 183 {0, 1, 0, 0}, 184 {-s, 0, c, 0}, 185 {0, 0, 0, 1}, 186 } 187 q.Mult(m, R) 188 } 189 190 func (q *Mat4x4) RotateZ(m *Mat4x4, angle float32) { 191 var s = sinf(angle) 192 var c = cosf(angle) 193 var R = &Mat4x4{ 194 {c, s, 0, 0}, 195 {-s, c, 0, 0}, 196 {0, 0, 1, 0}, 197 {0, 0, 0, 1}, 198 } 199 q.Mult(m, R) 200 } 201 202 func (t *Mat4x4) Invert(m *Mat4x4) { 203 var s = new([6]float32) 204 s[0] = m[0][0]*m[1][1] - m[1][0]*m[0][1] 205 s[1] = m[0][0]*m[1][2] - m[1][0]*m[0][2] 206 s[2] = m[0][0]*m[1][3] - m[1][0]*m[0][3] 207 s[3] = m[0][1]*m[1][2] - m[1][1]*m[0][2] 208 s[4] = m[0][1]*m[1][3] - m[1][1]*m[0][3] 209 s[5] = m[0][2]*m[1][3] - m[1][2]*m[0][3] 210 211 var c = new([6]float32) 212 c[0] = m[2][0]*m[3][1] - m[3][0]*m[2][1] 213 c[1] = m[2][0]*m[3][2] - m[3][0]*m[2][2] 214 c[2] = m[2][0]*m[3][3] - m[3][0]*m[2][3] 215 c[3] = m[2][1]*m[3][2] - m[3][1]*m[2][2] 216 c[4] = m[2][1]*m[3][3] - m[3][1]*m[2][3] 217 c[5] = m[2][2]*m[3][3] - m[3][2]*m[2][3] 218 219 // Assumes it is invertible 220 var idet float32 = 1.0 / (s[0]*c[5] - s[1]*c[4] + s[2]*c[3] + s[3]*c[2] - s[4]*c[1] + s[5]*c[0]) 221 222 t[0][0] = (m[1][1]*c[5] - m[1][2]*c[4] + m[1][3]*c[3]) * idet 223 t[0][1] = (-m[0][1]*c[5] + m[0][2]*c[4] - m[0][3]*c[3]) * idet 224 t[0][2] = (m[3][1]*s[5] - m[3][2]*s[4] + m[3][3]*s[3]) * idet 225 t[0][3] = (-m[2][1]*s[5] + m[2][2]*s[4] - m[2][3]*s[3]) * idet 226 227 t[1][0] = (-m[1][0]*c[5] + m[1][2]*c[2] - m[1][3]*c[1]) * idet 228 t[1][1] = (m[0][0]*c[5] - m[0][2]*c[2] + m[0][3]*c[1]) * idet 229 t[1][2] = (-m[3][0]*s[5] + m[3][2]*s[2] - m[3][3]*s[1]) * idet 230 t[1][3] = (m[2][0]*s[5] - m[2][2]*s[2] + m[2][3]*s[1]) * idet 231 t[2][0] = (m[1][0]*c[4] - m[1][1]*c[2] + m[1][3]*c[0]) * idet 232 t[2][1] = (-m[0][0]*c[4] + m[0][1]*c[2] - m[0][3]*c[0]) * idet 233 t[2][2] = (m[3][0]*s[4] - m[3][1]*s[2] + m[3][3]*s[0]) * idet 234 t[2][3] = (-m[2][0]*s[4] + m[2][1]*s[2] - m[2][3]*s[0]) * idet 235 236 t[3][0] = (-m[1][0]*c[3] + m[1][1]*c[1] - m[1][2]*c[0]) * idet 237 t[3][1] = (m[0][0]*c[3] - m[0][1]*c[1] + m[0][2]*c[0]) * idet 238 t[3][2] = (-m[3][0]*s[3] + m[3][1]*s[1] - m[3][2]*s[0]) * idet 239 t[3][3] = (m[2][0]*s[3] - m[2][1]*s[1] + m[2][2]*s[0]) * idet 240 } 241 242 func (r *Mat4x4) OrthoNormalize(m *Mat4x4) { 243 r.Dup(m) 244 var s float32 245 var h = new(Vec3) 246 r[2].Norm(&r[2]) 247 248 s = Vec4MultInner3(&r[1], &r[2]) 249 h.ScaleVec4(&r[2], s) 250 r[1].SubVec3(&r[1], h) 251 r[2].Norm(&r[2]) 252 253 s = Vec4MultInner3(&r[1], &r[2]) 254 h.ScaleVec4(&r[2], s) 255 r[1].SubVec3(&r[1], h) 256 r[1].Norm(&r[1]) 257 258 s = Vec4MultInner3(&r[0], &r[1]) 259 h.ScaleVec4(&r[1], s) 260 r[0].SubVec3(&r[0], h) 261 r[0].Norm(&r[0]) 262 } 263 264 func (m *Mat4x4) Frustum(l, r, b, t, n, f float32) { 265 m[0][0] = 2 * n / (r - l) 266 m[0][1] = 0 267 m[0][2] = 0 268 m[0][3] = 0 269 270 m[1][1] = 2 * n / (t - b) 271 m[1][0] = 0 272 m[1][2] = 0 273 m[1][3] = 0 274 275 m[2][0] = (r + l) / (r - l) 276 m[2][1] = (t + b) / (t - b) 277 m[2][2] = -(f + n) / (f - n) 278 m[2][3] = -1 279 280 m[3][2] = -2 * (f * n) / (f - n) 281 m[3][0] = 0 282 m[3][1] = 0 283 m[3][3] = 0 284 } 285 286 func (m *Mat4x4) Ortho(l, r, b, t, n, f float32) { 287 m[0][0] = 2 / (r - l) 288 m[0][1] = 0 289 m[0][2] = 0 290 m[0][3] = 0 291 292 m[1][1] = 2 / (t - b) 293 m[1][0] = 0 294 m[1][2] = 0 295 m[1][3] = 0 296 297 m[2][2] = -2 / (f - n) 298 m[2][0] = 0 299 m[2][1] = 0 300 m[2][3] = 0 301 302 m[3][0] = -(r + l) / (r - l) 303 m[3][1] = -(t + b) / (t - b) 304 m[3][2] = -(f + n) / (f - n) 305 m[3][3] = 1 306 } 307 308 func (m *Mat4x4) Perspective(y_fov, aspect, n, f float32) { 309 // NOTE: Degrees are an unhandy unit to work with. 310 // linmath.go uses radians for everything! 311 var a float32 = 1 / tanf(y_fov/2) 312 313 m[0][0] = a / aspect 314 m[0][1] = 0 315 m[0][2] = 0 316 m[0][3] = 0 317 318 m[1][0] = 0 319 m[1][1] = a 320 m[1][2] = 0 321 m[1][3] = 0 322 323 m[2][0] = 0 324 m[2][1] = 0 325 m[2][2] = -((f + n) / (f - n)) 326 m[2][3] = -1 327 328 m[3][0] = 0 329 m[3][1] = 0 330 m[3][2] = -((2 * f * n) / (f - n)) 331 m[3][3] = 0 332 } 333 334 func (m *Mat4x4) LookAt(eye, center, up *Vec3) { 335 // Adapted from Android's OpenGL Matrix.java. 336 // See the OpenGL GLUT documentation for gluLookAt for a description 337 // of the algorithm. We implement it in a straightforward way: 338 // 339 // TODO: The negation of of can be spared by swapping the order of 340 // operands in the following cross products in the right way. 341 var f = new(Vec3) 342 f.Sub(center, eye) 343 f.Norm(f) 344 345 var s = new(Vec3) 346 s.MultCross(f, up) 347 s.Norm(s) 348 349 var t = new(Vec3) 350 t.MultCross(s, f) 351 352 m[0][0] = s[0] 353 m[0][1] = t[0] 354 m[0][2] = -f[0] 355 m[0][3] = 0 356 357 m[1][0] = s[1] 358 m[1][1] = t[1] 359 m[1][2] = -f[1] 360 m[1][3] = 0 361 362 m[2][0] = s[2] 363 m[2][1] = t[2] 364 m[2][2] = -f[2] 365 m[2][3] = 0 366 367 m[3][0] = 0 368 m[3][1] = 0 369 m[3][2] = 0 370 m[3][3] = 1 371 372 m.TranslateInPlace(-eye[0], -eye[1], -eye[2]) 373 } 374 375 func (r *Vec3) QuatMultVec3(q *Quat, v *Vec3) { 376 // Method by Fabian 'ryg' Giessen (of Farbrausch) 377 // t = 2 * cross(q.xyz, v) 378 // v' = v + q.w * t + cross(q.xyz, t) 379 var t = new(Vec3) 380 var q_xyz = &Vec3{q[0], q[1], q[2]} 381 var u = &Vec3{q[0], q[1], q[2]} 382 383 t.MultCross(q_xyz, v) 384 t.Scale(t, 2) 385 386 u.MultCross(q_xyz, t) 387 t.Scale(t, q[3]) 388 389 r.Add(v, t) 390 r.Add(r, u) 391 } 392 393 func (r *Vec4) QuatMultVec4(q *Quat, v *Vec4) { 394 // Method by Fabian 'ryg' Giessen (of Farbrausch) 395 // t = 2 * cross(q.xyz, v) 396 // v' = v + q.w * t + cross(q.xyz, t) 397 var t = new(Vec4) 398 var q_xyz = &Vec4{q[0], q[1], q[2]} 399 var u = &Vec4{q[0], q[1], q[2]} 400 401 t.MultCross(q_xyz, v) 402 t.Scale(t, 2) 403 404 u.MultCross(q_xyz, t) 405 t.Scale(t, q[3]) 406 407 r.Add(v, t) 408 r.Add(r, u) 409 } 410 411 func (m *Mat4x4) FromQuat(q *Quat) { 412 var a float32 = q[3] 413 var b float32 = q[0] 414 var c float32 = q[1] 415 var d float32 = q[2] 416 var a2 float32 = a * a 417 var b2 float32 = b * b 418 var c2 float32 = c * c 419 var d2 float32 = d * d 420 421 m[0][0] = a2 + b2 - c2 - d2 422 m[0][1] = 2 * (b*c + a*d) 423 m[0][2] = 2 * (b*d - a*c) 424 m[0][3] = 0 425 426 m[1][0] = 2 * (b*c - a*d) 427 m[1][1] = a2 - b2 + c2 - d2 428 m[1][2] = 2 * (c*d + a*b) 429 m[1][3] = 0 430 431 m[2][0] = 2 * (b*d + a*c) 432 m[2][1] = 2 * (c*d - a*b) 433 m[2][2] = a2 - b2 - c2 + d2 434 m[2][3] = 0 435 436 m[3][0] = 0 437 m[3][1] = 0 438 m[3][2] = 0 439 m[3][3] = 1 440 } 441 442 func (r *Mat4x4) MultQuat(m *Mat4x4, q *Quat) { 443 // XXX: The way this is written only works for othogonal matrices. 444 // TODO: Take care of non-orthogonal case. 445 r[0].QuatMultVec4(q, &m[0]) 446 r[1].QuatMultVec4(q, &m[1]) 447 r[2].QuatMultVec4(q, &m[2]) 448 449 r[3][0] = 0 450 r[3][1] = 0 451 r[3][2] = 0 452 r[3][3] = 1 453 } 454 455 func (q *Quat) FromMat4x4(m *Mat4x4) { 456 var r float32 457 var p = []int{0, 1, 2, 0, 1} 458 var idx int 459 460 for i := 0; i < 3; i++ { 461 var m float32 = m[i][i] 462 if m < r { 463 continue 464 } 465 m = r 466 idx = i 467 } 468 469 p = p[idx:] // reslice p starting from idx 470 r = sqrtf(1 + m[p[0]][p[0]] - m[p[1]][p[1]] - m[p[2]][p[2]]) 471 472 if r < 1e-6 { 473 q[0] = 1 474 q[1] = 0 475 q[2] = 0 476 q[3] = 0 477 return 478 } 479 480 q[0] = r / 2 481 q[1] = (m[p[0]][p[1]] - m[p[1]][p[0]]) / (2 * r) 482 q[2] = (m[p[2]][p[0]] - m[p[0]][p[2]]) / (2 * r) 483 q[3] = (m[p[2]][p[1]] - m[p[1]][p[2]]) / (2 * r) 484 }