浏览代码

Merge pull request #806 from RaananW/physics-collision-events

Physics collision events
David Catuhe 9 年之前
父节点
当前提交
8ec2966dab

+ 1 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -74,6 +74,7 @@
         public _physicsMass: number;
         public _physicsMass: number;
         public _physicsFriction: number;
         public _physicsFriction: number;
         public _physicRestitution: number;
         public _physicRestitution: number;
+        public onPhysicsCollide: (collidedMesh: AbstractMesh) => void;
 
 
         // Collisions
         // Collisions
         private _checkCollisions = false;
         private _checkCollisions = false;

+ 23 - 6
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -54,12 +54,9 @@ var BABYLON;
             return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
             return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
         };
         };
         CannonJSPlugin.prototype.runOneStep = function (delta) {
         CannonJSPlugin.prototype.runOneStep = function (delta) {
+            var _this = this;
             this._world.step(delta);
             this._world.step(delta);
-            for (var index = 0; index < this._registeredMeshes.length; index++) {
-                var registeredMesh = this._registeredMeshes[index];
-                if (registeredMesh.isChild) {
-                    continue;
-                }
+            this._registeredMeshes.forEach(function (registeredMesh) {
                 // Body position
                 // Body position
                 var bodyX = registeredMesh.body.position.x, bodyY = registeredMesh.body.position.y, bodyZ = registeredMesh.body.position.z;
                 var bodyX = registeredMesh.body.position.x, bodyY = registeredMesh.body.position.y, bodyZ = registeredMesh.body.position.z;
                 registeredMesh.mesh.position.x = bodyX + registeredMesh.delta.x;
                 registeredMesh.mesh.position.x = bodyX + registeredMesh.delta.x;
@@ -69,7 +66,27 @@ var BABYLON;
                 if (registeredMesh.deltaRotation) {
                 if (registeredMesh.deltaRotation) {
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                 }
                 }
-            }
+                //is the physics collision callback is set?
+                if (registeredMesh.mesh.onPhysicsCollide) {
+                    if (!registeredMesh.collisionFunction) {
+                        registeredMesh.collisionFunction = function (e) {
+                            //find the mesh that collided with the registered mesh
+                            for (var idx = 0; idx < _this._registeredMeshes.length; idx++) {
+                                if (_this._registeredMeshes[idx].body == e.body) {
+                                    registeredMesh.mesh.onPhysicsCollide(_this._registeredMeshes[idx].mesh);
+                                }
+                            }
+                        };
+                        registeredMesh.body.addEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                }
+                else {
+                    //unregister, in case the function was removed for some reason
+                    if (registeredMesh.collisionFunction) {
+                        registeredMesh.body.removeEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                }
+            });
         };
         };
         CannonJSPlugin.prototype.setGravity = function (gravity) {
         CannonJSPlugin.prototype.setGravity = function (gravity) {
             this._world.gravity.set(gravity.x, gravity.y, gravity.z);
             this._world.gravity.set(gravity.x, gravity.y, gravity.z);

+ 34 - 8
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -1,10 +1,21 @@
 module BABYLON {
 module BABYLON {
     declare var CANNON;
     declare var CANNON;
+    
+    interface IRegisteredMesh {
+        mesh: AbstractMesh;
+        body: any; //Cannon body
+        material : any;
+        delta: Vector3;
+        deltaRotation: Quaternion;
+        heightmap: boolean;
+        collisionFunction?: (event: any) => void;
+        
+    }
 
 
     export class CannonJSPlugin implements IPhysicsEnginePlugin {
     export class CannonJSPlugin implements IPhysicsEnginePlugin {
 
 
         private _world: any;
         private _world: any;
-        private _registeredMeshes = [];
+        private _registeredMeshes : Array<IRegisteredMesh> = [];
         private _physicsMaterials = [];
         private _physicsMaterials = [];
 
 
         public initialize(iterations: number = 10): void {
         public initialize(iterations: number = 10): void {
@@ -20,12 +31,7 @@
         public runOneStep(delta: number): void {
         public runOneStep(delta: number): void {
             this._world.step(delta);
             this._world.step(delta);
 
 
-            for (var index = 0; index < this._registeredMeshes.length; index++) {
-                var registeredMesh = this._registeredMeshes[index];
-
-                if (registeredMesh.isChild) {
-                    continue;
-                }
+            this._registeredMeshes.forEach((registeredMesh) => {
 
 
                 // Body position
                 // Body position
                 var bodyX = registeredMesh.body.position.x,
                 var bodyX = registeredMesh.body.position.x,
@@ -40,7 +46,27 @@
                 if (registeredMesh.deltaRotation) {
                 if (registeredMesh.deltaRotation) {
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                 }
                 }
-            }
+                
+                //is the physics collision callback is set?
+                if(registeredMesh.mesh.onPhysicsCollide) {
+                    if(!registeredMesh.collisionFunction) {
+                        registeredMesh.collisionFunction = (e) => {
+                            //find the mesh that collided with the registered mesh
+                            for (var idx = 0; idx < this._registeredMeshes.length; idx++) {
+                                if(this._registeredMeshes[idx].body == e.body) {
+                                    registeredMesh.mesh.onPhysicsCollide(this._registeredMeshes[idx].mesh);
+                                }
+                            }
+                        }
+                        registeredMesh.body.addEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                } else {
+                    //unregister, in case the function was removed for some reason
+                    if(registeredMesh.collisionFunction) {
+                        registeredMesh.body.removeEventListener("collide", registeredMesh.collisionFunction)
+                    }
+                }
+            })
         }
         }
 
 
         public setGravity(gravity: Vector3): void {
         public setGravity(gravity: Vector3): void {

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

@@ -60,6 +60,7 @@ var BABYLON;
             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
             var bodyConfig = {
             var bodyConfig = {
+                name: mesh.uniqueId,
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 move: options.mass != 0,
                 move: options.mass != 0,
@@ -145,6 +146,7 @@ var BABYLON;
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
             var bodyParameters = {
             var bodyParameters = {
+                name: mesh.uniqueId,
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 rot: [0, 0, 0],
                 rot: [0, 0, 0],
@@ -300,6 +302,22 @@ var BABYLON;
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.computeWorldMatrix();
                     mesh.computeWorldMatrix();
                 }
                 }
+                //check if the collide callback is set. 
+                if (mesh.onPhysicsCollide) {
+                    var meshUniqueName = mesh.uniqueId;
+                    var contact = this._world.contacts;
+                    while (contact !== null) {
+                        //is this body colliding with any other?
+                        if ((contact.body1.name == mesh.uniqueId || contact.body2.name == mesh.uniqueId) && contact.touching && !contact.sleeping) {
+                            var otherUniqueId = contact.body1.name == mesh.uniqueId ? contact.body2.name : contact.body1.name;
+                            //get the mesh and execute the callback
+                            var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
+                            if (otherMesh)
+                                mesh.onPhysicsCollide(otherMesh);
+                        }
+                        contact = contact.next;
+                    }
+                }
             }
             }
         };
         };
         return OimoJSPlugin;
         return OimoJSPlugin;

+ 20 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -41,6 +41,7 @@ module BABYLON {
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
 
 
             var bodyConfig: any = {
             var bodyConfig: any = {
+                name: mesh.uniqueId,
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 move: options.mass != 0,
                 move: options.mass != 0,
@@ -121,6 +122,7 @@ module BABYLON {
             }
             }
 
 
             var body = new OIMO.Body({
             var body = new OIMO.Body({
+                name: initialMesh.uniqueId,
                 type: types,
                 type: types,
                 size: sizes,
                 size: sizes,
                 pos: positions,
                 pos: positions,
@@ -156,6 +158,7 @@ module BABYLON {
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
 
 
             var bodyParameters: any = {
             var bodyParameters: any = {
+                name: mesh.uniqueId,
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 rot: [0, 0, 0],
                 rot: [0, 0, 0],
@@ -379,6 +382,23 @@ module BABYLON {
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.computeWorldMatrix();
                     mesh.computeWorldMatrix();
                 }
                 }
+                
+                //check if the collide callback is set. 
+                if(mesh.onPhysicsCollide) {
+                    var meshUniqueName = mesh.uniqueId;
+                    var contact = this._world.contacts;
+                    while(contact!==null){
+                        //is this body colliding with any other?
+                        if((contact.body1.name == mesh.uniqueId || contact.body2.name == mesh.uniqueId) && contact.touching && /* !contact.sleeping*/ !contact.body1.sleeping && !contact.body2.sleeping) {
+                            var otherUniqueId = contact.body1.name == mesh.uniqueId ? contact.body2.name : contact.body1.name;
+                            //get the mesh and execute the callback
+                            var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
+                            if(otherMesh)
+                                mesh.onPhysicsCollide(otherMesh);
+                        }
+                        contact = contact.next;
+                    }
+                }
             }
             }
         }
         }
     }
     }