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:
parent
f2d5ca5203
commit
3659b14667
@ -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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user