Skip to content

Commit

Permalink
added object pools
Browse files Browse the repository at this point in the history
  • Loading branch information
schteppe committed Apr 6, 2015
1 parent 8f0907d commit 3537a2e
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 12 deletions.
41 changes: 29 additions & 12 deletions src/collision/Narrowphase.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ var vec2 = require('../math/vec2')
, add = vec2.add
, dot = vec2.dot
, Utils = require('../utils/Utils')
, ContactEquationPool = require('../utils/ContactEquationPool')
, FrictionEquationPool = require('../utils/FrictionEquationPool')
, TupleDictionary = require('../utils/TupleDictionary')
, Equation = require('../equations/Equation')
, ContactEquation = require('../equations/ContactEquation')
Expand Down Expand Up @@ -91,9 +93,24 @@ function Narrowphase(){
*/
this.surfaceVelocity = 0;

this.reuseObjects = true;
this.reusableContactEquations = [];
this.reusableFrictionEquations = [];
/**
* Keeps track of the allocated ContactEquations.
* @property {ContactEquationPool} contactEquationPool
*
* @example
*
* // Allocate a few equations before starting the simulation.
* // This way, no contact objects need to be created on the fly in the game loop.
* world.narrowphase.contactEquationPool.resize(1024);
* world.narrowphase.contactFrictionPool.resize(1024);
*/
this.contactEquationPool = new ContactEquationPool({ size: 32 });

/**
* Keeps track of the allocated ContactEquations.
* @property {FrictionEquationPool} frictionEquationPool
*/
this.frictionEquationPool = new FrictionEquationPool({ size: 64 });

/**
* The restitution value to use in the next contact equations.
Expand Down Expand Up @@ -230,13 +247,13 @@ Narrowphase.prototype.reset = function(){
this.collidingBodiesLastStep.set(id1, id2, true);
}

if(this.reuseObjects){
var ce = this.contactEquations,
fe = this.frictionEquations,
rfe = this.reusableFrictionEquations,
rce = this.reusableContactEquations;
Utils.appendArray(rce,ce);
Utils.appendArray(rfe,fe);
var ce = this.contactEquations,
fe = this.frictionEquations;
for(var i=0; i<ce.length; i++){
this.contactEquationPool.release(ce[i]);
}
for(var i=0; i<fe.length; i++){
this.frictionEquationPool.release(fe[i]);
}

// Reset
Expand All @@ -251,7 +268,7 @@ Narrowphase.prototype.reset = function(){
* @return {ContactEquation}
*/
Narrowphase.prototype.createContactEquation = function(bodyA, bodyB, shapeA, shapeB){
var c = this.reusableContactEquations.length ? this.reusableContactEquations.pop() : new ContactEquation(bodyA,bodyB);
var c = this.contactEquationPool.get();
c.bodyA = bodyA;
c.bodyB = bodyB;
c.shapeA = shapeA;
Expand All @@ -275,7 +292,7 @@ Narrowphase.prototype.createContactEquation = function(bodyA, bodyB, shapeA, sha
* @return {FrictionEquation}
*/
Narrowphase.prototype.createFrictionEquation = function(bodyA, bodyB, shapeA, shapeB){
var c = this.reusableFrictionEquations.length ? this.reusableFrictionEquations.pop() : new FrictionEquation(bodyA,bodyB);
var c = this.frictionEquationPool.get();
c.bodyA = bodyA;
c.bodyB = bodyB;
c.shapeA = shapeA;
Expand Down
3 changes: 3 additions & 0 deletions src/p2.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ module.exports = {
Circle : require('./shapes/Circle'),
Constraint : require('./constraints/Constraint'),
ContactEquation : require('./equations/ContactEquation'),
ContactEquationPool : require('./utils/ContactEquationPool'),
ContactMaterial : require('./material/ContactMaterial'),
Convex : require('./shapes/Convex'),
DistanceConstraint : require('./constraints/DistanceConstraint'),
Equation : require('./equations/Equation'),
EventEmitter : require('./events/EventEmitter'),
FrictionEquation : require('./equations/FrictionEquation'),
FrictionEquationPool : require('./utils/FrictionEquationPool'),
GearConstraint : require('./constraints/GearConstraint'),
GridBroadphase : require('./collision/GridBroadphase'),
GSSolver : require('./solver/GSSolver'),
Expand All @@ -25,6 +27,7 @@ module.exports = {
NaiveBroadphase : require('./collision/NaiveBroadphase'),
Particle : require('./shapes/Particle'),
Plane : require('./shapes/Plane'),
Pool : require('./utils/Pool'),
RevoluteConstraint : require('./constraints/RevoluteConstraint'),
PrismaticConstraint : require('./constraints/PrismaticConstraint'),
Ray : require('./collision/Ray'),
Expand Down
31 changes: 31 additions & 0 deletions src/utils/ContactEquationPool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
var ContactEquation = require('../equations/ContactEquation');
var Pool = require('./Pool');

module.exports = ContactEquationPool;

/**
* @class
*/
function ContactEquationPool() {
Pool.apply(this, arguments);
}
ContactEquationPool.prototype = new Pool();
ContactEquationPool.prototype.constructor = ContactEquationPool;

/**
* @method create
* @return {ContactEquation}
*/
ContactEquationPool.prototype.create = function () {
return new ContactEquation();
};

/**
* @method destroy
* @param {ContactEquation} equation
* @return {ContactEquationPool}
*/
ContactEquationPool.prototype.destroy = function (equation) {
equation.bodyA = equation.bodyB = null;
return this;
};
31 changes: 31 additions & 0 deletions src/utils/FrictionEquationPool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
var FrictionEquation = require('../equations/FrictionEquation');
var Pool = require('./Pool');

module.exports = FrictionEquationPool;

/**
* @class
*/
function FrictionEquationPool() {
Pool.apply(this, arguments);
}
FrictionEquationPool.prototype = new Pool();
FrictionEquationPool.prototype.constructor = FrictionEquationPool;

/**
* @method create
* @return {ContactEquation}
*/
FrictionEquationPool.prototype.create = function () {
return new FrictionEquation();
};

/**
* @method destroy
* @param {ContactEquation} equation
* @return {FrictionEquationPool}
*/
FrictionEquationPool.prototype.destroy = function (equation) {
equation.bodyA = equation.bodyB = null;
return this;
};
59 changes: 59 additions & 0 deletions src/utils/Pool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module.exports = Pool;

/**
* @class Object pooling utility.
*/
function Pool(options) {
options = options || {};

/**
* @property {Array} objects
* @type {Array}
*/
this.objects = [];

if(options.size !== undefined){
this.resize(options.size);
}
}

/**
* @method resize
* @param {number} size
* @return {Pool} Self, for chaining
*/
Pool.prototype.resize = function (size) {
var objects = this.objects;

while (objects.length > size) {
objects.pop();
}

while (objects.length < size) {
objects.push(this.create());
}

return this;
};

/**
* Get an object from the pool or create a new instance.
* @method get
* @returns {Object}
*/
Pool.prototype.get = function () {
var objects = this.objects;
return objects.length ? objects.pop() : this.create();
};

/**
* Clean up and put the object back into the pool for later use.
* @method release
* @param {Object} object
* @return {Pool} Self for chaining
*/
Pool.prototype.release = function (object) {
this.destroy(object);
this.objects.push(object);
return this;
};
32 changes: 32 additions & 0 deletions test/utils/ContactEquationPool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var ContactEquationPool = require(__dirname + '/../../src/utils/ContactEquationPool');
var ContactEquation = require(__dirname + '/../../src/equations/ContactEquation');

exports.construct = function(test){
var pool = new ContactEquationPool();
test.done();
};

exports.resize = function(test){
var pool = new ContactEquationPool();
pool.resize(10);
test.equal(pool.objects.length, 10);
test.done();
};

exports.getRelease = function(test){
var pool = new ContactEquationPool();
test.equal(pool.objects.length, 0);
var object = pool.get();
object.bodyA = 'asd';
object.bodyB = 'asd2';
test.ok(object instanceof ContactEquation, 'should create contact equations');
test.equal(pool.objects.length, 0, 'should not increase pool size when creating');
pool.release(object);
test.equal(object.bodyA, null, 'should clean released object');
test.equal(object.bodyB, null, 'should clean released object');
test.equal(pool.objects.length, 1, 'should add released object to pool');
var object2 = pool.get();
test.equal(object, object2, 'should return pooled object');
test.done();
};

0 comments on commit 3537a2e

Please sign in to comment.