Is there an obb collision test available?

Post Reply
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Is there an obb collision test available?

Post by lucky7456969 »

As far as I know, there is only a way to test 2 aabbs to collide during a broadphase calculation.
I want to cast obbs onto the ground, so that I need to work with collisions in obbs.
Are there any workaround it?
Thanks
Jack
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is there an obb collision test available?

Post by drleviathan »

Do you just want to know how an OBB collides with the ground? Or is there something more detailed inside the OBB that you want to collide with the ground?

If you just want to collide OBB's against the ground then you can just give your btCollisionObject a btBoxShape -- the BoxShape is its own OBB and will collide with full OBB fidelity in the narrowphase.

If you want to use OBB's in the broadphase before reaching the narrowphase (where you would collide something more detailed that lives inside the OBB) then you're out of luck. The broadphase is designed to rapidly cull the collision possibilities before sending them to the narrowphase for more accurate results... no OBB strategy is going to be faster than the AABB system that the broadphase uses.
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Re: Is there an obb collision test available?

Post by lucky7456969 »

Hmmm, actually I'd like to use the obb's as the bounding boxes of the agents, and use the projection of a box on the ground to perform cooperative pathfinding. Let's say an agent reserves a certain number of time steps, I reserve that duration of time with the same number of obb's. When another obb's collides with it, I don't let it reserve that area and the second agent has to pause or dodge the first agent.
Hope you get what I mean
Thanks
Jack
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is there an obb collision test available?

Post by drleviathan »

Perhaps I see what you mean. Let me repeat it back to see if it makes sense.

A character plans on where it wants to go and "claims" its path by plopping down instances of its own shape along the path (after first checking to make sure none of those spots are in contention with claims by other characters) . A second character is also planning on where it wants to go and tries to claim its path but the collision check might encounter the first's path and be unable to instantiate its own shape on the ground.

You don't need to worry about broadphase vs narrow phase. What you need to do is: before dropping a claim on the ground first call btCollisionWorld::contactTest() using the proposed shape as the query object. Read the relevant section of this wiki page for more info: http://www.bulletphysics.org/mediawiki- ... d_Triggers

If there are no contradicting collisions from the test then add the claim to the world and try the next one. Each claim would be a btRigidBody (or perhaps just a btCollisionObject) instance that has a pointer to the btBoxShape that is just big enough to enclose the character. You can add these claims to the physics world as normal objects, but use collision groups such that only other claim boxes actually collide with them. For filtering with collision groups/masks read this page: http://www.bulletphysics.org/mediawiki- ... _Filtering
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Re: Is there an obb collision test available?

Post by lucky7456969 »

Dear drleviathan,
I have got 2 more additional questions.
Is that the way you showed me only applies to Axis aligned boxes, not obbs?
Are there generally no differences between using obbs and aabbs?
And I can apply aabbs in my scenario?

Secondly, I wonder how I can cast the boxes onto the ground?
Are there any helpers for me to use in my case?
Thanks a lot
Really appreciated!
Jack
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is there an obb collision test available?

Post by drleviathan »

My suggestion would work for any shape. You could even use cylinders or spheres if they were a better approximation for your character's footprint along the path. A nice thing about using a SphereShape would be that the orientation of a claim object wouldn't matter at all. There is no AabbShape, instead you would give your btRigidBody a BoxShape and orient the RigidBody accordingly.

To place a claim object you could cast a ray toward the ground and use the results to compute the claim's position. There is a wiki page about how to cast rays: http://bulletphysics.org/mediawiki-1.5. ... ng_RayTest
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Re: Is there an obb collision test available?

Post by lucky7456969 »

Sorry for my dumbness.

Code: Select all

btDrawingResult renderCallback; 
collisionWorld->contactTest(&objects[0],renderCallback);
How can I query and collect the info about the objects that collide with objects[0]?
Does this method automatically calculate one or more than one objects that collide with objects[0]?
Am I able to get 3 things?
1) Has anything collided? (true or false)
2) How many of them have collided?
3) Where did they collide?
Do I get the results off the renderCallback, I don't know how to make use of the information
returned from renderCallback? Any ideas?

BTW, can the ray cast function cast a rectanglar box shape onto the ground, or is it just a point?


Thanks
Jack
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Re: Is there an obb collision test available?

Post by lucky7456969 »

Code: Select all

void Cooperative_Pathfinding_Test::createScene(void)
{
    Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");

    Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    headNode->attachObject(ogreHead);

    // Set ambient light
    mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));

    // Create a light
    Ogre::Light* l = mSceneMgr->createLight("MainLight");
    l->setPosition(20,80,50);
	 

	//////////////////////////////

	btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
	m_collisionShapes.push_back(groundShape);
	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
	btVector3 worldMin(-1000,-1000,-1000);
	btVector3 worldMax(1000,1000,1000);
	btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax);
	m_overlappingPairCache = sweepBP;

	m_constraintSolver = new btSequentialImpulseConstraintSolver();
	mWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
	
/*#ifdef DYNAMIC_CHARACTER_CONTROLLER
	m_character = new DynamicCharacterController ();
#else*/

	btTransform startTransform;
	startTransform.setIdentity ();	 
	startTransform.setOrigin (btVector3(10.210098,-1.6433364,16.453260));

	m_ghostObject = new btPairCachingGhostObject();
	m_ghostObject->setWorldTransform(startTransform);
	sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
	btScalar characterHeight=1.75;
	btScalar characterWidth =1.75;
	btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
	m_ghostObject->setCollisionShape (capsule);
	m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);

	mWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);


 	mWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
}


bool Cooperative_Pathfinding_Test::frameRenderingQueued(const Ogre::FrameEvent& evt) {
	btManifoldArray   manifoldArray;
	btBroadphasePairArray& pairArray = m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
	int numPairs = pairArray.size();

	for (int i=0;i<numPairs;i++)
	{
		manifoldArray.clear();

		const btBroadphasePair& pair = pairArray[i];

		//unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
		btBroadphasePair* collisionPair = mWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
		if (!collisionPair)
			continue;

		if (collisionPair->m_algorithm)
			collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);

		for (int j=0;j<manifoldArray.size();j++)
		{
			btPersistentManifold* manifold = manifoldArray[j];
			btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
			for (int p=0;p<manifold->getNumContacts();p++)
			{
				const btManifoldPoint&pt = manifold->getContactPoint(p);
				if (pt.getDistance()<0.f)
				{
					const btVector3& ptA = pt.getPositionWorldOnA();
					const btVector3& ptB = pt.getPositionWorldOnB();
					const btVector3& normalOnB = pt.m_normalWorldOnB;
					/// work here
				}
			}
		}
	}
	return BaseApplication::frameRenderingQueued(evt);
}
These 2 objects never collide, not quite sure why?
And you?
Thanks
Jack
Last edited by lucky7456969 on Tue Oct 28, 2014 3:47 am, edited 1 time in total.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is there an obb collision test available?

Post by drleviathan »

When it comes to peforming the collision test: you need to carefully read the wiki page about "Collision Callbacks and Triggers", in particular the section called "contactTest". There is example code there that you should examine carefully so you know what it is doing, but you should be able to cut and paste into your own code with very little modification. Look for the comment in the addSingleResult() that says "do stuff with the collision point" -- this is the spot where you would add your own custom code that dissects the information stored in the two btCollisionObjectWrapper pointers that are input arguments to the callback call.

My advice would be to start out simple: make the callback print out the pointers of the objects that are hit. Then you'll know it is working and have a better idea of how to modify the ContactSensorCallback struct to do more useful stuff.

When it comes to performing the ray test: re-read the wik page on how the ray test works. Again, you can practically cut and paste the example code into your own program, but look for the comment that says "Do some clever stuff here" -- that is where you add custom code to analyze the contents of the btCollisionWorld::ClosestRayResultCallback instance. If you look at the documentation for that struct you'll see that it has some data members that will allow you to figure out what happened. Also note that the ClosestRayResultCallback derives from RayResultCallback base class that also has data members that will be useful (such as a pointer to the object that the ray hit).

When you cast a ray it might pass right through object A and proceed to also hit object's B, C and D. The base class RayResultCallback has its addSingleResult() method called whenever the ray hits ANY object, so you could use that struct to collect the full list of object pierced by the ray. In the hypothetical example of objects A through D, the addSingleResult() method would be called four times as a consequence of the world->contactTest() call, once for each object. In contrast ClosestRayResultCallback stores information about the _closest_ object hit by the ray (e.g. the object whose hit point is closest to the ray's start) and you can examine this information after world->contactTest() returns (rather than in the addSingleResult() method). You probably want to know what is the first object hit, hence you probably want to use a ClosestRayResultCallback for the ray test.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Is there an obb collision test available?

Post by drleviathan »

I think maybe why your two objects are not colliding is because of the collision group/mask settings in addCollisionObject(). It appears that you're setting the group of the two objects to be group = btCollisionObject::CF_CHARACTER_OBJECT (16), but they only collide with mask = btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter (1|2 = 3) -- there is no bitwise overlap between numbers 16 and 3. Try setting the mask also to be btCollisionObject::CF_CHARACTER_OBJECT.
lucky7456969
Posts: 26
Joined: Thu Sep 11, 2014 5:40 am

Re: Is there an obb collision test available?

Post by lucky7456969 »

Sorry for some more questions.
In the ContactSensorCallback class,
How can I retrieve some results that reflect the fact that the 2 objects aren't actually colliding.
In the addSingleObject method, it is called whenever a collision occurs, but I need a way
to claim the reservation table whenever collision does not occur.

Any help would be greatly appreciated!
Thanks
Jack
Post Reply