[C++, DX9] Kinematic Character Controller doesn't collide

Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

[C++, DX9] Kinematic Character Controller doesn't collide

Post by Ripiz »

I've tested sphere->heightmap collision and it perfectly collides, however I tried to add Character Controller, but it fails to collide.
This is the only code I added:

Code: Select all

	btTransform startTransform;
	startTransform.setIdentity();
	startTransform.setOrigin(btVector3(0, 0, 20));
	btPairCachingGhostObject *m_ghostObject = new btPairCachingGhostObject();
	m_ghostObject->setWorldTransform(startTransform);
	btScalar characterHeight = 10.0;
	btScalar characterWidth = 10.0;
	btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
	m_ghostObject->setCollisionShape (capsule);
	m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);

	btScalar stepHeight = btScalar(0.35);
	extern btKinematicCharacterController *m_character;
	m_character = new btKinematicCharacterController(m_ghostObject,capsule,stepHeight);
	m_character->setUpAxis(2);
	m_character->reset();
	m_character->warp(btVector3(0, 0, 20));

	extern btDynamicsWorld *physics;
	physics->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
	physics->addAction(m_character);
I can see in debug drawer that my ghost object slowly falls through heightmap. Anyone got idea what might be wrong?

Thanks in advance.
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

Can you also post the code for the heightmap creation (or at least the part where you turn it into a rigid body and add it to your dynamics world)?

Without seeing your code, what I'm guessing is that somehow you moved your heightmap from its created location to a new location each frame (possibly to better center it around the player), but I can't be sure.

btw - I use addRigidBody() not addCollisionObject() to add my heightfield shape to my dynamics world.
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

The code I posted earlier was character controller code, or to be more precise, code I use to create it.

Here's my heightmap code:

Code: Select all

		btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, data, 1, -1024, 1016, 2, PHY_UCHAR, true);
		heightFieldShape->setUseDiamondSubdivision(true);
		heightFieldShape->setLocalScaling(btVector3(4000.0 / 127.0, 4000.0 / 127.0, 8));
		body = new btRigidBody(0, 0, heightFieldShape, btVector3(0, 0, 0));	
		body->setFriction(0.8);
		body->setHitFraction(0.8);
		body->setRestitution(0.6);
		body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
		btTransform matrix;
		matrix.setIdentity();
		matrix.setOrigin(btVector3(position.x, position.y, -1056));
		btQuaternion quat;
		quat = quat.getIdentity();
		quat.setRotation(btVector3(0, 0, 1), D3DX_PI / 2.0);
		matrix.setRotation(quat);
		body->setWorldTransform(matrix);
		extern btDynamicsWorld *physics;
		physics->addRigidBody(body);
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

Ok so you don't ever change the transform on the heightfield after it's created.

Can you try changing the body->setCollisionFlags() line to this instead?

Code: Select all

	body->setCollisionFlags( btCollisionObject::CF_KINEMATIC_OBJECT );
	body->setActivationState(DISABLE_DEACTIVATION);
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

Still falling through. Maybe there's some extra function I need to call each frame or something? I haven't done anything else than code posted.
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

My up axis is the y-axis... haven't been able to try the other ones, maybe they have a bug?
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

I think I changed all places to make it y axis, but it still falls through.

Initialization:

Code: Select all

	btDefaultCollisionConfiguration *m_collisionConfiguration = new btDefaultCollisionConfiguration();
	btCollisionDispatcher *m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
	btDbvtBroadphase *m_broadphase = new btDbvtBroadphase();
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	physics = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, solver, m_collisionConfiguration);
	physics->setGravity(btVector3(0, -150, 0));
	DebugDrawer debugDraw;
	physics->setDebugDrawer(&debugDraw);
Heightmap:

Code: Select all

		btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(128, 128, data, 1, -1024, 1016, 1, PHY_UCHAR, true);
		heightFieldShape->setUseDiamondSubdivision(true);
		heightFieldShape->setLocalScaling(btVector3(4000.0 / 127.0, 4000.0 / 127.0, 8));
		body = new btRigidBody(0, 0, heightFieldShape, btVector3(0, 0, 0));	
		body->setFriction(0.8);
		body->setHitFraction(0.8);
		body->setRestitution(0.6);
		btTransform matrix;
		matrix.setIdentity();
		matrix.setOrigin(btVector3(0, -4200, 0));
		btQuaternion quat;
		quat = quat.getIdentity();
		matrix.setRotation(quat);
		body->setWorldTransform(matrix);
		body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
		body->setActivationState(DISABLE_DEACTIVATION);
		extern btDynamicsWorld *physics;
		physics->addRigidBody(body);
Character Controller:

Code: Select all

	btTransform startTransform;
	startTransform.setIdentity();
	startTransform.setOrigin(btVector3(0, 0, 20));
	btPairCachingGhostObject *m_ghostObject = new btPairCachingGhostObject();
	m_ghostObject->setWorldTransform(startTransform);
	btScalar characterHeight = 10.0;
	btScalar characterWidth = 10.0;
	btConvexShape *capsule = new btCapsuleShape(characterWidth,characterHeight);
	m_ghostObject->setCollisionShape (capsule);
	m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);

	btScalar stepHeight = btScalar(0.35);
	extern btKinematicCharacterController *m_character;
	m_character = new btKinematicCharacterController(m_ghostObject, capsule, stepHeight);
	m_character->reset();
	m_character->warp(btVector3(0, 0, 20));

	extern btDynamicsWorld *physics;
	physics->addCollisionObject(m_ghostObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
	physics->addAction(m_character);
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

This is really hard for me to say with just this. Kinda looked like the character controller was still using z-axis (at least SetOrigin and Warp).

The reason it's so difficult for me is:

#1. I have a slightly modified btKinematicCharacterController that I adapted off the forums so that it can fall more realistically. I'm not sure which version of the character controller you are using?

#2. I don't really have any of your data, specifically your heightfield data, so I can't just plug all this code into a sample and see if it repros for me. For instance, I'm concerned with your SetLocalScaling on your heightfield, first it looks like it uses the z-axis still (which I'm not sure is actually bad), and second I have never tried putting an '8' into the height scaling.

Just from looking at the snippets I don't see any obvious errors, you appear to be using the library correctly.

Here's an idea: send me the heightfield data, and I will try it out on my own and send you back a small program that works with it?
Last edited by SteveSegreto on Sat Oct 09, 2010 2:10 am, edited 1 time in total.
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

Do you mean I should make demo with heightfield and controller, or just send you height values?
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

Just send me the heightfield data if you can...you can either post it on this forum as a zip or e-mail it to me.
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

It worked fine for me with no modifications to my controller or heightfield shape creation code. Have a look at the pictures:
screen1.png
screen2.png
screen3.png
You do not have the required permissions to view the files attached to this post.
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

I guess I'm just dumb...

Any chance you could check out what's wrong in my code if I make demo, where bug is reproducible?
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

Yeah I can totally do that - either post the ZIP file here or e-mail it to me. I was trying to think which was easier - fix your code or hack up mine to send you just the bits you'd be interested in.
SteveSegreto
Posts: 32
Joined: Sun Sep 12, 2010 10:25 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by SteveSegreto »

Your ghost object wasn't having any overlapping pairs added via the broadphase. You need these lines:

Code: Select all

	btOverlappingPairCallback* m_ghostPairCallback = new btGhostPairCallback();
	m_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(m_ghostPairCallback);
right after your

Code: Select all

btDbvtBroadphase *m_broadphase = new btDbvtBroadphase();
in WinMain.


Another issue is that you do not use power of 2 + 1 height and width for your heightmap collision object. So instead of 128x128 you must use 129x129 (see the comments in Bullet for this).

Also I noticed your program runs at approx. 1-2 frames per second, this is because you have added too much of the heightmap to the btHeightfieldTerrainShape collision object and your debug drawer is choking the system. I recommend only adding a couple of squares around the character, you will get much better performance:

Code: Select all

		byte *data = new byte[128 * 128];
		for(register uint x = 0; x < 128; x++)
			for(register uint y = 0; y < 128; y++)
				data[(127- x) * 128 + y] = heights[x][y];

		int half = (128 / 2) - (17 / 2);
		byte *subSquare = new byte[ 17 * 17 ];
		for(register uint x = 0; x < 17; x++)
			for(register uint y = 0; y < 17; y++)
				subSquare[ (16-x) * 17 + y ] = heights[x + half][y + half];

		btHeightfieldTerrainShape *heightFieldShape = new btHeightfieldTerrainShape(17, 17, subSquare, 1, -1024, 1024, 1, PHY_UCHAR, false);
Notice to add a 16x16 sub-square around the player, you use a 17x17 grid.
Ripiz
Posts: 47
Joined: Mon Aug 16, 2010 10:43 am

Re: [C++, DX9] Kinematic Character Controller doesn't collid

Post by Ripiz »

Thanks a lot!
Those missing lines fixed everything.

However I failed to find any article or notes why I must use x^2+1 size heightfield, any change you could give me a link to it?

Thank you.