mirror of
https://github.com/liabru/matter-js.git
synced 2024-12-27 13:59:01 -05:00
tweaks to collision filtering
This commit is contained in:
parent
3a32bdafd3
commit
5060c7626a
5 changed files with 106 additions and 47 deletions
|
@ -49,6 +49,7 @@
|
||||||
<option value="softBody">Basic Soft Bodies</option>
|
<option value="softBody">Basic Soft Bodies</option>
|
||||||
<option value="cloth">Cloth</option>
|
<option value="cloth">Cloth</option>
|
||||||
<option value="events">Events</option>
|
<option value="events">Events</option>
|
||||||
|
<option value="collisionFiltering">Collision Filtering</option>
|
||||||
<option value="chains">Chains</option>
|
<option value="chains">Chains</option>
|
||||||
<option value="ballPool">Ball Pool</option>
|
<option value="ballPool">Ball Pool</option>
|
||||||
<option value="stack">Stack</option>
|
<option value="stack">Stack</option>
|
||||||
|
@ -61,7 +62,6 @@
|
||||||
<option value="beachBalls">Beach Balls</option>
|
<option value="beachBalls">Beach Balls</option>
|
||||||
<option value="stress">Stress 1</option>
|
<option value="stress">Stress 1</option>
|
||||||
<option value="stress2">Stress 2</option>
|
<option value="stress2">Stress 2</option>
|
||||||
<option value="collisionFiltering">Collision Filtering</option>
|
|
||||||
</select>
|
</select>
|
||||||
<input id="demo-reset" value="Reset" type="submit">
|
<input id="demo-reset" value="Reset" type="submit">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -448,12 +448,12 @@
|
||||||
|
|
||||||
Demo.chains = function() {
|
Demo.chains = function() {
|
||||||
var _world = _engine.world,
|
var _world = _engine.world,
|
||||||
groupId = Body.nextNonCollidingGroupId();
|
group = Body.nextGroup(true);
|
||||||
|
|
||||||
Demo.reset();
|
Demo.reset();
|
||||||
|
|
||||||
var ropeA = Composites.stack(200, 100, 5, 2, 10, 10, function(x, y, column, row) {
|
var ropeA = Composites.stack(200, 100, 5, 2, 10, 10, function(x, y, column, row) {
|
||||||
return Bodies.rectangle(x, y, 50, 20, { collisionFilter: {group: groupId} });
|
return Bodies.rectangle(x, y, 50, 20, { collisionFilter: { group: group } });
|
||||||
});
|
});
|
||||||
|
|
||||||
Composites.chain(ropeA, 0.5, 0, -0.5, 0, { stiffness: 0.8, length: 2 });
|
Composites.chain(ropeA, 0.5, 0, -0.5, 0, { stiffness: 0.8, length: 2 });
|
||||||
|
@ -466,10 +466,10 @@
|
||||||
|
|
||||||
World.add(_world, ropeA);
|
World.add(_world, ropeA);
|
||||||
|
|
||||||
groupId = Body.nextNonCollidingGroupId();
|
group = Body.nextGroup(true);
|
||||||
|
|
||||||
var ropeB = Composites.stack(500, 100, 5, 2, 10, 10, function(x, y, column, row) {
|
var ropeB = Composites.stack(500, 100, 5, 2, 10, 10, function(x, y, column, row) {
|
||||||
return Bodies.circle(x, y, 20, { collisionFilter: {group: groupId} });
|
return Bodies.circle(x, y, 20, { collisionFilter: { group: group } });
|
||||||
});
|
});
|
||||||
|
|
||||||
Composites.chain(ropeB, 0.5, 0, -0.5, 0, { stiffness: 0.8, length: 2 });
|
Composites.chain(ropeB, 0.5, 0, -0.5, 0, { stiffness: 0.8, length: 2 });
|
||||||
|
@ -485,12 +485,12 @@
|
||||||
|
|
||||||
Demo.bridge = function() {
|
Demo.bridge = function() {
|
||||||
var _world = _engine.world,
|
var _world = _engine.world,
|
||||||
groupId = Body.nextNonCollidingGroupId();
|
group = Body.nextGroup(true);
|
||||||
|
|
||||||
Demo.reset();
|
Demo.reset();
|
||||||
|
|
||||||
var bridge = Composites.stack(150, 300, 9, 1, 10, 10, function(x, y, column, row) {
|
var bridge = Composites.stack(150, 300, 9, 1, 10, 10, function(x, y, column, row) {
|
||||||
return Bodies.rectangle(x, y, 50, 20, { collisionFilter: {group: groupId} });
|
return Bodies.rectangle(x, y, 50, 20, { collisionFilter: { group: group } });
|
||||||
});
|
});
|
||||||
|
|
||||||
Composites.chain(bridge, 0.5, 0, -0.5, 0, { stiffness: 0.9 });
|
Composites.chain(bridge, 0.5, 0, -0.5, 0, { stiffness: 0.9 });
|
||||||
|
@ -937,8 +937,8 @@
|
||||||
|
|
||||||
Demo.reset();
|
Demo.reset();
|
||||||
|
|
||||||
var groupId = Body.nextNonCollidingGroupId(),
|
var group = Body.nextGroup(true),
|
||||||
particleOptions = { friction: 0.00001, collisionFilter: { group: groupId }, render: { visible: false }},
|
particleOptions = { friction: 0.00001, collisionFilter: { group: group }, render: { visible: false }},
|
||||||
cloth = Composites.softBody(200, 200, 20, 12, 5, 5, false, 8, particleOptions);
|
cloth = Composites.softBody(200, 200, 20, 12, 5, 5, false, 8, particleOptions);
|
||||||
|
|
||||||
for (var i = 0; i < 20; i++) {
|
for (var i = 0; i < 20; i++) {
|
||||||
|
@ -1234,39 +1234,92 @@
|
||||||
Demo.collisionFiltering = function() {
|
Demo.collisionFiltering = function() {
|
||||||
var _world = _engine.world;
|
var _world = _engine.world;
|
||||||
|
|
||||||
|
// define our categories (as bit fields, there are up to 32 available)
|
||||||
|
|
||||||
|
var defaultCategory = 0x0001,
|
||||||
|
redCategory = 0x0002,
|
||||||
|
greenCategory = 0x0004,
|
||||||
|
blueCategory = 0x0008;
|
||||||
|
|
||||||
|
var redColor = '#C44D58',
|
||||||
|
blueColor = '#4ECDC4',
|
||||||
|
greenColor = '#C7F464';
|
||||||
|
|
||||||
Demo.reset();
|
Demo.reset();
|
||||||
|
|
||||||
var i;
|
// create a stack with varying body categories (but these bodies can all collide with each other)
|
||||||
|
|
||||||
World.add(_world,
|
World.add(_world,
|
||||||
Composites.stack(275, 150, 5, 10, 10, 10, function(x, y, column, row) {
|
Composites.stack(275, 150, 5, 10, 10, 10, function(x, y, column, row) {
|
||||||
|
var category = redCategory,
|
||||||
|
color = redColor;
|
||||||
|
|
||||||
|
if (row > 5) {
|
||||||
|
category = blueCategory;
|
||||||
|
color = blueColor;
|
||||||
|
} else if (row > 2) {
|
||||||
|
category = greenCategory;
|
||||||
|
color = greenColor;
|
||||||
|
}
|
||||||
|
|
||||||
return Bodies.circle(x, y, 20, {
|
return Bodies.circle(x, y, 20, {
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
category: row < 7 ? 2 : 4
|
category: category
|
||||||
},
|
},
|
||||||
render: {
|
render: {
|
||||||
strokeStyle: row < 7 ? 'red' : 'green',
|
strokeStyle: color,
|
||||||
fillStyle: 'transparent'
|
fillStyle: 'transparent'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// this body will only collide with the walls and the green bodies
|
||||||
|
|
||||||
|
World.add(_world,
|
||||||
|
Bodies.circle(310, 40, 30, {
|
||||||
|
collisionFilter: {
|
||||||
|
mask: defaultCategory | greenCategory
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
strokeStyle: Common.shadeColor(greenColor, -20),
|
||||||
|
fillStyle: greenColor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// this body will only collide with the walls and the red bodies
|
||||||
|
|
||||||
World.add(_world,
|
World.add(_world,
|
||||||
Bodies.circle(400, 40, 30, {
|
Bodies.circle(400, 40, 30, {
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
mask: 5
|
mask: defaultCategory | redCategory
|
||||||
},
|
},
|
||||||
render: {
|
render: {
|
||||||
fillStyle: 'blue'
|
strokeStyle: Common.shadeColor(redColor, -20),
|
||||||
|
fillStyle: redColor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// this body will only collide with the walls and the blue bodies
|
||||||
|
|
||||||
|
World.add(_world,
|
||||||
|
Bodies.circle(480, 40, 30, {
|
||||||
|
collisionFilter: {
|
||||||
|
mask: defaultCategory | blueCategory
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
strokeStyle: Common.shadeColor(blueColor, -20),
|
||||||
|
fillStyle: blueColor
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
var renderOptions = _engine.render.options;
|
var renderOptions = _engine.render.options;
|
||||||
renderOptions.wireframes = false;
|
renderOptions.wireframes = false;
|
||||||
renderOptions.background = '#111';
|
renderOptions.background = '#222';
|
||||||
renderOptions.showCollisions = true;
|
renderOptions.showAngleIndicator = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// the functions for the demo interface and controls below
|
// the functions for the demo interface and controls below
|
||||||
|
|
|
@ -51,7 +51,7 @@ var Body = {};
|
||||||
friction: 0.1,
|
friction: 0.1,
|
||||||
frictionAir: 0.01,
|
frictionAir: 0.01,
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
category: 1,
|
category: 0x0001,
|
||||||
mask: 0xFFFFFFFF,
|
mask: 0xFFFFFFFF,
|
||||||
group: 0
|
group: 0
|
||||||
},
|
},
|
||||||
|
@ -75,21 +75,18 @@ var Body = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next unique groupID number for which bodies will collide.
|
* Returns the next unique group index for which bodies will collide.
|
||||||
* @method nextCollidingGroupId
|
* If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.
|
||||||
* @return {Number} Unique groupID
|
* See `body.collisionFilter` for more information.
|
||||||
|
* @method nextGroup
|
||||||
|
* @param {bool} [isNonColliding=false]
|
||||||
|
* @return {Number} Unique group index
|
||||||
*/
|
*/
|
||||||
Body.nextCollidingGroupId = function() {
|
Body.nextGroup = function(isNonColliding) {
|
||||||
return _nextCollidingGroupId++;
|
if (isNonColliding)
|
||||||
};
|
return _nextNonCollidingGroupId--;
|
||||||
|
|
||||||
/**
|
return _nextCollidingGroupId++;
|
||||||
* Returns the next collisionFilter.group value for which bodies will not collide.
|
|
||||||
* @method nextNonCollidingGroupId
|
|
||||||
* @return {Number} Unique groupID
|
|
||||||
*/
|
|
||||||
Body.nextNonCollidingGroupId = function() {
|
|
||||||
return _nextNonCollidingGroupId--;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -699,6 +696,7 @@ var Body = {};
|
||||||
* value is used as a bit field and the category should have only one bit set, meaning that
|
* value is used as a bit field and the category should have only one bit set, meaning that
|
||||||
* the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
|
* the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
|
||||||
* different collision categories available.
|
* different collision categories available.
|
||||||
|
*
|
||||||
* Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
|
* Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
|
||||||
* the categories it collides with (the value is the bitwise AND value of all these categories).
|
* the categories it collides with (the value is the bitwise AND value of all these categories).
|
||||||
*
|
*
|
||||||
|
@ -711,7 +709,7 @@ var Body = {};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Integer `Number`, see `collisionFilter`
|
* An Integer `Number`, see `body.collisionFilter` for more information.
|
||||||
*
|
*
|
||||||
* @property collisionFilter.group
|
* @property collisionFilter.group
|
||||||
* @type object
|
* @type object
|
||||||
|
@ -719,7 +717,10 @@ var Body = {};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Integer `Number`, see `collisionFilter`
|
* A bit field that specifies the collision category this body belongs to.
|
||||||
|
* The category value should have only one bit set, for example `0x0001`.
|
||||||
|
* This means there are up to 32 unique collision categories available.
|
||||||
|
* See `body.collisionFilter` for more information.
|
||||||
*
|
*
|
||||||
* @property collisionFilter.category
|
* @property collisionFilter.category
|
||||||
* @type object
|
* @type object
|
||||||
|
@ -727,7 +728,7 @@ var Body = {};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Integer `Number`, see `collisionFilter`
|
* An Integer `Number`, see `body.collisionFilter` for more information.
|
||||||
*
|
*
|
||||||
* @property collisionFilter.mask
|
* @property collisionFilter.mask
|
||||||
* @type object
|
* @type object
|
||||||
|
|
|
@ -26,13 +26,10 @@ var Detector = {};
|
||||||
var bodyA = broadphasePairs[i][0],
|
var bodyA = broadphasePairs[i][0],
|
||||||
bodyB = broadphasePairs[i][1];
|
bodyB = broadphasePairs[i][1];
|
||||||
|
|
||||||
var collisionFilterA = bodyA.collisionFilter,
|
|
||||||
collisionFilterB = bodyB.collisionFilter;
|
|
||||||
|
|
||||||
if ((bodyA.isStatic || bodyA.isSleeping) && (bodyB.isStatic || bodyB.isSleeping))
|
if ((bodyA.isStatic || bodyA.isSleeping) && (bodyB.isStatic || bodyB.isSleeping))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!_pairCollides(collisionFilterA, collisionFilterB))
|
if (!Detector.canCollide(bodyA.collisionFilter, bodyB.collisionFilter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
metrics.midphaseTests += 1;
|
metrics.midphaseTests += 1;
|
||||||
|
@ -88,11 +85,11 @@ var Detector = {};
|
||||||
|
|
||||||
// NOTE: could share a function for the below, but may drop performance?
|
// NOTE: could share a function for the below, but may drop performance?
|
||||||
|
|
||||||
if (bodyA.groupId && bodyB.groupId && bodyA.groupId === bodyB.groupId)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((bodyA.isStatic || bodyA.isSleeping) && (bodyB.isStatic || bodyB.isSleeping))
|
if ((bodyA.isStatic || bodyA.isSleeping) && (bodyB.isStatic || bodyB.isSleeping))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!Detector.canCollide(bodyA.collisionFilter, bodyB.collisionFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
metrics.midphaseTests += 1;
|
metrics.midphaseTests += 1;
|
||||||
|
|
||||||
|
@ -128,12 +125,20 @@ var Detector = {};
|
||||||
|
|
||||||
return collisions;
|
return collisions;
|
||||||
};
|
};
|
||||||
|
|
||||||
var _pairCollides = function(filterA, filterB) {
|
/**
|
||||||
|
* Returns `true` if both supplied collision filters will allow a collision to occur.
|
||||||
|
* See `body.collisionFilter` for more information.
|
||||||
|
* @method canCollide
|
||||||
|
* @param {} filterA
|
||||||
|
* @param {} filterB
|
||||||
|
* @return {bool} `true` if collision can occur
|
||||||
|
*/
|
||||||
|
Detector.canCollide = function(filterA, filterB) {
|
||||||
if (filterA.group === filterB.group && filterA.group !== 0)
|
if (filterA.group === filterB.group && filterA.group !== 0)
|
||||||
return filterA.group > 0;
|
return filterA.group > 0;
|
||||||
|
|
||||||
return ((filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0);
|
return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -226,7 +226,7 @@ var Composites = {};
|
||||||
* @return {composite} A new composite car body
|
* @return {composite} A new composite car body
|
||||||
*/
|
*/
|
||||||
Composites.car = function(xx, yy, width, height, wheelSize) {
|
Composites.car = function(xx, yy, width, height, wheelSize) {
|
||||||
var collisionFilterGroup = Body.nextNonCollidingGroupId(),
|
var group = Body.nextGroup(true),
|
||||||
wheelBase = -20,
|
wheelBase = -20,
|
||||||
wheelAOffset = -width * 0.5 + wheelBase,
|
wheelAOffset = -width * 0.5 + wheelBase,
|
||||||
wheelBOffset = width * 0.5 - wheelBase,
|
wheelBOffset = width * 0.5 - wheelBase,
|
||||||
|
@ -235,7 +235,7 @@ var Composites = {};
|
||||||
var car = Composite.create({ label: 'Car' }),
|
var car = Composite.create({ label: 'Car' }),
|
||||||
body = Bodies.trapezoid(xx, yy, width, height, 0.3, {
|
body = Bodies.trapezoid(xx, yy, width, height, 0.3, {
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
group: collisionFilterGroup
|
group: group
|
||||||
},
|
},
|
||||||
friction: 0.01,
|
friction: 0.01,
|
||||||
chamfer: {
|
chamfer: {
|
||||||
|
@ -245,7 +245,7 @@ var Composites = {};
|
||||||
|
|
||||||
var wheelA = Bodies.circle(xx + wheelAOffset, yy + wheelYOffset, wheelSize, {
|
var wheelA = Bodies.circle(xx + wheelAOffset, yy + wheelYOffset, wheelSize, {
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
group: collisionFilterGroup
|
group: group
|
||||||
},
|
},
|
||||||
restitution: 0.5,
|
restitution: 0.5,
|
||||||
friction: 0.9,
|
friction: 0.9,
|
||||||
|
@ -254,7 +254,7 @@ var Composites = {};
|
||||||
|
|
||||||
var wheelB = Bodies.circle(xx + wheelBOffset, yy + wheelYOffset, wheelSize, {
|
var wheelB = Bodies.circle(xx + wheelBOffset, yy + wheelYOffset, wheelSize, {
|
||||||
collisionFilter: {
|
collisionFilter: {
|
||||||
group: collisionFilterGroup
|
group: group
|
||||||
},
|
},
|
||||||
restitution: 0.5,
|
restitution: 0.5,
|
||||||
friction: 0.9,
|
friction: 0.9,
|
||||||
|
|
Loading…
Reference in a new issue