btHeightfieldTerrainShape - no collisions

Post Reply
Kukanani
Posts: 25
Joined: Sat Feb 21, 2009 5:08 am

btHeightfieldTerrainShape - no collisions

Post by Kukanani »

I have a successful Ogre-Bullet setup working in my application, however, I can't make beHeightfieldTerrainShape work. I noticed that someone else had this problem a while back but they resolved it with a patch. However, I'm using SVN from late March, which was after the patch was submitted.

Here's my code:

Code: Select all

	btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btMatrix3x3(), btVector3(0.f, 0.f, 0.f)));

	btHeightfieldTerrainShape* shape =
		new btHeightfieldTerrainShape(1000, 1000, terrain->getHeightData(), 20, 1, true, true);
	shape->setUseDiamondSubdivision(true);

	shape->setLocalScaling(btVector3(1000.f, 1.f, 1000.f));

	btRigidBody::btRigidBodyConstructionInfo constructionInfo(0, motionState, shape);
	physicsHelper->addBody(constructionInfo);
Yet my rigid bodies fall right through the terrain. There's probably something wrong with the above code, I had a hard time getting it right. Any ideas?

Thanks,
Kukanani
Kukanani
Posts: 25
Joined: Sat Feb 21, 2009 5:08 am

Re: btHeightfieldTerrainShape - no collisions

Post by Kukanani »

I changed my code to this after digging around some more on the forums:
btHeightfieldTerrainShape* heightfieldShape = new btHeightfieldTerrainShape(1000, 1000, terrain->getHeightData(), 1, 0, 20, 1, PHY_FLOAT, false);
heightfieldShape->setUseDiamondSubdivision(true);

btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,17,0));

btDefaultMotionState* motionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo constructionInfo(0.f, motionState, heightfieldShape);
logString("adding terrain physics object", LOG_DEBUG);
Epee::getSingleton()->addBody(constructionInfo);
logString("done adding terrain physics", LOG_DEBUG);
Unfortunately, now my terrain is flat, which was a problem that someone else had a while back. I can't shake the feeling that there's something wrong with original terrain data, but it is a float* that comes from Ogre's terrain system.
robagar
Posts: 48
Joined: Fri May 21, 2010 1:49 am

Re: btHeightfieldTerrainShape - no collisions

Post by robagar »

I think I just had the same problem, and the solution was to fix the local scaling. It seems btHeightfieldTerrainShape defaults to a grid spacing of 1 unit, so I had to scale it horizontally to match my data.

Are your grid points really 1000.0 units apart? If not, you need to change this line

Code: Select all

shape->setLocalScaling(btVector3(1000.f, 1.f, 1000.f));
sum1nil
Posts: 3
Joined: Sat Jun 05, 2010 5:36 pm

Re: btHeightfieldTerrainShape - no collisions

Post by sum1nil »

Hi,
I'm new and trying to do much the same you were. I thought I could ask a few questions.
The code I am using doesn't detect collisions on the btheightfield (I'm sure due to my lack of knowledge) and so I instantly start to plummet, also, when I stop pressing 'w' for forward my ghost object continues to move away from my rendering cam (I want them to be in sync). Here is the code that I thought would just automatically test for collisions (granted it is a patchwork):

Code: Select all

void Character::Move(btKinematicCharacterController* theCharacter,btGhostObject* m_ghostObject, const btTransform &charTransform,scene::C3DCamera* cam,const btDiscreteDynamicsWorld& world,bool gForward, bool gBackward, bool gLeft, bool gRight)
{
		///set walkDirection for our character
		btTransform xform;
		xform = charTransform;

		btVector3 forwardDir = xform.getBasis()[2];
	//	printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
		btVector3 upDir = xform.getBasis()[1];
		btVector3 strafeDir = xform.getBasis()[0];
		forwardDir.normalize ();
		upDir.normalize ();
		strafeDir.normalize ();

		btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
		btScalar walkVelocity = btScalar(1.1); // 4 km/h -> 1.1 m/s
		btScalar walkSpeed = walkVelocity;


	//use the convex sweep test to find a safe theCharacterPositionition for the camera (not blocked by static geometry)
	
	btVector3 cameraPosition = tk.ConvertToBtVector(cam->getPosition() );
	btTransform cameraFrom,cameraTo;
	cameraFrom.setIdentity();
	cameraFrom.setOrigin(xform.getOrigin());
	cameraTo.setIdentity();
	cameraTo.setOrigin(cameraPosition);

	btCollisionWorld::ClosestConvexResultCallback cb( xform.getOrigin(), cameraTo.getOrigin() );
	cb.m_collisionFilterMask = btBroadphaseProxy::StaticFilter;

	btSphereShape cameraSphere(0.2f);
	world.convexSweepTest(&cameraSphere,cameraFrom,cameraTo,cb);

	if (cb.hasHit()) // I never get inside here
	{
		m_useWalkDirection = false;
		btScalar minFraction  = cb.m_closestHitFraction;//btMax(btScalar(0.3),cb.m_closestHitFraction);
		cameraPosition.setInterpolate3(cameraFrom.getOrigin(),cameraTo.getOrigin(),minFraction);
		cameraPosition.rotate(btVector3( 0, 1, 0),  walkDirection.getY() );
		m_useWalkDirection = true
		
	}

	//rotate view
		if (gLeft)
		{
			btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
			orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),0.01));
			m_ghostObject->getWorldTransform ().setBasis(orn);
			
		}

		if (gRight)
		{
			btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis();
			orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),-0.01));
			m_ghostObject->getWorldTransform ().setBasis(orn);
		}

		if (gForward)
		      walkDirection += forwardDir;
		
		if (gBackward)
			walkDirection -= forwardDir;
		gForward = false;
		gBackward = false;
		gLeft= false;
		gRight = false;
		theCharacter->setWalkDirection(walkDirection*walkSpeed);
		cam->setPosition(tk.ConvertToLfVector(xform.getOrigin() ) );
}
Thanks for a push in the right direction.
Post Reply