collisionCoordinator.ts 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { Nullable } from "../types";
  2. import { Scene } from "../scene";
  3. import { Vector3 } from "../Maths/math";
  4. import { Engine } from "../Engines/engine";
  5. import { Collider } from "./collider";
  6. import { AbstractMesh } from "../Meshes/abstractMesh";
  7. /** @hidden */
  8. export interface ICollisionCoordinator {
  9. createCollider(): Collider;
  10. getNewPosition(position: Vector3, displacement: Vector3, collider: Collider, maximumRetry: number, excludedMesh: Nullable<AbstractMesh>, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh: Nullable<AbstractMesh>) => void, collisionIndex: number): void;
  11. init(scene: Scene): void;
  12. }
  13. /** @hidden */
  14. export class DefaultCollisionCoordinator implements ICollisionCoordinator {
  15. private _scene: Scene;
  16. private _scaledPosition = Vector3.Zero();
  17. private _scaledVelocity = Vector3.Zero();
  18. private _finalPosition = Vector3.Zero();
  19. public getNewPosition(position: Vector3, displacement: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh: Nullable<AbstractMesh>) => void, collisionIndex: number): void {
  20. position.divideToRef(collider._radius, this._scaledPosition);
  21. displacement.divideToRef(collider._radius, this._scaledVelocity);
  22. collider.collidedMesh = null;
  23. collider._retry = 0;
  24. collider._initialVelocity = this._scaledVelocity;
  25. collider._initialPosition = this._scaledPosition;
  26. this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
  27. this._finalPosition.multiplyInPlace(collider._radius);
  28. //run the callback
  29. onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
  30. }
  31. public createCollider(): Collider {
  32. return new Collider();
  33. }
  34. public init(scene: Scene): void {
  35. this._scene = scene;
  36. }
  37. private _collideWithWorld(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: Nullable<AbstractMesh> = null): void {
  38. var closeDistance = Engine.CollisionsEpsilon * 10.0;
  39. if (collider._retry >= maximumRetry) {
  40. finalPosition.copyFrom(position);
  41. return;
  42. }
  43. // Check if this is a mesh else camera or -1
  44. var collisionMask = (excludedMesh ? excludedMesh.collisionMask : collider.collisionMask);
  45. collider._initialize(position, velocity, closeDistance);
  46. // Check all meshes
  47. for (var index = 0; index < this._scene.meshes.length; index++) {
  48. var mesh = this._scene.meshes[index];
  49. if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh && ((collisionMask & mesh.collisionGroup) !== 0)) {
  50. mesh._checkCollision(collider);
  51. }
  52. }
  53. if (!collider.collisionFound) {
  54. position.addToRef(velocity, finalPosition);
  55. return;
  56. }
  57. if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
  58. collider._getResponse(position, velocity);
  59. }
  60. if (velocity.length() <= closeDistance) {
  61. finalPosition.copyFrom(position);
  62. return;
  63. }
  64. collider._retry++;
  65. this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
  66. }
  67. }
  68. Scene.CollisionCoordinatorFactory = () => {
  69. return new DefaultCollisionCoordinator();
  70. };