Collision Detection Only

Post Reply
oberluz
Posts: 8
Joined: Tue Oct 25, 2016 2:12 pm

Collision Detection Only

Post by oberluz »

I'm trying to use bullet to perform collision detection only on an existing application but bullet seems to detect collisions when there shouldn't be any. I am trying to find out what I am doing incorrectly.

My application creates collision shapes and objects for the characters involved: a main object, which the application itself moves (ie no bullet dynamics) and a bunch of static objects.

If a collision between the main object and another object is detected then the main object is returned to its last position before colliding.

The main object rotates on the spot and when doing so I expect no collision to be detected because it is round, but collisions are being detected even just when the shape tries to turn a few degrees after being returned to a previous collision-free position.

I also implemented a debug drawer and I can see that the main object and the static object would not collide if it rotated on the spot. The attached screenshot below shows the main object stuck next to two rectangular objects:​

This is how I implemented the aplication

1. Created the world:

btDefaultCollisionConfiguration* m_collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
btBroadphaseInterface* m_broadphase = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* m_solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld* m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);

2. Created the main object:

// mainshape contains an array of vertices in local coordinates
btConvexHullShape* col = new btConvexHullShape();
for (Vector vertex : mainShape->GetVertices())
{

col->addPoint(btVector3(vertex.x(), vertex.y(), 0));
col->addPoint(btVector3(vertex.x(), vertex.y(), height));
}

btCollisionObject* m_mainCollisionObject->setCollisionShape(col);
m_dynamicsWorld->getCollisionWorld()->addCollisionObject(m_mainCollisionObject);

3. Created the static objects:

const int32_t numberOfObjects = objects->GetNumObjects();
for (int32_t i=0; i < numberOfObjects; i++)
{
AbstractObject* object = objects->GetObject(i);
btCollisionShape* col = object->CollisionShape();
btCollisionObject* obj = new btCollisionObject();
obj->setCollisionShape(col);

const Vector& pos = object->GetPosition();
const Angle& angle = object->GetRotation();
float degrees = angle.Degrees();
obj->setWorldTransform(btTransform(btQuaternion(0, 0, degrees), btVector3(pos.x(), pos.y(), object->GetDimensions().z()/2.0f)));
m_dynamicsWorld->getCollisionWorld()->addCollisionObject(obj);
}

4. Every time the program calculates a new position for the main object is calls the following method to detect collisions. If a collision
is detected the main object is repositioned back to the last non-colliding position:

Position Apply(const Positon& pos)
{
m_mainCollisionObject->setWorldTransform(btTransform(btQuaternion(0, 0, pos.Degrees()), btVector3(pos.x, pos.y, pos,z));

int numManifolds = collisionWorld->getDispatcher()->getNumManifolds();
for (int i=0; i < numManifolds; i++)
{
btPersistentManifold* contactManifold = collisionWorld->getDispatcher()->getManifoldByIndexInternal(i);

const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
const btCollisionObject* obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
if ((obA != m_mainCollisionObject) && (obB != m_mainCollisionObject))
{
continue;
}

for (int p=0; p < contactManifold->getNumContacts(); p++)
{
const btManifoldPoint& pt = contactManifold->getContactPoint(p);
if (pt.getDistance() < 0.f)
{
m_collided = true;
break;
}
}

if (m_collided)
{
break;
}

if (! m_collided)
{
m_oldPos = pos;
return pos;
}

// Main object collided so reposition to last non-collided position
m_mainCollisionObject->setWorldTransform(btTransform(btQuaternion(0, 0, m_oldPos.Degrees()), btVector3(m_oldPos.x, m_oldPos.y, m_oldPos,z));

return m_oldPos;
}
}

A trace of the main object colliding, being returned to its previous position, turning on the spot and colliding :

2317 new: { x=0.0291771, y=2.37609, z=0, theta=14.3193(100.435)} col: 1
2318 old: { x=0.0291771, y=2.37609, z=0, theta=14.2969(99.1535)} col: 1
2319 new: { x=0.0291771, y=2.37609, z=0, theta=14.3193(100.435)} col: 1
2320 old: { x=0.0291771, y=2.37609, z=0, theta=14.2969(99.1535)} col: 1
2321 new: { x=0.0291771, y=2.37609, z=0, theta=14.388(104.374)} col: 0
2322 old: { x=0.0291771, y=2.37609, z=0, theta=14.2969(99.1535)} col: 0
2323 new: { x=0.0291771, y=2.37609, z=0, theta=14.4792(109.595)} col: 1 <- here the main object turned on the spot but collided


Thank you
Attachments
main.png
main.png (23.71 KiB) Viewed 6431 times
oberluz
Posts: 8
Joined: Tue Oct 25, 2016 2:12 pm

Re: Collision Detection Only

Post by oberluz »

further progress:

I turned on btIDebugDraw::DBG_DrawAabb in the DebugDrawer debug mode and noticed that the bounding box around the main object seems to grow and shrink when the main object rotates on the spot.

I have been able to work around this issue by not doing the colising detection if I detect on the spot rotation (ie no translation), but I would really like to be able to collision detect when rotating only because the shape of he main object will not be symmetrical in general.

Any ideas why the AABB bounding box grows and shrinks when rotating on the spot or how to fix this?
benelot
Posts: 350
Joined: Sat Jul 04, 2015 10:33 am
Location: Bern, Switzerland
Contact:

Re: Collision Detection Only

Post by benelot »

So the bounding box only initiates collision detection, it is not the only check to detect it. Therefore, I think you should not worry about the changing bounding box. As a quick hack, can you increase the penetration depth check you are currently only testing for <0? Maybe there are different margins you have to consider (around 0.05 normally) so that you classify a collision too early as one. Can you exclude the possibility that your character collides with uneven ground? Maybe plot the contact points using the debugdrawer in order to see where you collide.

cheers
oberluz
Posts: 8
Joined: Tue Oct 25, 2016 2:12 pm

Re: Collision Detection Only

Post by oberluz »

Hi benelot,

Thank you for the suggestions.

> I think you should not worry about the changing bounding box

ok, I'll assume the bounding boxes varying sizes are ok.

> As a quick hack, can you increase the penetration depth check you are currently only testing for <0? Maybe there are different margins you have to consider (around 0.05 normally) so that you classify a collision too early as one

Are you referring to this line that reads:

if (pt.getDistance() < 0.f)

if, so that already tests for < 0. I did a couple of tests changing 0 for -10 and + 10 but they seemed to make no difference.

> Can you exclude the possibility that your character collides with uneven ground?

Yes, as there is no ground (for now), the shapes are essentially floating/suspended mid-air, with no gravity or physics.

> Maybe plot the contact points using the Debugdrawer in order to see where you collide

I tried this but never saw them drawn, even though I set the DebugDraw to btIDebugDraw::DBG_DrawContactPoints. I thought they may be drawn in black and hence blending into the background so I changed the color to 0.5, 0.5, 0.5 but even that did not make them visible.

I also tried the suggestion you made http://bulletphysics.org/Bullet/phpBB3/ ... hp?t=11165 to scale things up, without success. I've been reading a lot of material regarding bullet collision, but I'm no closer to finding a solution to my problem.
benelot
Posts: 350
Joined: Sat Jul 04, 2015 10:33 am
Location: Bern, Switzerland
Contact:

Re: Collision Detection Only

Post by benelot »

That the distance check (pt.getDistance() < 0) seems to make no difference is strange. You can try to plot the constact points manually by using a collision callback like this:

Code: Select all

bool legContactProcessedCallback(btManifoldPoint& cp, void* body0, void* body1)
{
    btCollisionObject* o1 = static_cast<btCollisionObject*>(body0);
    btCollisionObject* o2 = static_cast<btCollisionObject*>(body1);

    void* ID1 = o1->getUserPointer();
    void* ID2 = o2->getUserPointer();

	    // Make a circle with a 0.9 radius at (0,0,0)
	    // with RGB color (1,0,0).
		if(m_dynamicsWorld->getDebugDrawer() != NULL){
				m_dynamicsWorld->getDebugDrawer()->drawSphere(cp.getPositionWorldOnA(), 0.1, btVector3(1., 0., 0.));
			}
	
    return false;
}

Check out here how to properly setup a callback here:
http://www.bulletphysics.org/mediawiki- ... d_Triggers

Edit: You already have that callback above, you simply can add the drawing line of mine to yours.
Post Reply