Fixes vector normalisation issues (which can result in crashes due to NAN values).

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1720 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-04-22 14:02:07 +00:00
parent a4f2247f15
commit 70badaa9ea

View File

@ -97,16 +97,33 @@ void DefaultRobot::update( float delta )
/*Get information that is needed by more than 1 of the handling funcs*/ /*Get information that is needed by more than 1 of the handling funcs*/
//Detect if we are going to crash with the track and/or kart //Detect if we are going to crash with the track and/or kart
const int STEPS = calc_steps(); int steps = 0;
check_crashes( STEPS, m_curr_pos.xyz );
// This should not happen (anymore :) ), but it keeps the game running
// in case that m_future_sector becomes undefined.
if(m_future_sector == Track::UNKNOWN_SECTOR )
{
#ifdef DEBUG
fprintf(stderr,"DefaultRobot: m_future_sector is undefined.\n");
fprintf(stderr,"This shouldn't happen, but can be ignored.\n");
#endif
forceRescue();
m_future_sector = 0;
}
else
{
steps = calc_steps();
}
check_crashes( steps, m_curr_pos.xyz );
find_curve(); find_curve();
/*Response handling functions*/ /*Response handling functions*/
handle_acceleration( delta ); handle_acceleration( delta );
handle_steering(); handle_steering();
handle_items( delta, STEPS ); handle_items( delta, steps );
handle_rescue( delta ); handle_rescue( delta );
handle_wheelie( STEPS ); handle_wheelie( steps );
handle_braking(); handle_braking();
//TODO:handle jumping //TODO:handle jumping
@ -415,16 +432,18 @@ bool DefaultRobot::do_wheelie ( const int STEPS )
if( m_crashes.m_road ) return false; if( m_crashes.m_road ) return false;
if( m_crashes.m_kart != -1 ) return false; if( m_crashes.m_kart != -1 ) return false;
sgVec2 step_coord;
sgVec3 step_track_coord;
float distance;
//We have to be careful with normalizing, because if the source argument //We have to be careful with normalizing, because if the source argument
//has both the X and Y axis set to 0, it returns nan to the destiny. //has both the X and Y axis set to 0, it returns nan to the destiny.
const btVector3 &VEL=getVelocity(); const btVector3 &VEL=getVelocity();
if( VEL.getX() == 0.0 && VEL.getY() == 0.0 ) return false;
btVector3 vel_normal(VEL.getX(), VEL.getY(), 0.0); btVector3 vel_normal(VEL.getX(), VEL.getY(), 0.0);
vel_normal.normalize(); float len=vel_normal.length();
// Too slow for wheelies, and it avoids normalisation problems.
if(len<getMaxSpeed()*getWheelieMaxSpeedRatio()) return false;
vel_normal/=len;
sgVec2 step_coord;
sgVec3 step_track_coord;
float distance;
//FIXME: instead of using 1.5, it should find out how much time it //FIXME: instead of using 1.5, it should find out how much time it
//will pass to stop doing the wheelie completely from the current state. //will pass to stop doing the wheelie completely from the current state.
@ -569,14 +588,15 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
//Protection against having vel_normal with nan values //Protection against having vel_normal with nan values
const btVector3 &VEL = getVelocity(); const btVector3 &VEL = getVelocity();
if( VEL.getX() == 0.0 && VEL.getY() == 0.0 ) vel_normal.setValue(VEL.getX(), VEL.getY(), 0.0);
float len=vel_normal.length();
if(len>0.0f)
{ {
vel_normal.setValue(0.0, 0.0, 0.0); vel_normal/=len;
} }
else else
{ {
vel_normal.setValue(VEL.getX(), VEL.getY(), 0.0); vel_normal.setValue(0.0, 0.0, 0.0);
vel_normal.normalize();
} }
for(int i = 1; STEPS > i; ++i) for(int i = 1; STEPS > i; ++i)
@ -645,7 +665,7 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
if( m_sector == Track::UNKNOWN_SECTOR ) if( m_sector == Track::UNKNOWN_SECTOR )
{ {
m_future_sector = world->m_track->findOutOfRoadSector( step_coord, m_future_sector = world->getTrack()->findOutOfRoadSector( step_coord,
Track::RS_DONT_KNOW, m_future_sector ); Track::RS_DONT_KNOW, m_future_sector );
m_crashes.m_road = true; m_crashes.m_road = true;
break; break;
@ -659,6 +679,7 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
} }
} }
//-----------------------------------------------------------------------------
/** Find the sector that at the longest distance from the kart, that can be /** Find the sector that at the longest distance from the kart, that can be
* driven to without crashing with the track, then find towards which of * driven to without crashing with the track, then find towards which of
* the two edges of the track is closest to the next curve after wards, * the two edges of the track is closest to the next curve after wards,
@ -688,17 +709,16 @@ void DefaultRobot::find_non_crashing_point( sgVec2 result )
sgSubVec2( direction, world->m_track->m_driveline[target_sector], sgSubVec2( direction, world->m_track->m_driveline[target_sector],
m_curr_pos.xyz ); m_curr_pos.xyz );
steps = int( sgLengthVec2( direction ) / m_kart_properties->getKartLength() ); float len=sgLengthVec2(direction);
steps = int( len / m_kart_properties->getKartLength() );
if( steps < 3 ) steps = 3; if( steps < 3 ) steps = 3;
sgVec2 step_coord;
//Protection against having vel_normal with nan values //Protection against having vel_normal with nan values
if( direction[0] != 0.0 && direction[1] != 0.0 ) if(len>0.0f) {
{ sgScaleVec2(direction, 1.0f/len);
sgNormalizeVec2( direction );
} }
sgVec2 step_coord;
//Test if we crash if we drive towards the target sector //Test if we crash if we drive towards the target sector
for( int i = 2; i < steps; ++i ) for( int i = 2; i < steps; ++i )
{ {
@ -784,8 +804,10 @@ inline float DefaultRobot::normalize_angle( float angle )
return angle; return angle;
} }
//-----------------------------------------------------------------------------
/** calc_steps() divides the velocity vector by the lenght of the kart, /** calc_steps() divides the velocity vector by the lenght of the kart,
* and gets the number of steps to use for the sight line of the kart.. * and gets the number of steps to use for the sight line of the kart.
* The calling sequence guarantees that m_future_sector is not UNKNOWN.
*/ */
int DefaultRobot::calc_steps() int DefaultRobot::calc_steps()
{ {
@ -796,9 +818,9 @@ int DefaultRobot::calc_steps()
//mostly for curves. //mostly for curves.
if( fabsf(m_controls.lr) > 0.95 ) if( fabsf(m_controls.lr) > 0.95 )
{ {
assert( m_future_sector > -1 ); const int WIDTH_STEPS =
const int WIDTH_STEPS = (int)( world->m_track->getWidth( (int)( world->m_track->getWidth()[m_future_sector]
)[m_future_sector] / ( m_kart_properties->getKartLength() * 2.0 )); /( m_kart_properties->getKartLength() * 2.0 ) );
steps += WIDTH_STEPS; steps += WIDTH_STEPS;
} }
@ -806,6 +828,7 @@ int DefaultRobot::calc_steps()
return steps; return steps;
} }
//-----------------------------------------------------------------------------
/** Translates coordinates from an angle(in degrees) to values within the range /** Translates coordinates from an angle(in degrees) to values within the range
* of -1.0 to 1.0 to use the same format as the KartControl::lr variable. * of -1.0 to 1.0 to use the same format as the KartControl::lr variable.
*/ */
@ -819,6 +842,7 @@ float DefaultRobot::angle_to_control( float angle ) const
return angle; return angle;
} }
//-----------------------------------------------------------------------------
/** Finds the approximate radius of a track's curve. It needs two arguments, /** Finds the approximate radius of a track's curve. It needs two arguments,
* the number of the drivepoint that marks the beginning of the curve, and * the number of the drivepoint that marks the beginning of the curve, and
* the number of the drivepoint that marks the ending of the curve. * the number of the drivepoint that marks the ending of the curve.
@ -894,6 +918,7 @@ float DefaultRobot::get_approx_radius(const int START, const int END) const
return radius; return radius;
} }
//-----------------------------------------------------------------------------
/**Find_curve() gathers info about the closest sectors ahead: the curve /**Find_curve() gathers info about the closest sectors ahead: the curve
* angle, the direction of the next turn, and the optimal speed at which the * angle, the direction of the next turn, and the optimal speed at which the
* curve can be travelled at it's widest angle. * curve can be travelled at it's widest angle.