Moving character to avoid collision

Nacho
Posts: 31
Joined: Tue Mar 04, 2008 1:41 pm

Moving character to avoid collision

Post by Nacho »

Hello,

I'm using Bullet in a third person game. For character (player or NPC) collision, I'm using a vertical capsule (btCapsuleShape) and, after animating (moving or no) it, I test capsule collisions with convexSweepTest. It works well and I get (through ClosestConvexResultCallback) the hitPoint, hitNormal, hitCollisionObject, closesthitFraction... When the collision occurs, I want move the character-capsule to avoid collision. If the collisionObject is with a static object (or no moving), the operation is clear because the collision is procated by the character displacement. But if the collisionObject is moving (a kinematic object that push character), I don't know what distance the character must move in hitNormal direction to avoid collision.

How can I do that? Is it posible?

thanks in advance.
Nacho
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Moving character to avoid collision

Post by Dirk Gregorius »

I think Erwin added a first example for a character controller in the latest release. Maybe you want to look there as a start...
Nacho
Posts: 31
Joined: Tue Mar 04, 2008 1:41 pm

Re: Moving character to avoid collision

Post by Nacho »

Yes, I see it. My approach was diferent, since to test collision I was using convexSweepTest with a test shape (capsule) that wasn't in the dynamic-world. My characters have another capsule (this in dynamic-world) but was kinematic one (moving by me). This allows that dynamic objects (crates, explosion-pieces...) collision with the characters.

I try to change my code to adapt to Erwin's character controller.

Thanks,
Nacho.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Moving character to avoid collision

Post by Erwin Coumans »

First of all, it is not 'my' character controller ;-) I asked my collegue John to add a quick prototype using a dynamic rigid body, as one of the examples.

However, we plan to add a pure kinematic character controller (non-dynamic), using the convexSweepTest, as you are already doing. So you better stick with that approach.
a kinematic object that push character
If you have access to the new location of the kinematic object, you can use the convexSweepTest. Alternatively, you can use the penetration depth to push the character out of the kinematic object, and use the raycast to measure the velocity of the kinematic object (if it acts as ground).

Can you contribute some of your code as Bullet example/demo? Does it handle sliding / stairs climbing?

Hope this helps,
Erwin
Nacho
Posts: 31
Joined: Tue Mar 04, 2008 1:41 pm

Re: Moving character to avoid collision

Post by Nacho »

Thanks.

Before your answer (Erwin), I did some test using dynamic object, but they didn't work satisfactorily because my character is animation-controlled (displacement and rotation) and with dynamic object, it was moving uncontrollably.

Please, another important question: How can I get penetration depth? This is the key I was looking for.

Really, my game isn't a third-person, else a platform-like one (in 3D) (http://www.crocoware.net/screenshots.html). About my contribution to Bullet example/demo, I try to do something.

By the moment, if anybody serves it, I enhance the cylinder shape draw for DebugDrawer in btDiscreteDynamicsWorld.cpp (line 907). I needed it to see what happens with cylinders. Only need #define DEBUG_DRAW_ENHANCED_SHAPES to works:

Code: Select all

		case CYLINDER_SHAPE_PROXYTYPE:
			{
				const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
				int upAxis = cylinder->getUpAxis();
				btScalar radius = cylinder->getRadius();
				btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
				btVector3 start = worldTransform.getOrigin();
				btVector3	offsetHeight(0,0,0);
				offsetHeight[upAxis] = halfHeight;
				btVector3	offsetRadius(0,0,0);
				offsetRadius[(upAxis+1)%3] = radius;
#ifdef DEBUG_DRAW_ENHANCED_SHAPES
#define DEBUG_DRAW_NUM_CYLINDER_DIAMETERS	8
				btQuaternion qRot(btVector3(0, 1, 0), SIMD_2_PI/float(DEBUG_DRAW_NUM_CYLINDER_DIAMETERS));
				btVector3 vPrevPoint[4];
				btVector3 vNewPoint[4];
				// Set 'previous' point (last in this case)
				vPrevPoint[0]=start+worldTransform.getBasis() * (offsetHeight-offsetRadius);
				vPrevPoint[1]=start+worldTransform.getBasis() * (offsetHeight+offsetRadius);
				vPrevPoint[2]=start+worldTransform.getBasis() * (-offsetHeight-offsetRadius);
				vPrevPoint[3]=start+worldTransform.getBasis() * (-offsetHeight+offsetRadius);
				// Draw diameters
				for(int i=0; i<DEBUG_DRAW_NUM_CYLINDER_DIAMETERS; i++)
				{
					// Rotate offsetRadius
					offsetRadius=qRot*offsetRadius;
					// Compute new points (diameters end points in both basis)
					vNewPoint[0]=start+worldTransform.getBasis() * (offsetHeight-offsetRadius);
					vNewPoint[1]=start+worldTransform.getBasis() * (offsetHeight+offsetRadius);
					vNewPoint[2]=start+worldTransform.getBasis() * (-offsetHeight-offsetRadius);
					vNewPoint[3]=start+worldTransform.getBasis() * (-offsetHeight+offsetRadius);
					// Draw lines
					getDebugDrawer()->drawLine(vNewPoint[0], vNewPoint[1], color);
					getDebugDrawer()->drawLine(vNewPoint[2], vNewPoint[3], color);
					getDebugDrawer()->drawLine(vNewPoint[0], vNewPoint[2], color);
					getDebugDrawer()->drawLine(vNewPoint[1], vNewPoint[3], color);
					getDebugDrawer()->drawLine(vPrevPoint[0], vNewPoint[0], color);
					getDebugDrawer()->drawLine(vPrevPoint[1], vNewPoint[1], color);
					getDebugDrawer()->drawLine(vPrevPoint[2], vNewPoint[2], color);
					getDebugDrawer()->drawLine(vPrevPoint[3], vNewPoint[3], color);
					// Save current points to next iteration
					vPrevPoint[0]=vNewPoint[0];
					vPrevPoint[1]=vNewPoint[1];
					vPrevPoint[2]=vNewPoint[2];
					vPrevPoint[3]=vNewPoint[3];
				}
#else //  DEBUG_DRAW_ENHANCED_SHAPES
				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight+offsetRadius),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color);
				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color);
#endif //  DEBUG_DRAW_ENHANCED_SHAPES
				break;
			}
Nacho
colinvella
Posts: 24
Joined: Sat Feb 09, 2008 2:38 pm
Location: Malta

Re: Moving character to avoid collision

Post by colinvella »

Slightly oot, are you the guy who worked on Navy Moves for the Commodore Amiga in the '80s? :)
Nacho
Posts: 31
Joined: Tue Mar 04, 2008 1:41 pm

Re: Moving character to avoid collision

Post by Nacho »

No. He was my brother (Carlos Abril). He did Amiga and Atari ST versions. I did the Amstrad, Spectrum and MSX (directly copied from spectrum version) versions.

The last 8 years of my life (oh! anybody mention Duke Nuke forever?), I have been doing a "remake" of that game (http://www.fxinteractive.com/claves-navy-beta2.pdf). The game
has not yet released (company policy), and then my brother, a friend and I create a new game development studio.

This is my curriculum :wink:.

Nacho
colinvella
Posts: 24
Joined: Sat Feb 09, 2008 2:38 pm
Location: Malta

Re: Moving character to avoid collision

Post by colinvella »

I don't wish to deviate this topic further, so I'll close by saying it really looks very impressive and is very reminiscent of the original (missile-equipped jeep, chopper, RIB, submarine inflitration etc.). I wish you guys the best of luck! :)