Made QuadGraph use a singleton-like behaviour. It is still created with

explicit calls to QuadGraph::create(...), and the get() function can
return NULL (in case of a race mode that does not use a quad graph).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9421 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-08-04 23:02:58 +00:00
parent 7b5160be59
commit 428ed5a07b
14 changed files with 227 additions and 202 deletions

View File

@ -48,13 +48,12 @@ RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBE
computeTarget();
const LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
m_quad_graph = &(world->getTrack()->getQuadGraph());
m_current_graph_node = world->getSectorForKart(kart->getWorldKartId());
// Determine distance along track
Vec3 ball_distance_vec;
m_quad_graph->spatialToTrack(&ball_distance_vec, getXYZ(),
m_current_graph_node);
QuadGraph::get()->spatialToTrack(&ball_distance_vec, getXYZ(),
m_current_graph_node);
m_distance_along_track = ball_distance_vec[2];
// We have to start aiming at the next sector (since it might be possible
@ -62,14 +61,14 @@ RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBE
m_aimed_graph_node = getSuccessorToHitTarget(m_current_graph_node);
// Get 4 points for the interpolation
int pred = m_quad_graph->getNode(m_current_graph_node)
int pred = QuadGraph::get()->getNode(m_current_graph_node)
.getPredecessor();
m_aiming_points[0] = m_quad_graph->getQuad(pred).getCenter();
m_aiming_points[1] = m_quad_graph->getQuad(m_current_graph_node)
m_aiming_points[0] = QuadGraph::get()->getQuadOfNode(pred).getCenter();
m_aiming_points[1] = QuadGraph::get()->getQuadOfNode(m_current_graph_node)
.getCenter();
m_aiming_points[2] = m_quad_graph->getQuad(m_aimed_graph_node).getCenter();
m_aiming_points[2] = QuadGraph::get()->getQuadOfNode(m_aimed_graph_node).getCenter();
int succ_succ = getSuccessorToHitTarget(m_aimed_graph_node);
m_aiming_points[3] = m_quad_graph->getQuad(succ_succ).getCenter();
m_aiming_points[3] = QuadGraph::get()->getQuadOfNode(succ_succ).getCenter();
m_t = 0;
m_t_increase = 1.0f/(m_aiming_points[2]-m_aiming_points[1]).length();
@ -116,7 +115,7 @@ void RubberBall::computeTarget()
unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index)
{
// For now: always pick a successor on the main driveline.
return m_quad_graph->getNode(node_index).getSuccessor(0);
return QuadGraph::get()->getNode(node_index).getSuccessor(0);
} // getSuccessorToHitTarget
// -----------------------------------------------------------------------------
@ -170,20 +169,18 @@ void RubberBall::update(float dt)
// FIXME: use interpolation here for smooth curves
Vec3 next_xyz = getXYZ() + delta * (m_speed * dt / delta.length());
GraphNode &gn = m_quad_graph->getNode(m_current_graph_node);
int indx = getSuccessorToHitTarget(m_current_graph_node);
GraphNode &gn_next = m_quad_graph->getNode(indx);
// Determine new distance along track
Vec3 ball_distance_vec;
m_quad_graph->findRoadSector(next_xyz, &m_current_graph_node);
QuadGraph::get()->findRoadSector(next_xyz, &m_current_graph_node);
if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR)
{
m_current_graph_node =
m_quad_graph->findOutOfRoadSector(next_xyz,
QuadGraph::get()->findOutOfRoadSector(next_xyz,
QuadGraph::UNKNOWN_SECTOR );
}
m_quad_graph->spatialToTrack(&ball_distance_vec, getXYZ(),
QuadGraph::get()->spatialToTrack(&ball_distance_vec, getXYZ(),
m_current_graph_node);
// Detect wrap around, i.e. crossing the start line
@ -290,7 +287,7 @@ void RubberBall::determineTargetCoordinates(float dt, Vec3 *aim_xyz)
// Aiming at a graph node
// ----------------------
GraphNode *gn = &(m_quad_graph->getNode(m_aimed_graph_node));
GraphNode *gn = &(QuadGraph::get()->getNode(m_aimed_graph_node));
// At this stage m_distance_along track is already the new distance (set
// in the previous time step when aiming). It has to be detected if the
@ -334,7 +331,7 @@ void RubberBall::determineTargetCoordinates(float dt, Vec3 *aim_xyz)
// FIXME: aim better if necessary!
m_aimed_graph_node = getSuccessorToHitTarget(m_aimed_graph_node);
gn = &(m_quad_graph->getNode(m_aimed_graph_node));
gn = &(QuadGraph::get()->getNode(m_aimed_graph_node));
m_aiming_points[3] = gn->getQuad().getCenter();
// Detect a wrap around of the graph node. We could just test if

View File

@ -88,9 +88,6 @@ private:
* used to keep track of the state of this ball. */
bool m_aiming_at_target;
/** For convenience keep a pointer to the quad graph. */
QuadGraph *m_quad_graph;
void computeTarget();
void determineTargetCoordinates(float dt, Vec3 *aim_xyz);
unsigned int getSuccessorToHitTarget(unsigned int node_index);

View File

@ -39,7 +39,6 @@ AIBaseController::AIBaseController(Kart *kart,
{
m_world = dynamic_cast<LinearWorld*>(World::getWorld());
m_track = m_world->getTrack();
m_quad_graph = &m_track->getQuadGraph();
computePath();
}
else
@ -48,7 +47,6 @@ AIBaseController::AIBaseController(Kart *kart,
// a linear world, since it assumes the existance of drivelines)
m_world = NULL;
m_track = NULL;
m_quad_graph = NULL;
m_next_node_index.clear();
m_all_look_aheads.clear();
m_successor_index.clear();
@ -73,15 +71,14 @@ void AIBaseController::newLap(int lap)
*/
void AIBaseController::computePath()
{
m_next_node_index.resize(m_quad_graph->getNumNodes());
m_successor_index.resize(m_quad_graph->getNumNodes());
m_next_node_index.resize(QuadGraph::get()->getNumNodes());
m_successor_index.resize(QuadGraph::get()->getNumNodes());
std::vector<unsigned int> next;
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
{
next.clear();
// Get all successors the AI is allowed to take.
m_quad_graph->getSuccessors(i, next, /*for_ai*/true);
QuadGraph::get()->getSuccessors(i, next, /*for_ai*/true);
// For now pick one part on random, which is not adjusted during the
// race. Long term statistics might be gathered to determine the
// best way, potentially depending on race position etc.
@ -102,8 +99,8 @@ void AIBaseController::computePath()
// find too good a driveline. Note that in general this list should
// be computed recursively, but since the AI for now is using only
// (randomly picked) path this is fine
m_all_look_aheads.resize(m_quad_graph->getNumNodes());
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
m_all_look_aheads.resize(QuadGraph::get()->getNumNodes());
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
{
std::vector<int> l;
int current = i;
@ -121,20 +118,20 @@ void AIBaseController::update(float dt)
{
Controller::update(dt);
if(m_quad_graph)
if(QuadGraph::get())
{
// Update the current node:
int old_node = m_track_node;
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
{
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node,
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node,
&m_all_look_aheads[m_track_node]);
}
// If we can't find a proper place on the track, to a broader search
// on off-track locations.
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
{
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
}
// IF the AI is off track (or on a branch of the track it did not
// select to be on), keep the old position.
@ -155,7 +152,7 @@ void AIBaseController::update(float dt)
unsigned int AIBaseController::getNextSector(unsigned int index)
{
std::vector<unsigned int> successors;
m_quad_graph->getSuccessors(index, successors);
QuadGraph::get()->getSuccessors(index, successors);
return successors[0];
} // getNextSector
@ -167,7 +164,8 @@ unsigned int AIBaseController::getNextSector(unsigned int index)
float AIBaseController::steerToAngle(const unsigned int sector,
const float add_angle)
{
float angle = m_quad_graph->getAngleToNext(sector, getNextSector(sector));
float angle = QuadGraph::get()->getAngleToNext(sector,
getNextSector(sector));
//Desired angle minus current angle equals how many angles to turn
float steer_angle = angle - m_kart->getHeading();

View File

@ -52,9 +52,6 @@ protected:
/** Keep a pointer to world. */
LinearWorld *m_world;
/** The graph of qudas of this track. */
const QuadGraph *m_quad_graph;
/** The current node the kart is on. This can be different from the value
* in LinearWorld, since it takes the chosen path of the AI into account
* (e.g. the closest point in LinearWorld might be on a branch not

View File

@ -49,7 +49,6 @@
DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
{
// Reset must be called after m_quad_graph etc. is set up
reset();
switch( race_manager->getDifficulty())
@ -132,12 +131,14 @@ void DefaultAIController::reset()
AIBaseController::reset();
m_track_node = QuadGraph::UNKNOWN_SECTOR;
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
{
fprintf(stderr, "Invalid starting position for '%s' - not on track - can be ignored.\n",
fprintf(stderr,
"Invalid starting position for '%s' - not on track"
" - can be ignored.\n",
m_kart->getIdent().c_str());
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
}
} // reset
@ -287,7 +288,7 @@ void DefaultAIController::handleBraking()
m_world->isOnRoad(m_kart->getWorldKartId()) )
{
float kart_ang_diff =
m_quad_graph->getAngleToNext(m_track_node,
QuadGraph::get()->getAngleToNext(m_track_node,
m_successor_index[m_track_node])
- m_kart->getHeading();
kart_ang_diff = normalizeAngle(kart_ang_diff);
@ -307,8 +308,9 @@ void DefaultAIController::handleBraking()
//even if we are in the inside, because the kart would be 'thrown'
//out of the curve.
if(!(m_world->getDistanceToCenterForKart(m_kart->getWorldKartId())
> m_quad_graph->getNode(m_track_node).getPathWidth() *
-CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE*m_kart->getMaxSteerAngle()))
> QuadGraph::get()->getNode(m_track_node).getPathWidth() *
-CURVE_INSIDE_PERC ||
m_curve_angle > RAD_TO_DEGREE*m_kart->getMaxSteerAngle()) )
{
m_controls->m_brake = false;
return;
@ -317,8 +319,9 @@ void DefaultAIController::handleBraking()
else if( m_curve_angle < -MIN_TRACK_ANGLE ) //Next curve is right
{
if(!(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )
< m_quad_graph->getNode(m_track_node).getPathWidth() *
CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE*m_kart->getMaxSteerAngle()))
< QuadGraph::get()->getNode(m_track_node).getPathWidth() *
CURVE_INSIDE_PERC ||
m_curve_angle < -RAD_TO_DEGREE*m_kart->getMaxSteerAngle()))
{
m_controls->m_brake = false;
return;
@ -355,12 +358,14 @@ void DefaultAIController::handleSteering(float dt)
*/
//Reaction to being outside of the road
if( fabsf(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )) >
0.5f* m_quad_graph->getNode(m_track_node).getPathWidth()+0.5f )
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+0.5f )
{
steer_angle = steerToPoint(m_quad_graph->getQuad(next).getCenter());
steer_angle = steerToPoint(QuadGraph::get()->getQuadOfNode(next)
.getCenter());
#ifdef AI_DEBUG
m_debug_sphere->setPosition(m_quad_graph->getQuad(next).getCenter().toIrrVector());
m_debug_sphere->setPosition(QuadGraph::get()->getQuad(next)
.getCenter().toIrrVector());
std::cout << "- Outside of road: steer to center point." <<
std::endl;
#endif
@ -886,7 +891,7 @@ void DefaultAIController::checkCrashes(int steps, const Vec3& pos )
/*Find if we crash with the drivelines*/
if(current_node!=QuadGraph::UNKNOWN_SECTOR &&
m_next_node_index[current_node]!=-1)
m_quad_graph->findRoadSector(step_coord, &current_node,
QuadGraph::get()->findRoadSector(step_coord, &current_node,
/* sectors to test*/ &m_all_look_aheads[current_node]);
if( current_node == QuadGraph::UNKNOWN_SECTOR)
@ -921,7 +926,7 @@ void DefaultAIController::findNonCrashingPoint(Vec3 *result)
target_sector = m_next_node_index[sector];
//direction is a vector from our kart to the sectors we are testing
direction = m_quad_graph->getQuad(target_sector).getCenter()
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
- m_kart->getXYZ();
float len=direction.length_2d();
@ -944,22 +949,22 @@ void DefaultAIController::findNonCrashingPoint(Vec3 *result)
{
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
m_quad_graph->spatialToTrack(&step_track_coord, step_coord,
sector );
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
sector );
float distance = fabsf(step_track_coord[0]);
//If we are outside, the previous sector is what we are looking for
if ( distance + m_kart_width * 0.5f
> m_quad_graph->getNode(sector).getPathWidth() )
> QuadGraph::get()->getNode(sector).getPathWidth() )
{
*result = m_quad_graph->getQuad(sector).getCenter();
*result = QuadGraph::get()->getQuadOfNode(sector).getCenter();
return;
}
}
sector = target_sector;
} // for i<100
*result = m_quad_graph->getQuad(sector).getCenter();
*result = QuadGraph::get()->getQuadOfNode(sector).getCenter();
} // findNonCrashingPoint
//-----------------------------------------------------------------------------
@ -982,7 +987,7 @@ int DefaultAIController::calcSteps()
if( fabsf(m_controls->m_steer) > 0.95 )
{
const int WIDTH_STEPS =
(int)( m_quad_graph->getNode(m_future_sector).getPathWidth()
(int)( QuadGraph::get()->getNode(m_future_sector).getPathWidth()
/( m_kart_length * 2.0 ) );
steps += WIDTH_STEPS;
@ -1007,14 +1012,16 @@ void DefaultAIController::findCurve()
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getZ();
i = m_next_node_index[i])
{
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);
total_dist += QuadGraph::get()->getDistanceToNext(i,
m_successor_index[i]);
}
m_curve_angle =
normalizeAngle(m_quad_graph->getAngleToNext(i, m_successor_index[i])
-m_quad_graph->getAngleToNext(m_track_node,
m_successor_index[m_track_node]) );
normalizeAngle(QuadGraph::get()->getAngleToNext(i,
m_successor_index[i])
-QuadGraph::get()->getAngleToNext(m_track_node,
m_successor_index[m_track_node]) );
m_curve_target_speed = m_kart->getCurrentMaxSpeed();
} // findCurve

View File

@ -56,14 +56,14 @@ EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
// with a path that always picks the first branch (i.e. it follows
// the main driveline).
std::vector<unsigned int> next;
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
{
// 0 is always a valid successor - so even if the kart should end
// up by accident on a non-selected path, it will keep on working.
m_successor_index[i] = 0;
next.clear();
m_quad_graph->getSuccessors(i, next);
QuadGraph::get()->getSuccessors(i, next);
m_next_node_index[i] = next[0];
}
@ -75,7 +75,7 @@ EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
// find too good a driveline. Note that in general this list should
// be computed recursively, but since the AI for now is using only
// (randomly picked) path this is fine
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
{
std::vector<int> l;
int current = i;
@ -88,7 +88,7 @@ EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
}
} // if not battle mode
// Reset must be called after m_quad_graph etc. is set up
// Reset must be called after QuadGraph::get() etc. is set up
reset();
m_max_handicap_accel = 1.0f;
@ -122,15 +122,15 @@ void EndController::reset()
m_track_node = QuadGraph::UNKNOWN_SECTOR;
// In battle mode there is no quad graph, so nothing to do in this case
if(m_quad_graph)
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
{
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
// Node that this can happen quite easily, e.g. an AI kart is
// taken over by the end controller while it is off track.
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
{
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
}
}
} // reset
@ -187,10 +187,10 @@ void EndController::handleSteering(float dt)
*/
//Reaction to being outside of the road
if( fabsf(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )) >
0.5f* m_quad_graph->getNode(m_track_node).getPathWidth()+0.5f )
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+0.5f )
{
const int next = m_next_node_index[m_track_node];
target_point = m_quad_graph->getQuad(next).getCenter();
target_point = QuadGraph::get()->getQuadOfNode(next).getCenter();
#ifdef AI_DEBUG
std::cout << "- Outside of road: steer to center point." <<
std::endl;
@ -251,7 +251,8 @@ void EndController::findNonCrashingPoint(Vec3 *result)
target_sector = m_next_node_index[sector];
//direction is a vector from our kart to the sectors we are testing
direction = m_quad_graph->getQuad(target_sector).getCenter() - m_kart->getXYZ();
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
- m_kart->getXYZ();
float len=direction.length_2d();
steps = int( len / m_kart_length );
@ -268,16 +269,16 @@ void EndController::findNonCrashingPoint(Vec3 *result)
{
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
m_quad_graph->spatialToTrack(&step_track_coord, step_coord,
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
sector );
distance = fabsf(step_track_coord[0]);
//If we are outside, the previous sector is what we are looking for
if ( distance + m_kart_width * 0.5f
> m_quad_graph->getNode(sector).getPathWidth() )
> QuadGraph::get()->getNode(sector).getPathWidth() )
{
*result = m_quad_graph->getQuad(sector).getCenter();
*result = QuadGraph::get()->getQuadOfNode(sector).getCenter();
return;
}
}

View File

@ -48,7 +48,7 @@
NewAIController::NewAIController(Kart *kart) : AIBaseController(kart)
{
// Reset must be called after m_quad_graph etc. is set up
// Reset must be called after QuadGraph::get() etc. is set up
reset();
switch( race_manager->getDifficulty())
@ -227,7 +227,7 @@ void NewAIController::handleBraking()
m_world->isOnRoad(m_kart->getWorldKartId()) )
{
float kart_ang_diff =
m_quad_graph->getAngleToNext(m_track_node,
QuadGraph::get()->getAngleToNext(m_track_node,
m_successor_index[m_track_node])
- m_kart->getHeading();
kart_ang_diff = normalizeAngle(kart_ang_diff);
@ -244,7 +244,7 @@ void NewAIController::handleBraking()
//even if we are in the inside, because the kart would be 'thrown'
//out of the curve.
if(!(m_world->getDistanceToCenterForKart(m_kart->getWorldKartId())
> m_quad_graph->getNode(m_track_node).getPathWidth() *
> QuadGraph::get()->getNode(m_track_node).getPathWidth() *
-CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE*m_kart->getMaxSteerAngle()))
{
m_controls->m_brake = false;
@ -254,7 +254,7 @@ void NewAIController::handleBraking()
else if( m_curve_angle < -MIN_TRACK_ANGLE ) //Next curve is right
{
if(!(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )
< m_quad_graph->getNode(m_track_node).getPathWidth() *
< QuadGraph::get()->getNode(m_track_node).getPathWidth() *
CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE*m_kart->getMaxSteerAngle()))
{
m_controls->m_brake = false;
@ -292,7 +292,7 @@ void NewAIController::handleSteering(float dt)
*/
//Reaction to being outside of the road
if( fabsf(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )) >
0.5f* m_quad_graph->getNode(m_track_node).getPathWidth()+1.0f )
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+1.0f )
{
steer_angle = steerToPoint(m_last_target_point);
@ -723,7 +723,7 @@ void NewAIController::checkCrashes( const int STEPS, const Vec3& pos )
/*Find if we crash with the drivelines*/
if(current_node!=QuadGraph::UNKNOWN_SECTOR &&
m_next_node_index[current_node]!=-1)
m_quad_graph->findRoadSector(step_coord, &current_node,
QuadGraph::get()->findRoadSector(step_coord, &current_node,
/* sectors to test*/ &m_all_look_aheads[current_node]);
if( current_node == QuadGraph::UNKNOWN_SECTOR)
@ -739,7 +739,7 @@ float NewAIController::findNonCrashingAngle()
{
unsigned int current_sector = m_next_node_index[m_track_node];
const Vec3 &xyz = m_kart->getXYZ();
const Quad &q = m_quad_graph->getQuad(current_sector);
const Quad &q = QuadGraph::get()->getQuadOfNode(current_sector);
const Vec3 &right = q[2];
const Vec3 &left = q[3];
Vec3 final_right = q[2];
@ -763,7 +763,7 @@ float NewAIController::findNonCrashingAngle()
while(dist<40.0f)
{
const Quad &q = m_quad_graph->getQuad(current_sector);
const Quad &q = QuadGraph::get()->getQuadOfNode(current_sector);
const Vec3 &right = q[2];
const Vec3 &left = q[3];
@ -794,7 +794,7 @@ float NewAIController::findNonCrashingAngle()
very_right = angle_right;
final_right = right;
}
dist += m_quad_graph->getDistanceToNext(current_sector,
dist += QuadGraph::get()->getDistanceToNext(current_sector,
m_successor_index[current_sector]);
current_sector = m_next_node_index[current_sector];
}
@ -825,12 +825,12 @@ void NewAIController::reset()
m_distance_behind = 0.0f;
m_track_node = QuadGraph::UNKNOWN_SECTOR;
AIBaseController::reset();
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
{
fprintf(stderr, "Invalid starting position for '%s' - not on track - can be ignored.\n",
m_kart->getIdent().c_str());
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
}
} // reset
@ -855,7 +855,7 @@ int NewAIController::calcSteps()
if( fabsf(m_controls->m_steer) > 0.95 )
{
const int WIDTH_STEPS =
(int)( m_quad_graph->getNode(m_future_sector).getPathWidth()
(int)( QuadGraph::get()->getNode(m_future_sector).getPathWidth()
/( m_kart_length * 2.0 ) );
steps += WIDTH_STEPS;
@ -878,13 +878,13 @@ void NewAIController::findCurve()
for(i = m_track_node; total_dist < m_kart->getVelocityLC().getZ();
i = m_next_node_index[i])
{
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);
total_dist += QuadGraph::get()->getDistanceToNext(i, m_successor_index[i]);
}
m_curve_angle =
normalizeAngle(m_quad_graph->getAngleToNext(i, m_successor_index[i])
-m_quad_graph->getAngleToNext(m_track_node,
normalizeAngle(QuadGraph::get()->getAngleToNext(i, m_successor_index[i])
-QuadGraph::get()->getAngleToNext(m_track_node,
m_successor_index[m_track_node]) );
m_curve_target_speed = m_kart->getCurrentMaxSpeed();

View File

@ -64,8 +64,8 @@ void LinearWorld::init()
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR;
info.m_last_valid_sector = 0;
info.m_lap_start_time = 0;
m_track->getQuadGraph().findRoadSector(m_karts[n]->getXYZ(),
&info.m_track_sector);
QuadGraph::get()->findRoadSector(m_karts[n]->getXYZ(),
&info.m_track_sector);
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
//the road, so we have to use another function to find the sector.
@ -73,13 +73,13 @@ void LinearWorld::init()
if (!info.m_on_road)
{
info.m_track_sector =
m_track->getQuadGraph().findOutOfRoadSector(m_karts[n]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR );
QuadGraph::get()->findOutOfRoadSector(m_karts[n]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR );
}
m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords,
m_karts[n]->getXYZ(),
info.m_track_sector );
QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords,
m_karts[n]->getXYZ(),
info.m_track_sector );
info.m_race_lap = -1;
info.m_lap_start_time = 0;
@ -118,8 +118,8 @@ void LinearWorld::restartRace()
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR;
info.m_last_valid_sector = 0;
info.m_lap_start_time = 0;
m_track->getQuadGraph().findRoadSector(m_karts[i]->getXYZ(),
&info.m_track_sector);
QuadGraph::get()->findRoadSector(m_karts[i]->getXYZ(),
&info.m_track_sector);
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
//the road, so we have to use another function to find the sector.
@ -127,13 +127,13 @@ void LinearWorld::restartRace()
if (!info.m_on_road)
{
info.m_track_sector =
m_track->getQuadGraph().findOutOfRoadSector(m_karts[i]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR );
QuadGraph::get()->findOutOfRoadSector(m_karts[i]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR);
}
m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords,
m_karts[i]->getXYZ(),
info.m_track_sector );
QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords,
m_karts[i]->getXYZ(),
info.m_track_sector );
info.m_race_lap = -1;
info.m_lap_start_time = -0;
info.m_time_at_last_lap = 99999.9f;
@ -197,8 +197,8 @@ void LinearWorld::update(float dt)
// update sector variables
int prev_sector = kart_info.m_track_sector;
m_track->getQuadGraph().findRoadSector(kart->getXYZ(),
&kart_info.m_track_sector);
QuadGraph::get()->findRoadSector(kart->getXYZ(),
&kart_info.m_track_sector);
kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
if(kart_info.m_on_road)
@ -209,11 +209,11 @@ void LinearWorld::update(float dt)
{
// Kart off road. Find the closest sector instead.
kart_info.m_track_sector =
m_track->getQuadGraph().findOutOfRoadSector(kart->getXYZ(), prev_sector );
QuadGraph::get()->findOutOfRoadSector(kart->getXYZ(), prev_sector );
}
// Update track coords (=progression)
m_track->getQuadGraph().spatialToTrack(&kart_info.m_curr_track_coords,
QuadGraph::get()->spatialToTrack(&kart_info.m_curr_track_coords,
kart->getXYZ(),
kart_info.m_track_sector );
@ -581,11 +581,13 @@ void LinearWorld::moveKartAfterRescue(Kart* kart)
// Using the predecessor has the additional afvantage (besides punishing
// the player a bit more) that it makes it less likely to fall in a
// rescue loop since the kart moves back on each attempt.
const QuadGraph &qg = m_track->getQuadGraph();
info.m_track_sector = qg.getNode(info.m_track_sector).getPredecessor();
info.m_last_valid_sector= qg.getNode(info.m_track_sector).getPredecessor();
info.m_track_sector = QuadGraph::get()->getNode(info.m_track_sector)
.getPredecessor();
info.m_last_valid_sector= QuadGraph::get()->getNode(info.m_track_sector)
.getPredecessor();
kart->setXYZ( m_track->trackToSpatial(info.m_track_sector) );
kart->setXYZ( QuadGraph::get()->getQuadOfNode(info.m_track_sector)
.getCenter());
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(info.m_track_sector) );
@ -820,7 +822,7 @@ void LinearWorld::checkForWrongDirection(unsigned int i)
// If the kart can go in more than one directions from the current track
// don't do any reverse message handling, since it is likely that there
// will be one direction in which it isn't going backwards anyway.
if(m_track->getQuadGraph().getNumberOfSuccessors(m_kart_info[i].m_track_sector)>1)
if(QuadGraph::get()->getNumberOfSuccessors(m_kart_info[i].m_track_sector)>1)
return;
// check if the player is going in the wrong direction

View File

@ -367,11 +367,10 @@ void World::resetAllKarts()
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
UserConfigParams::m_track_debug)
{
const QuadGraph &qg=m_track->getQuadGraph();
Vec3 eps = Vec3(0,1.5f*m_karts[0]->getKartHeight(),0);
for(unsigned int quad=0; quad<qg.getNumNodes(); quad++)
for(unsigned int quad=0; quad<QuadGraph::get()->getNumNodes(); quad++)
{
const Quad &q = qg.getQuad(quad);
const Quad &q = QuadGraph::get()->getQuadOfNode(quad);
const Vec3 center = q.getCenter();
// We have to test for all karts, since the karts have different
// heights and so things might change from kart to kart.

View File

@ -75,7 +75,7 @@ void GraphNode::addSuccessor(unsigned int to)
const Quad &this_quad = m_all_quads->getQuad(m_quad_index);
// to is the graph node, so we have to use m_all_nodes to get the right quad
GraphNode &gn = m_all_nodes->getNode(to);
const Quad &next_quad = m_all_nodes->getQuad(to);
const Quad &next_quad = m_all_nodes->getQuadOfNode(to);
// Keep the first predecessor, which is usually the most 'natural' one.
if(gn.m_predecessor==-1)

View File

@ -32,6 +32,7 @@
#include "tracks/quad_set.hpp"
const int QuadGraph::UNKNOWN_SECTOR = -1;
QuadGraph *QuadGraph::m_quad_graph = NULL;
/** Constructor, loads the graph information for a given set of quads
* from a graph file.
@ -533,7 +534,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
{
// Most likely the kart will still be on the sector it was before,
// so this simple case is tested first.
if(*sector!=UNKNOWN_SECTOR && getQuad(*sector).pointInQuad(xyz) )
if(*sector!=UNKNOWN_SECTOR && getQuadOfNode(*sector).pointInQuad(xyz) )
{
return;
} // if still on same quad
@ -562,7 +563,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
indx = (*all_sectors)[i];
else
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
const Quad &q = getQuad(indx);
const Quad &q = getQuadOfNode(indx);
float dist = xyz.getY() - q.getMinHeight();
// While negative distances are unlikely, we allow some small netative
// numbers in case that the kart is partly in the track.

View File

@ -39,13 +39,21 @@ using namespace irr;
class CheckLine;
/**
* \brief This class stores a graph of quads.
* \ingroup tracks
* \brief This class stores a graph of quads. It uses a 'simplified singleton'
* design pattern: it has a static create function to create exactly instance,
* a destroy function, and a get function (that does not have the side effect
* of the 'normal singleton' design pattern to create an instance). Besides
* saving on the if statement in get(), this is necessary since certain race
* modes might not have a quad graph at all (e.g. battle mode). So get()
* returns NULL in this case, and this is tested where necessary.
* \ingroup tracks
*/
class QuadGraph : public NoCopy
{
private:
static QuadGraph *m_quad_graph;
/** The actual graph data structure. */
std::vector<GraphNode*> m_all_nodes;
/** The set of all quads. */
@ -74,12 +82,12 @@ private:
void createMesh(bool show_invisible=true,
const video::SColor *track_color=NULL,
const video::SColor *lap_color=NULL);
QuadGraph (const std::string &quad_file_name,
const std::string graph_file_name);
~QuadGraph ();
public:
static const int UNKNOWN_SECTOR;
QuadGraph (const std::string &quad_file_name,
const std::string graph_file_name);
~QuadGraph ();
void createDebugMesh();
void cleanupDebugMesh();
void getSuccessors(int node_number,
@ -106,7 +114,33 @@ public:
void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const;
void updateDistancesForAllSuccessors(unsigned int indx, float delta);
// ----------------------------------------------------------------------
/** Returns the one instance of this object. It is possible that there
* is no instance created (e.g. in battle mode, since it doesn't have
* a quad graph), so we don't assert that an instance exist, and we
* also don't create one if it doesn't exists. */
static QuadGraph *get() { return m_quad_graph; }
// ----------------------------------------------------------------------
/** Creates a QuadGraph instance. */
static void create(const std::string &quad_file_name,
const std::string graph_file_name)
{
assert(m_quad_graph==NULL);
m_quad_graph = new QuadGraph(quad_file_name, graph_file_name);
} // create
// ----------------------------------------------------------------------
/** Cleans up the quad graph. It is possible that this function is called
* even if no instance exists (e.g. in battle mode). So it is not an
* error if there is no instance. */
static void destroy()
{
if(m_quad_graph)
{
delete m_quad_graph;
m_quad_graph = NULL;
}
} // destroy
// ----------------------------------------------------------------------
/** Returns the number of nodes in the graph. */
unsigned int getNumNodes() const { return m_all_nodes.size(); }
// ----------------------------------------------------------------------
@ -124,7 +158,7 @@ public:
{ return m_all_nodes[n]->getNumberOfSuccessors(); }
// ----------------------------------------------------------------------
/** Returns the quad that belongs to a graph node. */
const Quad& getQuad(unsigned int j) const
const Quad& getQuadOfNode(unsigned int j) const
{ return m_all_quads->getQuad(m_all_nodes[j]->getIndex()); }
// ----------------------------------------------------------------------
/** Returns the quad that belongs to a graph node. */

View File

@ -65,7 +65,7 @@ using namespace irr;
const float Track::NOHIT = -99999.9f;
// ----------------------------------------------------------------------------
Track::Track(std::string filename)
Track::Track(const std::string &filename)
{
#ifdef DEBUG
m_magic_number = 0x17AC3802;
@ -83,7 +83,6 @@ Track::Track(std::string filename)
m_all_cached_meshes.clear();
m_is_arena = false;
m_camera_far = 1000.0f;
m_quad_graph = NULL;
m_check_manager = NULL;
m_mini_map = NULL;
m_sky_particles = NULL;
@ -121,14 +120,9 @@ void Track::reset()
/** Removes the physical body from the world.
* Called at the end of a race.
*/
void Track::cleanup()
{
if(m_quad_graph)
{
delete m_quad_graph;
m_quad_graph = NULL;
}
QuadGraph::destroy();
ParticleKindManager::get()->cleanUpTrackSpecificGfx();
@ -191,7 +185,7 @@ void Track::cleanup()
}
m_all_cached_meshes.clear();
if(m_quad_graph) delete m_quad_graph;
QuadGraph::destroy();
if(m_check_manager) delete m_check_manager;
if(m_mini_map)
{
@ -256,12 +250,6 @@ void Track::cleanup()
} // cleanup
//-----------------------------------------------------------------------------
const Vec3& Track::trackToSpatial(const int sector) const
{
return m_quad_graph->getQuad(sector).getCenter();
} // trackToSpatial
//-----------------------------------------------------------------------------
void Track::loadTrackInfo()
{
@ -388,6 +376,8 @@ void Track::getMusicInformation(std::vector<std::string>& filenames,
} // getMusicInformation
//-----------------------------------------------------------------------------
/** Select and set the music for this track (doesn't actually start it yet).
*/
void Track::startMusic() const
{
// In case that the music wasn't found (a warning was already printed)
@ -401,29 +391,34 @@ void Track::startMusic() const
*/
void Track::loadQuadGraph(unsigned int mode_id)
{
m_quad_graph = new QuadGraph(m_root+"/"+m_all_modes[mode_id].m_quad_name,
m_root+"/"+m_all_modes[mode_id].m_graph_name);
QuadGraph::create(m_root+"/"+m_all_modes[mode_id].m_quad_name,
m_root+"/"+m_all_modes[mode_id].m_graph_name);
#ifdef DEBUG
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
{
assert(m_quad_graph->getNode(i).getPredecessor()!=-1);
assert(QuadGraph::get()->getNode(i).getPredecessor()!=-1);
}
#endif
if(m_quad_graph->getNumNodes()==0)
if(QuadGraph::get()->getNumNodes()==0)
{
fprintf(stderr, "[Track] WARNING: No graph nodes defined for track '%s'\n",
fprintf(stderr,
"[Track] WARNING: No graph nodes defined for track '%s'\n",
m_filename.c_str());
if (race_manager->getNumberOfKarts() > 1)
{
fprintf(stderr, "[Track] FATAL: I can handle the lack of driveline in single kart mode, but not with AIs\n");
fprintf(stderr,
"[Track] FATAL: I can handle the lack of driveline in single"
"kart mode, but not with AIs\n");
exit(-1);
}
}
else
{
m_mini_map = m_quad_graph->makeMiniMap(World::getWorld()->getRaceGUI()->getMiniMapSize(),
"minimap::"+m_ident);
m_mini_map=
QuadGraph::get()->makeMiniMap(World::getWorld()->getRaceGUI()
->getMiniMapSize(),
"minimap::"+m_ident);
}
} // loadQuadGraph
@ -1122,11 +1117,11 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
}
m_start_transforms.resize(race_manager->getNumberOfKarts());
if(!m_is_arena)
m_quad_graph->setDefaultStartPositions(&m_start_transforms,
karts_per_row,
forwards_distance,
sidewards_distance,
upwards_distance);
QuadGraph::get()->setDefaultStartPositions(&m_start_transforms,
karts_per_row,
forwards_distance,
sidewards_distance,
upwards_distance);
loadMainTrack(*root);
unsigned int main_track_count = m_all_nodes.size();
@ -1366,7 +1361,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
createPhysicsModel(main_track_count);
if (UserConfigParams::m_track_debug) m_quad_graph->createDebugMesh();
if (UserConfigParams::m_track_debug) QuadGraph::get()->createDebugMesh();
// Only print warning if not in battle mode, since battle tracks don't have
// any quads or check lines.

View File

@ -136,9 +136,6 @@ private:
/** Far value for cameras for this track. */
float m_camera_far;
/** The graph used to connect the quads. */
QuadGraph *m_quad_graph;
/** The type of sky to be used for the track. */
enum {SKY_NONE, SKY_BOX,
SKY_DOME, SKY_COLOR} m_sky_type;
@ -255,37 +252,9 @@ public:
static const float NOHIT;
Track (std::string filename);
Track (const std::string &filename);
~Track ();
bool isArena () const { return m_is_arena; }
void cleanup ();
/** Returns the texture with the mini map for this track. */
const video::ITexture*getMiniMap () const { return m_mini_map; }
const Vec3& trackToSpatial (const int SECTOR) const;
void loadTrackModel (World* parent, unsigned int mode_id=0);
void addMusic (MusicInformation* mi)
{m_music.push_back(mi); }
float getGravity () const {return m_gravity; }
/** Returns the version of the .track file. */
int getVersion () const {return m_version; }
/** Returns the length of the main driveline. */
float getTrackLength () const {return m_quad_graph->getLapLength(); }
/** Returns a unique identifier for this track (the directory name). */
const std::string& getIdent () const {return m_ident; }
/** Returns the name of the track, which is e.g. displayed on the screen.
\note this is the LTR name, invoke fribidi as needed
*/
const wchar_t* getName () const {return translations->w_gettext(m_name.c_str()); }
/** Returns all groups this track belongs to. */
const std::vector<std::string>
getGroups () const {return m_groups; }
/** Select and set the music for this track (doesn't actually start it yet) */
void startMusic () const;
bool setTerrainHeight(Vec3 *pos) const;
@ -298,15 +267,48 @@ public:
unsigned int k);
void handleExplosion(const Vec3 &pos,
const PhysicalObject *mp) const;
std::vector< std::vector<float> >
buildHeightMap();
// ------------------------------------------------------------------------
/** Returns the texture with the mini map for this track. */
const video::ITexture*getMiniMap () const { return m_mini_map; }
// ------------------------------------------------------------------------
bool isArena () const { return m_is_arena; }
// ------------------------------------------------------------------------
void loadTrackModel (World* parent, unsigned int mode_id=0);
// ------------------------------------------------------------------------
void addMusic (MusicInformation* mi)
{m_music.push_back(mi); }
// ------------------------------------------------------------------------
float getGravity () const {return m_gravity; }
// ------------------------------------------------------------------------
/** Returns the version of the .track file. */
int getVersion () const {return m_version; }
// ------------------------------------------------------------------------
/** Returns the length of the main driveline. */
float getTrackLength () const
{return QuadGraph::get()->getLapLength();}
// ------------------------------------------------------------------------
/** Returns a unique identifier for this track (the directory name). */
const std::string& getIdent () const {return m_ident; }
// ------------------------------------------------------------------------
/** Returns the name of the track, which is e.g. displayed on the screen.
\note this is the LTR name, invoke fribidi as needed. */
const wchar_t* getName () const
{return translations->w_gettext(m_name.c_str()); }
// ------------------------------------------------------------------------
/** Returns all groups this track belongs to. */
const std::vector<std::string>
getGroups () const {return m_groups; }
// ------------------------------------------------------------------------
/** Returns the filename of this track. */
const std::string& getFilename () const {return m_filename; }
const std::string& getFilename () const {return m_filename; }
// ------------------------------------------------------------------------
/** Returns the name of the designer. */
const core::stringw& getDesigner () const {return m_designer; }
const core::stringw& getDesigner () const {return m_designer; }
// ------------------------------------------------------------------------
/** Returns an absolute path to the screenshot file of this track */
const std::string& getScreenshotFile () const {return m_screenshot; }
const std::string& getScreenshotFile () const {return m_screenshot; }
// ------------------------------------------------------------------------
/** Returns the start coordinates for a kart with a given index.
* \param index Index of kart ranging from 0 to kart_num-1. */
@ -317,9 +319,6 @@ public:
void getAABB(const Vec3 **min, const Vec3 **max) const
{ *min = &m_aabb_min; *max = &m_aabb_max; }
// ------------------------------------------------------------------------
/** Returns the graph of quads, mainly for the AI. */
QuadGraph& getQuadGraph() const { return *m_quad_graph; }
// ------------------------------------------------------------------------
/** Returns 'a' angle for quad n. This angle is used to position a kart
* after a rescue, and to detect wrong directions. This function will
* always return the angle towards the first successor, i.e. the angle
@ -327,7 +326,7 @@ public:
* \param n Number of the quad for which the angle is asked.
*/
float getAngle(int n) const
{ return m_quad_graph->getAngleToNext(n, 0); }
{ return QuadGraph::get()->getAngleToNext(n, 0); }
// ------------------------------------------------------------------------
/** Returns the 2d coordinates of a point when drawn on the mini map
* texture.
@ -336,7 +335,7 @@ public:
* only the first two coordinates will be used.
*/
void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const
{ m_quad_graph->mapPoint2MiniMap(xyz, draw_at); }
{ QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at); }
// ------------------------------------------------------------------------
/** Returns the full path of a given file inside this track directory. */
std::string getTrackFile(const std::string &s) const
@ -347,15 +346,14 @@ public:
// ------------------------------------------------------------------------
/** Returns the name of the i-th. mode. */
const std::string &getModeName(unsigned int i) const
{ return m_all_modes[i].m_name;}
{ return m_all_modes[i].m_name; }
// ------------------------------------------------------------------------
/** Returns the default ambient color. */
const video::SColor &getDefaultAmbientColor() const
{ return m_default_ambient_color;}
{ return m_default_ambient_color; }
// ------------------------------------------------------------------------
/** Returns the far value for cameras. */
float getCameraFar() const { return m_camera_far; }
// ------------------------------------------------------------------------
/** Returns the triangle mesh for this track. */
const TriangleMesh& getTriangleMesh() const {return *m_track_mesh; }
@ -365,15 +363,14 @@ public:
// ------------------------------------------------------------------------
/** Get the number of start positions defined in the scene file. */
unsigned int getNumberOfStartPositions() const
{ return m_start_transforms.size(); }
{ return m_start_transforms.size(); }
// ------------------------------------------------------------------------
WeatherType getWeatherType () const { return m_weather_type; }
// ------------------------------------------------------------------------
ParticleKind* getSkyParticles () { return m_sky_particles; }
// ------------------------------------------------------------------------
bool isFogEnabled() const { return m_use_fog; }
std::vector< std::vector<float> > buildHeightMap();
}; // class Track
#endif