1// Copyright 2013 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5part of engine; 6 7class Matrix4 { 8 final Float64List _m4storage; 9 10 /// The components of the matrix. 11 Float64List get storage => _m4storage; 12 13 /// Returns a matrix that is the inverse of [other] if [other] is invertible, 14 /// otherwise `null`. 15 static Matrix4 tryInvert(Matrix4 other) { 16 final Matrix4 r = Matrix4.zero(); 17 final double determinant = r.copyInverse(other); 18 if (determinant == 0.0) { 19 return null; 20 } 21 return r; 22 } 23 24 /// Return index in storage for [row], [col] value. 25 int index(int row, int col) => (col * 4) + row; 26 27 /// Value at [row], [col]. 28 double entry(int row, int col) { 29 assert((row >= 0) && (row < dimension)); 30 assert((col >= 0) && (col < dimension)); 31 32 return _m4storage[index(row, col)]; 33 } 34 35 /// Set value at [row], [col] to be [v]. 36 void setEntry(int row, int col, double v) { 37 assert((row >= 0) && (row < dimension)); 38 assert((col >= 0) && (col < dimension)); 39 40 _m4storage[index(row, col)] = v; 41 } 42 43 /// Constructs a new mat4. 44 factory Matrix4( 45 double arg0, 46 double arg1, 47 double arg2, 48 double arg3, 49 double arg4, 50 double arg5, 51 double arg6, 52 double arg7, 53 double arg8, 54 double arg9, 55 double arg10, 56 double arg11, 57 double arg12, 58 double arg13, 59 double arg14, 60 double arg15) => 61 Matrix4.zero() 62 ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 63 arg10, arg11, arg12, arg13, arg14, arg15); 64 65 /// New matrix from [values]. 66 factory Matrix4.fromList(List<double> values) => Matrix4.zero() 67 ..setValues( 68 values[0], 69 values[1], 70 values[2], 71 values[3], 72 values[4], 73 values[5], 74 values[6], 75 values[7], 76 values[8], 77 values[9], 78 values[10], 79 values[11], 80 values[12], 81 values[13], 82 values[14], 83 values[15]); 84 85 /// Zero matrix. 86 Matrix4.zero() : _m4storage = Float64List(16); 87 88 /// Identity matrix. 89 factory Matrix4.identity() => Matrix4.zero()..setIdentity(); 90 91 /// Copies values from [other]. 92 factory Matrix4.copy(Matrix4 other) => Matrix4.zero()..setFrom(other); 93 94 /// Constructs a matrix that is the inverse of [other]. 95 factory Matrix4.inverted(Matrix4 other) { 96 final Matrix4 r = Matrix4.zero(); 97 final double determinant = r.copyInverse(other); 98 if (determinant == 0.0) { 99 throw ArgumentError.value(other, 'other', 'Matrix cannot be inverted'); 100 } 101 return r; 102 } 103 104 /// Rotation of [radians_] around X. 105 factory Matrix4.rotationX(double radians) => Matrix4.zero() 106 .._m4storage[15] = 1.0 107 ..setRotationX(radians); 108 109 /// Rotation of [radians_] around Y. 110 factory Matrix4.rotationY(double radians) => Matrix4.zero() 111 .._m4storage[15] = 1.0 112 ..setRotationY(radians); 113 114 /// Rotation of [radians_] around Z. 115 factory Matrix4.rotationZ(double radians) => Matrix4.zero() 116 .._m4storage[15] = 1.0 117 ..setRotationZ(radians); 118 119 /// Translation matrix. 120 factory Matrix4.translation(Vector3 translation) => Matrix4.zero() 121 ..setIdentity() 122 ..setTranslation(translation); 123 124 /// Translation matrix. 125 factory Matrix4.translationValues(double x, double y, double z) => 126 Matrix4.zero() 127 ..setIdentity() 128 ..setTranslationRaw(x, y, z); 129 130 /// Scale matrix. 131 factory Matrix4.diagonal3Values(double x, double y, double z) => 132 Matrix4.zero() 133 .._m4storage[15] = 1.0 134 .._m4storage[10] = z 135 .._m4storage[5] = y 136 .._m4storage[0] = x; 137 138 /// Constructs Matrix4 with given [Float64List] as [storage]. 139 Matrix4.fromFloat64List(this._m4storage); 140 141 /// Constructs Matrix4 with a [storage] that views given [buffer] starting at 142 /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement]. 143 Matrix4.fromBuffer(ByteBuffer buffer, int offset) 144 : _m4storage = Float64List.view(buffer, offset, 16); 145 146 /// Sets the matrix with specified values. 147 void setValues( 148 double arg0, 149 double arg1, 150 double arg2, 151 double arg3, 152 double arg4, 153 double arg5, 154 double arg6, 155 double arg7, 156 double arg8, 157 double arg9, 158 double arg10, 159 double arg11, 160 double arg12, 161 double arg13, 162 double arg14, 163 double arg15) { 164 _m4storage[15] = arg15; 165 _m4storage[14] = arg14; 166 _m4storage[13] = arg13; 167 _m4storage[12] = arg12; 168 _m4storage[11] = arg11; 169 _m4storage[10] = arg10; 170 _m4storage[9] = arg9; 171 _m4storage[8] = arg8; 172 _m4storage[7] = arg7; 173 _m4storage[6] = arg6; 174 _m4storage[5] = arg5; 175 _m4storage[4] = arg4; 176 _m4storage[3] = arg3; 177 _m4storage[2] = arg2; 178 _m4storage[1] = arg1; 179 _m4storage[0] = arg0; 180 } 181 182 /// Sets the entire matrix to the matrix in [arg]. 183 void setFrom(Matrix4 arg) { 184 final Float64List argStorage = arg._m4storage; 185 _m4storage[15] = argStorage[15]; 186 _m4storage[14] = argStorage[14]; 187 _m4storage[13] = argStorage[13]; 188 _m4storage[12] = argStorage[12]; 189 _m4storage[11] = argStorage[11]; 190 _m4storage[10] = argStorage[10]; 191 _m4storage[9] = argStorage[9]; 192 _m4storage[8] = argStorage[8]; 193 _m4storage[7] = argStorage[7]; 194 _m4storage[6] = argStorage[6]; 195 _m4storage[5] = argStorage[5]; 196 _m4storage[4] = argStorage[4]; 197 _m4storage[3] = argStorage[3]; 198 _m4storage[2] = argStorage[2]; 199 _m4storage[1] = argStorage[1]; 200 _m4storage[0] = argStorage[0]; 201 } 202 203 /// Dimension of the matrix. 204 int get dimension => 4; 205 206 /// Access the element of the matrix at the index [i]. 207 double operator [](int i) => _m4storage[i]; 208 209 /// Set the element of the matrix at the index [i]. 210 void operator []=(int i, double v) { 211 _m4storage[i] = v; 212 } 213 214 /// Clone matrix. 215 Matrix4 clone() => Matrix4.copy(this); 216 217 /// Copy into [arg]. 218 Matrix4 copyInto(Matrix4 arg) { 219 final Float64List argStorage = arg._m4storage; 220 argStorage[0] = _m4storage[0]; 221 argStorage[1] = _m4storage[1]; 222 argStorage[2] = _m4storage[2]; 223 argStorage[3] = _m4storage[3]; 224 argStorage[4] = _m4storage[4]; 225 argStorage[5] = _m4storage[5]; 226 argStorage[6] = _m4storage[6]; 227 argStorage[7] = _m4storage[7]; 228 argStorage[8] = _m4storage[8]; 229 argStorage[9] = _m4storage[9]; 230 argStorage[10] = _m4storage[10]; 231 argStorage[11] = _m4storage[11]; 232 argStorage[12] = _m4storage[12]; 233 argStorage[13] = _m4storage[13]; 234 argStorage[14] = _m4storage[14]; 235 argStorage[15] = _m4storage[15]; 236 return arg; 237 } 238 239 /// Translate this matrix by a [Vector3], [Vector4], or x,y,z 240 void translate(dynamic x, [double y = 0.0, double z = 0.0]) { 241 double tx; 242 double ty; 243 double tz; 244 const double tw = 1.0; 245 if (x is Vector3) { 246 tx = x.x; 247 ty = x.y; 248 tz = x.z; 249 } else if (x is double) { 250 tx = x; 251 ty = y; 252 tz = z; 253 } 254 final double t1 = _m4storage[0] * tx + 255 _m4storage[4] * ty + 256 _m4storage[8] * tz + 257 _m4storage[12] * tw; 258 final double t2 = _m4storage[1] * tx + 259 _m4storage[5] * ty + 260 _m4storage[9] * tz + 261 _m4storage[13] * tw; 262 final double t3 = _m4storage[2] * tx + 263 _m4storage[6] * ty + 264 _m4storage[10] * tz + 265 _m4storage[14] * tw; 266 final double t4 = _m4storage[3] * tx + 267 _m4storage[7] * ty + 268 _m4storage[11] * tz + 269 _m4storage[15] * tw; 270 _m4storage[12] = t1; 271 _m4storage[13] = t2; 272 _m4storage[14] = t3; 273 _m4storage[15] = t4; 274 } 275 276 /// Scale this matrix by a [Vector3], [Vector4], or x,y,z 277 void scale(dynamic x, [double y, double z]) { 278 double sx; 279 double sy; 280 double sz; 281 const double sw = 1.0; 282 if (x is Vector3) { 283 sx = x.x; 284 sy = x.y; 285 sz = x.z; 286 } else if (x is double) { 287 sx = x; 288 sy = y ?? x; 289 sz = z ?? x; 290 } 291 _m4storage[0] *= sx; 292 _m4storage[1] *= sx; 293 _m4storage[2] *= sx; 294 _m4storage[3] *= sx; 295 _m4storage[4] *= sy; 296 _m4storage[5] *= sy; 297 _m4storage[6] *= sy; 298 _m4storage[7] *= sy; 299 _m4storage[8] *= sz; 300 _m4storage[9] *= sz; 301 _m4storage[10] *= sz; 302 _m4storage[11] *= sz; 303 _m4storage[12] *= sw; 304 _m4storage[13] *= sw; 305 _m4storage[14] *= sw; 306 _m4storage[15] *= sw; 307 } 308 309 /// Create a copy of [this] scaled by a [Vector3], [Vector4] or [x],[y], and 310 /// [z]. 311 Matrix4 scaled(dynamic x, [double y, double z]) => clone()..scale(x, y, z); 312 313 /// Zeros [this]. 314 void setZero() { 315 _m4storage[0] = 0.0; 316 _m4storage[1] = 0.0; 317 _m4storage[2] = 0.0; 318 _m4storage[3] = 0.0; 319 _m4storage[4] = 0.0; 320 _m4storage[5] = 0.0; 321 _m4storage[6] = 0.0; 322 _m4storage[7] = 0.0; 323 _m4storage[8] = 0.0; 324 _m4storage[9] = 0.0; 325 _m4storage[10] = 0.0; 326 _m4storage[11] = 0.0; 327 _m4storage[12] = 0.0; 328 _m4storage[13] = 0.0; 329 _m4storage[14] = 0.0; 330 _m4storage[15] = 0.0; 331 } 332 333 /// Makes [this] into the identity matrix. 334 void setIdentity() { 335 _m4storage[0] = 1.0; 336 _m4storage[1] = 0.0; 337 _m4storage[2] = 0.0; 338 _m4storage[3] = 0.0; 339 _m4storage[4] = 0.0; 340 _m4storage[5] = 1.0; 341 _m4storage[6] = 0.0; 342 _m4storage[7] = 0.0; 343 _m4storage[8] = 0.0; 344 _m4storage[9] = 0.0; 345 _m4storage[10] = 1.0; 346 _m4storage[11] = 0.0; 347 _m4storage[12] = 0.0; 348 _m4storage[13] = 0.0; 349 _m4storage[14] = 0.0; 350 _m4storage[15] = 1.0; 351 } 352 353 /// Returns the tranpose of this. 354 Matrix4 transposed() => clone()..transpose(); 355 356 void transpose() { 357 double temp; 358 temp = _m4storage[4]; 359 _m4storage[4] = _m4storage[1]; 360 _m4storage[1] = temp; 361 temp = _m4storage[8]; 362 _m4storage[8] = _m4storage[2]; 363 _m4storage[2] = temp; 364 temp = _m4storage[12]; 365 _m4storage[12] = _m4storage[3]; 366 _m4storage[3] = temp; 367 temp = _m4storage[9]; 368 _m4storage[9] = _m4storage[6]; 369 _m4storage[6] = temp; 370 temp = _m4storage[13]; 371 _m4storage[13] = _m4storage[7]; 372 _m4storage[7] = temp; 373 temp = _m4storage[14]; 374 _m4storage[14] = _m4storage[11]; 375 _m4storage[11] = temp; 376 } 377 378 /// Returns the determinant of this matrix. 379 double determinant() { 380 final double det2_01_01 = 381 _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4]; 382 final double det2_01_02 = 383 _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4]; 384 final double det2_01_03 = 385 _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4]; 386 final double det2_01_12 = 387 _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5]; 388 final double det2_01_13 = 389 _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5]; 390 final double det2_01_23 = 391 _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6]; 392 final double det3_201_012 = _m4storage[8] * det2_01_12 - 393 _m4storage[9] * det2_01_02 + 394 _m4storage[10] * det2_01_01; 395 final double det3_201_013 = _m4storage[8] * det2_01_13 - 396 _m4storage[9] * det2_01_03 + 397 _m4storage[11] * det2_01_01; 398 final double det3_201_023 = _m4storage[8] * det2_01_23 - 399 _m4storage[10] * det2_01_03 + 400 _m4storage[11] * det2_01_02; 401 final double det3_201_123 = _m4storage[9] * det2_01_23 - 402 _m4storage[10] * det2_01_13 + 403 _m4storage[11] * det2_01_12; 404 return -det3_201_123 * _m4storage[12] + 405 det3_201_023 * _m4storage[13] - 406 det3_201_013 * _m4storage[14] + 407 det3_201_012 * _m4storage[15]; 408 } 409 410 /// Returns a new vector or matrix by multiplying [this] with [arg]. 411 dynamic operator *(dynamic arg) { 412 if (arg is double) { 413 return scaled(arg); 414 } 415 if (arg is Vector3) { 416 return transformed3(arg); 417 } 418 if (arg is Matrix4) { 419 return multiplied(arg); 420 } 421 throw ArgumentError(arg); 422 } 423 424 /// Transform [arg] of type [Vector3] using the perspective transformation 425 /// defined by [this]. 426 Vector3 perspectiveTransform(Vector3 arg) { 427 final Float64List argStorage = arg._v3storage; 428 final double x = (_m4storage[0] * argStorage[0]) + 429 (_m4storage[4] * argStorage[1]) + 430 (_m4storage[8] * argStorage[2]) + 431 _m4storage[12]; 432 final double y = (_m4storage[1] * argStorage[0]) + 433 (_m4storage[5] * argStorage[1]) + 434 (_m4storage[9] * argStorage[2]) + 435 _m4storage[13]; 436 final double z = (_m4storage[2] * argStorage[0]) + 437 (_m4storage[6] * argStorage[1]) + 438 (_m4storage[10] * argStorage[2]) + 439 _m4storage[14]; 440 final double w = 1.0 / 441 ((_m4storage[3] * argStorage[0]) + 442 (_m4storage[7] * argStorage[1]) + 443 (_m4storage[11] * argStorage[2]) + 444 _m4storage[15]); 445 argStorage[0] = x * w; 446 argStorage[1] = y * w; 447 argStorage[2] = z * w; 448 return arg; 449 } 450 451 bool isIdentity() => 452 _m4storage[0] == 1.0 // col 1 453 && 454 _m4storage[1] == 0.0 && 455 _m4storage[2] == 0.0 && 456 _m4storage[3] == 0.0 && 457 _m4storage[4] == 0.0 // col 2 458 && 459 _m4storage[5] == 1.0 && 460 _m4storage[6] == 0.0 && 461 _m4storage[7] == 0.0 && 462 _m4storage[8] == 0.0 // col 3 463 && 464 _m4storage[9] == 0.0 && 465 _m4storage[10] == 1.0 && 466 _m4storage[11] == 0.0 && 467 _m4storage[12] == 0.0 // col 4 468 && 469 _m4storage[13] == 0.0 && 470 _m4storage[14] == 0.0 && 471 _m4storage[15] == 1.0; 472 473 /// Returns the translation vector from this homogeneous transformation matrix. 474 Vector3 getTranslation() { 475 final double z = _m4storage[14]; 476 final double y = _m4storage[13]; 477 final double x = _m4storage[12]; 478 return Vector3(x, y, z); 479 } 480 481 void rotate(Vector3 axis, double angle) { 482 final double len = axis.length; 483 final Float64List axisStorage = axis._v3storage; 484 final double x = axisStorage[0] / len; 485 final double y = axisStorage[1] / len; 486 final double z = axisStorage[2] / len; 487 final double c = math.cos(angle); 488 final double s = math.sin(angle); 489 final double C = 1.0 - c; 490 final double m11 = x * x * C + c; 491 final double m12 = x * y * C - z * s; 492 final double m13 = x * z * C + y * s; 493 final double m21 = y * x * C + z * s; 494 final double m22 = y * y * C + c; 495 final double m23 = y * z * C - x * s; 496 final double m31 = z * x * C - y * s; 497 final double m32 = z * y * C + x * s; 498 final double m33 = z * z * C + c; 499 final double t1 = 500 _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31; 501 final double t2 = 502 _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31; 503 final double t3 = 504 _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31; 505 final double t4 = 506 _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31; 507 final double t5 = 508 _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32; 509 final double t6 = 510 _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32; 511 final double t7 = 512 _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32; 513 final double t8 = 514 _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32; 515 final double t9 = 516 _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33; 517 final double t10 = 518 _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33; 519 final double t11 = 520 _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33; 521 final double t12 = 522 _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33; 523 _m4storage[0] = t1; 524 _m4storage[1] = t2; 525 _m4storage[2] = t3; 526 _m4storage[3] = t4; 527 _m4storage[4] = t5; 528 _m4storage[5] = t6; 529 _m4storage[6] = t7; 530 _m4storage[7] = t8; 531 _m4storage[8] = t9; 532 _m4storage[9] = t10; 533 _m4storage[10] = t11; 534 _m4storage[11] = t12; 535 } 536 537 void rotateZ(double angle) { 538 final double cosAngle = math.cos(angle); 539 final double sinAngle = math.sin(angle); 540 final double t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle; 541 final double t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle; 542 final double t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle; 543 final double t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle; 544 final double t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle; 545 final double t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle; 546 final double t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle; 547 final double t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle; 548 _m4storage[0] = t1; 549 _m4storage[1] = t2; 550 _m4storage[2] = t3; 551 _m4storage[3] = t4; 552 _m4storage[4] = t5; 553 _m4storage[5] = t6; 554 _m4storage[6] = t7; 555 _m4storage[7] = t8; 556 } 557 558 /// Sets the translation vector in this homogeneous transformation matrix. 559 void setTranslation(Vector3 t) { 560 final Float64List tStorage = t._v3storage; 561 final double z = tStorage[2]; 562 final double y = tStorage[1]; 563 final double x = tStorage[0]; 564 _m4storage[14] = z; 565 _m4storage[13] = y; 566 _m4storage[12] = x; 567 } 568 569 /// Sets the translation vector in this homogeneous transformation matrix. 570 void setTranslationRaw(double x, double y, double z) { 571 _m4storage[14] = z; 572 _m4storage[13] = y; 573 _m4storage[12] = x; 574 } 575 576 /// Transposes just the upper 3x3 rotation matrix. 577 void transposeRotation() { 578 double temp; 579 temp = _m4storage[1]; 580 _m4storage[1] = _m4storage[4]; 581 _m4storage[4] = temp; 582 temp = _m4storage[2]; 583 _m4storage[2] = _m4storage[8]; 584 _m4storage[8] = temp; 585 temp = _m4storage[4]; 586 _m4storage[4] = _m4storage[1]; 587 _m4storage[1] = temp; 588 temp = _m4storage[6]; 589 _m4storage[6] = _m4storage[9]; 590 _m4storage[9] = temp; 591 temp = _m4storage[8]; 592 _m4storage[8] = _m4storage[2]; 593 _m4storage[2] = temp; 594 temp = _m4storage[9]; 595 _m4storage[9] = _m4storage[6]; 596 _m4storage[6] = temp; 597 } 598 599 /// Invert [this]. 600 double invert() => copyInverse(this); 601 602 /// Set this matrix to be the inverse of [arg] 603 double copyInverse(Matrix4 arg) { 604 final Float64List argStorage = arg._m4storage; 605 final double a00 = argStorage[0]; 606 final double a01 = argStorage[1]; 607 final double a02 = argStorage[2]; 608 final double a03 = argStorage[3]; 609 final double a10 = argStorage[4]; 610 final double a11 = argStorage[5]; 611 final double a12 = argStorage[6]; 612 final double a13 = argStorage[7]; 613 final double a20 = argStorage[8]; 614 final double a21 = argStorage[9]; 615 final double a22 = argStorage[10]; 616 final double a23 = argStorage[11]; 617 final double a30 = argStorage[12]; 618 final double a31 = argStorage[13]; 619 final double a32 = argStorage[14]; 620 final double a33 = argStorage[15]; 621 final double b00 = a00 * a11 - a01 * a10; 622 final double b01 = a00 * a12 - a02 * a10; 623 final double b02 = a00 * a13 - a03 * a10; 624 final double b03 = a01 * a12 - a02 * a11; 625 final double b04 = a01 * a13 - a03 * a11; 626 final double b05 = a02 * a13 - a03 * a12; 627 final double b06 = a20 * a31 - a21 * a30; 628 final double b07 = a20 * a32 - a22 * a30; 629 final double b08 = a20 * a33 - a23 * a30; 630 final double b09 = a21 * a32 - a22 * a31; 631 final double b10 = a21 * a33 - a23 * a31; 632 final double b11 = a22 * a33 - a23 * a32; 633 final double det = 634 b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 635 if (det == 0.0) { 636 setFrom(arg); 637 return 0.0; 638 } 639 final double invDet = 1.0 / det; 640 _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet; 641 _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet; 642 _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet; 643 _m4storage[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet; 644 _m4storage[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet; 645 _m4storage[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet; 646 _m4storage[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet; 647 _m4storage[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet; 648 _m4storage[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet; 649 _m4storage[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet; 650 _m4storage[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet; 651 _m4storage[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet; 652 _m4storage[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet; 653 _m4storage[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet; 654 _m4storage[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet; 655 _m4storage[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet; 656 return det; 657 } 658 659 double invertRotation() { 660 final double det = determinant(); 661 if (det == 0.0) { 662 return 0.0; 663 } 664 final double invDet = 1.0 / det; 665 double ix; 666 double iy; 667 double iz; 668 double jx; 669 double jy; 670 double jz; 671 double kx; 672 double ky; 673 double kz; 674 ix = invDet * 675 (_m4storage[5] * _m4storage[10] - _m4storage[6] * _m4storage[9]); 676 iy = invDet * 677 (_m4storage[2] * _m4storage[9] - _m4storage[1] * _m4storage[10]); 678 iz = invDet * 679 (_m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5]); 680 jx = invDet * 681 (_m4storage[6] * _m4storage[8] - _m4storage[4] * _m4storage[10]); 682 jy = invDet * 683 (_m4storage[0] * _m4storage[10] - _m4storage[2] * _m4storage[8]); 684 jz = invDet * 685 (_m4storage[2] * _m4storage[4] - _m4storage[0] * _m4storage[6]); 686 kx = invDet * 687 (_m4storage[4] * _m4storage[9] - _m4storage[5] * _m4storage[8]); 688 ky = invDet * 689 (_m4storage[1] * _m4storage[8] - _m4storage[0] * _m4storage[9]); 690 kz = invDet * 691 (_m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4]); 692 _m4storage[0] = ix; 693 _m4storage[1] = iy; 694 _m4storage[2] = iz; 695 _m4storage[4] = jx; 696 _m4storage[5] = jy; 697 _m4storage[6] = jz; 698 _m4storage[8] = kx; 699 _m4storage[9] = ky; 700 _m4storage[10] = kz; 701 return det; 702 } 703 704 /// Sets the upper 3x3 to a rotation of [radians] around X 705 void setRotationX(double radians) { 706 final double c = math.cos(radians); 707 final double s = math.sin(radians); 708 _m4storage[0] = 1.0; 709 _m4storage[1] = 0.0; 710 _m4storage[2] = 0.0; 711 _m4storage[4] = 0.0; 712 _m4storage[5] = c; 713 _m4storage[6] = s; 714 _m4storage[8] = 0.0; 715 _m4storage[9] = -s; 716 _m4storage[10] = c; 717 _m4storage[3] = 0.0; 718 _m4storage[7] = 0.0; 719 _m4storage[11] = 0.0; 720 } 721 722 /// Sets the upper 3x3 to a rotation of [radians] around Y 723 void setRotationY(double radians) { 724 final double c = math.cos(radians); 725 final double s = math.sin(radians); 726 _m4storage[0] = c; 727 _m4storage[1] = 0.0; 728 _m4storage[2] = -s; 729 _m4storage[4] = 0.0; 730 _m4storage[5] = 1.0; 731 _m4storage[6] = 0.0; 732 _m4storage[8] = s; 733 _m4storage[9] = 0.0; 734 _m4storage[10] = c; 735 _m4storage[3] = 0.0; 736 _m4storage[7] = 0.0; 737 _m4storage[11] = 0.0; 738 } 739 740 /// Sets the upper 3x3 to a rotation of [radians] around Z 741 void setRotationZ(double radians) { 742 final double c = math.cos(radians); 743 final double s = math.sin(radians); 744 _m4storage[0] = c; 745 _m4storage[1] = s; 746 _m4storage[2] = 0.0; 747 _m4storage[4] = -s; 748 _m4storage[5] = c; 749 _m4storage[6] = 0.0; 750 _m4storage[8] = 0.0; 751 _m4storage[9] = 0.0; 752 _m4storage[10] = 1.0; 753 _m4storage[3] = 0.0; 754 _m4storage[7] = 0.0; 755 _m4storage[11] = 0.0; 756 } 757 758 /// Multiply [this] by [arg]. 759 void multiply(Matrix4 arg) { 760 final double m00 = _m4storage[0]; 761 final double m01 = _m4storage[4]; 762 final double m02 = _m4storage[8]; 763 final double m03 = _m4storage[12]; 764 final double m10 = _m4storage[1]; 765 final double m11 = _m4storage[5]; 766 final double m12 = _m4storage[9]; 767 final double m13 = _m4storage[13]; 768 final double m20 = _m4storage[2]; 769 final double m21 = _m4storage[6]; 770 final double m22 = _m4storage[10]; 771 final double m23 = _m4storage[14]; 772 final double m30 = _m4storage[3]; 773 final double m31 = _m4storage[7]; 774 final double m32 = _m4storage[11]; 775 final double m33 = _m4storage[15]; 776 final Float64List argStorage = arg._m4storage; 777 final double n00 = argStorage[0]; 778 final double n01 = argStorage[4]; 779 final double n02 = argStorage[8]; 780 final double n03 = argStorage[12]; 781 final double n10 = argStorage[1]; 782 final double n11 = argStorage[5]; 783 final double n12 = argStorage[9]; 784 final double n13 = argStorage[13]; 785 final double n20 = argStorage[2]; 786 final double n21 = argStorage[6]; 787 final double n22 = argStorage[10]; 788 final double n23 = argStorage[14]; 789 final double n30 = argStorage[3]; 790 final double n31 = argStorage[7]; 791 final double n32 = argStorage[11]; 792 final double n33 = argStorage[15]; 793 _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30); 794 _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31); 795 _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32); 796 _m4storage[12] = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33); 797 _m4storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30); 798 _m4storage[5] = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31); 799 _m4storage[9] = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32); 800 _m4storage[13] = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33); 801 _m4storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30); 802 _m4storage[6] = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31); 803 _m4storage[10] = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32); 804 _m4storage[14] = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33); 805 _m4storage[3] = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30); 806 _m4storage[7] = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31); 807 _m4storage[11] = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32); 808 _m4storage[15] = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33); 809 } 810 811 /// Multiply a copy of [this] with [arg]. 812 Matrix4 multiplied(Matrix4 arg) => clone()..multiply(arg); 813 814 /// Multiply a transposed [this] with [arg]. 815 void transposeMultiply(Matrix4 arg) { 816 final double m00 = _m4storage[0]; 817 final double m01 = _m4storage[1]; 818 final double m02 = _m4storage[2]; 819 final double m03 = _m4storage[3]; 820 final double m10 = _m4storage[4]; 821 final double m11 = _m4storage[5]; 822 final double m12 = _m4storage[6]; 823 final double m13 = _m4storage[7]; 824 final double m20 = _m4storage[8]; 825 final double m21 = _m4storage[9]; 826 final double m22 = _m4storage[10]; 827 final double m23 = _m4storage[11]; 828 final double m30 = _m4storage[12]; 829 final double m31 = _m4storage[13]; 830 final double m32 = _m4storage[14]; 831 final double m33 = _m4storage[15]; 832 final Float64List argStorage = arg._m4storage; 833 _m4storage[0] = (m00 * argStorage[0]) + 834 (m01 * argStorage[1]) + 835 (m02 * argStorage[2]) + 836 (m03 * argStorage[3]); 837 _m4storage[4] = (m00 * argStorage[4]) + 838 (m01 * argStorage[5]) + 839 (m02 * argStorage[6]) + 840 (m03 * argStorage[7]); 841 _m4storage[8] = (m00 * argStorage[8]) + 842 (m01 * argStorage[9]) + 843 (m02 * argStorage[10]) + 844 (m03 * argStorage[11]); 845 _m4storage[12] = (m00 * argStorage[12]) + 846 (m01 * argStorage[13]) + 847 (m02 * argStorage[14]) + 848 (m03 * argStorage[15]); 849 _m4storage[1] = (m10 * argStorage[0]) + 850 (m11 * argStorage[1]) + 851 (m12 * argStorage[2]) + 852 (m13 * argStorage[3]); 853 _m4storage[5] = (m10 * argStorage[4]) + 854 (m11 * argStorage[5]) + 855 (m12 * argStorage[6]) + 856 (m13 * argStorage[7]); 857 _m4storage[9] = (m10 * argStorage[8]) + 858 (m11 * argStorage[9]) + 859 (m12 * argStorage[10]) + 860 (m13 * argStorage[11]); 861 _m4storage[13] = (m10 * argStorage[12]) + 862 (m11 * argStorage[13]) + 863 (m12 * argStorage[14]) + 864 (m13 * argStorage[15]); 865 _m4storage[2] = (m20 * argStorage[0]) + 866 (m21 * argStorage[1]) + 867 (m22 * argStorage[2]) + 868 (m23 * argStorage[3]); 869 _m4storage[6] = (m20 * argStorage[4]) + 870 (m21 * argStorage[5]) + 871 (m22 * argStorage[6]) + 872 (m23 * argStorage[7]); 873 _m4storage[10] = (m20 * argStorage[8]) + 874 (m21 * argStorage[9]) + 875 (m22 * argStorage[10]) + 876 (m23 * argStorage[11]); 877 _m4storage[14] = (m20 * argStorage[12]) + 878 (m21 * argStorage[13]) + 879 (m22 * argStorage[14]) + 880 (m23 * argStorage[15]); 881 _m4storage[3] = (m30 * argStorage[0]) + 882 (m31 * argStorage[1]) + 883 (m32 * argStorage[2]) + 884 (m33 * argStorage[3]); 885 _m4storage[7] = (m30 * argStorage[4]) + 886 (m31 * argStorage[5]) + 887 (m32 * argStorage[6]) + 888 (m33 * argStorage[7]); 889 _m4storage[11] = (m30 * argStorage[8]) + 890 (m31 * argStorage[9]) + 891 (m32 * argStorage[10]) + 892 (m33 * argStorage[11]); 893 _m4storage[15] = (m30 * argStorage[12]) + 894 (m31 * argStorage[13]) + 895 (m32 * argStorage[14]) + 896 (m33 * argStorage[15]); 897 } 898 899 /// Multiply [this] with a transposed [arg]. 900 void multiplyTranspose(Matrix4 arg) { 901 final double m00 = _m4storage[0]; 902 final double m01 = _m4storage[4]; 903 final double m02 = _m4storage[8]; 904 final double m03 = _m4storage[12]; 905 final double m10 = _m4storage[1]; 906 final double m11 = _m4storage[5]; 907 final double m12 = _m4storage[9]; 908 final double m13 = _m4storage[13]; 909 final double m20 = _m4storage[2]; 910 final double m21 = _m4storage[6]; 911 final double m22 = _m4storage[10]; 912 final double m23 = _m4storage[14]; 913 final double m30 = _m4storage[3]; 914 final double m31 = _m4storage[7]; 915 final double m32 = _m4storage[11]; 916 final double m33 = _m4storage[15]; 917 final Float64List argStorage = arg._m4storage; 918 _m4storage[0] = (m00 * argStorage[0]) + 919 (m01 * argStorage[4]) + 920 (m02 * argStorage[8]) + 921 (m03 * argStorage[12]); 922 _m4storage[4] = (m00 * argStorage[1]) + 923 (m01 * argStorage[5]) + 924 (m02 * argStorage[9]) + 925 (m03 * argStorage[13]); 926 _m4storage[8] = (m00 * argStorage[2]) + 927 (m01 * argStorage[6]) + 928 (m02 * argStorage[10]) + 929 (m03 * argStorage[14]); 930 _m4storage[12] = (m00 * argStorage[3]) + 931 (m01 * argStorage[7]) + 932 (m02 * argStorage[11]) + 933 (m03 * argStorage[15]); 934 _m4storage[1] = (m10 * argStorage[0]) + 935 (m11 * argStorage[4]) + 936 (m12 * argStorage[8]) + 937 (m13 * argStorage[12]); 938 _m4storage[5] = (m10 * argStorage[1]) + 939 (m11 * argStorage[5]) + 940 (m12 * argStorage[9]) + 941 (m13 * argStorage[13]); 942 _m4storage[9] = (m10 * argStorage[2]) + 943 (m11 * argStorage[6]) + 944 (m12 * argStorage[10]) + 945 (m13 * argStorage[14]); 946 _m4storage[13] = (m10 * argStorage[3]) + 947 (m11 * argStorage[7]) + 948 (m12 * argStorage[11]) + 949 (m13 * argStorage[15]); 950 _m4storage[2] = (m20 * argStorage[0]) + 951 (m21 * argStorage[4]) + 952 (m22 * argStorage[8]) + 953 (m23 * argStorage[12]); 954 _m4storage[6] = (m20 * argStorage[1]) + 955 (m21 * argStorage[5]) + 956 (m22 * argStorage[9]) + 957 (m23 * argStorage[13]); 958 _m4storage[10] = (m20 * argStorage[2]) + 959 (m21 * argStorage[6]) + 960 (m22 * argStorage[10]) + 961 (m23 * argStorage[14]); 962 _m4storage[14] = (m20 * argStorage[3]) + 963 (m21 * argStorage[7]) + 964 (m22 * argStorage[11]) + 965 (m23 * argStorage[15]); 966 _m4storage[3] = (m30 * argStorage[0]) + 967 (m31 * argStorage[4]) + 968 (m32 * argStorage[8]) + 969 (m33 * argStorage[12]); 970 _m4storage[7] = (m30 * argStorage[1]) + 971 (m31 * argStorage[5]) + 972 (m32 * argStorage[9]) + 973 (m33 * argStorage[13]); 974 _m4storage[11] = (m30 * argStorage[2]) + 975 (m31 * argStorage[6]) + 976 (m32 * argStorage[10]) + 977 (m33 * argStorage[14]); 978 _m4storage[15] = (m30 * argStorage[3]) + 979 (m31 * argStorage[7]) + 980 (m32 * argStorage[11]) + 981 (m33 * argStorage[15]); 982 } 983 984 /// Rotate [arg] of type [Vector3] using the rotation defined by [this]. 985 Vector3 rotate3(Vector3 arg) { 986 final Float64List argStorage = arg._v3storage; 987 final double x = (_m4storage[0] * argStorage[0]) + 988 (_m4storage[4] * argStorage[1]) + 989 (_m4storage[8] * argStorage[2]); 990 final double y = (_m4storage[1] * argStorage[0]) + 991 (_m4storage[5] * argStorage[1]) + 992 (_m4storage[9] * argStorage[2]); 993 final double z = (_m4storage[2] * argStorage[0]) + 994 (_m4storage[6] * argStorage[1]) + 995 (_m4storage[10] * argStorage[2]); 996 argStorage[0] = x; 997 argStorage[1] = y; 998 argStorage[2] = z; 999 return arg; 1000 } 1001 1002 /// Rotate a copy of [arg] of type [Vector3] using the rotation defined by 1003 /// [this]. If a [out] parameter is supplied, the copy is stored in [out]. 1004 Vector3 rotated3(Vector3 arg, [Vector3 out]) { 1005 if (out == null) { 1006 out = Vector3.copy(arg); 1007 } else { 1008 out.setFrom(arg); 1009 } 1010 return rotate3(out); 1011 } 1012 1013 /// Transform [arg] of type [Vector3] using the transformation defined by 1014 /// [this]. 1015 Vector3 transform3(Vector3 arg) { 1016 final Float64List argStorage = arg._v3storage; 1017 final double x = (_m4storage[0] * argStorage[0]) + 1018 (_m4storage[4] * argStorage[1]) + 1019 (_m4storage[8] * argStorage[2]) + 1020 _m4storage[12]; 1021 final double y = (_m4storage[1] * argStorage[0]) + 1022 (_m4storage[5] * argStorage[1]) + 1023 (_m4storage[9] * argStorage[2]) + 1024 _m4storage[13]; 1025 final double z = (_m4storage[2] * argStorage[0]) + 1026 (_m4storage[6] * argStorage[1]) + 1027 (_m4storage[10] * argStorage[2]) + 1028 _m4storage[14]; 1029 argStorage[0] = x; 1030 argStorage[1] = y; 1031 argStorage[2] = z; 1032 return arg; 1033 } 1034 1035 /// Transform a copy of [arg] of type [Vector3] using the transformation 1036 /// defined by [this]. If a [out] parameter is supplied, the copy is stored in 1037 /// [out]. 1038 Vector3 transformed3(Vector3 arg, [Vector3 out]) { 1039 if (out == null) { 1040 out = Vector3.copy(arg); 1041 } else { 1042 out.setFrom(arg); 1043 } 1044 return transform3(out); 1045 } 1046 1047 /// Copies [this] into [array] starting at [offset]. 1048 void copyIntoArray(List<num> array, [int offset = 0]) { 1049 final int i = offset; 1050 array[i + 15] = _m4storage[15]; 1051 array[i + 14] = _m4storage[14]; 1052 array[i + 13] = _m4storage[13]; 1053 array[i + 12] = _m4storage[12]; 1054 array[i + 11] = _m4storage[11]; 1055 array[i + 10] = _m4storage[10]; 1056 array[i + 9] = _m4storage[9]; 1057 array[i + 8] = _m4storage[8]; 1058 array[i + 7] = _m4storage[7]; 1059 array[i + 6] = _m4storage[6]; 1060 array[i + 5] = _m4storage[5]; 1061 array[i + 4] = _m4storage[4]; 1062 array[i + 3] = _m4storage[3]; 1063 array[i + 2] = _m4storage[2]; 1064 array[i + 1] = _m4storage[1]; 1065 array[i + 0] = _m4storage[0]; 1066 } 1067 1068 /// Copies elements from [array] into [this] starting at [offset]. 1069 void copyFromArray(List<double> array, [int offset = 0]) { 1070 final int i = offset; 1071 _m4storage[15] = array[i + 15]; 1072 _m4storage[14] = array[i + 14]; 1073 _m4storage[13] = array[i + 13]; 1074 _m4storage[12] = array[i + 12]; 1075 _m4storage[11] = array[i + 11]; 1076 _m4storage[10] = array[i + 10]; 1077 _m4storage[9] = array[i + 9]; 1078 _m4storage[8] = array[i + 8]; 1079 _m4storage[7] = array[i + 7]; 1080 _m4storage[6] = array[i + 6]; 1081 _m4storage[5] = array[i + 5]; 1082 _m4storage[4] = array[i + 4]; 1083 _m4storage[3] = array[i + 3]; 1084 _m4storage[2] = array[i + 2]; 1085 _m4storage[1] = array[i + 1]; 1086 _m4storage[0] = array[i + 0]; 1087 } 1088} 1089 1090/// 3D column vector. 1091class Vector3 { 1092 final Float64List _v3storage; 1093 1094 /// The components of the vector. 1095 Float64List get storage => _v3storage; 1096 1097 /// Set the values of [result] to the minimum of [a] and [b] for each line. 1098 static void min(Vector3 a, Vector3 b, Vector3 result) { 1099 result 1100 ..x = math.min(a.x, b.x) 1101 ..y = math.min(a.y, b.y) 1102 ..z = math.min(a.z, b.z); 1103 } 1104 1105 /// Set the values of [result] to the maximum of [a] and [b] for each line. 1106 static void max(Vector3 a, Vector3 b, Vector3 result) { 1107 result 1108 ..x = math.max(a.x, b.x) 1109 ..y = math.max(a.y, b.y) 1110 ..z = math.max(a.z, b.z); 1111 } 1112 1113 /// Interpolate between [min] and [max] with the amount of [a] using a linear 1114 /// interpolation and store the values in [result]. 1115 static void mix(Vector3 min, Vector3 max, double a, Vector3 result) { 1116 result 1117 ..x = min.x + a * (max.x - min.x) 1118 ..y = min.y + a * (max.y - min.y) 1119 ..z = min.z + a * (max.z - min.z); 1120 } 1121 1122 /// Construct a new vector with the specified values. 1123 factory Vector3(double x, double y, double z) => 1124 Vector3.zero()..setValues(x, y, z); 1125 1126 /// Zero vector. 1127 Vector3.zero() : _v3storage = Float64List(3); 1128 1129 /// Splat [value] into all lanes of the vector. 1130 factory Vector3.all(double value) => Vector3.zero()..splat(value); 1131 1132 /// Copy of [other]. 1133 factory Vector3.copy(Vector3 other) => Vector3.zero()..setFrom(other); 1134 1135 /// Constructs Vector3 with given Float64List as [storage]. 1136 Vector3.fromFloat64List(this._v3storage); 1137 1138 /// Constructs Vector3 with a [storage] that views given [buffer] starting at 1139 /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement]. 1140 Vector3.fromBuffer(ByteBuffer buffer, int offset) 1141 : _v3storage = Float64List.view(buffer, offset, 3); 1142 1143 /// Generate random vector in the range (0, 0, 0) to (1, 1, 1). You can 1144 /// optionally pass your own random number generator. 1145 factory Vector3.random([math.Random rng]) { 1146 rng ??= math.Random(); 1147 return Vector3(rng.nextDouble(), rng.nextDouble(), rng.nextDouble()); 1148 } 1149 1150 /// Set the values of the vector. 1151 void setValues(double x, double y, double z) { 1152 _v3storage[0] = x; 1153 _v3storage[1] = y; 1154 _v3storage[2] = z; 1155 } 1156 1157 /// Zero vector. 1158 void setZero() { 1159 _v3storage[2] = 0.0; 1160 _v3storage[1] = 0.0; 1161 _v3storage[0] = 0.0; 1162 } 1163 1164 /// Set the values by copying them from [other]. 1165 void setFrom(Vector3 other) { 1166 final Float64List otherStorage = other._v3storage; 1167 _v3storage[0] = otherStorage[0]; 1168 _v3storage[1] = otherStorage[1]; 1169 _v3storage[2] = otherStorage[2]; 1170 } 1171 1172 /// Splat [arg] into all lanes of the vector. 1173 void splat(double arg) { 1174 _v3storage[2] = arg; 1175 _v3storage[1] = arg; 1176 _v3storage[0] = arg; 1177 } 1178 1179 /// Access the component of the vector at the index [i]. 1180 double operator [](int i) => _v3storage[i]; 1181 1182 /// Set the component of the vector at the index [i]. 1183 void operator []=(int i, double v) { 1184 _v3storage[i] = v; 1185 } 1186 1187 /// Set the length of the vector. A negative [value] will change the vectors 1188 /// orientation and a [value] of zero will set the vector to zero. 1189 set length(double value) { 1190 if (value == 0.0) { 1191 setZero(); 1192 } else { 1193 double l = length; 1194 if (l == 0.0) { 1195 return; 1196 } 1197 l = value / l; 1198 _v3storage[0] *= l; 1199 _v3storage[1] *= l; 1200 _v3storage[2] *= l; 1201 } 1202 } 1203 1204 /// Length. 1205 double get length => math.sqrt(length2); 1206 1207 /// Length squared. 1208 double get length2 { 1209 double sum; 1210 sum = _v3storage[0] * _v3storage[0]; 1211 sum += _v3storage[1] * _v3storage[1]; 1212 sum += _v3storage[2] * _v3storage[2]; 1213 return sum; 1214 } 1215 1216 /// Normalizes [this]. 1217 double normalize() { 1218 final double l = length; 1219 if (l == 0.0) { 1220 return 0.0; 1221 } 1222 final double d = 1.0 / l; 1223 _v3storage[0] *= d; 1224 _v3storage[1] *= d; 1225 _v3storage[2] *= d; 1226 return l; 1227 } 1228 1229 /// Normalizes copy of [this]. 1230 Vector3 normalized() => Vector3.copy(this)..normalize(); 1231 1232 /// Normalize vector into [out]. 1233 Vector3 normalizeInto(Vector3 out) { 1234 out 1235 ..setFrom(this) 1236 ..normalize(); 1237 return out; 1238 } 1239 1240 /// Distance from [this] to [arg] 1241 double distanceTo(Vector3 arg) => math.sqrt(distanceToSquared(arg)); 1242 1243 /// Squared distance from [this] to [arg] 1244 double distanceToSquared(Vector3 arg) { 1245 final Float64List argStorage = arg._v3storage; 1246 final double dx = _v3storage[0] - argStorage[0]; 1247 final double dy = _v3storage[1] - argStorage[1]; 1248 final double dz = _v3storage[2] - argStorage[2]; 1249 1250 return dx * dx + dy * dy + dz * dz; 1251 } 1252 1253 /// Returns the angle between [this] vector and [other] in radians. 1254 double angleTo(Vector3 other) { 1255 final Float64List otherStorage = other._v3storage; 1256 if (_v3storage[0] == otherStorage[0] && 1257 _v3storage[1] == otherStorage[1] && 1258 _v3storage[2] == otherStorage[2]) { 1259 return 0.0; 1260 } 1261 1262 final double d = dot(other) / (length * other.length); 1263 1264 return math.acos(d.clamp(-1.0, 1.0)); 1265 } 1266 1267 /// Inner product. 1268 double dot(Vector3 other) { 1269 final Float64List otherStorage = other._v3storage; 1270 double sum; 1271 sum = _v3storage[0] * otherStorage[0]; 1272 sum += _v3storage[1] * otherStorage[1]; 1273 sum += _v3storage[2] * otherStorage[2]; 1274 return sum; 1275 } 1276 1277 /// Projects [this] using the projection matrix [arg] 1278 void applyProjection(Matrix4 arg) { 1279 final Float64List argStorage = arg.storage; 1280 final double x = _v3storage[0]; 1281 final double y = _v3storage[1]; 1282 final double z = _v3storage[2]; 1283 final double d = 1.0 / 1284 (argStorage[3] * x + 1285 argStorage[7] * y + 1286 argStorage[11] * z + 1287 argStorage[15]); 1288 _v3storage[0] = (argStorage[0] * x + 1289 argStorage[4] * y + 1290 argStorage[8] * z + 1291 argStorage[12]) * 1292 d; 1293 _v3storage[1] = (argStorage[1] * x + 1294 argStorage[5] * y + 1295 argStorage[9] * z + 1296 argStorage[13]) * 1297 d; 1298 _v3storage[2] = (argStorage[2] * x + 1299 argStorage[6] * y + 1300 argStorage[10] * z + 1301 argStorage[14]) * 1302 d; 1303 } 1304 1305 /// True if any component is infinite. 1306 bool get isInfinite { 1307 bool isInfinite = false; 1308 isInfinite = isInfinite || _v3storage[0].isInfinite; 1309 isInfinite = isInfinite || _v3storage[1].isInfinite; 1310 isInfinite = isInfinite || _v3storage[2].isInfinite; 1311 return isInfinite; 1312 } 1313 1314 /// True if any component is NaN. 1315 bool get isNaN { 1316 bool isNan = false; 1317 isNan = isNan || _v3storage[0].isNaN; 1318 isNan = isNan || _v3storage[1].isNaN; 1319 isNan = isNan || _v3storage[2].isNaN; 1320 return isNan; 1321 } 1322 1323 /// Add [arg] to [this]. 1324 void add(Vector3 arg) { 1325 final Float64List argStorage = arg._v3storage; 1326 _v3storage[0] = _v3storage[0] + argStorage[0]; 1327 _v3storage[1] = _v3storage[1] + argStorage[1]; 1328 _v3storage[2] = _v3storage[2] + argStorage[2]; 1329 } 1330 1331 /// Add [arg] scaled by [factor] to [this]. 1332 void addScaled(Vector3 arg, double factor) { 1333 final Float64List argStorage = arg._v3storage; 1334 _v3storage[0] = _v3storage[0] + argStorage[0] * factor; 1335 _v3storage[1] = _v3storage[1] + argStorage[1] * factor; 1336 _v3storage[2] = _v3storage[2] + argStorage[2] * factor; 1337 } 1338 1339 /// Subtract [arg] from [this]. 1340 void sub(Vector3 arg) { 1341 final Float64List argStorage = arg._v3storage; 1342 _v3storage[0] = _v3storage[0] - argStorage[0]; 1343 _v3storage[1] = _v3storage[1] - argStorage[1]; 1344 _v3storage[2] = _v3storage[2] - argStorage[2]; 1345 } 1346 1347 /// Multiply entries in [this] with entries in [arg]. 1348 void multiply(Vector3 arg) { 1349 final Float64List argStorage = arg._v3storage; 1350 _v3storage[0] = _v3storage[0] * argStorage[0]; 1351 _v3storage[1] = _v3storage[1] * argStorage[1]; 1352 _v3storage[2] = _v3storage[2] * argStorage[2]; 1353 } 1354 1355 /// Divide entries in [this] with entries in [arg]. 1356 void divide(Vector3 arg) { 1357 final Float64List argStorage = arg._v3storage; 1358 _v3storage[0] = _v3storage[0] / argStorage[0]; 1359 _v3storage[1] = _v3storage[1] / argStorage[1]; 1360 _v3storage[2] = _v3storage[2] / argStorage[2]; 1361 } 1362 1363 /// Scale [this]. 1364 void scale(double arg) { 1365 _v3storage[2] = _v3storage[2] * arg; 1366 _v3storage[1] = _v3storage[1] * arg; 1367 _v3storage[0] = _v3storage[0] * arg; 1368 } 1369 1370 /// Create a copy of [this] and scale it by [arg]. 1371 Vector3 scaled(double arg) => clone()..scale(arg); 1372 1373 /// Clone of [this]. 1374 Vector3 clone() => Vector3.copy(this); 1375 1376 /// Copy [this] into [arg]. 1377 Vector3 copyInto(Vector3 arg) { 1378 final Float64List argStorage = arg._v3storage; 1379 argStorage[0] = _v3storage[0]; 1380 argStorage[1] = _v3storage[1]; 1381 argStorage[2] = _v3storage[2]; 1382 return arg; 1383 } 1384 1385 /// Copies [this] into [array] starting at [offset]. 1386 void copyIntoArray(List<double> array, [int offset = 0]) { 1387 array[offset + 2] = _v3storage[2]; 1388 array[offset + 1] = _v3storage[1]; 1389 array[offset + 0] = _v3storage[0]; 1390 } 1391 1392 set x(double arg) => _v3storage[0] = arg; 1393 set y(double arg) => _v3storage[1] = arg; 1394 set z(double arg) => _v3storage[2] = arg; 1395 1396 double get x => _v3storage[0]; 1397 double get y => _v3storage[1]; 1398 double get z => _v3storage[2]; 1399} 1400