Ammo.js Collision Separation

Started by
0 comments, last by BUnzaga 9 years, 7 months ago

I'm using Ammo.js with the Goo webGL engine, and I'm working on trying to get triggers implemented, but I'm having some struggle finding a 'good' way to handle collision separation.

Here is a jsFiddle which shows how to handle collision starting:

http://jsfiddle.net/ajd7vd1o/

I'm also planning to implement a 'callback' type thing like this:

http://gamedev.stackexchange.com/questions/22442/how-get-collision-callback-of-two-specific-objects-using-bullet-physics

So when one object collides with another, it will pass in some collision info.

The problem I am having, is figuring out a good way to handle the separation, when the two previously colliding objects are no longer colliding.

Supposedly, there are gContactProcessed and gContactDestroyed callbacks which I could tap into, but I don't think these are currently possible.

http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers

So I'm reaching out, before I start from scratch creating my own functionality, to see how other people have handled this.

Here is my main idea:

1. Have a map of collisions.

2. At the start of each pass, set a boolean value for all current collisions to false.

3. The fist time a collision is added to the map, trigger the onCollisionBegin callback, with the data from the collision.

4. During the collision check, if two objects are still colliding, set their boolean value to true.

5. For each collision in the map, if their boolean value is still false, trigger the onCollisionEnd callback and remove it from the map.

Does something like this seem good? Are there any current implementations of Ammo.js with collision separation mechanics that I can look at?

Thank you in advance!

Advertisement

Well I went with what I posted above, only instead of handling the callback during the collision iteration, I handle it afterward, because removing the rigidbody in the middle of iterating them was causing the browser to lock up biggrin.png

Here is what I ended up with for those of you who are interested in Ammo.js and this topic. Please, if someone knows a better way, let me know.

Demo: https://goote.ch/d3a10e52808241ada183928d966fadd8.project (webGL).

Code:


for(var key in AmmoUtil.collision){
	if(AmmoUtil.collision.hasOwnProperty(key)){
		AmmoUtil.collision[key].separated ++;
	}
}
		
var dp = this.dispatcher;
for(var i = 0, ilen = dp.getNumManifolds(); i < ilen; i++){
	var manifold = dp.getManifoldByIndexInternal(i);
	var num_contacts = manifold.getNumContacts();
    if(num_contacts === 0){
		continue;
	}
    var bodyA = AmmoUtil.rigidBodies[manifold.getBody0()];
	var bodyB = AmmoUtil.rigidBodies[manifold.getBody1()];

	for (var j = 0; j < num_contacts; j++){
		var pt = manifold.getContactPoint(j);
		if(pt.getDistance() < 0.0){
			var colID = bodyA.entity.id+"_"+bodyB.entity.id;
			if(AmmoUtil.collision[colID] === undefined){
				pt.getPositionWorldOnA(pvec);
    				pt.getPositionWorldOnB(pvec2);
				var normalOnB = pt.get_m_normalWorldOnB();
				var pointOnA = new goo.Vector3(pvec.x(), pvec.y(), pvec.z());
				var pointOnB = new goo.Vector3(pvec2.x(), pvec2.y(), pvec2.z());
				var normalOnB = new goo.Vector3(normalOnB.x(), normalOnB.y(), normalOnB.z());
				
				var info = {
					first:true,
					entityA:bodyA.entity,
					entityB:bodyB.entity,
					dataA:{other:bodyB.entity, pointA:pointOnA, pointB:pointOnB, normal:normalOnB},
					dataB:{other:bodyA.entity, pointA:pointOnB, pointB:pointOnA, normal:normalOnB}};
				
				AmmoUtil.collision[colID] = info;
			}
			AmmoUtil.collision[colID].separated = 0;
			break;
		}
	}
}

for(var key in AmmoUtil.collision){
	if(AmmoUtil.collision.hasOwnProperty(key)){
		if(true === AmmoUtil.collision[key].first){
			AmmoUtil.collision[key].first = false;
			var entA = AmmoUtil.collision[key].entityA;
			if(entA){
				var rbc = entA.getComponent('RigidBodyComponent');
				if(rbc){
					if(rbc.collisionBegin){
						rbc.collisionBegin(AmmoUtil.collision[key].dataA);
					}
				}
			}
			var entB = AmmoUtil.collision[key].entityB;
			if(entB){
				var rbc = entB.getComponent('RigidBodyComponent');
				if(rbc){
					if(rbc.collisionBegin){
						rbc.collisionBegin(AmmoUtil.collision[key].dataB);
					}
				}
			}
		}
		else{
			if(AmmoUtil.collision[key].separated > 1){
				var entA = AmmoUtil.collision[key].entityA;
				var entB = AmmoUtil.collision[key].entityB;
				if(entA){
					var rbc = entA.getComponent("RigidBodyComponent");
					if(rbc){
						if(rbc.collisionEnd){
							rbc.collisionEnd(entB);
						}
					}
				}
				if(entB){
					var rbc = entB.getComponent("RigidBodyComponent");
					if(rbc){
						if(rbc.collisionEnd){
							rbc.collisionEnd(entA);
						}
					}
				}
				delete AmmoUtil.collision[key];
			}
		}
	}
}

This topic is closed to new replies.

Advertisement