Ghost Object collide with Soft Bodies?

Post Reply
Saso222
Posts: 5
Joined: Fri Oct 17, 2014 12:14 pm

Ghost Object collide with Soft Bodies?

Post by Saso222 »

Hey,

I have the next objective in my project:

Doing a Character Controller and make that character being able to "bounce" on the top of a SoftBody. I'm using Bullet (obviously) and Ogre3D, but I think that this doesn't mind right now.

Right now, I have my world running, with a Kinematic Character Controller (quite similar to the one that comes with the demos) that makes use of a GhostObject to simulate the character behaviour, RigidBodies being "shot" when I press F key and a single SoftBody lying at some height.

All is working fine when I shoot RigidBodies to the SoftBody since both of them are reacting as it is intended: the SoftBody is getting deformed, and the RigiBody is bouncing on it.

Troubles comes when it refers to the main character. When I jump with the character into the SoftBody, the GhostObject (and the rendered model) are sinking into the SoftBody, ignoring the collision with it, but the SoftBody is actually reacting to the collision, being deformed.

I did some debugging and I could see that after my convexSweepTest call, my callback doesn't have any hit. Furthermore, I'm not receiving any call to the addSingleResult() function of my ClosestConvexResultCallback implementation. Does this means that convexSweepTest doesn't detect Ghost-Soft collisions? Because, obviously, this is the same method I follow to detect collisions between the character and the ground RigidBody and it's working perfectly.

Thanks in advance.
tmason
Posts: 19
Joined: Wed Aug 27, 2014 5:02 pm

Re: Ghost Object collide with Soft Bodies?

Post by tmason »

Is it possible to post the code that you are using? At least for the initialization of the objects but preferably for everything else?
Saso222
Posts: 5
Joined: Fri Oct 17, 2014 12:14 pm

Re: Ghost Object collide with Soft Bodies?

Post by Saso222 »

Hi!

Since the code is really huge, I will post only what I think is the key.

Setting up the world:

Code: Select all

mCollisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
	mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
	//mBroadphase = new btDbvtBroadphase();
	mBroadphase = new btAxisSweep3(btVector3(-10000,-10000,-10000), btVector3(10000,10000,10000), 1024);
	mSolver = new btSequentialImpulseConstraintSolver();
	mWorld = new btSoftRigidDynamicsWorld(mDispatcher, mBroadphase, mSolver, mCollisionConfiguration);
	mWorld->setGravity(btVector3(0,-10,0));
Initializing the RigidBodies (those which collide perfectly with the SoftBody):

Code: Select all

btRigidBody* Physics::addRigidBody(btTransform transform, btCollisionShape * shape, btScalar mass, Ogre::SceneNode * node)
{
	numCollisionObjects++;
	mCollisionShapes.push_back(shape);
	btVector3 localInertia(0, 0, 0);

	shape->calculateLocalInertia(mass, localInertia);
	MyMotionState * motionState = new MyMotionState(transform, node);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, motionState, shape, localInertia);
	btRigidBody * body = new btRigidBody(rbInfo);

	mWorld->addRigidBody(body, COL_WORLD, everythingCollidesWith);

	return body;
}
The "SceneNode" thing is just a reference to the Graphic Engine's node, so I can update its position every frame in the MotionState. And shapes are mainly btStaticPlaneShape and btBoxShape.

Initializing the ghost object:

Code: Select all

btTransform startTransform;
	startTransform.setIdentity();
	startTransform.setOrigin(btVector3(0, 20, 0));
	Ogre::Vector3 origin(0, 20, 0);

	btPairCachingGhostObject * characterGhostObject = new btPairCachingGhostObject();
	characterGhostObject->setWorldTransform(startTransform);

	btScalar characterHeight = 7.f;
	btScalar characterWidth = 1.75f;

	btConvexShape * capsule = new btCapsuleShape(characterWidth, characterHeight);

	mPhysicsEngine->addCollisionShape(capsule);
	characterGhostObject->setCollisionShape(capsule);
	characterGhostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);

Later on, I have created a CharacterControllerInterface implementation which works well.

Initializing the SoftBody:

Code: Select all

btSoftBody* Physics::addSoftFromEntity(Ogre::SceneNode* node, Ogre::Entity* ent)
{
	StaticMeshToSoftBodyConverter converter(&mWorld->getWorldInfo(), ent);
	btSoftBody* msb = converter.createSoftBodyFromTrimesh();
	msb->setTotalMass(5,true);

	mWorld->addSoftBody(msb, COL_CLOAK, cloakCollidesWith);

	msb->m_cfg.piterations   =   3;
	msb->m_cfg.kDF         =   0.5;
	msb->randomizeConstraints();

	MySoftBody* mMsb = new MySoftBody(node, msb);
	mSoftBodies.push_back(mMsb);
	return msb;
}
The code to create the SoftBody from a trimesh is just a code that count the vertices and triangles and create the indexes array from an Ogre3D mesh, and the make this call:

Code: Select all

btSoftBody* mSoftBody = btSoftBodyHelpers::CreateFromTriMesh(*mWorldInfo, vertices, indexes, ntriangles);
No further modifications are made to this SoftBody until it returns to the other function.

To control the collisions with the GhostObject, I implement several functions, first one is to make the other bodies suffer the transformations:

Code: Select all

void CharacterPhysics::setRBForceImpulseBasedOnCollision()
{
	if (!mWalkDirection.isZero())
	{
		for (int i = 0; i < mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
		{
			btBroadphasePair * collisionPair = &mGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];

			btRigidBody * rb = (btRigidBody*)collisionPair->m_pProxy1->m_clientObject;

			if (mMass > rb->getInvMass())
			{
				btScalar resultMass = mMass - rb->getInvMass();
				btVector3 reflection = computeReflectionDirection(mWalkDirection * resultMass, getNormalizedVector(mWalkDirection));
				rb->applyCentralImpulse(reflection * -1);
			}
		}
	}
}
And this one (and others, but this is the one which does it when the character is falling), is the one who must tell the GhostObject that he has collided with the other object, so he will change his movement behaviour:

Code: Select all

void CharacterPhysics::stepDown(btCollisionWorld * collisionWorld, btScalar dt)
{
	btTransform start, end;

	btScalar downVelocity = (mVerticalVelocity < 0 ? -mVerticalVelocity : 0) * dt;

	if (downVelocity > 0 && downVelocity < mStepHeight && (mWasOnGround || !mWasJumping))
	{
		downVelocity = mStepHeight;
	}

	btVector3 stepDrop = getUpAxisDirections()[mUpAxis] * (mCurrentStepOffset + downVelocity);

	mTargetPosition -= stepDrop;


	start.setIdentity();
	end.setIdentity();

	start.setOrigin(mCurrentPosition);
	end.setOrigin(mTargetPosition);

	ClosestNotMeConvexResultCallback callback(mGhostObject, getUpAxisDirections()[mUpAxis], mMaxSlopeCosine);
	callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
	callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;

	if (mUseGhostObjectSweepTest)
		mGhostObject->convexSweepTest(mConvexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
	else
		collisionWorld->convexSweepTest(mConvexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);

	if (callback.hasHit())
	{
		std::cout << "Down Callback has hit" << std::endl;
		mCurrentPosition.setInterpolate3(mCurrentPosition, mTargetPosition, callback.m_closestHitFraction);
		mVerticalOffset = mVerticalVelocity = 0;
		mWasJumping = false;
	}
	else{
		mCurrentPosition = mTargetPosition;
	}
}
As you can see, I've put a flag there and checked if the GhostBody is detecting the collision in his covexSweepTest, and it is not detecting it when we are talking about the SoftBody, but yes when it refers to the main static plane or the other RigidBody boxes.

With this code, the RigidBodies are colliding and "getting collided by" the SoftBody nicely; I mean, they both suffer transformations when interacting together.

Thank you so much, and please, let me know if you need other fragments of my code.
Saso222
Posts: 5
Joined: Fri Oct 17, 2014 12:14 pm

Re: Ghost Object collide with Soft Bodies?

Post by Saso222 »

I've been thinking and maybe the solution is to make the character to be simulated by a RigidBody instead of by a GhostObject?

Do you guys know any example of this?

Thank you.
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Ghost Object collide with Soft Bodies?

Post by xexuxjy »

Have you set up a ghost pair callback? rusty on this, but think that the ghost object won't have any overlapping pairs added (and thus convexsweep will fail) unless this is in place. If you're getting collisions with rigid bodies this may be wrong though. You should at least be able to breakpoint if a softbody is being added to the ghost objects internal pairs.
Post Reply