diff --git a/src/goo/addons/physicspack/components/AbstractColliderComponent.js b/src/goo/addons/physicspack/components/AbstractColliderComponent.js index 7933620d5..86335099b 100644 --- a/src/goo/addons/physicspack/components/AbstractColliderComponent.js +++ b/src/goo/addons/physicspack/components/AbstractColliderComponent.js @@ -90,6 +90,7 @@ AbstractColliderComponent.prototype.attached = function (entity) { */ AbstractColliderComponent.prototype.detached = function (/*entity*/) { this.entity = null; + this.system = null; }; /** diff --git a/src/goo/addons/physicspack/components/ColliderComponent.js b/src/goo/addons/physicspack/components/ColliderComponent.js index e2a58ceda..7714c1f54 100644 --- a/src/goo/addons/physicspack/components/ColliderComponent.js +++ b/src/goo/addons/physicspack/components/ColliderComponent.js @@ -46,6 +46,8 @@ ColliderComponent.type = 'ColliderComponent'; * Initialize the collider as a static rigid body in the physics world. */ ColliderComponent.prototype.initialize = function () { + var entity = this.entity; + var material = null; if (this.material) { material = new CANNON.Material(); @@ -56,10 +58,11 @@ ColliderComponent.prototype.initialize = function () { var cannonShape = this.cannonShape = ColliderComponent.getCannonShape(this.worldCollider); cannonShape.material = material; + this.updateLayerAndMask(); + cannonShape.collisionResponse = !this.isTrigger; // Get transform from entity - var entity = this.entity; var transform = entity.transformComponent.sync().worldTransform; var position = new CANNON.Vec3(); var quaternion = new CANNON.Quaternion(); @@ -168,4 +171,17 @@ ColliderComponent.applyOnEntity = function (obj, entity) { } }; +ColliderComponent.prototype.updateLayerAndMask = function () { + ColliderComponent.updateLayerAndMask(this.entity); +}; + +ColliderComponent.updateLayerAndMask = function (entity) { + var layer = entity.layer; + var cannonShape = entity.colliderComponent.cannonShape; + if (cannonShape) { + cannonShape.collisionFilterMask = entity._world.getSystem('PhysicsSystem').getLayerMask(layer); + cannonShape.collisionFilterGroup = Math.pow(2, layer); + } +}; + module.exports = ColliderComponent; diff --git a/src/goo/addons/physicspack/components/RigidBodyComponent.js b/src/goo/addons/physicspack/components/RigidBodyComponent.js index 3051ca9d2..3e442f479 100644 --- a/src/goo/addons/physicspack/components/RigidBodyComponent.js +++ b/src/goo/addons/physicspack/components/RigidBodyComponent.js @@ -773,6 +773,8 @@ RigidBodyComponent.prototype.addCollider = function (entity, position, quaternio cannonShape.collisionResponse = !colliderComponent.isTrigger; + ColliderComponent.updateLayerAndMask(entity); + // Add the shape var cannonPos = new CANNON.Vec3(); if (position) { diff --git a/src/goo/addons/physicspack/systems/PhysicsSystem.js b/src/goo/addons/physicspack/systems/PhysicsSystem.js index bb69a559f..006d270d0 100644 --- a/src/goo/addons/physicspack/systems/PhysicsSystem.js +++ b/src/goo/addons/physicspack/systems/PhysicsSystem.js @@ -101,12 +101,63 @@ function PhysicsSystem(settings) { this.initialized = false; + // Collision masks + this.masks = []; + for (var i=0; i<32; i++) { + this.masks.push(-1); // Everything collides with everything by default + } + AbstractPhysicsSystem.call(this, 'PhysicsSystem', ['RigidBodyComponent']); } - PhysicsSystem.prototype = Object.create(AbstractPhysicsSystem.prototype); PhysicsSystem.prototype.constructor = PhysicsSystem; +/** + * Make the system ignore (or un-ignore) collisions between layerA or layerB. + * @param {number} layerA + * @param {number} layerB + * @param {boolean} [ignore=true] + */ +PhysicsSystem.prototype.ignoreLayerCollision = function (layerA, layerB, ignore) { + ignore = ignore !== undefined ? ignore : true; + var maskA = Math.pow(2, layerA); + var maskB = Math.pow(2, layerB); + var masks = this.masks; + if (ignore) { + masks[layerA] &= ~maskB; + masks[layerB] &= ~maskA; + } else { + masks[layerA] |= maskB; + masks[layerB] |= maskA; + } + + this.updateLayersAndMasks(); +}; + +/** + * @param {number} layerA + * @param {number} layerB + */ +PhysicsSystem.prototype.getIgnoreLayerCollision = function (layerA, layerB) { + return !(this.masks[layerA] & Math.pow(2, layerB)); +}; + +PhysicsSystem.prototype.updateLayersAndMasks = function () { + var entities = this._activeColliderEntities; + for (var i=0; i