浏览代码

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 10 年之前
父节点
当前提交
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);