[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