Explorar o código

First major changes for worker collisions

The new architecture fits an async paradigm - callbacks for position
change were added to all three nodes that are detecting collisions (free
camera, arc rotate camera and abstract mesh).
Scene now doesn't directly handle collisions.
Raanan Weber %!s(int64=10) %!d(string=hai) anos
pai
achega
9a41252c66

+ 20 - 10
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -10,6 +10,7 @@ var BABYLON;
     var ArcRotateCamera = (function (_super) {
         __extends(ArcRotateCamera, _super);
         function ArcRotateCamera(name, alpha, beta, radius, target, scene) {
+            var _this = this;
             _super.call(this, name, BABYLON.Vector3.Zero(), scene);
             this.alpha = alpha;
             this.beta = beta;
@@ -41,6 +42,19 @@ var BABYLON;
             this._previousPosition = BABYLON.Vector3.Zero();
             this._collisionVelocity = BABYLON.Vector3.Zero();
             this._newPosition = BABYLON.Vector3.Zero();
+            this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
+                if (collidedMesh === void 0) { collidedMesh = null; }
+                if (!newPosition.equalsWithEpsilon(_this.position)) {
+                    _this.position.copyFrom(_this._previousPosition);
+                    _this.alpha = _this._previousAlpha;
+                    _this.beta = _this._previousBeta;
+                    _this.radius = _this._previousRadius;
+                    if (_this.onCollide && collidedMesh) {
+                        _this.onCollide(collidedMesh);
+                    }
+                }
+                _this._collisionTriggered = false;
+            };
             if (!this.target) {
                 this.target = BABYLON.Vector3.Zero();
             }
@@ -274,6 +288,10 @@ var BABYLON;
             }
         };
         ArcRotateCamera.prototype._update = function () {
+            //if (async) collision inspection was triggered, don't update the camera's position - until the collision callback was called.
+            if (this._collisionTriggered) {
+                return;
+            }
             for (var index = 0; index < this._keys.length; index++) {
                 var keyCode = this._keys[index];
                 if (this.keysLeft.indexOf(keyCode) !== -1) {
@@ -346,16 +364,8 @@ var BABYLON;
             if (this.checkCollisions) {
                 this._collider.radius = this.collisionRadius;
                 this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
-                this.getScene()._getNewPosition(this._previousPosition, this._collisionVelocity, this._collider, 3, this._newPosition);
-                if (!this._newPosition.equalsWithEpsilon(this.position)) {
-                    this.position.copyFrom(this._previousPosition);
-                    this.alpha = this._previousAlpha;
-                    this.beta = this._previousBeta;
-                    this.radius = this._previousRadius;
-                    if (this.onCollide) {
-                        this.onCollide(this._collider.collidedMesh);
-                    }
-                }
+                this._collisionTriggered = true;
+                this.getScene().collisionCoordinator._getNewPosition(this._previousPosition, this._collisionVelocity, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
             }
             BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
             this._previousAlpha = this.alpha;

+ 26 - 13
Babylon/Cameras/babylon.arcRotateCamera.ts

@@ -50,6 +50,8 @@
         private _previousAlpha: number;
         private _previousBeta: number;
         private _previousRadius: number;
+        //due to async collision inspection
+        private _collisionTriggered: boolean;
 
         constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: any, scene: Scene) {
             super(name, Vector3.Zero(), scene);
@@ -344,6 +346,12 @@
         }
 
         public _update(): void {
+
+            //if (async) collision inspection was triggered, don't update the camera's position - until the collision callback was called.
+            if (this._collisionTriggered) {
+                return;
+            }
+
             // Keyboard
             for (var index = 0; index < this._keys.length; index++) {
                 var keyCode = this._keys[index];
@@ -431,19 +439,8 @@
                 this._collider.radius = this.collisionRadius;
                 this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
 
-                this.getScene()._getNewPosition(this._previousPosition, this._collisionVelocity, this._collider, 3, this._newPosition);
-
-                if (!this._newPosition.equalsWithEpsilon(this.position)) {
-                    this.position.copyFrom(this._previousPosition);
-
-                    this.alpha = this._previousAlpha;
-                    this.beta = this._previousBeta;
-                    this.radius = this._previousRadius;
-
-                    if (this.onCollide) {
-                        this.onCollide(this._collider.collidedMesh);
-                    }
-                }
+                this._collisionTriggered = true;
+                this.getScene().collisionCoordinator._getNewPosition(this._previousPosition, this._collisionVelocity, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
             }
 
             Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
@@ -459,6 +456,22 @@
             return this._viewMatrix;
         }
 
+        private _onCollisionPositionChange = (collisionId: number, newPosition: Vector3, collidedMesh: AbstractMesh = null) => {
+
+            if (!newPosition.equalsWithEpsilon(this.position)) {
+                this.position.copyFrom(this._previousPosition);
+
+                this.alpha = this._previousAlpha;
+                this.beta = this._previousBeta;
+                this.radius = this._previousRadius;
+
+                if (this.onCollide && collidedMesh) {
+                    this.onCollide(collidedMesh);
+                }
+            }
+            this._collisionTriggered = false;
+        }
+
         public zoomOn(meshes?: AbstractMesh[]): void {
             meshes = meshes || this.getScene().meshes;
 

+ 21 - 13
Babylon/Cameras/babylon.freeCamera.js

@@ -9,6 +9,7 @@ var BABYLON;
     var FreeCamera = (function (_super) {
         __extends(FreeCamera, _super);
         function FreeCamera(name, position, scene) {
+            var _this = this;
             _super.call(this, name, position, scene);
             this.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
             this.keysUp = [38];
@@ -24,6 +25,21 @@ var BABYLON;
             this._oldPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
             this._newPosition = BABYLON.Vector3.Zero();
+            this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
+                if (collidedMesh === void 0) { collidedMesh = null; }
+                newPosition.subtractToRef(_this._oldPosition, _this._diffPosition);
+                var oldPosition = _this.position.clone();
+                if (_this._diffPosition.length() > BABYLON.Engine.CollisionsEpsilon) {
+                    _this.position.addInPlace(_this._diffPosition);
+                    if (_this.onCollide && collidedMesh) {
+                        _this.onCollide(collidedMesh);
+                    }
+                }
+                //check if it is the gravity inspection
+                if (collisionId != _this.uniqueId) {
+                    _this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, _this.position) != 0);
+                }
+            };
         }
         // Controls
         FreeCamera.prototype.attachControl = function (element, noPreventDefault) {
@@ -141,7 +157,8 @@ var BABYLON;
                 this._reset();
             }
         };
-        FreeCamera.prototype._collideWithWorld = function (velocity) {
+        FreeCamera.prototype._collideWithWorld = function (velocity, gravityInspection) {
+            if (gravityInspection === void 0) { gravityInspection = false; }
             var globalPosition;
             if (this.parent) {
                 globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
@@ -151,14 +168,7 @@ var BABYLON;
             }
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
-            this.getScene()._getNewPosition(this._oldPosition, velocity, this._collider, 3, this._newPosition);
-            this._newPosition.subtractToRef(this._oldPosition, this._diffPosition);
-            if (this._diffPosition.length() > BABYLON.Engine.CollisionsEpsilon) {
-                this.position.addInPlace(this._diffPosition);
-                if (this.onCollide) {
-                    this.onCollide(this._collider.collidedMesh);
-                }
-            }
+            this.getScene().collisionCoordinator._getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, velocity.equals(this.getScene().gravity) ? this.uniqueId + 100000 : this.uniqueId);
         };
         FreeCamera.prototype._checkInputs = function () {
             if (!this._localDirection) {
@@ -190,11 +200,9 @@ var BABYLON;
         };
         FreeCamera.prototype._updatePosition = function () {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
-                this._collideWithWorld(this.cameraDirection);
+                this._collideWithWorld(this.cameraDirection, false);
                 if (this.applyGravity) {
-                    var oldPosition = this.position;
-                    this._collideWithWorld(this.getScene().gravity);
-                    this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, this.position) != 0);
+                    this._collideWithWorld(this.getScene().gravity, true);
                 }
             }
             else {

+ 16 - 10
Babylon/Cameras/babylon.freeCamera.ts

@@ -177,7 +177,7 @@
             }
         }
 
-        public _collideWithWorld(velocity: Vector3): void {
+        public _collideWithWorld(velocity: Vector3, gravityInspection: boolean = false): void {
             var globalPosition: Vector3;
 
             if (this.parent) {
@@ -189,17 +189,25 @@
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
 
-            this.getScene()._getNewPosition(this._oldPosition, velocity, this._collider, 3, this._newPosition);
-            this._newPosition.subtractToRef(this._oldPosition, this._diffPosition);
+            this.getScene().collisionCoordinator._getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, velocity.equals(this.getScene().gravity) ? this.uniqueId + 100000 : this.uniqueId);
+            
+        }
 
+        private _onCollisionPositionChange = (collisionId: number, newPosition: Vector3, collidedMesh: AbstractMesh = null) => {
+            newPosition.subtractToRef(this._oldPosition, this._diffPosition);
+            var oldPosition = this.position.clone();
             if (this._diffPosition.length() > Engine.CollisionsEpsilon) {
                 this.position.addInPlace(this._diffPosition);
-                if (this.onCollide) {
-                    this.onCollide(this._collider.collidedMesh);
+                if (this.onCollide && collidedMesh) {
+                    this.onCollide(collidedMesh);
                 }
             }
+            //check if it is the gravity inspection
+            if (collisionId != this.uniqueId) {
+                this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, this.position) != 0);
+            }
         }
-
+        
         public _checkInputs(): void {
             if (!this._localDirection) {
                 this._localDirection = BABYLON.Vector3.Zero();
@@ -233,11 +241,9 @@
 
         public _updatePosition(): void {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
-                this._collideWithWorld(this.cameraDirection);
+                this._collideWithWorld(this.cameraDirection, false);
                 if (this.applyGravity) {
-                    var oldPosition = this.position;
-                    this._collideWithWorld(this.getScene().gravity);
-                    this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, this.position) != 0);
+                    this._collideWithWorld(this.getScene().gravity, true);
                 }
             } else {
                 this.position.addInPlace(this.cameraDirection);

+ 62 - 0
Babylon/Collisions/babylon.collisionCoordinator.js

@@ -0,0 +1,62 @@
+var BABYLON;
+(function (BABYLON) {
+    var CollisionCoordinator = (function () {
+        function CollisionCoordinator(_scene) {
+            this._scene = _scene;
+            this._scaledPosition = BABYLON.Vector3.Zero();
+            this._scaledVelocity = BABYLON.Vector3.Zero();
+            this._finalPosition = BABYLON.Vector3.Zero();
+            this._collisionsCallbackArray = [];
+            //TODO initialize worker here
+        }
+        // Collisions
+        CollisionCoordinator.prototype._getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
+            if (excludedMesh === void 0) { excludedMesh = null; }
+            if (collisionIndex === void 0) { collisionIndex = 0; }
+            position.divideToRef(collider.radius, this._scaledPosition);
+            velocity.divideToRef(collider.radius, this._scaledVelocity);
+            if (this._scene.workerCollisions) {
+            }
+            else {
+                collider.retry = 0;
+                collider.initialVelocity = this._scaledVelocity;
+                collider.initialPosition = this._scaledPosition;
+                this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
+                this._finalPosition.multiplyInPlace(collider.radius);
+                //run the callback
+                onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
+            }
+        };
+        CollisionCoordinator.prototype._collideWithWorld = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
+            if (excludedMesh === void 0) { excludedMesh = null; }
+            var closeDistance = BABYLON.Engine.CollisionsEpsilon * 10.0;
+            if (collider.retry >= maximumRetry) {
+                finalPosition.copyFrom(position);
+                return;
+            }
+            collider._initialize(position, velocity, closeDistance);
+            for (var index = 0; index < this._scene.meshes.length; index++) {
+                var mesh = this._scene.meshes[index];
+                if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
+                    mesh._checkCollision(collider);
+                }
+            }
+            if (!collider.collisionFound) {
+                position.addToRef(velocity, finalPosition);
+                return;
+            }
+            if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
+                collider._getResponse(position, velocity);
+            }
+            if (velocity.length() <= closeDistance) {
+                finalPosition.copyFrom(position);
+                return;
+            }
+            collider.retry++;
+            this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
+        };
+        return CollisionCoordinator;
+    })();
+    BABYLON.CollisionCoordinator = CollisionCoordinator;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.collisionCoordinator.js.map

+ 74 - 0
Babylon/Collisions/babylon.collisionCoordinator.ts

@@ -0,0 +1,74 @@
+module BABYLON {
+    
+    export class CollisionCoordinator {
+        
+        private _collisionsCallbackArray: Array<Function>;
+
+        private _scaledPosition = Vector3.Zero();
+        private _scaledVelocity = Vector3.Zero();
+
+        private _finalPosition = Vector3.Zero();
+        
+        constructor(private _scene:Scene) {
+            this._collisionsCallbackArray = [];
+            //TODO initialize worker here
+        }    
+
+        // Collisions
+        public _getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh = null, onNewPosition?: (collisionId : number, newPosition: BABYLON.Vector3, collidedMesh?: BABYLON.AbstractMesh) => void, collisionIndex: number = 0): void {
+            position.divideToRef(collider.radius, this._scaledPosition);
+            velocity.divideToRef(collider.radius, this._scaledVelocity);
+
+            if (this._scene.workerCollisions) {
+
+            } else {
+                collider.retry = 0;
+                collider.initialVelocity = this._scaledVelocity;
+                collider.initialPosition = this._scaledPosition;
+                this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
+                
+                this._finalPosition.multiplyInPlace(collider.radius);
+                //run the callback
+                onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
+            }
+        }
+
+        private _collideWithWorld(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: AbstractMesh = null): void {
+            var closeDistance = Engine.CollisionsEpsilon * 10.0;
+
+            if (collider.retry >= maximumRetry) {
+                finalPosition.copyFrom(position);
+                return;
+            }
+
+            collider._initialize(position, velocity, closeDistance);
+
+            // Check all meshes
+            for (var index = 0; index < this._scene.meshes.length; index++) {
+                var mesh = this._scene.meshes[index];
+                if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
+                    mesh._checkCollision(collider);
+                }
+            }
+
+            if (!collider.collisionFound) {
+                position.addToRef(velocity, finalPosition);
+                return;
+            }
+
+            if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
+                collider._getResponse(position, velocity);
+            }
+
+            if (velocity.length() <= closeDistance) {
+                finalPosition.copyFrom(position);
+                return;
+            }
+
+            collider.retry++;
+            this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
+        }
+
+    }
+
+}

+ 9 - 5
Babylon/Mesh/babylon.abstractMesh.js

@@ -9,6 +9,7 @@ var BABYLON;
     var AbstractMesh = (function (_super) {
         __extends(AbstractMesh, _super);
         function AbstractMesh(name, scene) {
+            var _this = this;
             _super.call(this, name, scene);
             // Properties
             this.definedFacingForward = true; // orientation for POV movement & rotation
@@ -71,6 +72,13 @@ var BABYLON;
             this._intersectionsInProgress = new Array();
             this._onAfterWorldMatrixUpdate = new Array();
             this._isWorldMatrixFrozen = false;
+            this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
+                if (collidedMesh === void 0) { collidedMesh = null; }
+                newPosition.subtractToRef(_this._oldPositionForCollisions, _this._diffPositionForCollisions);
+                if (_this._diffPositionForCollisions.length() > BABYLON.Engine.CollisionsEpsilon) {
+                    _this.position.addInPlace(_this._diffPositionForCollisions);
+                }
+            };
             scene.addMesh(this);
         }
         Object.defineProperty(AbstractMesh, "BILLBOARDMODE_NONE", {
@@ -602,11 +610,7 @@ var BABYLON;
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPositionForCollisions);
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._collider.radius = this.ellipsoid;
-            this.getScene()._getNewPosition(this._oldPositionForCollisions, velocity, this._collider, 3, this._newPositionForCollisions, this);
-            this._newPositionForCollisions.subtractToRef(this._oldPositionForCollisions, this._diffPositionForCollisions);
-            if (this._diffPositionForCollisions.length() > BABYLON.Engine.CollisionsEpsilon) {
-                this.position.addInPlace(this._diffPositionForCollisions);
-            }
+            this.getScene().collisionCoordinator._getNewPosition(this._oldPositionForCollisions, velocity, this._collider, 3, this, this._onCollisionPositionChange, this.uniqueId);
         };
         // Submeshes octree
         /**

+ 5 - 2
Babylon/Mesh/babylon.abstractMesh.ts

@@ -714,8 +714,11 @@
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._collider.radius = this.ellipsoid;
 
-            this.getScene()._getNewPosition(this._oldPositionForCollisions, velocity, this._collider, 3, this._newPositionForCollisions, this);
-            this._newPositionForCollisions.subtractToRef(this._oldPositionForCollisions, this._diffPositionForCollisions);
+            this.getScene().collisionCoordinator._getNewPosition(this._oldPositionForCollisions, velocity, this._collider, 3, this, this._onCollisionPositionChange, this.uniqueId);
+        }
+
+        private _onCollisionPositionChange = (collisionId: number, newPosition: Vector3, collidedMesh: AbstractMesh = null) => {
+            newPosition.subtractToRef(this._oldPositionForCollisions, this._diffPositionForCollisions);
 
             if (this._diffPositionForCollisions.length() > Engine.CollisionsEpsilon) {
                 this.position.addInPlace(this._diffPositionForCollisions);

+ 3 - 41
Babylon/babylon.scene.js

@@ -86,6 +86,7 @@ var BABYLON;
             this.lensFlareSystems = new Array();
             // Collisions
             this.collisionsEnabled = true;
+            this.workerCollisions = true;
             this.gravity = new BABYLON.Vector3(0, -9.0, 0);
             // Postprocesses
             this.postProcessesEnabled = true;
@@ -128,8 +129,6 @@ var BABYLON;
             this._activeBones = 0;
             this._activeAnimatables = new Array();
             this._transformMatrix = BABYLON.Matrix.Zero();
-            this._scaledPosition = BABYLON.Vector3.Zero();
-            this._scaledVelocity = BABYLON.Vector3.Zero();
             this._uniqueIdCounter = 0;
             this._engine = engine;
             engine.scenes.push(this);
@@ -143,6 +142,8 @@ var BABYLON;
             this.mainSoundTrack = new BABYLON.SoundTrack(this, { mainTrack: true });
             //simplification queue
             this.simplificationQueue = new BABYLON.SimplificationQueue();
+            //collision coordinator
+            this.collisionCoordinator = new BABYLON.CollisionCoordinator(this);
         }
         Object.defineProperty(Scene, "FOGMODE_NONE", {
             get: function () {
@@ -1488,45 +1489,6 @@ var BABYLON;
                 this.soundTracks[scIndex].dispose();
             }
         };
-        // Collisions
-        Scene.prototype._getNewPosition = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
-            if (excludedMesh === void 0) { excludedMesh = null; }
-            position.divideToRef(collider.radius, this._scaledPosition);
-            velocity.divideToRef(collider.radius, this._scaledVelocity);
-            collider.retry = 0;
-            collider.initialVelocity = this._scaledVelocity;
-            collider.initialPosition = this._scaledPosition;
-            this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, finalPosition, excludedMesh);
-            finalPosition.multiplyInPlace(collider.radius);
-        };
-        Scene.prototype._collideWithWorld = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
-            if (excludedMesh === void 0) { excludedMesh = null; }
-            var closeDistance = BABYLON.Engine.CollisionsEpsilon * 10.0;
-            if (collider.retry >= maximumRetry) {
-                finalPosition.copyFrom(position);
-                return;
-            }
-            collider._initialize(position, velocity, closeDistance);
-            for (var index = 0; index < this.meshes.length; index++) {
-                var mesh = this.meshes[index];
-                if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
-                    mesh._checkCollision(collider);
-                }
-            }
-            if (!collider.collisionFound) {
-                position.addToRef(velocity, finalPosition);
-                return;
-            }
-            if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
-                collider._getResponse(position, velocity);
-            }
-            if (velocity.length() <= closeDistance) {
-                finalPosition.copyFrom(position);
-                return;
-            }
-            collider.retry++;
-            this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
-        };
         // Octrees
         Scene.prototype.getWorldExtends = function () {
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);

+ 4 - 52
Babylon/babylon.scene.ts

@@ -163,6 +163,8 @@
 
         // Collisions
         public collisionsEnabled = true;
+        public workerCollisions = true;
+        public collisionCoordinator: CollisionCoordinator;
         public gravity = new Vector3(0, -9.0, 0);
 
         // Postprocesses
@@ -247,9 +249,6 @@
         private _transformMatrix = Matrix.Zero();
         private _pickWithRayInverseMatrix: Matrix;
 
-        private _scaledPosition = Vector3.Zero();
-        private _scaledVelocity = Vector3.Zero();
-
         private _boundingBoxRenderer: BoundingBoxRenderer;
         private _outlineRenderer: OutlineRenderer;
 
@@ -292,6 +291,8 @@
 
             //simplification queue
             this.simplificationQueue = new SimplificationQueue();
+            //collision coordinator
+            this.collisionCoordinator = new CollisionCoordinator(this);
         }
 
         // Properties 
@@ -1892,55 +1893,6 @@
             }
         }
 
-        // Collisions
-        public _getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: AbstractMesh = null): void {
-            position.divideToRef(collider.radius, this._scaledPosition);
-            velocity.divideToRef(collider.radius, this._scaledVelocity);
-
-            collider.retry = 0;
-            collider.initialVelocity = this._scaledVelocity;
-            collider.initialPosition = this._scaledPosition;
-            this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, finalPosition, excludedMesh);
-
-            finalPosition.multiplyInPlace(collider.radius);
-        }
-
-        private _collideWithWorld(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh: AbstractMesh = null): void {
-            var closeDistance = Engine.CollisionsEpsilon * 10.0;
-
-            if (collider.retry >= maximumRetry) {
-                finalPosition.copyFrom(position);
-                return;
-            }
-
-            collider._initialize(position, velocity, closeDistance);
-
-            // Check all meshes
-            for (var index = 0; index < this.meshes.length; index++) {
-                var mesh = this.meshes[index];
-                if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
-                    mesh._checkCollision(collider);
-                }
-            }
-
-            if (!collider.collisionFound) {
-                position.addToRef(velocity, finalPosition);
-                return;
-            }
-
-            if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
-                collider._getResponse(position, velocity);
-            }
-
-            if (velocity.length() <= closeDistance) {
-                finalPosition.copyFrom(position);
-                return;
-            }
-
-            collider.retry++;
-            this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
-        }
-
         // Octrees
         public getWorldExtends(): { min: Vector3; max: Vector3 } {
             var min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);