Sign in to follow this  

Ammo.js Collision Separation

This topic is 1174 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Edited by BUnzaga

Share this post


Link to post
Share on other sites

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];
			}
		}
	}
}

Share this post


Link to post
Share on other sites

This topic is 1174 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this