1) Removed some of the old driveline usage (not all yet, work

in progress).
2) Removed shortcut detection and handling.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3505 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2009-05-17 12:57:40 +00:00
parent 46ff769916
commit 616acb985a
15 changed files with 146 additions and 292 deletions

View File

@@ -101,7 +101,8 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
// -----------------------------------------------------------------------------
Plunger::~Plunger()
{
m_rubber_band->removeFromScene();
if(m_rubber_band)
m_rubber_band->removeFromScene();
} // ~Plunger
// -----------------------------------------------------------------------------

View File

@@ -251,10 +251,6 @@ public:
const std::string& getName () const {return m_kart_properties->getName();}
const std::string& getIdent () const {return m_kart_properties->getIdent();}
virtual bool isPlayerKart () const {return false; }
/** Called by world in case of the kart taking a shortcut. The player kart
* will display a message in this case, default behaviour is to do nothing.
*/
virtual void doingShortcut() {};
// addMessages gets called by world to add messages to the gui
virtual void addMessages () {};
virtual void collectedItem (const Item &item, int random_attachment);

View File

@@ -381,15 +381,3 @@ void PlayerKart::collectedItem(const Item &item, int add_info)
}
}
} // collectedItem
//-----------------------------------------------------------------------------
/** Called when the kart is doing a shortcut. The player kart will display
* a message for the user.
*/
void PlayerKart::doingShortcut()
{
RaceGUI* m=(RaceGUI*)getRaceGUI();
// Can happen if the option menu is called
if(m)
m->addMessage(_("Invalid short-cut!!"), this, 2.0f, 60);
} // doingShortcut

View File

@@ -63,7 +63,6 @@ public:
virtual void crashed (Kart *k);
virtual void setPosition (int p);
virtual void raceFinished (float time);
virtual void doingShortcut ();
bool isPlayerKart () const {return true;}
Camera* getCamera () {return m_camera;}
void reset ();

View File

@@ -149,23 +149,12 @@ void LinearWorld::update(float delta)
// update sector variables
int prev_sector = kart_info.m_track_sector;
m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector,
/*tolerance*/ true);
m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector);
// Check if the kart is taking a shortcut (if it's not already doing one):
// -----------------------------------------------------------------------
kart_info.m_on_road = kart_info.m_track_sector != Track::UNKNOWN_SECTOR;
if(kart_info.m_on_road)
{
if(m_track->isShortcut(kart_info.m_last_valid_sector, kart_info.m_track_sector))
{
// bring karts back to where they left the track.
rescueKartAfterShortcut(kart, kart_info);
}
kart_info.m_last_valid_sector = kart_info.m_track_sector;
kart_info.m_last_valid_race_lap = kart_info.m_race_lap;
} // last_valid_sectpr!=UNKNOWN_SECTOR
else
if(!kart_info.m_on_road)
{
// Kart off road. Find the closest sector instead.
kart_info.m_track_sector =
@@ -174,8 +163,6 @@ void LinearWorld::update(float delta)
? Track::RS_RIGHT
: Track::RS_LEFT,
prev_sector );
if(m_track->isShortcut(prev_sector, kart_info.m_track_sector))
rescueKartAfterShortcut(kart, kart_info);
}
// Update track coords (=progression)
@@ -500,23 +487,6 @@ float LinearWorld::estimateFinishTimeForKart(Kart* kart)
return getTime() + (full_distance - distance_covered) / average_speed;
} // estimateFinishTime
//-----------------------------------------------------------------------------
/** Rescues a kart after a shortcut was detected. The kart is placed at the
* last valid position.
*/
void LinearWorld::rescueKartAfterShortcut(Kart* kart, KartInfo& kart_info)
{
// Reset the kart to the segment where the shortcut started
// add one because 'moveKartAfterRescue' removes 1
kart_info.m_track_sector = kart_info.m_last_valid_sector+1;
if(kart_info.m_track_sector>=(int)m_track->m_driveline.size())
kart_info.m_track_sector = 0;
kart_info.m_race_lap = kart_info.m_last_valid_race_lap;
kart->doingShortcut();
kart->forceRescue();
} // rescueKartAfterShortcut
//-----------------------------------------------------------------------------
/** Decide where to drop a rescued kart

View File

@@ -43,6 +43,7 @@
#include "modes/linear_world.hpp"
#include "network/network_manager.hpp"
#include "robots/track_info.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@@ -63,6 +64,21 @@ DefaultRobot::DefaultRobot(const std::string& kart_name,
m_kart_length = m_kart_properties->getKartModel()->getLength();
m_kart_width = m_kart_properties->getKartModel()->getWidth();
m_track = RaceManager::getTrack();
m_quad_graph = &m_track->getQuadGraph();
m_next_quad_index.reserve(m_quad_graph->getNumNodes());
m_successor_index.reserve(m_quad_graph->getNumNodes());
// For now pick one part on random, which is not adjusted during the run
std::vector<unsigned int> next;
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
{
next.clear();
m_quad_graph->getSuccessors(i, next);
int indx = rand() % next.size();
m_successor_index.push_back(indx);
m_next_quad_index.push_back(next[indx]);
}
m_world = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
assert(m_world != NULL);
@@ -304,9 +320,8 @@ void DefaultRobot::handleBraking()
//-----------------------------------------------------------------------------
void DefaultRobot::handleSteering(float dt)
{
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
const size_t NEXT_SECTOR = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
? m_track_sector + 1 : 0;
const int next = m_next_quad_index[m_track_sector];
float steer_angle = 0.0f;
/*The AI responds based on the information we just gathered, using a
@@ -316,7 +331,7 @@ void DefaultRobot::handleSteering(float dt)
if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5f >
m_track->getWidth()[m_track_sector] )
{
steer_angle = steerToPoint( m_track->m_driveline[NEXT_SECTOR], dt );
steer_angle = steerToPoint(m_quad_graph->getCenterOfQuad(next), dt );
#ifdef AI_DEBUG
std::cout << "- Outside of road: steer to center point." <<
@@ -330,12 +345,12 @@ void DefaultRobot::handleSteering(float dt)
//-1 = left, 1 = right, 0 = no crash.
if( m_start_kart_crash_direction == 1 )
{
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
steer_angle = steerToAngle(next, -M_PI*0.5f );
m_start_kart_crash_direction = 0;
}
else if(m_start_kart_crash_direction == -1)
{
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f);
steer_angle = steerToAngle(next, M_PI*0.5f);
m_start_kart_crash_direction = 0;
}
else
@@ -343,12 +358,12 @@ void DefaultRobot::handleSteering(float dt)
if(m_world->getDistanceToCenterForKart( getWorldKartId() ) >
m_world->getDistanceToCenterForKart( m_crashes.m_kart ))
{
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
steer_angle = steerToAngle(next, -M_PI*0.5f );
m_start_kart_crash_direction = 1;
}
else
{
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f );
steer_angle = steerToAngle(next, M_PI*0.5f );
m_start_kart_crash_direction = -1;
}
}
@@ -367,20 +382,20 @@ void DefaultRobot::handleSteering(float dt)
{
case FT_FAREST_POINT:
{
Vec2 straight_point;
findNonCrashingPoint( straight_point );
Vec3 straight_point;
findNonCrashingPoint(&straight_point);
steer_angle = steerToPoint(straight_point, dt);
}
break;
case FT_PARALLEL:
steer_angle = steerToAngle( NEXT_SECTOR, 0.0f );
steer_angle = steerToAngle(next, 0.0f );
break;
case FT_AVOID_TRACK_CRASH:
if( m_crashes.m_road )
{
steer_angle = steerToAngle( m_track_sector, 0.0f );
steer_angle = steerToAngle(m_track_sector, 0.0f );
}
else steer_angle = 0.0f;
@@ -736,12 +751,12 @@ float DefaultRobot::steerToAngle(const size_t SECTOR, const float ANGLE)
* \param point Point to steer towards.
* \param dt Time step.
*/
float DefaultRobot::steerToPoint(const Vec2 point, float dt)
float DefaultRobot::steerToPoint(const Vec3 &point, float dt)
{
// No sense steering if we are not driving.
if(getSpeed()==0) return 0.0f;
const float dx = point[0] - getXYZ().getX();
const float dy = point[1] - getXYZ().getY();
const float dx = point.getX() - getXYZ().getX();
const float dy = point.getY() - getXYZ().getY();
/** Angle from the kart position to the point in world coordinates. */
float theta = -atan2(dx, dy);
@@ -899,12 +914,9 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos )
* the two edges of the track is closest to the next curve after wards,
* and return the position of that edge.
*/
void DefaultRobot::findNonCrashingPoint( Vec2 result )
{
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
unsigned int sector = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
? m_track_sector + 1 : 0;
void DefaultRobot::findNonCrashingPoint(Vec3 *result)
{
unsigned int sector = m_next_quad_index[m_track_sector];
int target_sector;
Vec3 direction;
@@ -917,10 +929,10 @@ void DefaultRobot::findNonCrashingPoint( Vec2 result )
{
//target_sector is the sector at the longest distance that we can drive
//to without crashing with the track.
target_sector = sector + 1 < DRIVELINE_SIZE ? sector + 1 : 0;
target_sector = m_next_quad_index[sector];
//direction is a vector from our kart to the sectors we are testing
direction = m_track->m_driveline[target_sector] - getXYZ();
direction = m_quad_graph->getCenterOfQuad(target_sector) - getXYZ();
float len=direction.length_2d();
steps = int( len / m_kart_length );
@@ -946,8 +958,7 @@ void DefaultRobot::findNonCrashingPoint( Vec2 result )
//If we are outside, the previous sector is what we are looking for
if ( distance + m_kart_width * 0.5f > m_track->getWidth()[sector] )
{
result = m_track->m_driveline[sector];
//sgCopyVec2( result, m_track->m_driveline[sector] );
*result = m_quad_graph->getCenterOfQuad(sector);
#ifdef SHOW_NON_CRASHING_POINT
ssgaSphere *sphere = new ssgaSphere;
@@ -1080,83 +1091,6 @@ void DefaultRobot::setSteering(float angle, float dt)
}
} // setSteering
//-----------------------------------------------------------------------------
/** 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 ending of the curve.
*
* Based on that you can construct any circle out of 3 points in it, we use
* the two arguments to use the drivelines as the first and last point; the
* middle sector is averaged.
*/
float DefaultRobot::getApproxRadius(const int START, const int END) const
{
const int MIDDLE = (START + END) / 2;
//If the START and END sectors are very close, their average will be one
//of them, and using twice the same point just generates a huge radius
//(too big to be of any use) but it also can generate a division by zero,
//so here is some special handling for that case.
if (MIDDLE == START || MIDDLE == END ) return 99999.0f;
float X1, Y1, X2, Y2, X3, Y3;
//The next line is just to avoid compiler warnings.
X1 = X2 = X3 = Y1 = Y2 = Y3 = 0.0;
if(m_inner_curve == -1)
{
X1 = m_track->m_left_driveline[START][0];
Y1 = m_track->m_left_driveline[START][1];
X2 = m_track->m_left_driveline[MIDDLE][0];
Y2 = m_track->m_left_driveline[MIDDLE][1];
X3 = m_track->m_left_driveline[END][0];
Y3 = m_track->m_left_driveline[END][1];
}
else if (m_inner_curve == 0)
{
X1 = m_track->m_driveline[START][0];
Y1 = m_track->m_driveline[START][1];
X2 = m_track->m_driveline[MIDDLE][0];
Y2 = m_track->m_driveline[MIDDLE][1];
X3 = m_track->m_driveline[END][0];
Y3 = m_track->m_driveline[END][1];
}
else if (m_inner_curve == 1)
{
X1 = m_track->m_right_driveline[START][0];
Y1 = m_track->m_right_driveline[START][1];
X2 = m_track->m_right_driveline[MIDDLE][0];
Y2 = m_track->m_right_driveline[MIDDLE][1];
X3 = m_track->m_right_driveline[END][0];
Y3 = m_track->m_right_driveline[END][1];
}
const float A = X2 - X1;
const float B = Y2 - Y1;
const float C = X3 - X1;
const float D = Y3 - Y1;
const float E = A * ( X1 + X2) + B * (Y1 + Y2);
const float F = C * ( X1 + X3) + D * (Y1 + Y3);
const float G = 2.0f * ( A*( Y3-Y2 ) - B*( X3 - X2 ) );
const float pX = ( D*E - B*F) / G;
const float pY = ( A*F - C*E) / G;
const float radius = sqrt( ( X1 - pX) * ( X1 - pX) + (Y1 - pY) * (Y1 - pY) );
return radius;
} // getApproxRadius
//-----------------------------------------------------------------------------
/**FindCurve() gathers info about the closest sectors ahead: the curve
* angle, the direction of the next turn, and the optimal speed at which the
@@ -1166,23 +1100,12 @@ float DefaultRobot::getApproxRadius(const int START, const int END) const
*/
void DefaultRobot::findCurve()
{
const int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
float total_dist = 0.0f;
int next_hint = m_track_sector;
int i;
for(i = m_track_sector; total_dist < getVelocityLC().getY(); i = next_hint)
for(i = m_track_sector; total_dist < getVelocityLC().getY();
i = m_next_quad_index[i])
{
next_hint = i + 1 < DRIVELINE_SIZE ? i + 1 : 0;
// Note that m_driveline[...].getZ() might be undefined and trigger
// an exception when used. So we can't just write
// (m_driveline[i]-m_driveline[next_hint]).length_2d()
Vec3 v;
v.setX(m_track->m_driveline[i].getX() - m_track->m_driveline[next_hint].getX());
v.setY(m_track->m_driveline[i].getY() - m_track->m_driveline[next_hint].getY());
// length_2d only uses the X and Y component.
// FIXME: the values of v.length could be pre-computed and saved
total_dist += v.length_2d();
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);
}

View File

@@ -23,11 +23,11 @@
#include "utils/vec3.hpp"
/* third coord won't be used */
typedef Vec3 Vec2;
class Track;
class LinearWorld;
class TrackInfo;
class QuadGraph;
class DefaultRobot : public AutoKart
{
@@ -106,7 +106,7 @@ private:
/** Time an item has been collected and not used. */
float m_time_since_last_shot;
int m_future_sector;
Vec2 m_future_location;
Vec3 m_future_location;
float m_time_till_start; //Used to simulate a delay at the start of the
//race, since human players don't accelerate
@@ -124,8 +124,16 @@ private:
LinearWorld *m_world;
/** Cache kart_info.m_track_sector. */
int m_track_sector;
/** The graph of qudas of this track. */
const QuadGraph *m_quad_graph;
/** Which of the successors of a node was selected by the AI. */
std::vector<int> m_successor_index;
/** For each node in the graph this list contained the chosen next node.
* For normal lap track without branches we always have
* m_next_quad_index[i] = (i+1) % size;
* but if a branch is possible, the AI will select one option here. */
std::vector<int> m_next_quad_index;
float m_time_since_stuck;
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.
@@ -167,15 +175,14 @@ private:
/*Lower level functions not called directly from update()*/
float steerToAngle(const size_t SECTOR, const float ANGLE);
float steerToPoint(const Vec2 point, float dt);
float steerToPoint(const Vec3 &point, float dt);
void checkCrashes(const int STEPS, const Vec2& pos);
void findNonCrashingPoint(Vec2 result);
void checkCrashes(const int STEPS, const Vec3& pos);
void findNonCrashingPoint(Vec3 *result);
float normalizeAngle(float angle);
int calcSteps();
void setSteering(float angle, float dt);
float getApproxRadius(const int START, const int END) const;
void findCurve();
public:

View File

@@ -19,6 +19,7 @@
#include "robots/track_info.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@@ -36,7 +37,7 @@ void TrackInfo::setupSteerInfo()
// First find the beginning of a new section, i.e. a place where the track
// direction changes from either straight to curve or the other way round.
int i = 0;
int num_drivelines = m_track->m_driveline.size();
int num_drivelines = m_track->getQuadGraph().getNumNodes();
// not ready yet float current_angle = m_track->m_angle[i];
while(i<num_drivelines)
{

View File

@@ -104,8 +104,6 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_zipper_time, "zipper-time" );
CHECK_NEG(m_zipper_force, "zipper-force" );
CHECK_NEG(m_zipper_speed_gain, "zipper-speed-gain" );
CHECK_NEG(m_shortcut_length, "shortcut-length" );
CHECK_NEG(m_offroad_tolerance, "offroad-tolerance" );
CHECK_NEG(m_final_camera_time, "final-camera-time" );
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
@@ -137,11 +135,9 @@ void STKConfig::init_defaults()
m_anvil_time = m_zipper_time =
m_zipper_force = m_zipper_speed_gain =
m_explosion_impulse = m_explosion_impulse_objects =
m_shortcut_length = m_music_credit_time =
m_music_credit_time = m_slowdown_factor =
m_delay_finish_time = m_skid_fadeout_time =
m_slowdown_factor = m_offroad_tolerance =
m_final_camera_time = m_near_ground =
UNDEFINED;
m_final_camera_time = m_near_ground = UNDEFINED;
m_max_karts = -100;
m_grid_order = -100;
m_max_history = -100;
@@ -184,8 +180,6 @@ void STKConfig::getAllData(const lisp::Lisp* lisp)
// Get the values which are not part of the default KartProperties
// ---------------------------------------------------------------
lisp->get("anvil-weight", m_anvil_weight );
lisp->get("shortcut-length", m_shortcut_length );
lisp->get("offroad-tolerance", m_offroad_tolerance );
lisp->get("final-camera-time", m_final_camera_time );
lisp->get("anvil-speed-factor", m_anvil_speed_factor );
lisp->get("parachute-friction", m_parachute_friction );

View File

@@ -53,11 +53,6 @@ public:
float m_zipper_force; /**<Additional force added to the
acceleration. */
float m_zipper_speed_gain; /**<Initial one time speed gain. */
float m_shortcut_length; /**<Skipping more than this distance
in segments triggers a shortcut. */
float m_offroad_tolerance; /**<Road width is extended by that
fraction to make shortcut detection
more forgiving. */
float m_final_camera_time; /**<Time for the movement of the final
* camera. */
float m_explosion_impulse; /**<Impulse affecting each non-hit kart.*/

View File

@@ -25,22 +25,25 @@
/** Constructor, loads the graph information for a given set of quads
* from a graph file.
* \param filename Name of the file to load.
* \param quad_set The set of quads to which the graph applies.
* \param quad_file_name Name of the file of all quads
* \param graph_file_name Name of the file describing the actual graph
*/
QuadGraph::QuadGraph(const std::string &filename, QuadSet* quad_set)
QuadGraph::QuadGraph(const std::string &quad_file_name,
const std::string graph_file_name)
{
m_all_quads = new QuadSet(quad_file_name);
// First create all nodes
for(unsigned int i=0; i<quad_set->getSize(); i++) {
m_all_nodes.push_back(new GraphNode);
for(unsigned int i=0; i<m_all_quads->getSize(); i++) {
m_all_nodes.push_back(new GraphNode(i));
}
load(filename);
load(graph_file_name);
} // QuadGraph
// -----------------------------------------------------------------------------
/** Destructor, removes all nodes of the graph. */
QuadGraph::~QuadGraph()
{
delete m_all_quads;
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
delete m_all_nodes[i];
}
@@ -73,7 +76,7 @@ void QuadGraph::load(const std::string &filename)
node->get("from", &from);
node->get("to", &to);
assert(from>=0 && from <(int)m_all_nodes.size());
m_all_nodes[from]->addSuccessor(to);
m_all_nodes[from]->addSuccessor(to, *m_all_quads);
} // from
delete xml;
@@ -88,7 +91,8 @@ void QuadGraph::setDefaultSuccessors()
{
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
if(m_all_nodes[i]->getNumberOfSuccessors()==0) {
m_all_nodes[i]->addSuccessor( i+1>=m_all_nodes.size() ? 0 : i+1);
m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1,
*m_all_quads);
} // if size==0
} // for i<m_allNodes.size()
} // setDefaultSuccessors
@@ -98,10 +102,23 @@ void QuadGraph::setDefaultSuccessors()
* \param node_number The number of the node.
* \param succ A vector of ints to which the successors are added.
*/
void QuadGraph::getSuccessors(int node_number, std::vector<int>& succ) const {
void QuadGraph::getSuccessors(int node_number, std::vector<unsigned int>& succ) const {
const GraphNode *v=m_all_nodes[node_number];
for(unsigned int i=0; i<v->getNumberOfSuccessors(); i++) {
succ.push_back((*v)[i]);
}
} // getSuccessors
// ============================================================================
/** Adds a successor to a node. This function will also pre-compute certain
* values (like distance from this node to the successor, angle (in world)
* between this node and the successor.
* \param to The index of the successor.
*/
void QuadGraph::GraphNode::addSuccessor(int to, const QuadSet &quad_set)
{
m_vertices.push_back(to);
Vec3 diff = quad_set.getCenterOfQuad(to)
- quad_set.getCenterOfQuad(m_index);
m_distance_to_next.push_back(diff.length());
} // addSuccessor

View File

@@ -23,7 +23,7 @@
#include <vector>
#include <string>
class QuadSet;
#include "tracks/quad_set.hpp"
/** This class stores a graph of quads. */
class QuadGraph {
@@ -31,27 +31,54 @@ class QuadGraph {
* edges. */
class GraphNode
{
/** Index of this node in m_all_quads. */
int m_index;
/** The list of successors. */
std::vector<int> m_vertices;
std::vector<int> m_vertices;
/** The distance to each of the successors. */
std::vector<float> m_distance_to_next;
public:
/** Adds a successor to a node. */
void addSuccessor (int to) {m_vertices.push_back(to); }
/** Constructor, stores the index.
* \param index Index of this node in m_all_quads. */
GraphNode(int index) { m_index = index; }
void addSuccessor (int to, const QuadSet &quad_set);
/** Returns the i-th successor. */
unsigned int operator[] (int i) const {return m_vertices[i]; }
unsigned int operator[] (int i) const {return m_vertices[i]; }
/** Returns the number of successors. */
unsigned int getNumberOfSuccessors() const
{ return (unsigned int)m_vertices.size(); }
{ return (unsigned int)m_vertices.size(); }
/** Returns the distance to the j-th. successor. */
float getDistanceToSuccessor(int j) const
{ return m_distance_to_next[j]; }
};
// ========================================================================
protected:
/** The actual graph data structure. */
std::vector<GraphNode*> m_all_nodes;
QuadSet *m_all_quads;
void setDefaultSuccessors();
void load (const std::string &filename);
public:
QuadGraph (const std::string &filename, QuadSet *quad_set);
~QuadGraph ();
void getSuccessors(int quadNumber, std::vector<int>& succ) const;
QuadGraph (const std::string &quad_file_name,
const std::string graph_file_name);
~QuadGraph ();
void getSuccessors(int quadNumber,
std::vector<unsigned int>& succ) const;
/** Returns the number of nodes in the graph. */
unsigned int getNumNodes() const { return m_all_nodes.size(); }
/** Returns the quad set for this graph. */
const QuadSet* getQuads() const { return m_all_quads; }
/** Returns the center of a quad.
* \param n Index of the quad. */
const Vec3& getCenterOfQuad(int n) const
{ return m_all_quads->getCenterOfQuad(n); }
/** Return the distance to the j-th successor of node n. */
float getDistanceToNext(int n, int j) const
{ return m_all_nodes[n]->getDistanceToSuccessor(j);}
}; // QuadGraph
#endif

View File

@@ -37,7 +37,7 @@ private:
computations at runtime. */
Vec3 m_center;
/** Constructor, takes 4 points. */
Quad(btVector3 p0, btVector3 p1, btVector3 p2, btVector3 p3)
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3)
{
m_p[0]=p0; m_p[1]=p1; m_p[2]=p2; m_p[3]=p3;
m_center = 0.25f*(p0+p1+p2+p3);
@@ -48,7 +48,7 @@ private:
/** Returns the i-th. point of a quad. */
const btVector3& operator[](int i) const {return m_p[i]; }
/** Returns the center of a quad. */
const btVector3& getCenter () const {return m_center; }
const Vec3& getCenter () const {return m_center; }
}; // class Quad
// =======================================================================
/** The 2d bounding box, used for hashing. */
@@ -78,7 +78,7 @@ public:
/** Returns the number of quads. */
unsigned int getSize() const {return (unsigned int)m_allQuads.size(); }
/** Returns the center of quad n. */
const btVector3& getCenterOfQuad(int n) const
const Vec3& getCenterOfQuad(int n) const
{return m_allQuads[n]->getCenter(); }
}; // QuadSet
#endif

View File

@@ -74,7 +74,6 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
m_all_meshes.clear();
m_has_final_camera = false;
m_is_arena = false;
m_quads = NULL;
m_quad_graph = NULL;
loadTrack(m_filename);
loadDriveline();
@@ -85,7 +84,6 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
/** Destructor, removes quad data structures etc. */
Track::~Track()
{
if(m_quads) delete m_quads;
if(m_quad_graph) delete m_quad_graph;
} // ~Track
@@ -169,34 +167,18 @@ int Track::pointInQuad
* \param XYZ Position for which the segment should be determined.
* \param sector Contains the previous sector (as a shortcut, since usually
* the sector is the same as the last one), and on return the result
* \param with_tolerance If true, the drivelines with tolerance are used.
* This reduces the impact of driving slightly off road.
*/
void Track::findRoadSector(const Vec3& XYZ, int *sector,
bool with_tolerance )const
void Track::findRoadSector(const Vec3& XYZ, int *sector)const
{
if(*sector!=UNKNOWN_SECTOR)
{
int next = (unsigned)(*sector) + 1 < m_left_driveline.size() ? *sector + 1 : 0;
if(with_tolerance)
{
if(pointInQuad(m_dl_with_tolerance_left[*sector],
m_dl_with_tolerance_right[*sector],
m_dl_with_tolerance_right[next],
m_dl_with_tolerance_left[next],
XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
}
else
{
if(pointInQuad(m_left_driveline[*sector],
m_right_driveline[*sector],
m_right_driveline[next],
m_left_driveline[next], XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
}
if(pointInQuad(m_left_driveline[*sector],
m_right_driveline[*sector],
m_right_driveline[next],
m_left_driveline[next], XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
}
/* To find in which 'sector' of the track the kart is, we use a
'point in triangle' algorithm for each triangle in the quad
@@ -210,12 +192,7 @@ void Track::findRoadSector(const Vec3& XYZ, int *sector,
for( size_t i = 0; i < DRIVELINE_SIZE ; ++i )
{
next = (unsigned int)i + 1 < DRIVELINE_SIZE ? (int)i + 1 : 0;
triangle = with_tolerance
? pointInQuad(m_dl_with_tolerance_left[i],
m_dl_with_tolerance_right[i],
m_dl_with_tolerance_right[next],
m_dl_with_tolerance_left[next], XYZ )
: pointInQuad(m_left_driveline[i], m_right_driveline[i],
triangle = pointInQuad(m_left_driveline[i], m_right_driveline[i],
m_right_driveline[next], m_left_driveline[next],
XYZ );
@@ -501,33 +478,6 @@ btTransform Track::getStartTransform(unsigned int pos) const
return start;
} // getStartTransform
//-----------------------------------------------------------------------------
/** Determines if a kart moving from sector OLDSEC to sector NEWSEC
* would be taking a shortcut, i.e. if the distance is larger
* than a certain delta
*/
bool Track::isShortcut(const int OLDSEC, const int NEWSEC) const
{
// If the kart was off the road, don't do any shortcuts
if(OLDSEC==UNKNOWN_SECTOR || NEWSEC==UNKNOWN_SECTOR) return false;
int next_sector = OLDSEC==(int)m_driveline.size()-1 ? 0 : OLDSEC+1;
if(next_sector==NEWSEC)
return false;
int distance_sectors = (int)(m_distance_from_start[std::max(NEWSEC, OLDSEC)] -
m_distance_from_start[std::min(NEWSEC, OLDSEC)] );
// Handle 'warp around'
const int track_length = (int)m_distance_from_start[m_driveline.size()-1];
if( distance_sectors < 0 ) distance_sectors += track_length;
//else if( distance_sectors > track_length*3.0f/4.0f) distance_sectors -= track_length;
if(std::max(NEWSEC, OLDSEC) > (int)RaceManager::getTrack()->m_distance_from_start.size()-6 &&
std::min(NEWSEC, OLDSEC) < 6) distance_sectors -= track_length; // crossed start line
return (distance_sectors > stk_config->m_shortcut_length);
} // isShortcut
//-----------------------------------------------------------------------------
void Track::addDebugToScene(int type) const
{
@@ -559,16 +509,14 @@ void Track::addDebugToScene(int type) const
} // for i
*/
} /// type ==1
// 2: drivelines, 4: driveline with tolerance
if(type & 6)
// 2: drivelines
if(type & 2)
{
/*
ssgVertexArray* v_array = new ssgVertexArray();
ssgColourArray* c_array = new ssgColourArray();
const std::vector<Vec3> &left = type&2 ? m_left_driveline
: m_dl_with_tolerance_left;
const std::vector<Vec3> &right = type&2 ? m_right_driveline
: m_dl_with_tolerance_right;
const std::vector<Vec3> &left = m_left_driveline;
const std::vector<Vec3> &right = m_right_driveline;
for(unsigned int i = 0; i < m_driveline.size(); i++)
{
int ip1 = i==m_driveline.size()-1 ? 0 : i+1;
@@ -1002,9 +950,8 @@ void Track::startMusic() const
//-----------------------------------------------------------------------------
void Track::loadDriveline()
{
m_quads = new QuadSet (file_manager->getTrackFile(m_ident+".quads"));
m_quad_graph = new QuadGraph(file_manager->getTrackFile(m_ident+".graph"),
m_quads);
m_quad_graph = new QuadGraph(file_manager->getTrackFile(m_ident+".quads"),
file_manager->getTrackFile(m_ident+".graph"));
readDrivelineFromFile(m_left_driveline, ".drvl");
const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size();
@@ -1017,8 +964,6 @@ void Track::loadDriveline()
"and the left driveline is " << m_left_driveline.size()
<< " vertex long. Track is " << m_name << " ." << std::endl;
m_dl_with_tolerance_left.reserve(DRIVELINE_SIZE);
m_dl_with_tolerance_right.reserve(DRIVELINE_SIZE);
m_driveline.reserve(DRIVELINE_SIZE);
m_path_width.reserve(DRIVELINE_SIZE);
m_angle.reserve(DRIVELINE_SIZE);
@@ -1029,13 +974,6 @@ void Track::loadDriveline()
float width = ( m_right_driveline[i] - center_point ).length();
m_path_width.push_back(width);
// Compute the drivelines with tolerance
Vec3 diff = (m_left_driveline[i] - m_right_driveline[i])
* stk_config->m_offroad_tolerance;
m_dl_with_tolerance_left.push_back(m_left_driveline[i]+diff);
m_dl_with_tolerance_right.push_back(m_right_driveline[i]-diff);
}
for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i)

View File

@@ -42,7 +42,6 @@ class TriangleMesh;
class MovingTexture;
class XMLNode;
class PhysicalObject;
class QuadSet;
class QuadGraph;
class Track
@@ -70,8 +69,6 @@ private:
int m_version;
bool loadMainTrack(const XMLNode &node);
void createWater(const XMLNode &node);
/** The set of all quads for this track. */
QuadSet *m_quads;
/** The graph used to connect the quads. */
QuadGraph *m_quad_graph;
/** The type of sky to be used for the track. */
@@ -138,11 +135,11 @@ public:
//FIXME: Maybe the next 4 vectors should be inside an struct and be used
//from a vector of structs?
//FIXME: should the driveline be set as a sgVec2?
private:
std::vector<Vec3> m_driveline;
public:
/** Same as drivelines, but with stk_config->m_offroad_tolerance applied
* to widen the road (to make shortcut detection less severe). */
std::vector<Vec3> m_dl_with_tolerance_left;
std::vector<Vec3> m_dl_with_tolerance_right;
std::vector<float> m_distance_from_start;
std::vector<float> m_path_width;
std::vector<float> m_angle;
@@ -179,8 +176,7 @@ public:
void drawScaled2D (float x, float y, float w,
float h ) const;
void findRoadSector (const Vec3& XYZ, int *sector,
bool with_tolerance=false) const;
void findRoadSector (const Vec3& XYZ, int *sector) const;
int findOutOfRoadSector(const Vec3& XYZ,
const RoadSide SIDE,
const int CURR_SECTOR
@@ -190,7 +186,6 @@ public:
const int SECTOR ) const;
const Vec3& trackToSpatial (const int SECTOR) const;
void loadTrackModel ();
bool isShortcut (const int OLDSEC, const int NEWSEC) const;
void addMusic (MusicInformation* mi)
{m_music.push_back(mi); }
float getGravity () const {return m_gravity; }
@@ -228,6 +223,9 @@ public:
void createPhysicsModel();
void update(float dt);
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const;
/** Returns the graph of quads, mainly for the AI. */
const QuadGraph& getQuadGraph() const { return *m_quad_graph; }
/*
void glVtx (sgVec2 v, float x_offset, float y_offset) const
{