Redone 'distance from start' calculation to use the proper graph structure

(and not to assume that the quads/graph nodes will be added in a specific
order, i.e. in the order in which they are connected).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10819 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-02-07 03:10:43 +00:00
parent f2d5ca5203
commit 3659b14667
3 changed files with 75 additions and 50 deletions

View File

@ -35,7 +35,7 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index)
m_quad_index = quad_index;
m_node_index = node_index;
m_predecessor = -1;
m_distance_from_start = 0;
m_distance_from_start = -1.0f;
const Quad &quad = QuadSet::get()->getQuad(m_quad_index);
// FIXME: the following values should depend on the actual orientation
@ -75,42 +75,13 @@ void GraphNode::addSuccessor(unsigned int to)
// Keep the first predecessor, which is usually the most 'natural' one.
if(gn.m_predecessor==-1)
gn.m_predecessor = m_node_index;
core::vector2df d2 = m_lower_center_2d
- QuadGraph::get()->getNode(to).m_lower_center_2d;
Vec3 diff = next_quad.getCenter() - this_quad.getCenter();
m_distance_to_next.push_back(d2.getLength());
float theta = atan2(diff.getX(), diff.getZ());
m_angle_to_next.push_back(theta);
Vec3 d = m_lower_center - QuadGraph::get()->getNode(to).m_lower_center;
m_distance_to_next.push_back(d.length());
Vec3 diff = next_quad.getCenter() - this_quad.getCenter();
m_angle_to_next.push_back(atan2(diff.getX(), diff.getZ()));
// The length of this quad is the average of the left and right side
float distance_to_next = ( this_quad[2].distance(this_quad[1])
+ this_quad[3].distance(this_quad[0]) ) *0.5f;
// The distance from start for the successor node
if(to!=0)
{
float distance_for_next = m_distance_from_start+distance_to_next;
// If the successor node does not have a distance from start defined,
// update its distance. Otherwise if the node already has a distance,
// it is potentially necessary to update its distance from start:
// without this the length of the track (as taken by the distance
// from start of the last node) could be smaller than some of the
// paths. This can result in incorrect results for the arrival time
// estimation of the AI karts. See trac #354 for details.
if(QuadGraph::get()->getNode(to).m_distance_from_start==0)
{
QuadGraph::get()->getNode(to).m_distance_from_start
= distance_for_next;
}
else if(QuadGraph::get()->getNode(to).m_distance_from_start
< distance_for_next)
{
float delta = distance_for_next
- QuadGraph::get()->getNode(to).getDistanceFromStart();
QuadGraph::get()->updateDistancesForAllSuccessors(to, delta);
}
}
} // addSuccessor
// ----------------------------------------------------------------------------
@ -196,6 +167,7 @@ void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result)
else
result->setX(-(closest-xyz2d).getLength()); // to the left
result->setZ( m_distance_from_start + (closest-m_lower_center_2d).getLength());
printf("get distances %f %f\n", result->getX(), result->getZ());
} // getDistances
// ----------------------------------------------------------------------------

View File

@ -185,21 +185,28 @@ void QuadGraph::load(const std::string &filename)
}
delete xml;
// Define the track length
setDefaultSuccessors();
// The track exporter always exports quad 0 as first quad after (or at)
// the start line (start line is lower side of quad 0). In reverse mode
// the start quad is the predecessor of node 0.
unsigned int start_node = m_reverse ? m_all_nodes[0]->getPredecessor()
: 0;
computeDistanceFromStart(start_node, 0.0f);
// Define the track length as the maximum at the end of a quad
// (i.e. distance_from_start + length till successor 0).
m_lap_length = -1;
for(unsigned int i=0; i<m_all_nodes.size(); i++)
{
if(m_all_nodes[i]->getSuccessor(0)==0)
{
m_lap_length = m_all_nodes[i]->getDistanceFromStart()
float l = m_all_nodes[i]->getDistanceFromStart()
+ m_all_nodes[i]->getDistanceToSuccessor(0);
break;
}
if(l > m_lap_length)
m_lap_length = l;
}
setDefaultSuccessors();
} // load
// ----------------------------------------------------------------------------
/**
* Finds which checklines must be visited before driving on this quad
* (useful for rescue)
@ -581,7 +588,52 @@ void QuadGraph::getSuccessors(int node_number,
} // getSuccessors
// ----------------------------------------------------------------------------
/** Increases
void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
{
GraphNode *gn = m_all_nodes[node];
float current_distance = gn->getDistanceFromStart();
// If this node already has a distance defined, check if the new distance
// is longer, and if so adjust all following nodes. Without this the
// length of the track (as taken by the distance from start of the last
// node) could be smaller than some of the paths. This can result in
// incorrect results for the arrival time estimation of the AI karts.
// See trac #354 for details.
// Then there is no need to test/adjust any more nodes.
if(current_distance>=0)
{
if(current_distance<new_distance)
{
float delta = new_distance - current_distance;
updateDistancesForAllSuccessors(gn->getIndex(), delta);
}
return;
}
// Otherwise this node has no distance defined yet. Set the new
// distance, and recursively update all following nodes.
gn->setDistanceFromStart(new_distance);
for(unsigned int i=0; i<gn->getNumberOfSuccessors(); i++)
{
GraphNode *gn_next = m_all_nodes[gn->getSuccessor(i)];
// The start node (only node with distance 0) is reached again,
// recursion can stop now
if(gn_next->getDistanceFromStart()==0)
continue;
computeDistanceFromStart(gn_next->getIndex(),
new_distance + gn->getDistanceToSuccessor(i));
} // for i
} // computeDistanceFromStart
// ----------------------------------------------------------------------------
/** Increases the distance from start for all nodes that are directly or
* indirectly a successor of the given node. This code is used when two
* branches merge together, but since the latest 'fork' indicates a longer
* distance from start.
* \param indx Index of the node for which to increase the distance.
* \param delta Amount by which to increase the distance.
*/
void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta)
{
@ -590,11 +642,9 @@ void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta)
for(unsigned int i=0; i<g.getNumberOfSuccessors(); i++)
{
GraphNode &g_next = getNode(g.getSuccessor(i));
// If we reach the beginning of the graph (usually node with index 0,
// but just in case also test for nodes with distance 0), all nodes
// are updated, so no need to recurse any further.
if(g_next.getIndex()==0 ||
g_next.getDistanceFromStart()==0)
// Stop when we reach the start node, i.e. the only node with a
// distance of 0
if(g_next.getDistanceFromStart()==0)
continue;
// Only increase the distance from start of a successor node, if

View File

@ -83,6 +83,7 @@ private:
void addSuccessor(unsigned int from, unsigned int to);
void load (const std::string &filename);
void computeDistanceFromStart(unsigned int start_node, float distance);
void createMesh(bool show_invisible=true,
const video::SColor *track_color=NULL,
const video::SColor *lap_color=NULL);
@ -179,7 +180,9 @@ public:
/** Returns the length of the main driveline. */
float getLapLength() const {return m_lap_length; }
// ----------------------------------------------------------------------
/** Returns true if the graph is to be reversed. */
bool isReverse() const {return m_reverse; }
// ----------------------------------------------------------------------
void setChecklineRequirements()
{
setChecklineRequirements(m_all_nodes[0], -1);