[ODE] Levitation for 1st person character

Shamyl Zakariya shamyl at zakariya.net
Wed Jan 11 13:42:48 MST 2006


Having read about the floating lozenge approach to 1st person  
characters, I thought I'd give it a whirl. My approach is to float  
the lozenge a short distance above the ground, using ray collision to  
detect the height of what's beneath the lozenge, and using forces to  
push the lozenge upwards to maintain the distance.

Basically, it works great. The lozenge floats like I want it to, it  
works great for jumping off things like ledges or boulders.

My trouble, quite simply, is that I get a weird periodical "jump". It  
seems that maybe once per second, the lozenge instantly *descends*  
about 2 or 3 cm, and then rises back up to where it wants to be. I  
can't figure out where this period is coming from, so I'm hoping  
somebody here can look at my code and give me an idea what's going  
wrong.

Also, for what it's worth, I dampen the z component of the lozenge's  
velocity to prevent spring-like oscillations.

Finally, this is run once per timestep, and I'm updating at 120hz.

(For reference, I know at least that I'm calculating the base  
floating force correctly, since if I just apply that force ( mass * - 
gravity ) the lozenge floats in space, going neither up or down.)


_mass -- the mass used to configure the lozenge, using  
dMassSetCappedCylinderTotal
_tracking -- a struct describing the downward ray test, I'm only  
accessing position from it, here
_pad -- the distance above the ground the lozenge floats.




vec3 pos( dBodyGetPosition( body() ));
float pad = 1.0f;

//get the minimum height for the center of the lozenge to be at
float minZ = _tracking.position.z + pad + _lozengeRadius +  
( _lozengeLength * 0.5f );

//this is the force to float the lozenge
float supportingForce = _mass * -world()->gravity().z;

if ( pos.z >= minZ )
{
	float dist = pos.z - minZ;
	float error = clamp( dist / pad, 0.0f, 1.0f );

	/*
		We want to scale out the corrective force the higher we go from  
minZ, so
		the player can fall.
	*/
	
	float correctiveForce = -error * supportingForce;
	dBodyAddForce( body(), 0,0, supportingForce + correctiveForce );
	
	vec3 lv( dBodyGetLinearVel( body() ));
	dBodySetLinearVel( body(), lv.x, lv.y, lv.z * lrp( error, 0.925f,  
1.0f ) );

}
else if ( pos.z < minZ )
{
	float dist = minZ - pos.z;
	float error = clamp( dist / pad, 0.0f, 1.0f );
	float correctiveForce = ( error * supportingForce * 0.5f );
				
	dBodyAddForce( body(), 0,0, supportingForce + correctiveForce );
	
	vec3 lv( dBodyGetLinearVel( body() ));
	dBodySetLinearVel( body(), lv.x, lv.y, lv.z * lrp( error, 0.95f,  
0.0f ) );
}

Thanks,

shamyl zakariya
     "all humans are vermin, in the eyes of morbo"
         -- morbo



More information about the ODE mailing list