浏览代码

Merge pull request #551 from RaananW/collisionFix

ArcRotate Camera collision fix
David Catuhe 10 年之前
父节点
当前提交
99f0bb0b78

+ 26 - 34
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -1,4 +1,4 @@
-var __extends = (this && this.__extends) || function (d, b) {
+var __extends = this.__extends || function (d, b) {
     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
     function __() { this.constructor = d; }
     __.prototype = b.prototype;
@@ -45,19 +45,24 @@ var BABYLON;
             this._newPosition = BABYLON.Vector3.Zero();
             this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
                 if (collidedMesh === void 0) { collidedMesh = null; }
-                if (collisionId != null || collisionId != undefined)
+                if (_this.getScene().workerCollisions && _this.checkCollisions) {
                     newPosition.multiplyInPlace(_this._collider.radius);
-                if (newPosition.equalsWithEpsilon(_this.position)) {
-                    _this.position.copyFrom(_this._previousPosition);
-                    _this.alpha = _this._previousAlpha;
-                    _this.beta = _this._previousBeta;
-                    _this.radius = _this._previousRadius;
+                }
+                if (!collidedMesh) {
+                    _this._previousPosition.copyFrom(_this.position);
+                    _this.setPosition(_this._newPosition);
+                    _this.position.copyFrom(_this._newPosition);
                 }
                 else {
-                    if (_this.onCollide && collidedMesh) {
+                    _this.setPosition(_this._previousPosition);
+                    _this.position.copyFrom(_this._previousPosition);
+                    if (_this.onCollide) {
                         _this.onCollide(collidedMesh);
                     }
                 }
+                BABYLON.Matrix.LookAtLHToRef(_this.position, _this._getTargetPosition(), _this.upVector, _this._viewMatrix);
+                _this._viewMatrix.m[12] += _this.targetScreenOffset.x;
+                _this._viewMatrix.m[13] += _this.targetScreenOffset.y;
                 _this._collisionTriggered = false;
             };
             if (!this.target) {
@@ -91,11 +96,7 @@ var BABYLON;
         ArcRotateCamera.prototype._isSynchronizedViewMatrix = function () {
             if (!_super.prototype._isSynchronizedViewMatrix.call(this))
                 return false;
-            return this._cache.target.equals(this._getTargetPosition())
-                && this._cache.alpha === this.alpha
-                && this._cache.beta === this.beta
-                && this._cache.radius === this.radius
-                && this._cache.targetScreenOffset.equals(this.targetScreenOffset);
+            return this._cache.target.equals(this._getTargetPosition()) && this._cache.alpha === this.alpha && this._cache.beta === this.beta && this._cache.radius === this.radius && this._cache.targetScreenOffset.equals(this.targetScreenOffset);
         };
         // Methods
         ArcRotateCamera.prototype.attachControl = function (element, noPreventDefault) {
@@ -190,10 +191,7 @@ var BABYLON;
                     }
                 };
                 this._onKeyDown = function (evt) {
-                    if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysRight.indexOf(evt.keyCode) !== -1) {
+                    if (_this.keysUp.indexOf(evt.keyCode) !== -1 || _this.keysDown.indexOf(evt.keyCode) !== -1 || _this.keysLeft.indexOf(evt.keyCode) !== -1 || _this.keysRight.indexOf(evt.keyCode) !== -1) {
                         var index = _this._keys.indexOf(evt.keyCode);
                         if (index === -1) {
                             _this._keys.push(evt.keyCode);
@@ -206,10 +204,7 @@ var BABYLON;
                     }
                 };
                 this._onKeyUp = function (evt) {
-                    if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        _this.keysRight.indexOf(evt.keyCode) !== -1) {
+                    if (_this.keysUp.indexOf(evt.keyCode) !== -1 || _this.keysDown.indexOf(evt.keyCode) !== -1 || _this.keysLeft.indexOf(evt.keyCode) !== -1 || _this.keysRight.indexOf(evt.keyCode) !== -1) {
                         var index = _this._keys.indexOf(evt.keyCode);
                         if (index >= 0) {
                             _this._keys.splice(index, 1);
@@ -300,7 +295,6 @@ var BABYLON;
             if (this._collisionTriggered) {
                 return;
             }
-            // Keyboard
             for (var index = 0; index < this._keys.length; index++) {
                 var keyCode = this._keys[index];
                 if (this.keysLeft.indexOf(keyCode) !== -1) {
@@ -370,20 +364,19 @@ var BABYLON;
             var cosb = Math.cos(this.beta);
             var sinb = Math.sin(this.beta);
             var target = this._getTargetPosition();
-            target.addToRef(new BABYLON.Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this.position);
-            if (this.checkCollisions) {
+            target.addToRef(new BABYLON.Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this._newPosition);
+            if (this.getScene().collisionsEnabled && this.checkCollisions) {
                 this._collider.radius = this.collisionRadius;
-                this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
+                this._newPosition.subtractToRef(this.position, this._collisionVelocity);
                 this._collisionTriggered = true;
-                this.getScene().collisionCoordinator.getNewPosition(this._previousPosition, this._collisionVelocity, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
+                this.getScene().collisionCoordinator.getNewPosition(this.position, this._collisionVelocity, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
+            }
+            else {
+                this.position.copyFrom(this._newPosition);
+                BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
+                this._viewMatrix.m[12] += this.targetScreenOffset.x;
+                this._viewMatrix.m[13] += this.targetScreenOffset.y;
             }
-            BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
-            this._previousAlpha = this.alpha;
-            this._previousBeta = this.beta;
-            this._previousRadius = this.radius;
-            this._previousPosition.copyFrom(this.position);
-            this._viewMatrix.m[12] += this.targetScreenOffset.x;
-            this._viewMatrix.m[13] += this.targetScreenOffset.y;
             return this._viewMatrix;
         };
         ArcRotateCamera.prototype.zoomOn = function (meshes) {
@@ -433,4 +426,3 @@ var BABYLON;
     })(BABYLON.Camera);
     BABYLON.ArcRotateCamera = ArcRotateCamera;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.arcRotateCamera.js.map

+ 30 - 29
Babylon/Cameras/babylon.arcRotateCamera.ts

@@ -429,45 +429,46 @@
 
             var target = this._getTargetPosition();
 
-            target.addToRef(new Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this.position);
-
-            if (this.checkCollisions) {
+            target.addToRef(new Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this._newPosition);
+			
+			if (this.getScene().collisionsEnabled && this.checkCollisions) {
                 this._collider.radius = this.collisionRadius;
-                this.position.subtractToRef(this._previousPosition, this._collisionVelocity);
+                this._newPosition.subtractToRef(this.position, this._collisionVelocity);
 
                 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);
-
-            this._previousAlpha = this.alpha;
-            this._previousBeta = this.beta;
-            this._previousRadius = this.radius;
-            this._previousPosition.copyFrom(this.position);
-
-            this._viewMatrix.m[12] += this.targetScreenOffset.x;
-            this._viewMatrix.m[13] += this.targetScreenOffset.y;
+                this.getScene().collisionCoordinator.getNewPosition(this.position, this._collisionVelocity, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
+            } else {
+				this.position.copyFrom(this._newPosition);
+				Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
+				this._viewMatrix.m[12] += this.targetScreenOffset.x;
+				this._viewMatrix.m[13] += this.targetScreenOffset.y;
+			}
 
             return this._viewMatrix;
         }
 
         private _onCollisionPositionChange = (collisionId: number, newPosition: Vector3, collidedMesh: AbstractMesh = null) => {
 
-            if (collisionId != null || collisionId != undefined)
+            if (this.getScene().workerCollisions && this.checkCollisions) {
                 newPosition.multiplyInPlace(this._collider.radius);
-
-            if (newPosition.equalsWithEpsilon(this.position)) {
-                this.position.copyFrom(this._previousPosition);
-
-                this.alpha = this._previousAlpha;
-                this.beta = this._previousBeta;
-                this.radius = this._previousRadius;
-            } else {
-                if (this.onCollide && collidedMesh) {
-                    this.onCollide(collidedMesh);
-                }
-            }
+			}
+			
+			if(!collidedMesh) {
+				this._previousPosition.copyFrom(this.position);
+				this.setPosition(this._newPosition);
+				this.position.copyFrom(this._newPosition);
+			} else {
+				this.setPosition(this._previousPosition);
+				this.position.copyFrom(this._previousPosition);
+			
+				if (this.onCollide) {
+				   this.onCollide(collidedMesh);
+				} 
+			}
+			
+			Matrix.LookAtLHToRef(this.position, this._getTargetPosition(), this.upVector, this._viewMatrix);
+			this._viewMatrix.m[12] += this.targetScreenOffset.x;
+			this._viewMatrix.m[13] += this.targetScreenOffset.y;
 
             this._collisionTriggered = false;
         }

+ 20 - 15
Babylon/Collisions/babylon.collisionCoordinator.js

@@ -44,7 +44,7 @@ var BABYLON;
                 };
                 var message = {
                     payload: payload,
-                    taskType: WorkerTaskType.UPDATE
+                    taskType: 1 /* UPDATE */
                 };
                 var serializable = [];
                 for (var id in payload.updatedGeometries) {
@@ -63,13 +63,13 @@ var BABYLON;
             };
             this._onMessageFromWorker = function (e) {
                 var returnData = e.data;
-                if (returnData.error != WorkerReplyType.SUCCESS) {
+                if (returnData.error != 0 /* SUCCESS */) {
                     //TODO what errors can be returned from the worker?
                     BABYLON.Tools.Warn("error returned from worker!");
                     return;
                 }
                 switch (returnData.taskType) {
-                    case WorkerTaskType.INIT:
+                    case 0 /* INIT */:
                         _this._init = true;
                         //Update the worked with ALL of the scene's current state
                         _this._scene.meshes.forEach(function (mesh) {
@@ -79,10 +79,10 @@ var BABYLON;
                             _this.onGeometryAdded(geometry);
                         });
                         break;
-                    case WorkerTaskType.UPDATE:
+                    case 1 /* UPDATE */:
                         _this._runningUpdated--;
                         break;
-                    case WorkerTaskType.COLLIDE:
+                    case 2 /* COLLIDE */:
                         _this._runningCollisionTask = false;
                         var returnPayload = returnData.payload;
                         if (!_this._collisionsCallbackArray[returnPayload.collisionId])
@@ -122,7 +122,7 @@ var BABYLON;
             };
             var message = {
                 payload: payload,
-                taskType: WorkerTaskType.COLLIDE
+                taskType: 2 /* COLLIDE */
             };
             this._worker.postMessage(message);
         };
@@ -134,7 +134,7 @@ var BABYLON;
             this._worker.onmessage = this._onMessageFromWorker;
             var message = {
                 payload: {},
-                taskType: WorkerTaskType.INIT
+                taskType: 0 /* INIT */
             };
             this._worker.postMessage(message);
         };
@@ -210,6 +210,7 @@ var BABYLON;
         CollisionCoordinatorLegacy.prototype.getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
             position.divideToRef(collider.radius, this._scaledPosition);
             velocity.divideToRef(collider.radius, this._scaledVelocity);
+            collider.collidedMesh = null;
             collider.retry = 0;
             collider.initialVelocity = this._scaledVelocity;
             collider.initialPosition = this._scaledPosition;
@@ -225,12 +226,18 @@ var BABYLON;
             //Legacy need no destruction method.
         };
         //No update in legacy mode
-        CollisionCoordinatorLegacy.prototype.onMeshAdded = function (mesh) { };
-        CollisionCoordinatorLegacy.prototype.onMeshUpdated = function (mesh) { };
-        CollisionCoordinatorLegacy.prototype.onMeshRemoved = function (mesh) { };
-        CollisionCoordinatorLegacy.prototype.onGeometryAdded = function (geometry) { };
-        CollisionCoordinatorLegacy.prototype.onGeometryUpdated = function (geometry) { };
-        CollisionCoordinatorLegacy.prototype.onGeometryDeleted = function (geometry) { };
+        CollisionCoordinatorLegacy.prototype.onMeshAdded = function (mesh) {
+        };
+        CollisionCoordinatorLegacy.prototype.onMeshUpdated = function (mesh) {
+        };
+        CollisionCoordinatorLegacy.prototype.onMeshRemoved = function (mesh) {
+        };
+        CollisionCoordinatorLegacy.prototype.onGeometryAdded = function (geometry) {
+        };
+        CollisionCoordinatorLegacy.prototype.onGeometryUpdated = function (geometry) {
+        };
+        CollisionCoordinatorLegacy.prototype.onGeometryDeleted = function (geometry) {
+        };
         CollisionCoordinatorLegacy.prototype._collideWithWorld = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
             if (excludedMesh === void 0) { excludedMesh = null; }
             var closeDistance = BABYLON.Engine.CollisionsEpsilon * 10.0;
@@ -239,7 +246,6 @@ var BABYLON;
                 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) {
@@ -264,4 +270,3 @@ var BABYLON;
     })();
     BABYLON.CollisionCoordinatorLegacy = CollisionCoordinatorLegacy;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.collisionCoordinator.js.map

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

@@ -345,7 +345,7 @@ 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 {
             position.divideToRef(collider.radius, this._scaledPosition);
             velocity.divideToRef(collider.radius, this._scaledVelocity);
-
+			collider.collidedMesh = null;
             collider.retry = 0;
             collider.initialVelocity = this._scaledVelocity;
             collider.initialPosition = this._scaledPosition;

+ 12 - 11
Babylon/Collisions/babylon.collisionWorker.js

@@ -112,6 +112,9 @@ var BABYLON;
                 if (len > 1 && !this.checkSubmeshCollision(subMesh))
                     continue;
                 this.collideForSubMesh(subMesh, transformMatrix, meshGeometry);
+                if (this.collider.collisionFound) {
+                    this.collider.collidedMesh = mesh.id;
+                }
             }
         };
         CollideWorker.prototype.collideForSubMesh = function (subMesh, transformMatrix, meshGeometry) {
@@ -147,8 +150,8 @@ var BABYLON;
         CollisionDetectorTransferable.prototype.onInit = function (payload) {
             this._collisionCache = new CollisionCache();
             var reply = {
-                error: BABYLON.WorkerReplyType.SUCCESS,
-                taskType: BABYLON.WorkerTaskType.INIT
+                error: 0 /* SUCCESS */,
+                taskType: 0 /* INIT */
             };
             postMessage(reply, undefined);
         };
@@ -164,8 +167,8 @@ var BABYLON;
                 }
             }
             var replay = {
-                error: BABYLON.WorkerReplyType.SUCCESS,
-                taskType: BABYLON.WorkerTaskType.UPDATE
+                error: 0 /* SUCCESS */,
+                taskType: 1 /* UPDATE */
             };
             postMessage(replay, undefined);
         };
@@ -182,8 +185,8 @@ var BABYLON;
                 newPosition: finalPosition.asArray()
             };
             var reply = {
-                error: BABYLON.WorkerReplyType.SUCCESS,
-                taskType: BABYLON.WorkerTaskType.COLLIDE,
+                error: 0 /* SUCCESS */,
+                taskType: 2 /* COLLIDE */,
                 payload: replyPayload
             };
             postMessage(reply, undefined);
@@ -191,7 +194,6 @@ var BABYLON;
         return CollisionDetectorTransferable;
     })();
     BABYLON.CollisionDetectorTransferable = CollisionDetectorTransferable;
-    //check if we are in a web worker, as this code should NOT run on the main UI thread
     try {
         if (self && self instanceof WorkerGlobalScope) {
             //Window hack to allow including babylonjs native code. the <any> is for typescript.
@@ -206,13 +208,13 @@ var BABYLON;
             var onNewMessage = function (event) {
                 var message = event.data;
                 switch (message.taskType) {
-                    case BABYLON.WorkerTaskType.INIT:
+                    case 0 /* INIT */:
                         collisionDetector.onInit(message.payload);
                         break;
-                    case BABYLON.WorkerTaskType.COLLIDE:
+                    case 2 /* COLLIDE */:
                         collisionDetector.onCollision(message.payload);
                         break;
-                    case BABYLON.WorkerTaskType.UPDATE:
+                    case 1 /* UPDATE */:
                         collisionDetector.onUpdate(message.payload);
                         break;
                 }
@@ -224,4 +226,3 @@ var BABYLON;
         console.log("single worker init");
     }
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.collisionWorker.js.map

+ 4 - 0
Babylon/Collisions/babylon.collisionWorker.ts

@@ -137,6 +137,9 @@ module BABYLON {
                     continue;
 
                 this.collideForSubMesh(subMesh, transformMatrix, meshGeometry);
+				if (this.collider.collisionFound) {
+					this.collider.collidedMesh = <any> mesh.id;
+				}
             }
         }
 
@@ -162,6 +165,7 @@ module BABYLON {
 
             // Collide
             this.collider._collide(subMesh['_trianglePlanes'], subMesh['_lastColliderWorldVertices'], <any> meshGeometry.indices, subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart, subMesh.hasMaterial);
+			
         }
 
         private checkSubmeshCollision(subMesh: SerializedSubMesh) : boolean {