Pārlūkot izejas kodu

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 gadi atpakaļ
vecāks
revīzija
9a41252c66

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

@@ -10,6 +10,7 @@ var BABYLON;
     var ArcRotateCamera = (function (_super) {
     var ArcRotateCamera = (function (_super) {
         __extends(ArcRotateCamera, _super);
         __extends(ArcRotateCamera, _super);
         function ArcRotateCamera(name, alpha, beta, radius, target, scene) {
         function ArcRotateCamera(name, alpha, beta, radius, target, scene) {
+            var _this = this;
             _super.call(this, name, BABYLON.Vector3.Zero(), scene);
             _super.call(this, name, BABYLON.Vector3.Zero(), scene);
             this.alpha = alpha;
             this.alpha = alpha;
             this.beta = beta;
             this.beta = beta;
@@ -41,6 +42,19 @@ var BABYLON;
             this._previousPosition = BABYLON.Vector3.Zero();
             this._previousPosition = BABYLON.Vector3.Zero();
             this._collisionVelocity = BABYLON.Vector3.Zero();
             this._collisionVelocity = BABYLON.Vector3.Zero();
             this._newPosition = 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) {
             if (!this.target) {
                 this.target = BABYLON.Vector3.Zero();
                 this.target = BABYLON.Vector3.Zero();
             }
             }
@@ -274,6 +288,10 @@ var BABYLON;
             }
             }
         };
         };
         ArcRotateCamera.prototype._update = function () {
         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++) {
             for (var index = 0; index < this._keys.length; index++) {
                 var keyCode = this._keys[index];
                 var keyCode = this._keys[index];
                 if (this.keysLeft.indexOf(keyCode) !== -1) {
                 if (this.keysLeft.indexOf(keyCode) !== -1) {
@@ -346,16 +364,8 @@ var BABYLON;
             if (this.checkCollisions) {
             if (this.checkCollisions) {
                 this._collider.radius = this.collisionRadius;
                 this._collider.radius = this.collisionRadius;
                 this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
                 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);
             BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
             this._previousAlpha = this.alpha;
             this._previousAlpha = this.alpha;

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

@@ -50,6 +50,8 @@
         private _previousAlpha: number;
         private _previousAlpha: number;
         private _previousBeta: number;
         private _previousBeta: number;
         private _previousRadius: 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) {
         constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: any, scene: Scene) {
             super(name, Vector3.Zero(), scene);
             super(name, Vector3.Zero(), scene);
@@ -344,6 +346,12 @@
         }
         }
 
 
         public _update(): void {
         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
             // Keyboard
             for (var index = 0; index < this._keys.length; index++) {
             for (var index = 0; index < this._keys.length; index++) {
                 var keyCode = this._keys[index];
                 var keyCode = this._keys[index];
@@ -431,19 +439,8 @@
                 this._collider.radius = this.collisionRadius;
                 this._collider.radius = this.collisionRadius;
                 this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
                 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);
             Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
@@ -459,6 +456,22 @@
             return this._viewMatrix;
             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 {
         public zoomOn(meshes?: AbstractMesh[]): void {
             meshes = meshes || this.getScene().meshes;
             meshes = meshes || this.getScene().meshes;
 
 

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

@@ -9,6 +9,7 @@ var BABYLON;
     var FreeCamera = (function (_super) {
     var FreeCamera = (function (_super) {
         __extends(FreeCamera, _super);
         __extends(FreeCamera, _super);
         function FreeCamera(name, position, scene) {
         function FreeCamera(name, position, scene) {
+            var _this = this;
             _super.call(this, name, position, scene);
             _super.call(this, name, position, scene);
             this.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
             this.ellipsoid = new BABYLON.Vector3(0.5, 1, 0.5);
             this.keysUp = [38];
             this.keysUp = [38];
@@ -24,6 +25,21 @@ var BABYLON;
             this._oldPosition = BABYLON.Vector3.Zero();
             this._oldPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
             this._newPosition = 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
         // Controls
         FreeCamera.prototype.attachControl = function (element, noPreventDefault) {
         FreeCamera.prototype.attachControl = function (element, noPreventDefault) {
@@ -141,7 +157,8 @@ var BABYLON;
                 this._reset();
                 this._reset();
             }
             }
         };
         };
-        FreeCamera.prototype._collideWithWorld = function (velocity) {
+        FreeCamera.prototype._collideWithWorld = function (velocity, gravityInspection) {
+            if (gravityInspection === void 0) { gravityInspection = false; }
             var globalPosition;
             var globalPosition;
             if (this.parent) {
             if (this.parent) {
                 globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
                 globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
@@ -151,14 +168,7 @@ var BABYLON;
             }
             }
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
             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 () {
         FreeCamera.prototype._checkInputs = function () {
             if (!this._localDirection) {
             if (!this._localDirection) {
@@ -190,11 +200,9 @@ var BABYLON;
         };
         };
         FreeCamera.prototype._updatePosition = function () {
         FreeCamera.prototype._updatePosition = function () {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
-                this._collideWithWorld(this.cameraDirection);
+                this._collideWithWorld(this.cameraDirection, false);
                 if (this.applyGravity) {
                 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 {
             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;
             var globalPosition: Vector3;
 
 
             if (this.parent) {
             if (this.parent) {
@@ -189,17 +189,25 @@
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
             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) {
             if (this._diffPosition.length() > Engine.CollisionsEpsilon) {
                 this.position.addInPlace(this._diffPosition);
                 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 {
         public _checkInputs(): void {
             if (!this._localDirection) {
             if (!this._localDirection) {
                 this._localDirection = BABYLON.Vector3.Zero();
                 this._localDirection = BABYLON.Vector3.Zero();
@@ -233,11 +241,9 @@
 
 
         public _updatePosition(): void {
         public _updatePosition(): void {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
-                this._collideWithWorld(this.cameraDirection);
+                this._collideWithWorld(this.cameraDirection, false);
                 if (this.applyGravity) {
                 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 {
             } else {
                 this.position.addInPlace(this.cameraDirection);
                 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) {
     var AbstractMesh = (function (_super) {
         __extends(AbstractMesh, _super);
         __extends(AbstractMesh, _super);
         function AbstractMesh(name, scene) {
         function AbstractMesh(name, scene) {
+            var _this = this;
             _super.call(this, name, scene);
             _super.call(this, name, scene);
             // Properties
             // Properties
             this.definedFacingForward = true; // orientation for POV movement & rotation
             this.definedFacingForward = true; // orientation for POV movement & rotation
@@ -71,6 +72,13 @@ var BABYLON;
             this._intersectionsInProgress = new Array();
             this._intersectionsInProgress = new Array();
             this._onAfterWorldMatrixUpdate = new Array();
             this._onAfterWorldMatrixUpdate = new Array();
             this._isWorldMatrixFrozen = false;
             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);
             scene.addMesh(this);
         }
         }
         Object.defineProperty(AbstractMesh, "BILLBOARDMODE_NONE", {
         Object.defineProperty(AbstractMesh, "BILLBOARDMODE_NONE", {
@@ -602,11 +610,7 @@ var BABYLON;
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPositionForCollisions);
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPositionForCollisions);
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._collider.radius = this.ellipsoid;
             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
         // Submeshes octree
         /**
         /**

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

@@ -714,8 +714,11 @@
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._oldPositionForCollisions.addInPlace(this.ellipsoidOffset);
             this._collider.radius = this.ellipsoid;
             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) {
             if (this._diffPositionForCollisions.length() > Engine.CollisionsEpsilon) {
                 this.position.addInPlace(this._diffPositionForCollisions);
                 this.position.addInPlace(this._diffPositionForCollisions);

+ 3 - 41
Babylon/babylon.scene.js

@@ -86,6 +86,7 @@ var BABYLON;
             this.lensFlareSystems = new Array();
             this.lensFlareSystems = new Array();
             // Collisions
             // Collisions
             this.collisionsEnabled = true;
             this.collisionsEnabled = true;
+            this.workerCollisions = true;
             this.gravity = new BABYLON.Vector3(0, -9.0, 0);
             this.gravity = new BABYLON.Vector3(0, -9.0, 0);
             // Postprocesses
             // Postprocesses
             this.postProcessesEnabled = true;
             this.postProcessesEnabled = true;
@@ -128,8 +129,6 @@ var BABYLON;
             this._activeBones = 0;
             this._activeBones = 0;
             this._activeAnimatables = new Array();
             this._activeAnimatables = new Array();
             this._transformMatrix = BABYLON.Matrix.Zero();
             this._transformMatrix = BABYLON.Matrix.Zero();
-            this._scaledPosition = BABYLON.Vector3.Zero();
-            this._scaledVelocity = BABYLON.Vector3.Zero();
             this._uniqueIdCounter = 0;
             this._uniqueIdCounter = 0;
             this._engine = engine;
             this._engine = engine;
             engine.scenes.push(this);
             engine.scenes.push(this);
@@ -143,6 +142,8 @@ var BABYLON;
             this.mainSoundTrack = new BABYLON.SoundTrack(this, { mainTrack: true });
             this.mainSoundTrack = new BABYLON.SoundTrack(this, { mainTrack: true });
             //simplification queue
             //simplification queue
             this.simplificationQueue = new BABYLON.SimplificationQueue();
             this.simplificationQueue = new BABYLON.SimplificationQueue();
+            //collision coordinator
+            this.collisionCoordinator = new BABYLON.CollisionCoordinator(this);
         }
         }
         Object.defineProperty(Scene, "FOGMODE_NONE", {
         Object.defineProperty(Scene, "FOGMODE_NONE", {
             get: function () {
             get: function () {
@@ -1488,45 +1489,6 @@ var BABYLON;
                 this.soundTracks[scIndex].dispose();
                 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
         // Octrees
         Scene.prototype.getWorldExtends = function () {
         Scene.prototype.getWorldExtends = function () {
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             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
         // Collisions
         public collisionsEnabled = true;
         public collisionsEnabled = true;
+        public workerCollisions = true;
+        public collisionCoordinator: CollisionCoordinator;
         public gravity = new Vector3(0, -9.0, 0);
         public gravity = new Vector3(0, -9.0, 0);
 
 
         // Postprocesses
         // Postprocesses
@@ -247,9 +249,6 @@
         private _transformMatrix = Matrix.Zero();
         private _transformMatrix = Matrix.Zero();
         private _pickWithRayInverseMatrix: Matrix;
         private _pickWithRayInverseMatrix: Matrix;
 
 
-        private _scaledPosition = Vector3.Zero();
-        private _scaledVelocity = Vector3.Zero();
-
         private _boundingBoxRenderer: BoundingBoxRenderer;
         private _boundingBoxRenderer: BoundingBoxRenderer;
         private _outlineRenderer: OutlineRenderer;
         private _outlineRenderer: OutlineRenderer;
 
 
@@ -292,6 +291,8 @@
 
 
             //simplification queue
             //simplification queue
             this.simplificationQueue = new SimplificationQueue();
             this.simplificationQueue = new SimplificationQueue();
+            //collision coordinator
+            this.collisionCoordinator = new CollisionCoordinator(this);
         }
         }
 
 
         // Properties 
         // 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
         // Octrees
         public getWorldExtends(): { min: Vector3; max: Vector3 } {
         public getWorldExtends(): { min: Vector3; max: Vector3 } {
             var min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);