浏览代码

New scene.pointerDownPredicate, scene.pointerMovePredicate, scene.pointerUpPredicate to define your own predicates for meshes picking selection

David Catuhe 9 年之前
父节点
当前提交
ce9f7a5a2e

文件差异内容过多而无法显示
+ 22 - 32
dist/preview release/babylon.core.js


文件差异内容过多而无法显示
+ 1041 - 1028
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 29 - 41
dist/preview release/babylon.js


文件差异内容过多而无法显示
+ 4860 - 4817
dist/preview release/babylon.max.js


文件差异内容过多而无法显示
+ 27 - 38
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -8,6 +8,7 @@
     - StandardMaterial now supports Parallax and Parallax Occlusion Mapping ([nockawa](https://github.com/nockawa))
     - Animations blending. See [demo here](http://www.babylonjs-playground.com/#2BLI9T#2). More [info here](NEED DOC!) ([deltakosh](https://github.com/deltakosh))
   - **Updates**
+    - New scene.pointerDownPredicate, scene.pointerMovePredicate, scene.pointerUpPredicate to define your own predicates for meshes picking selection ([deltakosh](https://github.com/deltakosh))
     - New OnPickTrigger support for spritesManager ([deltakosh](https://github.com/deltakosh))
     - New SPS method `digest()` ([jerome](https://github.com/jbousquie))    
     - New SPS property `computeBoundingBox` ([jerome](https://github.com/jbousquie))  

+ 6 - 6
src/Materials/Textures/babylon.hdrcubetexture.ts

@@ -21,7 +21,7 @@ module BABYLON {
         ];
 
         public sphericalPolynomial: SphericalPolynomial = null;
-        
+
         public isPMREM = false;
 
         constructor(url: string, scene: Scene, size: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false) {
@@ -109,11 +109,10 @@ module BABYLON {
                 }
                 return results;
             }
-            
+
             var mipmapGenerator = null;
-            if (!this._noMipmap && this._usePMREMGenerator)
-            {
-                mipmapGenerator = (data: ArrayBufferView[]) => { 
+            if (!this._noMipmap && this._usePMREMGenerator) {
+                mipmapGenerator = (data: ArrayBufferView[]) => {
                     var generator = new BABYLON.Internals.PMREMGenerator(data,
                         this._size,
                         this._size,
@@ -124,7 +123,7 @@ module BABYLON {
                         0.25,
                         false,
                         true);
-                        
+
                     return generator.filterCubeMap();
                 };
             }
@@ -197,3 +196,4 @@ module BABYLON {
         }
     }
 } 
+

+ 14 - 0
src/Math/babylon.math.js

@@ -1285,6 +1285,20 @@ var BABYLON;
             this.multiplyToRef(q1, this);
             return this;
         };
+        Quaternion.prototype.conjugateToRef = function (ref) {
+            ref.copyFromFloats(-this.x, -this.y, -this.z, this.w);
+            return this;
+        };
+        Quaternion.prototype.conjugateInPlace = function () {
+            this.x *= -1;
+            this.y *= -1;
+            this.z *= -1;
+            return this;
+        };
+        Quaternion.prototype.conjugate = function () {
+            var result = new Quaternion(-this.x, -this.y, -this.z, this.w);
+            return result;
+        };
         Quaternion.prototype.length = function () {
             return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z) + (this.w * this.w));
         };

+ 5 - 4
src/Math/babylon.math.ts

@@ -591,7 +591,7 @@
     export class Vector3 {
 
         constructor(public x: number, public y: number, public z: number) {
-            
+
         }
 
         public toString(): string {
@@ -1592,19 +1592,19 @@
 
             return this;
         }
-        
+
         public conjugateToRef(ref: Quaternion) {
             ref.copyFromFloats(-this.x, -this.y, -this.z, this.w);
             return this;
         }
-        
+
         public conjugateInPlace() {
             this.x *= -1;
             this.y *= -1;
             this.z *= -1;
             return this;
         }
-        
+
         public conjugate() {
             var result = new Quaternion(-this.x, -this.y, -this.z, this.w);
             return result;
@@ -3733,3 +3733,4 @@
     }
 }
 
+

+ 17 - 3
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -139,9 +139,11 @@ var BABYLON;
                 pivotB: jointData.connectedPivot ? new CANNON.Vec3().copy(jointData.connectedPivot) : null,
                 axisA: jointData.mainAxis ? new CANNON.Vec3().copy(jointData.mainAxis) : null,
                 axisB: jointData.connectedAxis ? new CANNON.Vec3().copy(jointData.connectedAxis) : null,
-                maxForce: jointData.nativeParams.maxForce
+                maxForce: jointData.nativeParams.maxForce,
+                collideConnected: !!jointData.collision
             };
-            if (!jointData.collision) {
+            //Not needed, Cannon has a collideConnected flag
+            /*if (!jointData.collision) {
                 //add 1st body to a collision group of its own, if it is not in 1
                 if (mainBody.collisionFilterGroup === 1) {
                     mainBody.collisionFilterGroup = this._currentCollisionGroup;
@@ -154,7 +156,7 @@ var BABYLON;
                 //add their mask to the collisionFilterMask of each other:
                 connectedBody.collisionFilterMask = connectedBody.collisionFilterMask | ~mainBody.collisionFilterGroup;
                 mainBody.collisionFilterMask = mainBody.collisionFilterMask | ~connectedBody.collisionFilterGroup;
-            }
+            }*/
             switch (impostorJoint.joint.type) {
                 case BABYLON.PhysicsJoint.HingeJoint:
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
@@ -162,10 +164,22 @@ var BABYLON;
                 case BABYLON.PhysicsJoint.DistanceJoint:
                     constraint = new CANNON.DistanceConstraint(mainBody, connectedBody, jointData.maxDistance || 2);
                     break;
+                case BABYLON.PhysicsJoint.SpringJoint:
+                    var springData = jointData;
+                    constraint = new CANNON.Spring(mainBody, connectedBody, {
+                        restLength: springData.length,
+                        stiffness: springData.stiffness,
+                        damping: springData.damping,
+                        localAnchorA: constraintData.pivotA,
+                        localAnchorB: constraintData.pivotB
+                    });
+                    break;
                 default:
                     constraint = new CANNON.PointToPointConstraint(mainBody, constraintData.pivotA, connectedBody, constraintData.pivotA, constraintData.maxForce);
                     break;
             }
+            //set the collideConnected flag after the creation, since DistanceJoint ignores it.
+            constraint.collideConnected = !!jointData.collision;
             impostorJoint.joint.physicsJoint = constraint;
             this.world.addConstraint(constraint);
         };

+ 6 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -193,6 +193,12 @@ var BABYLON;
                 case BABYLON.PhysicsJoint.BallAndSocketJoint:
                     type = "jointBall";
                     break;
+                case BABYLON.PhysicsJoint.SpringJoint:
+                    BABYLON.Tools.Warn("Oimo.js doesn't support Spring Constraint. Simulating using DistanceJoint instead");
+                    var springData = jointData;
+                    nativeJointData.min = springData.length || nativeJointData.min;
+                    //Max should also be set, just make sure it is at least min
+                    nativeJointData.max = Math.max(nativeJointData.min, nativeJointData.max);
                 case BABYLON.PhysicsJoint.DistanceJoint:
                     type = "jointDistance";
                     nativeJointData.max = jointData.maxDistance;

+ 10 - 4
src/Physics/babylon.physicsImpostor.js

@@ -12,7 +12,6 @@ var BABYLON;
             this._onAfterPhysicsStepCallbacks = new Array();
             this._onPhysicsCollideCallbacks = [];
             this._deltaPosition = BABYLON.Vector3.Zero();
-            this._deltaRotation = new BABYLON.Quaternion();
             this._tmpPositionWithDelta = BABYLON.Vector3.Zero();
             this._tmpRotationWithDelta = new BABYLON.Quaternion();
             /**
@@ -21,8 +20,9 @@ var BABYLON;
             this.beforeStep = function () {
                 _this.mesh.position.subtractToRef(_this._deltaPosition, _this._tmpPositionWithDelta);
                 //conjugate deltaRotation
-                _this._tmpRotationWithDelta.copyFrom(_this._deltaRotation);
-                _this._tmpRotationWithDelta.multiplyInPlace(_this.mesh.rotationQuaternion);
+                if (_this._deltaRotationConjugated) {
+                    _this.mesh.rotationQuaternion.multiplyToRef(_this._deltaRotationConjugated, _this._tmpRotationWithDelta);
+                }
                 _this._physicsEngine.getPhysicsPlugin().setPhysicsBodyTransformation(_this, _this._tmpPositionWithDelta, _this._tmpRotationWithDelta);
                 _this._onBeforePhysicsStepCallbacks.forEach(function (func) {
                     func(_this);
@@ -37,7 +37,9 @@ var BABYLON;
                 });
                 _this._physicsEngine.getPhysicsPlugin().setTransformationFromPhysicsBody(_this);
                 _this.mesh.position.addInPlace(_this._deltaPosition);
-                _this.mesh.rotationQuaternion.multiplyInPlace(_this._deltaRotation);
+                if (_this._deltaRotation) {
+                    _this.mesh.rotationQuaternion.multiplyInPlace(_this._deltaRotation);
+                }
             };
             //event and body object due to cannon's event-based architecture.
             this.onCollide = function (e) {
@@ -273,7 +275,11 @@ var BABYLON;
             this._deltaPosition.copyFrom(position);
         };
         PhysicsImpostor.prototype.setDeltaRotation = function (rotation) {
+            if (!this._deltaRotation) {
+                this._deltaRotation = new BABYLON.Quaternion();
+            }
             this._deltaRotation.copyFrom(rotation);
+            this._deltaRotationConjugated = this._deltaRotation.conjugate();
         };
         //Impostor types
         PhysicsImpostor.NoImpostor = 0;

+ 2 - 0
src/Physics/babylon.physicsJoint.js

@@ -34,6 +34,8 @@ var BABYLON;
         //Similar to a Ball-Joint. Different in params
         //TODO check!!
         PhysicsJoint.PointToPointJoint = 8;
+        //Cannon only at the moment
+        PhysicsJoint.SpringJoint = 9;
         return PhysicsJoint;
     })();
     BABYLON.PhysicsJoint = PhysicsJoint;

+ 12 - 16
src/Tools/HDR/babylon.tools.cubemaptosphericalpolynomial.ts

@@ -1,7 +1,6 @@
 module BABYLON.Internals {
 
-    class FileFaceOrientation
-    {
+    class FileFaceOrientation {
         public name: string;
         public worldAxisForNormal: Vector3; // the world axis corresponding to the normal to the face
         public worldAxisForFileX: Vector3; // the world axis corresponding to texture right x-axis in file
@@ -15,7 +14,7 @@ module BABYLON.Internals {
         }
     };
 
-    export class CubeMapToSphericalPolynomialTools {        
+    export class CubeMapToSphericalPolynomialTools {
 
         private static FileFaces: FileFaceOrientation[] = [
             new FileFaceOrientation("right", new Vector3(1, 0, 0), new Vector3(0, 0, -1), new Vector3(0, -1, 0)), // +X east
@@ -25,7 +24,7 @@ module BABYLON.Internals {
             new FileFaceOrientation("front", new Vector3(0, 0, 1), new Vector3(1, 0, 0), new Vector3(0, -1, 0)), // +Z top
             new FileFaceOrientation("back", new Vector3(0, 0, -1), new Vector3(-1, 0, 0), new Vector3(0, -1, 0))// -Z bottom
         ];
-        
+
         public static ConvertCubeMapToSphericalPolynomial(cubeInfo: CubeMapInfo): SphericalPolynomial {
             var sphericalHarmonics = new SphericalHarmonics();
             var totalSolidAngle = 0.0;
@@ -37,8 +36,7 @@ module BABYLON.Internals {
             // The (u,v) of the first texel is half a texel from the corner (-1,-1).
             var minUV = du * 0.5 - 1.0;
 
-            for (var faceIndex = 0; faceIndex < 6; faceIndex++)
-            {
+            for (var faceIndex = 0; faceIndex < 6; faceIndex++) {
                 var fileFace = this.FileFaces[faceIndex];
                 var dataArray = cubeInfo[fileFace.name];
                 var v = minUV;
@@ -47,17 +45,15 @@ module BABYLON.Internals {
                 // This is possible because during the summation we do not need the SH-specific properties, e.g. orthogonality.
                 // Because SP is still linear, so summation is fine in that basis.
 
-                for (var y = 0; y < cubeInfo.size; y++)
-                {
+                for (var y = 0; y < cubeInfo.size; y++) {
                     var u = minUV;
 
-                    for (var x = 0; x < cubeInfo.size; x++)
-                    {
+                    for (var x = 0; x < cubeInfo.size; x++) {
                         // World direction (not normalised)
                         var worldDirection =
                             fileFace.worldAxisForFileX.scale(u).add(
-                            fileFace.worldAxisForFileY.scale(v)).add(
-                            fileFace.worldAxisForNormal);
+                                fileFace.worldAxisForFileY.scale(v)).add(
+                                fileFace.worldAxisForNormal);
                         worldDirection.normalize();
 
                         var deltaSolidAngle = Math.pow(1.0 + u * u + v * v, -3.0 / 2.0);
@@ -69,14 +65,14 @@ module BABYLON.Internals {
 
                             var color = new Color3(r, g, b);
 
-                            sphericalHarmonics.addLight(worldDirection, color, deltaSolidAngle);    
+                            sphericalHarmonics.addLight(worldDirection, color, deltaSolidAngle);
                         }
                         else {
 
                             if (faceIndex == 0) {
                                 dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 1;
                                 dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1] = 0;
-                                dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 0;                                
+                                dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 0;
                             }
                             else if (faceIndex == 1) {
                                 dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0] = 0;
@@ -104,8 +100,8 @@ module BABYLON.Internals {
                                 dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2] = 1;
                             }
 
-                            var color = new Color3(dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0], 
-                                dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1], 
+                            var color = new Color3(dataArray[(y * cubeInfo.size * 3) + (x * 3) + 0],
+                                dataArray[(y * cubeInfo.size * 3) + (x * 3) + 1],
                                 dataArray[(y * cubeInfo.size * 3) + (x * 3) + 2]);
 
                             sphericalHarmonics.addLight(worldDirection, color, deltaSolidAngle);

+ 9 - 9
src/Tools/HDR/babylon.tools.panoramaToCubemap.ts

@@ -57,12 +57,12 @@ module BABYLON.Internals {
                 throw "ConvertPanoramaToCubemap: input size is wrong";
             }
 
-            var textureFront  = this.CreateCubemapTexture(size, this.FACE_FRONT, float32Array, inputWidth, inputHeight);
-            var textureBack   = this.CreateCubemapTexture(size, this.FACE_BACK, float32Array, inputWidth, inputHeight);
-            var textureLeft   = this.CreateCubemapTexture(size, this.FACE_LEFT, float32Array, inputWidth, inputHeight);
-            var textureRight  = this.CreateCubemapTexture(size, this.FACE_RIGHT, float32Array, inputWidth, inputHeight);
-            var textureUp     = this.CreateCubemapTexture(size, this.FACE_UP, float32Array, inputWidth, inputHeight);
-            var textureDown   = this.CreateCubemapTexture(size, this.FACE_DOWN, float32Array, inputWidth, inputHeight);
+            var textureFront = this.CreateCubemapTexture(size, this.FACE_FRONT, float32Array, inputWidth, inputHeight);
+            var textureBack = this.CreateCubemapTexture(size, this.FACE_BACK, float32Array, inputWidth, inputHeight);
+            var textureLeft = this.CreateCubemapTexture(size, this.FACE_LEFT, float32Array, inputWidth, inputHeight);
+            var textureRight = this.CreateCubemapTexture(size, this.FACE_RIGHT, float32Array, inputWidth, inputHeight);
+            var textureUp = this.CreateCubemapTexture(size, this.FACE_UP, float32Array, inputWidth, inputHeight);
+            var textureDown = this.CreateCubemapTexture(size, this.FACE_DOWN, float32Array, inputWidth, inputHeight);
 
             return {
                 front: textureFront,
@@ -112,8 +112,8 @@ module BABYLON.Internals {
 
         private static CalcProjectionSpherical(vDir: Vector3, float32Array: Float32Array, inputWidth: number, inputHeight: number): any {
             var theta = Math.atan2(vDir.z, vDir.x);
-            var phi   = Math.acos(vDir.y);
-            
+            var phi = Math.acos(vDir.y);
+
             while (theta < -Math.PI) theta += 2 * Math.PI;
             while (theta > Math.PI) theta -= 2 * Math.PI;
 
@@ -143,4 +143,4 @@ module BABYLON.Internals {
             };
         }
     }
-} 
+} 

+ 2 - 2
src/Tools/HDR/babylon.tools.pmremgenerator.js

@@ -365,8 +365,8 @@ var BABYLON;
                 return PMREMGenerator._vectorTemp;
             };
             //--------------------------------------------------------------------------------------
-            //Original code from Ignacio CastaÒo
-            // This formula is from Manne ÷hrstrˆm's thesis.
+            //Original code from Ignacio Castao
+            // This formula is from Manne �hrstr�m's thesis.
             // Take two coordiantes in the range [-1, 1] that define a portion of a
             // cube face and return the area of the projection of that portion on the
             // surface of the sphere.

文件差异内容过多而无法显示
+ 1195 - 1202
src/Tools/HDR/babylon.tools.pmremgenerator.ts


+ 3 - 7
src/babylon.engine.ts

@@ -1954,7 +1954,7 @@
 
                 if (!noMipmap && isPot) {
                     if (mipmmapGenerator) {
-                        
+
                         var arrayTemp: ArrayBufferView[] = [];
                         // Data are known to be in +X +Y +Z -X -Y -Z
                         // mipmmapGenerator data is expected to be order in +X -X +Y -Y +Z -Z
@@ -1984,7 +1984,7 @@
                             var faceData = rgbeDataArrays[index];
                             gl.texImage2D(facesIndex[index], 0, internalFormat, width, height, 0, internalFormat, textureType, faceData);
                         }
-                        
+
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                     }
                 }
@@ -2317,8 +2317,4 @@
             }
         }
     }
-}
-
-
-
-
+}

+ 12 - 11
src/babylon.scene.js

@@ -330,8 +330,11 @@ var BABYLON;
                 }
                 var canvas = _this._engine.getRenderingCanvas();
                 _this._updatePointerPosition(evt);
+                if (!_this.pointerMovePredicate) {
+                    _this.pointerMovePredicate = function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && (_this.constantlyUpdateMeshUnderPointer || mesh.actionManager !== null && mesh.actionManager !== undefined); };
+                }
                 // Meshes
-                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && (_this.constantlyUpdateMeshUnderPointer || mesh.actionManager !== null && mesh.actionManager !== undefined); }, false, _this.cameraToUseForPointers);
+                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerMovePredicate, false, _this.cameraToUseForPointers);
                 if (pickResult.hit && pickResult.pickedMesh) {
                     _this.setPointerOverSprite(null);
                     _this.setPointerOverMesh(pickResult.pickedMesh);
@@ -368,15 +371,14 @@ var BABYLON;
                 _this._startingPointerPosition.x = _this._pointerX;
                 _this._startingPointerPosition.y = _this._pointerY;
                 _this._startingPointerTime = new Date().getTime();
-                var predicate = null;
-                // Meshes
-                _this._pickedDownMesh = null;
-                if (!_this.onPointerDown && !_this.onPointerPick) {
-                    predicate = function (mesh) {
+                if (!_this.pointerDownPredicate) {
+                    _this.pointerDownPredicate = function (mesh) {
                         return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasPointerTriggers;
                     };
                 }
-                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, predicate, false, _this.cameraToUseForPointers);
+                // Meshes
+                _this._pickedDownMesh = null;
+                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerDownPredicate, false, _this.cameraToUseForPointers);
                 if (pickResult.hit && pickResult.pickedMesh) {
                     if (pickResult.pickedMesh.actionManager) {
                         _this._pickedDownMesh = pickResult.pickedMesh;
@@ -440,15 +442,14 @@ var BABYLON;
                 if (!_this.cameraToUseForPointers && !_this.activeCamera) {
                     return;
                 }
-                var predicate = null;
                 _this._updatePointerPosition(evt);
-                if (!_this.onPointerUp && !_this.onPointerPick) {
-                    predicate = function (mesh) {
+                if (!_this.pointerUpPredicate) {
+                    _this.pointerUpPredicate = function (mesh) {
                         return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && (mesh.actionManager.hasPickTriggers || mesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnLongPressTrigger));
                     };
                 }
                 // Meshes
-                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, predicate, false, _this.cameraToUseForPointers);
+                var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerUpPredicate, false, _this.cameraToUseForPointers);
                 if (pickResult.hit && pickResult.pickedMesh) {
                     if (_this.onPointerPick && _this._pickedDownMesh != null && pickResult.pickedMesh == _this._pickedDownMesh) {
                         _this.onPointerPick(evt, pickResult);

+ 19 - 18
src/babylon.scene.ts

@@ -65,6 +65,9 @@
         public animations: Animation[] = [];
 
         // Pointers
+        public pointerDownPredicate: (Mesh: AbstractMesh) => boolean;
+        public pointerUpPredicate: (Mesh: AbstractMesh) => boolean;
+        public pointerMovePredicate: (Mesh: AbstractMesh) => boolean;
         private _onPointerMove: (evt: PointerEvent) => void;
         private _onPointerDown: (evt: PointerEvent) => void;
         private _onPointerUp: (evt: PointerEvent) => void;
@@ -479,12 +482,13 @@
 
                 this._updatePointerPosition(evt);
 
-                // Meshes
-                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY,
-                    (mesh: AbstractMesh): boolean => mesh.isPickable && mesh.isVisible && mesh.isReady() && (this.constantlyUpdateMeshUnderPointer || mesh.actionManager !== null && mesh.actionManager !== undefined),
-                    false,
-                    this.cameraToUseForPointers);
+                if (!this.pointerMovePredicate) {
+                    this.pointerMovePredicate = (mesh: AbstractMesh): boolean => mesh.isPickable && mesh.isVisible && mesh.isReady() && (this.constantlyUpdateMeshUnderPointer || mesh.actionManager !== null && mesh.actionManager !== undefined);
+                }
 
+                // Meshes
+                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerMovePredicate, false, this.cameraToUseForPointers);
+                    
                 if (pickResult.hit && pickResult.pickedMesh) {
                     this.setPointerOverSprite(null);
 
@@ -525,16 +529,15 @@
                 this._startingPointerPosition.y = this._pointerY;
                 this._startingPointerTime = new Date().getTime();
 
-                var predicate = null;
-
-                // Meshes
-                this._pickedDownMesh = null;
-                if (!this.onPointerDown && !this.onPointerPick) {
-                    predicate = (mesh: AbstractMesh): boolean => {
+                if (!this.pointerDownPredicate) {
+                    this.pointerDownPredicate = (mesh: AbstractMesh): boolean => {
                         return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasPointerTriggers;
                     };
                 }
-                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, predicate, false, this.cameraToUseForPointers);
+
+                // Meshes
+                this._pickedDownMesh = null;
+                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerDownPredicate, false, this.cameraToUseForPointers);
 
                 if (pickResult.hit && pickResult.pickedMesh) {
                     if (pickResult.pickedMesh.actionManager) {
@@ -607,19 +610,17 @@
                 if (!this.cameraToUseForPointers && !this.activeCamera) {
                     return;
                 }
-
-                var predicate = null;
-
+                
                 this._updatePointerPosition(evt);
 
-                if (!this.onPointerUp && !this.onPointerPick) {
-                    predicate = (mesh: AbstractMesh): boolean => {
+                if (!this.pointerUpPredicate) {
+                    this.pointerUpPredicate = (mesh: AbstractMesh): boolean => {
                         return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && (mesh.actionManager.hasPickTriggers || mesh.actionManager.hasSpecificTrigger(ActionManager.OnLongPressTrigger));
                     };
                 }
 
                 // Meshes
-                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, predicate, false, this.cameraToUseForPointers);
+                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerUpPredicate, false, this.cameraToUseForPointers);
 
                 if (pickResult.hit && pickResult.pickedMesh) {
                     if (this.onPointerPick && this._pickedDownMesh != null && pickResult.pickedMesh == this._pickedDownMesh) {