meshExploder.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { Mesh } from "../Meshes/mesh";
  2. import { Vector3 } from "../Maths/math";
  3. /**
  4. * Class used to explode meshes.
  5. */
  6. export class MeshExploder {
  7. private _centerMesh: Mesh;
  8. private _meshes: Array<Mesh>;
  9. private _meshesOrigins: Array<Vector3>;
  10. private _toCenterVectors: Array<Vector3>;
  11. private _scaledDirection = new Vector3(0.0, 0.0, 0.0);
  12. private _newPosition = new Vector3(0.0, 0.0, 0.0);
  13. private _centerPosition = new Vector3(0.0, 0.0, 0.0);
  14. /**
  15. * Explodes meshes from a center mesh.
  16. * @param meshes The meshes to explode.
  17. * @param centerMesh The mesh to be center of explosion.
  18. */
  19. constructor(meshes: Array<Mesh>, centerMesh?: Mesh) {
  20. this._meshes = meshes.slice();
  21. if (centerMesh) {
  22. this._centerMesh = centerMesh;
  23. } else {
  24. this._setCenterMesh();
  25. }
  26. this._centerPosition = this._centerMesh.getAbsolutePosition().clone();
  27. if (this._meshes.indexOf(this._centerMesh) >= 0) {
  28. this._meshes.splice(this._meshes.indexOf(this._centerMesh), 1);
  29. }
  30. if (this._meshes.length > 1 && this._centerMesh._boundingInfo) {
  31. this._meshesOrigins = [];
  32. this._toCenterVectors = [];
  33. for (var index = 0; index < this._meshes.length; index++) {
  34. if (this._meshes[index]) {
  35. var mesh = this._meshes[index];
  36. if (mesh._boundingInfo) {
  37. this._meshesOrigins.push(mesh.getAbsolutePosition().clone());
  38. this._toCenterVectors.push(mesh._boundingInfo.boundingBox.centerWorld.subtract(this._centerPosition));
  39. }
  40. }
  41. }
  42. }
  43. }
  44. private _setCenterMesh(): void {
  45. var averageCenter = new Vector3(0.0, 0.0, 0.0);
  46. var totalCenters = new Vector3(0.0, 0.0, 0.0);
  47. var shortestToCenter = Number.MAX_VALUE;
  48. for (var index = 0; index < this._meshes.length; index++) {
  49. if (this._meshes[index]) {
  50. var mesh = this._meshes[index];
  51. if (mesh._boundingInfo) {
  52. totalCenters.addInPlace(mesh._boundingInfo.boundingBox.centerWorld);
  53. }
  54. }
  55. }
  56. averageCenter = totalCenters.scale(1 / this._meshes.length);
  57. for (var index = 0; index < this._meshes.length; index++) {
  58. if (this._meshes[index]) {
  59. var mesh = this._meshes[index];
  60. if (mesh._boundingInfo) {
  61. var distanceToCenter = mesh._boundingInfo.boundingBox.centerWorld.subtract(averageCenter).length();
  62. if (distanceToCenter < shortestToCenter) {
  63. this._centerMesh = mesh;
  64. shortestToCenter = distanceToCenter;
  65. }
  66. }
  67. }
  68. }
  69. }
  70. /**
  71. * "MeshExploder"
  72. * @returns "MeshExploder"
  73. */
  74. public getClassName(): string {
  75. return "MeshExploder";
  76. }
  77. /**
  78. * "Exploded meshes"
  79. * @returns Array of meshes with the centerMesh at index 0.
  80. */
  81. public getMeshes(): Array<Mesh> {
  82. var meshArray: Array<Mesh>;
  83. meshArray = this._meshes.slice();
  84. meshArray.unshift(this._centerMesh);
  85. return meshArray;
  86. }
  87. /**
  88. * Explodes mesh a given number of times.
  89. * @param direction Number to multiply distance of each mesh's origin from center. Use a negative number to implode, or zero to reset.
  90. */
  91. public explode(direction: number = 1.0): void {
  92. for (var index = 0; index < this._meshes.length; index++) {
  93. if (this._meshes[index] && this._toCenterVectors[index]) {
  94. this._toCenterVectors[index].scaleToRef(direction, this._scaledDirection);
  95. this._meshesOrigins[index].addToRef(this._scaledDirection, this._newPosition);
  96. this._meshes[index].setAbsolutePosition(this._newPosition);
  97. this._meshes[index].computeWorldMatrix(true);
  98. }
  99. }
  100. this._centerMesh.setAbsolutePosition(this._centerPosition);
  101. }
  102. }