Source: utils.js

  1. import { Vector3, Matrix4 } from 'three';
  2. /**
  3. * A collection of utilities.
  4. * @module utils
  5. */
  6. const t1 = new Vector3();
  7. const t2 = new Vector3();
  8. const t3 = new Vector3();
  9. const m1 = new Matrix4();
  10. /**
  11. * Returns the world position of object and sets
  12. * it on target.
  13. *
  14. * @param {THREE.Object3D} object
  15. * @param {THREE.Vector3} target
  16. */
  17. export function getWorldPosition(object, target) {
  18. return target.setFromMatrixPosition(object.matrixWorld);
  19. }
  20. /**
  21. * Returns the distance between two objects.
  22. *
  23. * @param {THREE.Object3D} obj1
  24. * @param {THREE.Object3D} obj2
  25. * @return {number}
  26. */
  27. export function getWorldDistance(obj1, obj2) {
  28. getWorldPosition(obj1, t1);
  29. getWorldPosition(obj2, t2);
  30. return a.distanceTo(b);
  31. }
  32. /**
  33. * Sets the target to the centroid position between all passed in
  34. * positions.
  35. *
  36. * @param {Array<THREE.Vector3>} positions
  37. * @param {THREE.Vector3} target
  38. */
  39. export function getCentroid(positions, target) {
  40. target.set(0, 0, 0);
  41. for (let position of positions) {
  42. target.add(position);
  43. }
  44. target.divideScalar(positions.length);
  45. return target;
  46. };
  47. /**
  48. * Takes a direction vector and an up vector and sets
  49. * `target` quaternion to the rotation. Similar to THREE.Matrix4's
  50. * `lookAt` function, except rather than taking two Vector3 points,
  51. * we've already calculaeld the direction earlier so skip the first half.
  52. *
  53. * @param {THREE.Vector3} direction
  54. * @param {THREE.Vector3} up
  55. * @param {THREE.Quaternion} target
  56. */
  57. export function setQuaternionFromDirection(direction, up, target) {
  58. const x = t1;
  59. const y = t2;
  60. const z = t3;
  61. const m = m1;
  62. const el = m1.elements;
  63. z.copy(direction);
  64. x.crossVectors(up, z);
  65. if (x.lengthSq() === 0) {
  66. // parallel
  67. if (Math.abs(up.z) === 1) {
  68. z.x += 0.0001;
  69. } else {
  70. z.z += 0.0001;
  71. }
  72. z.normalize();
  73. x.crossVectors(up, z);
  74. }
  75. x.normalize();
  76. y.crossVectors(z, x);
  77. el[ 0 ] = x.x; el[ 4 ] = y.x; el[ 8 ] = z.x;
  78. el[ 1 ] = x.y; el[ 5 ] = y.y; el[ 9 ] = z.y;
  79. el[ 2 ] = x.z; el[ 6 ] = y.z; el[ 10 ] = z.z;
  80. target.setFromRotationMatrix(m);
  81. }
  82. /**
  83. * Implementation of Unity's Transform.transformPoint, which is similar
  84. * to three's Vector3.transformDirection, except we want to take scale into account,
  85. * as we're not transforming a direction. Function taken from BabylonJS.
  86. *
  87. * From BabylonJS's `Vector3.transformCoordinates`:
  88. * Sets the passed vector coordinates with the result of the transformation by the
  89. * passed matrix of the passed vector. This method computes tranformed coordinates only,
  90. * not transformed direction vectors (ie. it takes translation in account)
  91. *
  92. * @see https://docs.unity3d.com/ScriptReference/Transform.TransformPoint.html
  93. * @see https://github.com/BabylonJS/Babylon.js/blob/6050288da37623088d5f613ca2d85aef877c5cd5/src/Math/babylon.math.ts#L1936
  94. * @param {THREE.Vector3} vector
  95. * @param {THREE.Matrix4} matrix
  96. * @param {THREE.Vector3} target
  97. */
  98. export function transformPoint(vector, matrix, target) {
  99. const e = matrix.elements;
  100. const x = (vector.x * e[0]) + (vector.y * e[4]) + (vector.z * e[8]) + e[12];
  101. const y = (vector.x * e[1]) + (vector.y * e[5]) + (vector.z * e[9]) + e[13];
  102. const z = (vector.x * e[2]) + (vector.y * e[6]) + (vector.z * e[10]) + e[14];
  103. const w = (vector.x * e[3]) + (vector.y * e[7]) + (vector.z * e[11]) + e[15];
  104. target.set(x / w, y / w, z / w);
  105. };