Browse Source

Merge pull request #503 from RaananW/webworker-fix

Fix for collision worker and gravity
David Catuhe 10 years ago
parent
commit
c3dfb41b29

+ 34 - 18
Babylon/Cameras/babylon.freeCamera.js

@@ -21,28 +21,47 @@ var BABYLON;
             this.angularSensibility = 2000.0;
             this._keys = [];
             this._collider = new BABYLON.Collider();
-            this._needMoveForGravity = true;
+            this._needMoveForGravity = false;
             this._oldPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
             this._newPosition = BABYLON.Vector3.Zero();
+            this._newPositionBuffer = BABYLON.Vector3.Zero();
             this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
                 if (collidedMesh === void 0) { collidedMesh = null; }
+                var fromGravity = collisionId !== _this.uniqueId;
                 //TODO move this to the collision coordinator!
-                if (collisionId != null || collisionId != undefined)
+                if (_this.getScene().workerCollisions)
                     newPosition.multiplyInPlace(_this._collider.radius);
-                _this._newPosition.copyFrom(newPosition);
-                _this._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);
-                    }
+                //If this is a gravity-enabled camera AND this is the regular inspection, use the new position for grvity inspection.
+                if (!fromGravity && _this.applyGravity) {
+                    _this._newPositionBuffer.copyFrom(newPosition);
+                    _this._newPositionBuffer.subtractToRef(_this._oldPosition, _this._diffPosition);
+                    _this.position.addToRef(_this._diffPosition, _this._newPositionBuffer);
+                    //send the gravity collision inspection.
+                    _this._collideWithWorld(_this.getScene().gravity, true);
+                    //don't update the position yet, to prevent "jumping".
+                    return;
                 }
-                //check if it is the gravity inspection
-                if (collisionId != _this.uniqueId) {
-                    _this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, _this.position) != 0);
+                var updatePosition = function (newPos) {
+                    _this._newPosition.copyFrom(newPos);
+                    _this._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 (fromGravity) {
+                        _this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, _this.position) != 0);
+                    }
+                };
+                if (fromGravity) {
+                    //if arrived from gravity, use the buffered diffPosition that was created during the regular collision check.
+                    _this.position.addInPlace(_this._diffPosition);
                 }
+                updatePosition(newPosition);
             };
         }
         // Controls
@@ -165,14 +184,14 @@ var BABYLON;
             if (gravityInspection === void 0) { gravityInspection = false; }
             var globalPosition;
             if (this.parent) {
-                globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
+                globalPosition = BABYLON.Vector3.TransformCoordinates(gravityInspection ? this._newPositionBuffer : this.position, this.parent.getWorldMatrix());
             }
             else {
                 globalPosition = this.position;
             }
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
-            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, velocity.equals(this.getScene().gravity) ? this.uniqueId + 100000 : this.uniqueId);
+            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, gravityInspection ? this.uniqueId + 100000 : this.uniqueId);
         };
         FreeCamera.prototype._checkInputs = function () {
             if (!this._localDirection) {
@@ -205,9 +224,6 @@ var BABYLON;
         FreeCamera.prototype._updatePosition = function () {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
                 this._collideWithWorld(this.cameraDirection, false);
-                if (this.applyGravity) {
-                    this._collideWithWorld(this.getScene().gravity, true);
-                }
             }
             else {
                 this.position.addInPlace(this.cameraDirection);

+ 40 - 18
Babylon/Cameras/babylon.freeCamera.ts

@@ -12,10 +12,11 @@
 
         private _keys = [];
         private _collider = new Collider();
-        private _needMoveForGravity = true;
+        private _needMoveForGravity = false;
         private _oldPosition = BABYLON.Vector3.Zero();
         private _diffPosition = BABYLON.Vector3.Zero();
         private _newPosition = BABYLON.Vector3.Zero();
+        private _newPositionBuffer = BABYLON.Vector3.Zero();
         private _attachedElement: HTMLElement;
         private _localDirection: Vector3;
         private _transformedDirection: Vector3;
@@ -181,7 +182,7 @@
             var globalPosition: Vector3;
 
             if (this.parent) {
-                globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
+                globalPosition = BABYLON.Vector3.TransformCoordinates(gravityInspection ? this._newPositionBuffer : this.position, this.parent.getWorldMatrix());
             } else {
                 globalPosition = this.position;
             }
@@ -189,30 +190,51 @@
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPosition);
             this._collider.radius = this.ellipsoid;
 
-            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, velocity.equals(this.getScene().gravity) ? this.uniqueId + 100000 : this.uniqueId);
+            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, velocity, this._collider, 3, null, this._onCollisionPositionChange, gravityInspection ? this.uniqueId + 100000 : this.uniqueId);
             
         }
 
         private _onCollisionPositionChange = (collisionId: number, newPosition: Vector3, collidedMesh: AbstractMesh = null) => {
+            var fromGravity: boolean = collisionId !== this.uniqueId;
+
             //TODO move this to the collision coordinator!
-            if (collisionId != null || collisionId != undefined)
+            if (this.getScene().workerCollisions)
                 newPosition.multiplyInPlace(this._collider.radius);
 
-            this._newPosition.copyFrom(newPosition);
+            //If this is a gravity-enabled camera AND this is the regular inspection, use the new position for grvity inspection.
+            if (!fromGravity && this.applyGravity) {
+                this._newPositionBuffer.copyFrom(newPosition);
+                this._newPositionBuffer.subtractToRef(this._oldPosition, this._diffPosition);
+                this.position.addToRef(this._diffPosition, this._newPositionBuffer);
+                //send the gravity collision inspection.
+                this._collideWithWorld(this.getScene().gravity, true);
+                //don't update the position yet, to prevent "jumping".
+                return;
+            }
+
+            var updatePosition = (newPos) => {
+                this._newPosition.copyFrom(newPos);
 
-            this._newPosition.subtractToRef(this._oldPosition, this._diffPosition);
+                this._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 && collidedMesh) {
-                    this.onCollide(collidedMesh);
+                var oldPosition = this.position.clone();
+                if (this._diffPosition.length() > Engine.CollisionsEpsilon) {
+                    this.position.addInPlace(this._diffPosition);
+                    if (this.onCollide && collidedMesh) {
+                        this.onCollide(collidedMesh);
+                    }
                 }
+                //check if it is the gravity inspection
+                if (fromGravity) {
+                    this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, this.position) != 0);
+                }
+            }    
+            
+            if (fromGravity) {
+                //if arrived from gravity, use the buffered diffPosition that was created during the regular collision check.
+                this.position.addInPlace(this._diffPosition);
             }
-            //check if it is the gravity inspection
-            if (collisionId != this.uniqueId) {
-                this._needMoveForGravity = (BABYLON.Vector3.DistanceSquared(oldPosition, this.position) != 0);
-            }
+            updatePosition(newPosition);
         }
         
         public _checkInputs(): void {
@@ -249,9 +271,9 @@
         public _updatePosition(): void {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
                 this._collideWithWorld(this.cameraDirection, false);
-                if (this.applyGravity) {
-                    this._collideWithWorld(this.getScene().gravity, true);
-                }
+                //if (this.applyGravity) {
+                //    this._collideWithWorld(this.getScene().gravity, true);
+                //}
             } else {
                 this.position.addInPlace(this.cameraDirection);
             }

+ 3 - 3
Babylon/Collisions/babylon.collisionCoordinator.js

@@ -104,8 +104,8 @@ var BABYLON;
         }
         CollisionCoordinatorWorker.prototype.getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
             if (!this._init)
-                ;
-            if (this._collisionsCallbackArray[collisionIndex])
+                return;
+            if (this._collisionsCallbackArray[collisionIndex] || this._collisionsCallbackArray[collisionIndex + 100000])
                 return;
             position.divideToRef(collider.radius, this._scaledPosition);
             velocity.divideToRef(collider.radius, this._scaledVelocity);
@@ -216,7 +216,7 @@ var BABYLON;
             this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
             this._finalPosition.multiplyInPlace(collider.radius);
             //run the callback
-            onNewPosition(null, this._finalPosition, collider.collidedMesh);
+            onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
         };
         CollisionCoordinatorLegacy.prototype.init = function (scene) {
             this._scene = scene;

+ 3 - 3
Babylon/Collisions/babylon.collisionCoordinator.ts

@@ -182,8 +182,8 @@ module BABYLON {
         }
 
         public getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: BABYLON.Vector3, collidedMesh?: BABYLON.AbstractMesh) => void, collisionIndex: number): void {
-            if (!this._init);
-            if (this._collisionsCallbackArray[collisionIndex]) return;
+            if (!this._init) return;
+            if (this._collisionsCallbackArray[collisionIndex] || this._collisionsCallbackArray[collisionIndex + 100000]) return;
 
             position.divideToRef(collider.radius, this._scaledPosition);
             velocity.divideToRef(collider.radius, this._scaledVelocity);
@@ -353,7 +353,7 @@ module BABYLON {
 
             this._finalPosition.multiplyInPlace(collider.radius);
             //run the callback
-            onNewPosition(null, this._finalPosition, collider.collidedMesh);
+            onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
         }
 
         public init(scene: Scene): void {