Rename QuadGraph to DriveGraph, make it use the new Graph interface
This commit is contained in:
parent
606a5401d3
commit
eeac5668d9
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
|
|
||||||
#include "ICameraSceneNode.h"
|
#include "ICameraSceneNode.h"
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ void CameraEnd::readEndCamera(const XMLNode &root)
|
|||||||
unsigned int index = i;
|
unsigned int index = i;
|
||||||
// In reverse mode, reverse the order in which the
|
// In reverse mode, reverse the order in which the
|
||||||
// end cameras are read.
|
// end cameras are read.
|
||||||
if(QuadGraph::get()->isReverse())
|
if(DriveGraph::get()->isReverse())
|
||||||
index = root.getNumNodes() - 1 - i;
|
index = root.getNumNodes() - 1 - i;
|
||||||
const XMLNode *node = root.getNode(index);
|
const XMLNode *node = root.getNode(index);
|
||||||
EndCameraInformation eci;
|
EndCameraInformation eci;
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "utils/random_generator.hpp"
|
#include "utils/random_generator.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
|
||||||
#include "tracks/quad_graph.hpp"
|
|
||||||
|
|
||||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
#include "modes/three_strikes_battle.hpp"
|
#include "modes/three_strikes_battle.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "tracks/arena_graph.hpp"
|
#include "tracks/arena_graph.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
#include "utils/vec3.hpp"
|
#include "utils/vec3.hpp"
|
||||||
@ -145,15 +145,15 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
|
|||||||
{
|
{
|
||||||
Graph::get()->findRoadSector(xyz, &m_graph_node);
|
Graph::get()->findRoadSector(xyz, &m_graph_node);
|
||||||
}
|
}
|
||||||
if (Graph::get() && !ArenaGraph::get()) // Todo replace with driveline graph
|
if (DriveGraph::get() && m_graph_node != Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
// Item is on quad graph. Pre-compute the distance from center
|
// Item is on drive graph. Pre-compute the distance from center
|
||||||
// of this item, which is used by the AI (mostly for avoiding items)
|
// of this item, which is used by the AI (mostly for avoiding items)
|
||||||
Vec3 distances;
|
Vec3 distances;
|
||||||
QuadGraph::get()->spatialToTrack(&distances, m_xyz, m_graph_node);
|
DriveGraph::get()->spatialToTrack(&distances, m_xyz, m_graph_node);
|
||||||
m_distance_from_center = distances.getX();
|
m_distance_from_center = distances.getX();
|
||||||
const GraphNode* gn = QuadGraph::get()->getNode(m_graph_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(m_graph_node);
|
||||||
const Vec3& right = gn->getRightUnitVector();
|
const Vec3& right = dn->getRightUnitVector();
|
||||||
// Give it 10% more space, since the kart will not always come
|
// Give it 10% more space, since the kart will not always come
|
||||||
// parallel to the drive line.
|
// parallel to the drive line.
|
||||||
Vec3 delta = right * sqrt(m_distance_2) * 1.3f;
|
Vec3 delta = right * sqrt(m_distance_2) * 1.3f;
|
||||||
|
@ -225,7 +225,7 @@ void ItemManager::insertItem(Item *item)
|
|||||||
if(m_items_in_quads)
|
if(m_items_in_quads)
|
||||||
{
|
{
|
||||||
int graph_node = item->getGraphNode();
|
int graph_node = item->getGraphNode();
|
||||||
// If the item is on the driveline, store it at the appropriate index
|
// If the item is on the graph, store it at the appropriate index
|
||||||
if(graph_node > -1)
|
if(graph_node > -1)
|
||||||
{
|
{
|
||||||
(*m_items_in_quads)[graph_node].push_back(item);
|
(*m_items_in_quads)[graph_node].push_back(item);
|
||||||
|
@ -82,7 +82,7 @@ private:
|
|||||||
|
|
||||||
/** Stores which items are on which quad. m_items_in_quads[#quads]
|
/** Stores which items are on which quad. m_items_in_quads[#quads]
|
||||||
* contains all items that are not on a quad. Note that this
|
* contains all items that are not on a quad. Note that this
|
||||||
* field is undefined if no QuadGraph exist, e.g. in battle mode. */
|
* field is undefined if no Graph exist, e.g. arena without navmesh. */
|
||||||
std::vector< AllItemTypes > *m_items_in_quads;
|
std::vector< AllItemTypes > *m_items_in_quads;
|
||||||
|
|
||||||
/** What item this item is switched to. */
|
/** What item this item is switched to. */
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "physics/btKart.hpp"
|
#include "physics/btKart.hpp"
|
||||||
#include "physics/triangle_mesh.hpp"
|
#include "physics/triangle_mesh.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
|
|
||||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||||
@ -100,7 +100,7 @@ RubberBall::RubberBall(AbstractKart *kart)
|
|||||||
// initialises the current graph node
|
// initialises the current graph node
|
||||||
TrackSector::update(getXYZ());
|
TrackSector::update(getXYZ());
|
||||||
const Vec3& normal =
|
const Vec3& normal =
|
||||||
QuadGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
||||||
TerrainInfo::update(getXYZ(), -normal);
|
TerrainInfo::update(getXYZ(), -normal);
|
||||||
initializeControlPoints(m_owner->getXYZ());
|
initializeControlPoints(m_owner->getXYZ());
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
|
|||||||
// left or right when firing the ball off track.
|
// left or right when firing the ball off track.
|
||||||
getNextControlPoint();
|
getNextControlPoint();
|
||||||
m_control_points[2] =
|
m_control_points[2] =
|
||||||
QuadGraph::get()->getNode(m_last_aimed_graph_node)->getCenter();
|
DriveGraph::get()->getNode(m_last_aimed_graph_node)->getCenter();
|
||||||
|
|
||||||
// This updates m_last_aimed_graph_node, and sets m_control_points[3]
|
// This updates m_last_aimed_graph_node, and sets m_control_points[3]
|
||||||
getNextControlPoint();
|
getNextControlPoint();
|
||||||
@ -201,12 +201,12 @@ unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index,
|
|||||||
|
|
||||||
unsigned int sect =
|
unsigned int sect =
|
||||||
lin_world->getSectorForKart(m_target);
|
lin_world->getSectorForKart(m_target);
|
||||||
succ = QuadGraph::get()->getNode(node_index)->getSuccessorToReach(sect);
|
succ = DriveGraph::get()->getNode(node_index)->getSuccessorToReach(sect);
|
||||||
|
|
||||||
if(dist)
|
if(dist)
|
||||||
*dist += QuadGraph::get()->getNode(node_index)
|
*dist += DriveGraph::get()->getNode(node_index)
|
||||||
->getDistanceToSuccessor(succ);
|
->getDistanceToSuccessor(succ);
|
||||||
return QuadGraph::get()->getNode(node_index)->getSuccessor(succ);
|
return DriveGraph::get()->getNode(node_index)->getSuccessor(succ);
|
||||||
} // getSuccessorToHitTarget
|
} // getSuccessorToHitTarget
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -224,21 +224,21 @@ void RubberBall::getNextControlPoint()
|
|||||||
// spline between the control points.
|
// spline between the control points.
|
||||||
float dist=0;
|
float dist=0;
|
||||||
|
|
||||||
float f = QuadGraph::get()->getDistanceFromStart(m_last_aimed_graph_node);
|
float f = DriveGraph::get()->getDistanceFromStart(m_last_aimed_graph_node);
|
||||||
|
|
||||||
int next = getSuccessorToHitTarget(m_last_aimed_graph_node, &dist);
|
int next = getSuccessorToHitTarget(m_last_aimed_graph_node, &dist);
|
||||||
float d = QuadGraph::get()->getDistanceFromStart(next)-f;
|
float d = DriveGraph::get()->getDistanceFromStart(next)-f;
|
||||||
while(d<m_st_min_interpolation_distance && d>=0)
|
while(d<m_st_min_interpolation_distance && d>=0)
|
||||||
{
|
{
|
||||||
next = getSuccessorToHitTarget(next, &dist);
|
next = getSuccessorToHitTarget(next, &dist);
|
||||||
d = QuadGraph::get()->getDistanceFromStart(next)-f;
|
d = DriveGraph::get()->getDistanceFromStart(next)-f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_aimed_graph_node = next;
|
m_last_aimed_graph_node = next;
|
||||||
m_length_cp_2_3 = dist;
|
m_length_cp_2_3 = dist;
|
||||||
const GraphNode* gn =
|
const DriveNode* dn =
|
||||||
QuadGraph::get()->getNode(m_last_aimed_graph_node);
|
DriveGraph::get()->getNode(m_last_aimed_graph_node);
|
||||||
m_control_points[3] = gn->getCenter();
|
m_control_points[3] = dn->getCenter();
|
||||||
} // getNextControlPoint
|
} // getNextControlPoint
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "tracks/track_sector.hpp"
|
#include "tracks/track_sector.hpp"
|
||||||
|
|
||||||
class AbstractKart;
|
class AbstractKart;
|
||||||
class QuadGraph;
|
|
||||||
class SFXBase;
|
class SFXBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
#include "karts/controller/ai_properties.hpp"
|
#include "karts/controller/ai_properties.hpp"
|
||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ I.e. the controller that takes over from a player (or AI) when the race is
|
|||||||
finished.
|
finished.
|
||||||
|
|
||||||
This base class defines some basic operations:
|
This base class defines some basic operations:
|
||||||
- It takes care on which part of the QuadGraph the AI currently is.
|
- It takes care on which part of the DriveGraph the AI currently is.
|
||||||
- It determines which path the AI should take (in case of shortcuts
|
- It determines which path the AI should take (in case of shortcuts
|
||||||
or forks in the road).
|
or forks in the road).
|
||||||
|
|
||||||
@ -139,14 +139,14 @@ void AIBaseLapController::newLap(int lap)
|
|||||||
*/
|
*/
|
||||||
void AIBaseLapController::computePath()
|
void AIBaseLapController::computePath()
|
||||||
{
|
{
|
||||||
m_next_node_index.resize(QuadGraph::get()->getNumNodes());
|
m_next_node_index.resize(DriveGraph::get()->getNumNodes());
|
||||||
m_successor_index.resize(QuadGraph::get()->getNumNodes());
|
m_successor_index.resize(DriveGraph::get()->getNumNodes());
|
||||||
std::vector<unsigned int> next;
|
std::vector<unsigned int> next;
|
||||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
next.clear();
|
next.clear();
|
||||||
// Get all successors the AI is allowed to take.
|
// Get all successors the AI is allowed to take.
|
||||||
QuadGraph::get()->getSuccessors(i, next, /*for_ai*/true);
|
DriveGraph::get()->getSuccessors(i, next, /*for_ai*/true);
|
||||||
// In case of short cuts hidden for the AI it can be that a node
|
// In case of short cuts hidden for the AI it can be that a node
|
||||||
// might not have a successor (since the first and last edge of
|
// might not have a successor (since the first and last edge of
|
||||||
// a hidden shortcut is ignored). Since in the case that the AI
|
// a hidden shortcut is ignored). Since in the case that the AI
|
||||||
@ -154,7 +154,7 @@ void AIBaseLapController::computePath()
|
|||||||
// allowed way to drive, it should still be able to drive, so add
|
// allowed way to drive, it should still be able to drive, so add
|
||||||
// the non-AI successors of that node in this case.
|
// the non-AI successors of that node in this case.
|
||||||
if(next.size()==0)
|
if(next.size()==0)
|
||||||
QuadGraph::get()->getSuccessors(i, next, /*for_ai*/false);
|
DriveGraph::get()->getSuccessors(i, next, /*for_ai*/false);
|
||||||
// For now pick one part on random, which is not adjusted during the
|
// For now pick one part on random, which is not adjusted during the
|
||||||
// race. Long term statistics might be gathered to determine the
|
// race. Long term statistics might be gathered to determine the
|
||||||
// best way, potentially depending on race position etc.
|
// best way, potentially depending on race position etc.
|
||||||
@ -171,12 +171,12 @@ void AIBaseLapController::computePath()
|
|||||||
// Now compute for each node in the graph the list of the next 'look_ahead'
|
// Now compute for each node in the graph the list of the next 'look_ahead'
|
||||||
// graph nodes. This is the list of node that is tested in checkCrashes.
|
// graph nodes. This is the list of node that is tested in checkCrashes.
|
||||||
// If the look_ahead is too big, the AI can skip loops (see
|
// If the look_ahead is too big, the AI can skip loops (see
|
||||||
// QuadGraph::findRoadSector for details), if it's too short the AI won't
|
// Graph::findRoadSector for details), if it's too short the AI won't
|
||||||
// find too good a driveline. Note that in general this list should
|
// find too good a driveline. Note that in general this list should
|
||||||
// be computed recursively, but since the AI for now is using only
|
// be computed recursively, but since the AI for now is using only
|
||||||
// (randomly picked) path this is fine
|
// (randomly picked) path this is fine
|
||||||
m_all_look_aheads.resize(QuadGraph::get()->getNumNodes());
|
m_all_look_aheads.resize(DriveGraph::get()->getNumNodes());
|
||||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
std::vector<int> l;
|
std::vector<int> l;
|
||||||
int current = i;
|
int current = i;
|
||||||
@ -199,24 +199,24 @@ void AIBaseLapController::computePath()
|
|||||||
void AIBaseLapController::update(float dt)
|
void AIBaseLapController::update(float dt)
|
||||||
{
|
{
|
||||||
AIBaseController::update(dt);
|
AIBaseController::update(dt);
|
||||||
if(QuadGraph::get())
|
if(DriveGraph::get())
|
||||||
{
|
{
|
||||||
// Update the current node:
|
// Update the current node:
|
||||||
int old_node = m_track_node;
|
int old_node = m_track_node;
|
||||||
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node!=Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
||||||
&m_all_look_aheads[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
|
// If we can't find a proper place on the track, to a broader search
|
||||||
// on off-track locations.
|
// on off-track locations.
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
m_track_node = DriveGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
}
|
}
|
||||||
// IF the AI is off track (or on a branch of the track it did not
|
// IF the AI is off track (or on a branch of the track it did not
|
||||||
// select to be on), keep the old position.
|
// select to be on), keep the old position.
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR ||
|
if(m_track_node==Graph::UNKNOWN_SECTOR ||
|
||||||
m_next_node_index[m_track_node]==-1)
|
m_next_node_index[m_track_node]==-1)
|
||||||
m_track_node = old_node;
|
m_track_node = old_node;
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ void AIBaseLapController::update(float dt)
|
|||||||
unsigned int AIBaseLapController::getNextSector(unsigned int index)
|
unsigned int AIBaseLapController::getNextSector(unsigned int index)
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> successors;
|
std::vector<unsigned int> successors;
|
||||||
QuadGraph::get()->getSuccessors(index, successors);
|
DriveGraph::get()->getSuccessors(index, successors);
|
||||||
return successors[0];
|
return successors[0];
|
||||||
} // getNextSector
|
} // getNextSector
|
||||||
|
|
||||||
@ -245,8 +245,8 @@ unsigned int AIBaseLapController::getNextSector(unsigned int index)
|
|||||||
float AIBaseLapController::steerToAngle(const unsigned int sector,
|
float AIBaseLapController::steerToAngle(const unsigned int sector,
|
||||||
const float add_angle)
|
const float add_angle)
|
||||||
{
|
{
|
||||||
float angle = QuadGraph::get()->getAngleToNext(sector,
|
float angle = DriveGraph::get()->getAngleToNext(sector,
|
||||||
getNextSector(sector));
|
getNextSector(sector));
|
||||||
|
|
||||||
//Desired angle minus current angle equals how many angles to turn
|
//Desired angle minus current angle equals how many angles to turn
|
||||||
float steer_angle = angle - m_kart->getHeading();
|
float steer_angle = angle - m_kart->getHeading();
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
class AIProperties;
|
class AIProperties;
|
||||||
class LinearWorld;
|
class LinearWorld;
|
||||||
class QuadGraph;
|
|
||||||
class Track;
|
class Track;
|
||||||
class Vec3;
|
class Vec3;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@
|
|||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "states_screens/race_result_gui.hpp"
|
#include "states_screens/race_result_gui.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
@ -63,14 +63,14 @@ EndController::EndController(AbstractKart *kart,
|
|||||||
// with a path that always picks the first branch (i.e. it follows
|
// with a path that always picks the first branch (i.e. it follows
|
||||||
// the main driveline).
|
// the main driveline).
|
||||||
std::vector<unsigned int> next;
|
std::vector<unsigned int> next;
|
||||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
// 0 is always a valid successor - so even if the kart should end
|
// 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.
|
// up by accident on a non-selected path, it will keep on working.
|
||||||
m_successor_index[i] = 0;
|
m_successor_index[i] = 0;
|
||||||
|
|
||||||
next.clear();
|
next.clear();
|
||||||
QuadGraph::get()->getSuccessors(i, next);
|
DriveGraph::get()->getSuccessors(i, next);
|
||||||
m_next_node_index[i] = next[0];
|
m_next_node_index[i] = next[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,11 +78,11 @@ EndController::EndController(AbstractKart *kart,
|
|||||||
// Now compute for each node in the graph the list of the next 'look_ahead'
|
// Now compute for each node in the graph the list of the next 'look_ahead'
|
||||||
// graph nodes. This is the list of node that is tested in checkCrashes.
|
// graph nodes. This is the list of node that is tested in checkCrashes.
|
||||||
// If the look_ahead is too big, the AI can skip loops (see
|
// If the look_ahead is too big, the AI can skip loops (see
|
||||||
// QuadGraph::findRoadSector for details), if it's too short the AI won't
|
// DriveGraph::findRoadSector for details), if it's too short the AI won't
|
||||||
// find too good a driveline. Note that in general this list should
|
// find too good a driveline. Note that in general this list should
|
||||||
// be computed recursively, but since the AI for now is using only
|
// be computed recursively, but since the AI for now is using only
|
||||||
// (randomly picked) path this is fine
|
// (randomly picked) path this is fine
|
||||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
std::vector<int> l;
|
std::vector<int> l;
|
||||||
int current = i;
|
int current = i;
|
||||||
@ -95,7 +95,7 @@ EndController::EndController(AbstractKart *kart,
|
|||||||
}
|
}
|
||||||
} // if not battle mode
|
} // if not battle mode
|
||||||
|
|
||||||
// Reset must be called after QuadGraph::get() etc. is set up
|
// Reset must be called after DriveGraph::get() etc. is set up
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
m_max_handicap_accel = 1.0f;
|
m_max_handicap_accel = 1.0f;
|
||||||
@ -130,18 +130,18 @@ void EndController::reset()
|
|||||||
m_crash_time = 0.0f;
|
m_crash_time = 0.0f;
|
||||||
m_time_since_stuck = 0.0f;
|
m_time_since_stuck = 0.0f;
|
||||||
|
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||||
// In battle mode there is no quad graph, so nothing to do in this case
|
// In battle mode there is no quad graph, so nothing to do in this case
|
||||||
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||||
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_SOCCER)
|
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_SOCCER)
|
||||||
{
|
{
|
||||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
|
|
||||||
// Node that this can happen quite easily, e.g. an AI kart is
|
// Node that this can happen quite easily, e.g. an AI kart is
|
||||||
// taken over by the end controller while it is off track.
|
// taken over by the end controller while it is off track.
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
m_track_node = DriveGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // reset
|
} // reset
|
||||||
@ -212,10 +212,10 @@ void EndController::handleSteering(float dt)
|
|||||||
*/
|
*/
|
||||||
//Reaction to being outside of the road
|
//Reaction to being outside of the road
|
||||||
if( fabsf(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )) >
|
if( fabsf(m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() )) >
|
||||||
0.5f* QuadGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
0.5f* DriveGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
||||||
{
|
{
|
||||||
const int next = m_next_node_index[m_track_node];
|
const int next = m_next_node_index[m_track_node];
|
||||||
target_point = QuadGraph::get()->getNode(next)->getCenter();
|
target_point = DriveGraph::get()->getNode(next)->getCenter();
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
Log::debug("end_controller.cpp", "- Outside of road: steer to center point.");
|
Log::debug("end_controller.cpp", "- Outside of road: steer to center point.");
|
||||||
#endif
|
#endif
|
||||||
@ -275,7 +275,7 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
|||||||
target_sector = m_next_node_index[sector];
|
target_sector = m_next_node_index[sector];
|
||||||
|
|
||||||
//direction is a vector from our kart to the sectors we are testing
|
//direction is a vector from our kart to the sectors we are testing
|
||||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||||
- m_kart->getXYZ();
|
- m_kart->getXYZ();
|
||||||
|
|
||||||
float len=direction.length();
|
float len=direction.length();
|
||||||
@ -293,16 +293,16 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
|||||||
{
|
{
|
||||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||||
|
|
||||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
sector );
|
sector );
|
||||||
|
|
||||||
distance = fabsf(step_track_coord[0]);
|
distance = fabsf(step_track_coord[0]);
|
||||||
|
|
||||||
//If we are outside, the previous sector is what we are looking for
|
//If we are outside, the previous sector is what we are looking for
|
||||||
if ( distance + m_kart_width * 0.5f
|
if ( distance + m_kart_width * 0.5f
|
||||||
> QuadGraph::get()->getNode(sector)->getPathWidth()*0.5f )
|
> DriveGraph::get()->getNode(sector)->getPathWidth()*0.5f )
|
||||||
{
|
{
|
||||||
*result = QuadGraph::get()->getNode(sector)->getCenter();
|
*result = DriveGraph::get()->getNode(sector)->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class LinearWorld;
|
class LinearWorld;
|
||||||
class QuadGraph;
|
|
||||||
class Track;
|
class Track;
|
||||||
class Vec3;
|
class Vec3;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "modes/profile_world.hpp"
|
#include "modes/profile_world.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
@ -171,22 +171,22 @@ void SkiddingAI::reset()
|
|||||||
m_distance_behind = 0.0f;
|
m_distance_behind = 0.0f;
|
||||||
m_current_curve_radius = 0.0f;
|
m_current_curve_radius = 0.0f;
|
||||||
m_curve_center = Vec3(0,0,0);
|
m_curve_center = Vec3(0,0,0);
|
||||||
m_current_track_direction = GraphNode::DIR_STRAIGHT;
|
m_current_track_direction = DriveNode::DIR_STRAIGHT;
|
||||||
m_item_to_collect = NULL;
|
m_item_to_collect = NULL;
|
||||||
m_avoid_item_close = false;
|
m_avoid_item_close = false;
|
||||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||||
m_last_item_random = NULL;
|
m_last_item_random = NULL;
|
||||||
|
|
||||||
AIBaseLapController::reset();
|
AIBaseLapController::reset();
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
Log::error(getControllerName().c_str(),
|
Log::error(getControllerName().c_str(),
|
||||||
"Invalid starting position for '%s' - not on track"
|
"Invalid starting position for '%s' - not on track"
|
||||||
" - can be ignored.",
|
" - can be ignored.",
|
||||||
m_kart->getIdent().c_str());
|
m_kart->getIdent().c_str());
|
||||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
m_track_node = DriveGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
AIBaseLapController::reset();
|
AIBaseLapController::reset();
|
||||||
@ -414,7 +414,7 @@ void SkiddingAI::handleBraking()
|
|||||||
|
|
||||||
// If the kart is not facing roughly in the direction of the track, brake
|
// If the kart is not facing roughly in the direction of the track, brake
|
||||||
// so that it is easier for the kart to turn in the right direction.
|
// so that it is easier for the kart to turn in the right direction.
|
||||||
if(m_current_track_direction==GraphNode::DIR_UNDEFINED &&
|
if(m_current_track_direction==DriveNode::DIR_UNDEFINED &&
|
||||||
m_kart->getSpeed() > MIN_SPEED)
|
m_kart->getSpeed() > MIN_SPEED)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -426,8 +426,8 @@ void SkiddingAI::handleBraking()
|
|||||||
m_controls->m_brake = true;
|
m_controls->m_brake = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||||
{
|
{
|
||||||
float max_turn_speed =
|
float max_turn_speed =
|
||||||
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
||||||
@ -476,13 +476,13 @@ void SkiddingAI::handleSteering(float dt)
|
|||||||
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
||||||
|
|
||||||
if( fabsf(side_dist) >
|
if( fabsf(side_dist) >
|
||||||
0.5f* QuadGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
0.5f* DriveGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
||||||
{
|
{
|
||||||
steer_angle = steerToPoint(QuadGraph::get()->getNode(next)
|
steer_angle = steerToPoint(DriveGraph::get()->getNode(next)
|
||||||
->getCenter());
|
->getCenter());
|
||||||
|
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
m_debug_sphere[0]->setPosition(DriveGraph::get()->getNode(next)
|
||||||
->getCenter().toIrrVector());
|
->getCenter().toIrrVector());
|
||||||
Log::debug(getControllerName().c_str(),
|
Log::debug(getControllerName().c_str(),
|
||||||
"Outside of road: steer to center point.");
|
"Outside of road: steer to center point.");
|
||||||
@ -530,7 +530,7 @@ void SkiddingAI::handleSteering(float dt)
|
|||||||
{
|
{
|
||||||
m_start_kart_crash_direction = 0;
|
m_start_kart_crash_direction = 0;
|
||||||
Vec3 aim_point;
|
Vec3 aim_point;
|
||||||
int last_node = QuadGraph::UNKNOWN_SECTOR;
|
int last_node = Graph::UNKNOWN_SECTOR;
|
||||||
|
|
||||||
switch(m_point_selection_algorithm)
|
switch(m_point_selection_algorithm)
|
||||||
{
|
{
|
||||||
@ -623,7 +623,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||||
|
|
||||||
// Make sure we have a valid last_node
|
// Make sure we have a valid last_node
|
||||||
if(last_node==QuadGraph::UNKNOWN_SECTOR)
|
if(last_node==Graph::UNKNOWN_SECTOR)
|
||||||
last_node = m_next_node_index[m_track_node];
|
last_node = m_next_node_index[m_track_node];
|
||||||
|
|
||||||
int node = m_track_node;
|
int node = m_track_node;
|
||||||
@ -636,7 +636,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
const float max_item_lookahead_distance = 30.f;
|
const float max_item_lookahead_distance = 30.f;
|
||||||
while(distance < max_item_lookahead_distance)
|
while(distance < max_item_lookahead_distance)
|
||||||
{
|
{
|
||||||
int n_index= QuadGraph::get()->getNode(node)->getNodeIndex();
|
int n_index= DriveGraph::get()->getNode(node)->getIndex();
|
||||||
const std::vector<Item *> &items_ahead =
|
const std::vector<Item *> &items_ahead =
|
||||||
ItemManager::get()->getItemsInQuads(n_index);
|
ItemManager::get()->getItemsInQuads(n_index);
|
||||||
for(unsigned int i=0; i<items_ahead.size(); i++)
|
for(unsigned int i=0; i<items_ahead.size(); i++)
|
||||||
@ -644,7 +644,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
evaluateItems(items_ahead[i], kart_aim_direction,
|
evaluateItems(items_ahead[i], kart_aim_direction,
|
||||||
&items_to_avoid, &items_to_collect);
|
&items_to_avoid, &items_to_collect);
|
||||||
} // for i<items_ahead;
|
} // for i<items_ahead;
|
||||||
distance += QuadGraph::get()->getDistanceToNext(node,
|
distance += DriveGraph::get()->getDistanceToNext(node,
|
||||||
m_successor_index[node]);
|
m_successor_index[node]);
|
||||||
node = m_next_node_index[node];
|
node = m_next_node_index[node];
|
||||||
// Stop when we have reached the last quad
|
// Stop when we have reached the last quad
|
||||||
@ -781,7 +781,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
// so that it can potentially become a permanent target.
|
// so that it can potentially become a permanent target.
|
||||||
Vec3 xyz = item_to_collect->getXYZ();
|
Vec3 xyz = item_to_collect->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)
|
||||||
->getNormal();
|
->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
@ -865,7 +865,7 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
|||||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)->getNormal();
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
|
|
||||||
@ -926,7 +926,7 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
|||||||
// rightmost point - if so, nothing to do.
|
// rightmost point - if so, nothing to do.
|
||||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||||
Vec3 normal = QuadGraph::get()->getNode(node_index)->getNormal();
|
Vec3 normal = DriveGraph::get()->getNode(node_index)->getNormal();
|
||||||
Vec3 p1 = line_to_target.start,
|
Vec3 p1 = line_to_target.start,
|
||||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||||
p3 = line_to_target.end;
|
p3 = line_to_target.end;
|
||||||
@ -946,7 +946,7 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
|||||||
{
|
{
|
||||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||||
Vec3 normal = QuadGraph::get()->getNode(node_index)->getNormal();
|
Vec3 normal = DriveGraph::get()->getNode(node_index)->getNormal();
|
||||||
Vec3 p1 = line_to_target.start,
|
Vec3 p1 = line_to_target.start,
|
||||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||||
p3 = line_to_target.end;
|
p3 = line_to_target.end;
|
||||||
@ -1104,7 +1104,7 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
|||||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||||
const Vec3 &xyz = item->getXYZ();
|
const Vec3 &xyz = item->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)->getNormal();
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
|
|
||||||
@ -1714,14 +1714,14 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
m_kart->getSpeed()>1.0f &&
|
m_kart->getSpeed()>1.0f &&
|
||||||
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
||||||
{
|
{
|
||||||
GraphNode::DirectionType dir;
|
DriveNode::DirectionType dir;
|
||||||
unsigned int last;
|
unsigned int last;
|
||||||
const GraphNode* gn = QuadGraph::get()->getNode(m_track_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(m_track_node);
|
||||||
gn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
dn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||||
if(dir==GraphNode::DIR_STRAIGHT)
|
if(dir==DriveNode::DIR_STRAIGHT)
|
||||||
{
|
{
|
||||||
float diff = QuadGraph::get()->getDistanceFromStart(last)
|
float diff = DriveGraph::get()->getDistanceFromStart(last)
|
||||||
- QuadGraph::get()->getDistanceFromStart(m_track_node);
|
- DriveGraph::get()->getDistanceFromStart(m_track_node);
|
||||||
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
||||||
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
||||||
m_controls->m_fire = true;
|
m_controls->m_fire = true;
|
||||||
@ -1812,12 +1812,12 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*Find if we crash with the drivelines*/
|
/*Find if we crash with the drivelines*/
|
||||||
if(current_node!=QuadGraph::UNKNOWN_SECTOR &&
|
if(current_node!=Graph::UNKNOWN_SECTOR &&
|
||||||
m_next_node_index[current_node]!=-1)
|
m_next_node_index[current_node]!=-1)
|
||||||
QuadGraph::get()->findRoadSector(step_coord, ¤t_node,
|
DriveGraph::get()->findRoadSector(step_coord, ¤t_node,
|
||||||
/* sectors to test*/ &m_all_look_aheads[current_node]);
|
/* sectors to test*/ &m_all_look_aheads[current_node]);
|
||||||
|
|
||||||
if( current_node == QuadGraph::UNKNOWN_SECTOR)
|
if( current_node == Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
m_crashes.m_road = true;
|
m_crashes.m_road = true;
|
||||||
return;
|
return;
|
||||||
@ -1865,23 +1865,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
*last_node = m_next_node_index[m_track_node];
|
*last_node = m_next_node_index[m_track_node];
|
||||||
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
||||||
|
|
||||||
const GraphNode* g = QuadGraph::get()->getNode(*last_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(*last_node);
|
||||||
|
|
||||||
// Index of the left and right end of a quad.
|
// Index of the left and right end of a quad.
|
||||||
const unsigned int LEFT_END_POINT = 0;
|
const unsigned int LEFT_END_POINT = 0;
|
||||||
const unsigned int RIGHT_END_POINT = 1;
|
const unsigned int RIGHT_END_POINT = 1;
|
||||||
core::line2df left (xz, (*g)[LEFT_END_POINT ].toIrrVector2d());
|
core::line2df left (xz, (*dn)[LEFT_END_POINT ].toIrrVector2d());
|
||||||
core::line2df right(xz, (*g)[RIGHT_END_POINT].toIrrVector2d());
|
core::line2df right(xz, (*dn)[RIGHT_END_POINT].toIrrVector2d());
|
||||||
|
|
||||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||||
const Vec3 eps1(0,0.5f,0);
|
const Vec3 eps1(0,0.5f,0);
|
||||||
m_curve[CURVE_LEFT]->clear();
|
m_curve[CURVE_LEFT]->clear();
|
||||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_LEFT]->addPoint((*g)[LEFT_END_POINT]+eps1);
|
m_curve[CURVE_LEFT]->addPoint((*dn)[LEFT_END_POINT]+eps1);
|
||||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_RIGHT]->clear();
|
m_curve[CURVE_RIGHT]->clear();
|
||||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_RIGHT]->addPoint((*g)[RIGHT_END_POINT]+eps1);
|
m_curve[CURVE_RIGHT]->addPoint((*dn)[RIGHT_END_POINT]+eps1);
|
||||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
#endif
|
#endif
|
||||||
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||||
@ -1894,13 +1894,13 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
unsigned int next_sector = m_next_node_index[*last_node];
|
unsigned int next_sector = m_next_node_index[*last_node];
|
||||||
const GraphNode* g_next = QuadGraph::get()->getNode(next_sector);
|
const DriveNode* dn_next = DriveGraph::get()->getNode(next_sector);
|
||||||
// Test if the next left point is to the right of the left
|
// Test if the next left point is to the right of the left
|
||||||
// line. If so, a new left line is defined.
|
// line. If so, a new left line is defined.
|
||||||
if(left.getPointOrientation((*g_next)[LEFT_END_POINT].toIrrVector2d())
|
if(left.getPointOrientation((*dn_next)[LEFT_END_POINT].toIrrVector2d())
|
||||||
< 0 )
|
< 0 )
|
||||||
{
|
{
|
||||||
core::vector2df p = (*g_next)[LEFT_END_POINT].toIrrVector2d();
|
core::vector2df p = (*dn_next)[LEFT_END_POINT].toIrrVector2d();
|
||||||
// Stop if the new point is to the right of the right line
|
// Stop if the new point is to the right of the right line
|
||||||
if(right.getPointOrientation(p)<0)
|
if(right.getPointOrientation(p)<0)
|
||||||
break;
|
break;
|
||||||
@ -1916,10 +1916,10 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
|
|
||||||
// Test if new right point is to the left of the right line. If
|
// Test if new right point is to the left of the right line. If
|
||||||
// so, a new right line is defined.
|
// so, a new right line is defined.
|
||||||
if(right.getPointOrientation((*g_next)[RIGHT_END_POINT].toIrrVector2d())
|
if(right.getPointOrientation((*dn_next)[RIGHT_END_POINT].toIrrVector2d())
|
||||||
> 0 )
|
> 0 )
|
||||||
{
|
{
|
||||||
core::vector2df p = (*g_next)[RIGHT_END_POINT].toIrrVector2d();
|
core::vector2df p = (*dn_next)[RIGHT_END_POINT].toIrrVector2d();
|
||||||
// Break if new point is to the left of left line
|
// Break if new point is to the left of left line
|
||||||
if(left.getPointOrientation(p)>0)
|
if(left.getPointOrientation(p)>0)
|
||||||
break;
|
break;
|
||||||
@ -1941,7 +1941,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
// 0.5f*(left.end.Y+right.end.Y));
|
// 0.5f*(left.end.Y+right.end.Y));
|
||||||
//*result = ppp;
|
//*result = ppp;
|
||||||
|
|
||||||
*result = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*result = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPointNew
|
} // findNonCrashingPointNew
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1978,7 +1978,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
target_sector = m_next_node_index[*last_node];
|
target_sector = m_next_node_index[*last_node];
|
||||||
|
|
||||||
//direction is a vector from our kart to the sectors we are testing
|
//direction is a vector from our kart to the sectors we are testing
|
||||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||||
- m_kart->getXYZ();
|
- m_kart->getXYZ();
|
||||||
|
|
||||||
float len=direction.length();
|
float len=direction.length();
|
||||||
@ -2001,23 +2001,23 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
{
|
{
|
||||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||||
|
|
||||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
*last_node );
|
*last_node );
|
||||||
|
|
||||||
float distance = fabsf(step_track_coord[0]);
|
float distance = fabsf(step_track_coord[0]);
|
||||||
|
|
||||||
//If we are outside, the previous node is what we are looking for
|
//If we are outside, the previous node is what we are looking for
|
||||||
if ( distance + m_kart_width * 0.5f
|
if ( distance + m_kart_width * 0.5f
|
||||||
> QuadGraph::get()->getNode(*last_node)->getPathWidth()*0.5f )
|
> DriveGraph::get()->getNode(*last_node)->getPathWidth()*0.5f )
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
*aim_position = DriveGraph::get()->getNode(*last_node)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*last_node = target_sector;
|
*last_node = target_sector;
|
||||||
} // for i<100
|
} // for i<100
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPointFixed
|
} // findNonCrashingPointFixed
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2025,14 +2025,14 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
* 1. the test:
|
* 1. the test:
|
||||||
*
|
*
|
||||||
* distance + m_kart_width * 0.5f
|
* distance + m_kart_width * 0.5f
|
||||||
* > QuadGraph::get()->getNode(*last_node)->getPathWidth() )
|
* > DriveGraph::get()->getNode(*last_node)->getPathWidth() )
|
||||||
*
|
*
|
||||||
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
||||||
* is the distance from the center, i.e. it is half the path width if
|
* is the distance from the center, i.e. it is half the path width if
|
||||||
* the point is at the edge).
|
* the point is at the edge).
|
||||||
* 2. the test:
|
* 2. the test:
|
||||||
*
|
*
|
||||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
* DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
* *last_node );
|
* *last_node );
|
||||||
* in the for loop tests always against distance from the same
|
* in the for loop tests always against distance from the same
|
||||||
* graph node (*last_node), while de-fact the loop will test points
|
* graph node (*last_node), while de-fact the loop will test points
|
||||||
@ -2057,7 +2057,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
m_curve[CURVE_KART]->addPoint(m_kart->getTrans()(forw)+eps);
|
m_curve[CURVE_KART]->addPoint(m_kart->getTrans()(forw)+eps);
|
||||||
#endif
|
#endif
|
||||||
*last_node = m_next_node_index[m_track_node];
|
*last_node = m_next_node_index[m_track_node];
|
||||||
float angle = QuadGraph::get()->getAngleToNext(m_track_node,
|
float angle = DriveGraph::get()->getAngleToNext(m_track_node,
|
||||||
m_successor_index[m_track_node]);
|
m_successor_index[m_track_node]);
|
||||||
int target_sector;
|
int target_sector;
|
||||||
|
|
||||||
@ -2073,7 +2073,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
// target_sector is the sector at the longest distance that we can
|
// target_sector is the sector at the longest distance that we can
|
||||||
// drive to without crashing with the track.
|
// drive to without crashing with the track.
|
||||||
target_sector = m_next_node_index[*last_node];
|
target_sector = m_next_node_index[*last_node];
|
||||||
angle1 = QuadGraph::get()->getAngleToNext(target_sector,
|
angle1 = DriveGraph::get()->getAngleToNext(target_sector,
|
||||||
m_successor_index[target_sector]);
|
m_successor_index[target_sector]);
|
||||||
// In very sharp turns this algorithm tends to aim at off track points,
|
// In very sharp turns this algorithm tends to aim at off track points,
|
||||||
// resulting in hitting a corner. So test for this special case and
|
// resulting in hitting a corner. So test for this special case and
|
||||||
@ -2081,13 +2081,13 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
float diff = normalizeAngle(angle1-angle);
|
float diff = normalizeAngle(angle1-angle);
|
||||||
if(fabsf(diff)>1.5f)
|
if(fabsf(diff)>1.5f)
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
*aim_position = DriveGraph::get()->getNode(target_sector)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//direction is a vector from our kart to the sectors we are testing
|
//direction is a vector from our kart to the sectors we are testing
|
||||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||||
- m_kart->getXYZ();
|
- m_kart->getXYZ();
|
||||||
|
|
||||||
float len=direction.length();
|
float len=direction.length();
|
||||||
@ -2110,16 +2110,16 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
{
|
{
|
||||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||||
|
|
||||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
*last_node );
|
*last_node );
|
||||||
|
|
||||||
float distance = fabsf(step_track_coord[0]);
|
float distance = fabsf(step_track_coord[0]);
|
||||||
|
|
||||||
//If we are outside, the previous node is what we are looking for
|
//If we are outside, the previous node is what we are looking for
|
||||||
if ( distance + m_kart_width * 0.5f
|
if ( distance + m_kart_width * 0.5f
|
||||||
> QuadGraph::get()->getNode(*last_node)->getPathWidth() )
|
> DriveGraph::get()->getNode(*last_node)->getPathWidth() )
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
*aim_position = DriveGraph::get()->getNode(*last_node)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2127,7 +2127,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
angle = angle1;
|
angle = angle1;
|
||||||
*last_node = target_sector;
|
*last_node = target_sector;
|
||||||
} // for i<100
|
} // for i<100
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPoint
|
} // findNonCrashingPoint
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2136,7 +2136,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
*/
|
*/
|
||||||
void SkiddingAI::determineTrackDirection()
|
void SkiddingAI::determineTrackDirection()
|
||||||
{
|
{
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
unsigned int succ = m_successor_index[m_track_node];
|
unsigned int succ = m_successor_index[m_track_node];
|
||||||
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
||||||
|
|
||||||
@ -2165,7 +2165,7 @@ void SkiddingAI::determineTrackDirection()
|
|||||||
// quicker be aligned with the track again).
|
// quicker be aligned with the track again).
|
||||||
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
||||||
{
|
{
|
||||||
m_current_track_direction = GraphNode::DIR_UNDEFINED;
|
m_current_track_direction = DriveNode::DIR_UNDEFINED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2181,8 +2181,8 @@ void SkiddingAI::determineTrackDirection()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||||
{
|
{
|
||||||
handleCurve();
|
handleCurve();
|
||||||
} // if(m_current_track_direction == DIR_LEFT || DIR_RIGHT )
|
} // if(m_current_track_direction == DIR_LEFT || DIR_RIGHT )
|
||||||
@ -2207,7 +2207,7 @@ void SkiddingAI::handleCurve()
|
|||||||
// kart will already point towards the direction of the circle), and
|
// kart will already point towards the direction of the circle), and
|
||||||
// the case that the kart is facing wrong was already tested for before
|
// the case that the kart is facing wrong was already tested for before
|
||||||
|
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
Vec3 xyz = m_kart->getXYZ();
|
Vec3 xyz = m_kart->getXYZ();
|
||||||
Vec3 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
Vec3 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
||||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||||
@ -2227,7 +2227,7 @@ void SkiddingAI::handleCurve()
|
|||||||
{
|
{
|
||||||
i = m_next_node_index[i];
|
i = m_next_node_index[i];
|
||||||
// Pick either the lower left or right point:
|
// Pick either the lower left or right point:
|
||||||
int index = m_current_track_direction==GraphNode::DIR_LEFT
|
int index = m_current_track_direction==DriveNode::DIR_LEFT
|
||||||
? 0 : 1;
|
? 0 : 1;
|
||||||
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
||||||
if(m_current_curve_radius < r)
|
if(m_current_curve_radius < r)
|
||||||
@ -2286,8 +2286,8 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No skidding on straights
|
// No skidding on straights
|
||||||
if(m_current_track_direction==GraphNode::DIR_STRAIGHT ||
|
if(m_current_track_direction==DriveNode::DIR_STRAIGHT ||
|
||||||
m_current_track_direction==GraphNode::DIR_UNDEFINED )
|
m_current_track_direction==DriveNode::DIR_UNDEFINED )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(m_controls->m_skid && m_ai_debug)
|
if(m_controls->m_skid && m_ai_debug)
|
||||||
@ -2301,7 +2301,7 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float MIN_SKID_SPEED = 5.0f;
|
const float MIN_SKID_SPEED = 5.0f;
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||||
|
|
||||||
// Only try skidding when a certain minimum speed is reached.
|
// Only try skidding when a certain minimum speed is reached.
|
||||||
@ -2312,7 +2312,7 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
Vec3 diff_last = last_xyz - m_curve_center;
|
Vec3 diff_last = last_xyz - m_curve_center;
|
||||||
float angle_kart = atan2(diff_kart.getX(), diff_kart.getZ());
|
float angle_kart = atan2(diff_kart.getX(), diff_kart.getZ());
|
||||||
float angle_last = atan2(diff_last.getX(), diff_last.getZ());
|
float angle_last = atan2(diff_last.getX(), diff_last.getZ());
|
||||||
float angle = m_current_track_direction == GraphNode::DIR_RIGHT
|
float angle = m_current_track_direction == DriveNode::DIR_RIGHT
|
||||||
? angle_last - angle_kart
|
? angle_last - angle_kart
|
||||||
: angle_kart - angle_last;
|
: angle_kart - angle_last;
|
||||||
angle = normalizeAngle(angle);
|
angle = normalizeAngle(angle);
|
||||||
@ -2339,9 +2339,9 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
// left turn steer right to avoid getting too close to the left
|
// left turn steer right to avoid getting too close to the left
|
||||||
// vorder). In this case skidding will be useless.
|
// vorder). In this case skidding will be useless.
|
||||||
else if( (steer_fraction > 0 &&
|
else if( (steer_fraction > 0 &&
|
||||||
m_current_track_direction==GraphNode::DIR_LEFT) ||
|
m_current_track_direction==DriveNode::DIR_LEFT) ||
|
||||||
(steer_fraction < 0 &&
|
(steer_fraction < 0 &&
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT) )
|
m_current_track_direction==DriveNode::DIR_RIGHT) )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(m_controls->m_skid && m_ai_debug)
|
if(m_controls->m_skid && m_ai_debug)
|
||||||
|
@ -45,11 +45,11 @@
|
|||||||
|
|
||||||
#include "karts/controller/ai_base_lap_controller.hpp"
|
#include "karts/controller/ai_base_lap_controller.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "utils/random_generator.hpp"
|
#include "utils/random_generator.hpp"
|
||||||
|
|
||||||
class LinearWorld;
|
class LinearWorld;
|
||||||
class QuadGraph;
|
class DriveGraph;
|
||||||
class ShowCurve;
|
class ShowCurve;
|
||||||
class Track;
|
class Track;
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ private:
|
|||||||
int m_start_kart_crash_direction;
|
int m_start_kart_crash_direction;
|
||||||
|
|
||||||
/** The direction of the track where the kart is on atm. */
|
/** The direction of the track where the kart is on atm. */
|
||||||
GraphNode::DirectionType m_current_track_direction;
|
DriveNode::DirectionType m_current_track_direction;
|
||||||
|
|
||||||
/** The radius of the curve the kart is currently driving. Undefined
|
/** The radius of the curve the kart is currently driving. Undefined
|
||||||
* when being on a straigt section. */
|
* when being on a straigt section. */
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "modes/profile_world.hpp"
|
#include "modes/profile_world.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
@ -177,22 +177,22 @@ void SkiddingAI::reset()
|
|||||||
m_distance_behind = 0.0f;
|
m_distance_behind = 0.0f;
|
||||||
m_current_curve_radius = 0.0f;
|
m_current_curve_radius = 0.0f;
|
||||||
m_curve_center = Vec3(0,0,0);
|
m_curve_center = Vec3(0,0,0);
|
||||||
m_current_track_direction = GraphNode::DIR_STRAIGHT;
|
m_current_track_direction = DriveNode::DIR_STRAIGHT;
|
||||||
m_item_to_collect = NULL;
|
m_item_to_collect = NULL;
|
||||||
m_avoid_item_close = false;
|
m_avoid_item_close = false;
|
||||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||||
m_last_item_random = NULL;
|
m_last_item_random = NULL;
|
||||||
|
|
||||||
AIBaseLapController::reset();
|
AIBaseLapController::reset();
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
Log::error(getControllerName().c_str(),
|
Log::error(getControllerName().c_str(),
|
||||||
"Invalid starting position for '%s' - not on track"
|
"Invalid starting position for '%s' - not on track"
|
||||||
" - can be ignored.",
|
" - can be ignored.",
|
||||||
m_kart->getIdent().c_str());
|
m_kart->getIdent().c_str());
|
||||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
m_track_node = DriveGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
AIBaseLapController::reset();
|
AIBaseLapController::reset();
|
||||||
@ -420,7 +420,7 @@ void SkiddingAI::handleBraking()
|
|||||||
|
|
||||||
// If the kart is not facing roughly in the direction of the track, brake
|
// If the kart is not facing roughly in the direction of the track, brake
|
||||||
// so that it is easier for the kart to turn in the right direction.
|
// so that it is easier for the kart to turn in the right direction.
|
||||||
if(m_current_track_direction==GraphNode::DIR_UNDEFINED &&
|
if(m_current_track_direction==DriveNode::DIR_UNDEFINED &&
|
||||||
m_kart->getSpeed() > MIN_SPEED)
|
m_kart->getSpeed() > MIN_SPEED)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -432,8 +432,8 @@ void SkiddingAI::handleBraking()
|
|||||||
m_controls->m_brake = true;
|
m_controls->m_brake = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||||
{
|
{
|
||||||
float max_turn_speed =
|
float max_turn_speed =
|
||||||
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
||||||
@ -482,13 +482,13 @@ void SkiddingAI::handleSteering(float dt)
|
|||||||
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
||||||
|
|
||||||
if( fabsf(side_dist) >
|
if( fabsf(side_dist) >
|
||||||
0.5f* QuadGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
0.5f* DriveGraph::get()->getNode(m_track_node)->getPathWidth()+0.5f )
|
||||||
{
|
{
|
||||||
steer_angle = steerToPoint(QuadGraph::get()->getNode(next)
|
steer_angle = steerToPoint(DriveGraph::get()->getNode(next)
|
||||||
->getCenter());
|
->getCenter());
|
||||||
|
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
m_debug_sphere[0]->setPosition(DriveGraph::get()->getNode(next)
|
||||||
->getCenter().toIrrVector());
|
->getCenter().toIrrVector());
|
||||||
Log::debug(getControllerName().c_str(),
|
Log::debug(getControllerName().c_str(),
|
||||||
"Outside of road: steer to center point.");
|
"Outside of road: steer to center point.");
|
||||||
@ -536,7 +536,7 @@ void SkiddingAI::handleSteering(float dt)
|
|||||||
{
|
{
|
||||||
m_start_kart_crash_direction = 0;
|
m_start_kart_crash_direction = 0;
|
||||||
Vec3 aim_point;
|
Vec3 aim_point;
|
||||||
int last_node = QuadGraph::UNKNOWN_SECTOR;
|
int last_node = Graph::UNKNOWN_SECTOR;
|
||||||
|
|
||||||
switch(m_point_selection_algorithm)
|
switch(m_point_selection_algorithm)
|
||||||
{
|
{
|
||||||
@ -629,7 +629,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||||
|
|
||||||
// Make sure we have a valid last_node
|
// Make sure we have a valid last_node
|
||||||
if(last_node==QuadGraph::UNKNOWN_SECTOR)
|
if(last_node==Graph::UNKNOWN_SECTOR)
|
||||||
last_node = m_next_node_index[m_track_node];
|
last_node = m_next_node_index[m_track_node];
|
||||||
|
|
||||||
int node = m_track_node;
|
int node = m_track_node;
|
||||||
@ -642,7 +642,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
const float max_item_lookahead_distance = 30.f;
|
const float max_item_lookahead_distance = 30.f;
|
||||||
while(distance < max_item_lookahead_distance)
|
while(distance < max_item_lookahead_distance)
|
||||||
{
|
{
|
||||||
int n_index= QuadGraph::get()->getNode(node)->getNodeIndex();
|
int n_index= DriveGraph::get()->getNode(node)->getIndex();
|
||||||
const std::vector<Item *> &items_ahead =
|
const std::vector<Item *> &items_ahead =
|
||||||
ItemManager::get()->getItemsInQuads(n_index);
|
ItemManager::get()->getItemsInQuads(n_index);
|
||||||
for(unsigned int i=0; i<items_ahead.size(); i++)
|
for(unsigned int i=0; i<items_ahead.size(); i++)
|
||||||
@ -650,7 +650,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
evaluateItems(items_ahead[i], kart_aim_direction,
|
evaluateItems(items_ahead[i], kart_aim_direction,
|
||||||
&items_to_avoid, &items_to_collect);
|
&items_to_avoid, &items_to_collect);
|
||||||
} // for i<items_ahead;
|
} // for i<items_ahead;
|
||||||
distance += QuadGraph::get()->getDistanceToNext(node,
|
distance += DriveGraph::get()->getDistanceToNext(node,
|
||||||
m_successor_index[node]);
|
m_successor_index[node]);
|
||||||
node = m_next_node_index[node];
|
node = m_next_node_index[node];
|
||||||
// Stop when we have reached the last quad
|
// Stop when we have reached the last quad
|
||||||
@ -787,7 +787,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
|||||||
// so that it can potentially become a permanent target.
|
// so that it can potentially become a permanent target.
|
||||||
Vec3 xyz = item_to_collect->getXYZ();
|
Vec3 xyz = item_to_collect->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)
|
||||||
->getNormal();
|
->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
@ -871,7 +871,7 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
|||||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)->getNormal();
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
|
|
||||||
@ -932,7 +932,7 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
|||||||
// rightmost point - if so, nothing to do.
|
// rightmost point - if so, nothing to do.
|
||||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||||
Vec3 normal = QuadGraph::get()->getNode(node_index)->getNormal();
|
Vec3 normal = DriveGraph::get()->getNode(node_index)->getNormal();
|
||||||
Vec3 p1 = line_to_target.start,
|
Vec3 p1 = line_to_target.start,
|
||||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||||
p3 = line_to_target.end;
|
p3 = line_to_target.end;
|
||||||
@ -952,7 +952,7 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
|||||||
{
|
{
|
||||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||||
Vec3 normal = QuadGraph::get()->getNode(node_index)->getNormal();
|
Vec3 normal = DriveGraph::get()->getNode(node_index)->getNormal();
|
||||||
Vec3 p1 = line_to_target.start,
|
Vec3 p1 = line_to_target.start,
|
||||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||||
p3 = line_to_target.end;
|
p3 = line_to_target.end;
|
||||||
@ -1110,7 +1110,7 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
|||||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||||
const Vec3 &xyz = item->getXYZ();
|
const Vec3 &xyz = item->getXYZ();
|
||||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)->getNormal();
|
Vec3 plane_normal = DriveGraph::get()->getNode(m_track_node)->getNormal();
|
||||||
float dist_to_plane = item_direction.dot(plane_normal);
|
float dist_to_plane = item_direction.dot(plane_normal);
|
||||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||||
|
|
||||||
@ -1763,14 +1763,14 @@ void SkiddingAI::handleNitroAndZipper()
|
|||||||
m_kart->getSpeed()>1.0f &&
|
m_kart->getSpeed()>1.0f &&
|
||||||
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
||||||
{
|
{
|
||||||
GraphNode::DirectionType dir;
|
DriveNode::DirectionType dir;
|
||||||
unsigned int last;
|
unsigned int last;
|
||||||
const GraphNode* gn = QuadGraph::get()->getNode(m_track_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(m_track_node);
|
||||||
gn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
dn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||||
if(dir==GraphNode::DIR_STRAIGHT)
|
if(dir==DriveNode::DIR_STRAIGHT)
|
||||||
{
|
{
|
||||||
float diff = QuadGraph::get()->getDistanceFromStart(last)
|
float diff = DriveGraph::get()->getDistanceFromStart(last)
|
||||||
- QuadGraph::get()->getDistanceFromStart(m_track_node);
|
- DriveGraph::get()->getDistanceFromStart(m_track_node);
|
||||||
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
||||||
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
||||||
m_controls->m_fire = true;
|
m_controls->m_fire = true;
|
||||||
@ -1861,12 +1861,12 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*Find if we crash with the drivelines*/
|
/*Find if we crash with the drivelines*/
|
||||||
if(current_node!=QuadGraph::UNKNOWN_SECTOR &&
|
if(current_node!=Graph::UNKNOWN_SECTOR &&
|
||||||
m_next_node_index[current_node]!=-1)
|
m_next_node_index[current_node]!=-1)
|
||||||
QuadGraph::get()->findRoadSector(step_coord, ¤t_node,
|
DriveGraph::get()->findRoadSector(step_coord, ¤t_node,
|
||||||
/* sectors to test*/ &m_all_look_aheads[current_node]);
|
/* sectors to test*/ &m_all_look_aheads[current_node]);
|
||||||
|
|
||||||
if( current_node == QuadGraph::UNKNOWN_SECTOR)
|
if( current_node == Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
m_crashes.m_road = true;
|
m_crashes.m_road = true;
|
||||||
return;
|
return;
|
||||||
@ -1914,23 +1914,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
*last_node = m_next_node_index[m_track_node];
|
*last_node = m_next_node_index[m_track_node];
|
||||||
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
||||||
|
|
||||||
const GraphNode* g = QuadGraph::get()->getNode(*last_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(*last_node);
|
||||||
|
|
||||||
// Index of the left and right end of a quad.
|
// Index of the left and right end of a quad.
|
||||||
const unsigned int LEFT_END_POINT = 0;
|
const unsigned int LEFT_END_POINT = 0;
|
||||||
const unsigned int RIGHT_END_POINT = 1;
|
const unsigned int RIGHT_END_POINT = 1;
|
||||||
core::line2df left (xz, (*g)[LEFT_END_POINT ].toIrrVector2d());
|
core::line2df left (xz, (*dn)[LEFT_END_POINT ].toIrrVector2d());
|
||||||
core::line2df right(xz, (*g)[RIGHT_END_POINT].toIrrVector2d());
|
core::line2df right(xz, (*dn)[RIGHT_END_POINT].toIrrVector2d());
|
||||||
|
|
||||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||||
const Vec3 eps1(0,0.5f,0);
|
const Vec3 eps1(0,0.5f,0);
|
||||||
m_curve[CURVE_LEFT]->clear();
|
m_curve[CURVE_LEFT]->clear();
|
||||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_LEFT]->addPoint((*g)[LEFT_END_POINT]+eps1);
|
m_curve[CURVE_LEFT]->addPoint((*dn)[LEFT_END_POINT]+eps1);
|
||||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_RIGHT]->clear();
|
m_curve[CURVE_RIGHT]->clear();
|
||||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
m_curve[CURVE_RIGHT]->addPoint((*g)[RIGHT_END_POINT]+eps1);
|
m_curve[CURVE_RIGHT]->addPoint((*dn)[RIGHT_END_POINT]+eps1);
|
||||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||||
#endif
|
#endif
|
||||||
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||||
@ -1943,13 +1943,13 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
unsigned int next_sector = m_next_node_index[*last_node];
|
unsigned int next_sector = m_next_node_index[*last_node];
|
||||||
const GraphNode* g_next = QuadGraph::get()->getNode(next_sector);
|
const DriveNode* dn_next = DriveGraph::get()->getNode(next_sector);
|
||||||
// Test if the next left point is to the right of the left
|
// Test if the next left point is to the right of the left
|
||||||
// line. If so, a new left line is defined.
|
// line. If so, a new left line is defined.
|
||||||
if(left.getPointOrientation((*g_next)[LEFT_END_POINT].toIrrVector2d())
|
if(left.getPointOrientation((*dn_next)[LEFT_END_POINT].toIrrVector2d())
|
||||||
< 0 )
|
< 0 )
|
||||||
{
|
{
|
||||||
core::vector2df p = (*g_next)[LEFT_END_POINT].toIrrVector2d();
|
core::vector2df p = (*dn_next)[LEFT_END_POINT].toIrrVector2d();
|
||||||
// Stop if the new point is to the right of the right line
|
// Stop if the new point is to the right of the right line
|
||||||
if(right.getPointOrientation(p)<0)
|
if(right.getPointOrientation(p)<0)
|
||||||
break;
|
break;
|
||||||
@ -1965,10 +1965,10 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
|
|
||||||
// Test if new right point is to the left of the right line. If
|
// Test if new right point is to the left of the right line. If
|
||||||
// so, a new right line is defined.
|
// so, a new right line is defined.
|
||||||
if(right.getPointOrientation((*g_next)[RIGHT_END_POINT].toIrrVector2d())
|
if(right.getPointOrientation((*dn_next)[RIGHT_END_POINT].toIrrVector2d())
|
||||||
> 0 )
|
> 0 )
|
||||||
{
|
{
|
||||||
core::vector2df p = (*g_next)[RIGHT_END_POINT].toIrrVector2d();
|
core::vector2df p = (*dn_next)[RIGHT_END_POINT].toIrrVector2d();
|
||||||
// Break if new point is to the left of left line
|
// Break if new point is to the left of left line
|
||||||
if(left.getPointOrientation(p)>0)
|
if(left.getPointOrientation(p)>0)
|
||||||
break;
|
break;
|
||||||
@ -1990,7 +1990,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
|||||||
// 0.5f*(left.end.Y+right.end.Y));
|
// 0.5f*(left.end.Y+right.end.Y));
|
||||||
//*result = ppp;
|
//*result = ppp;
|
||||||
|
|
||||||
*result = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*result = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPointNew
|
} // findNonCrashingPointNew
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2027,7 +2027,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
target_sector = m_next_node_index[*last_node];
|
target_sector = m_next_node_index[*last_node];
|
||||||
|
|
||||||
//direction is a vector from our kart to the sectors we are testing
|
//direction is a vector from our kart to the sectors we are testing
|
||||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||||
- m_kart->getXYZ();
|
- m_kart->getXYZ();
|
||||||
|
|
||||||
float len=direction.length();
|
float len=direction.length();
|
||||||
@ -2050,23 +2050,23 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
{
|
{
|
||||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||||
|
|
||||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
*last_node );
|
*last_node );
|
||||||
|
|
||||||
float distance = fabsf(step_track_coord[0]);
|
float distance = fabsf(step_track_coord[0]);
|
||||||
|
|
||||||
//If we are outside, the previous node is what we are looking for
|
//If we are outside, the previous node is what we are looking for
|
||||||
if ( distance + m_kart_width * 0.5f
|
if ( distance + m_kart_width * 0.5f
|
||||||
> QuadGraph::get()->getNode(*last_node)->getPathWidth()*0.5f )
|
> DriveGraph::get()->getNode(*last_node)->getPathWidth()*0.5f )
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
*aim_position = DriveGraph::get()->getNode(*last_node)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*last_node = target_sector;
|
*last_node = target_sector;
|
||||||
} // for i<100
|
} // for i<100
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPointFixed
|
} // findNonCrashingPointFixed
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2074,14 +2074,14 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
* 1. the test:
|
* 1. the test:
|
||||||
*
|
*
|
||||||
* distance + m_kart_width * 0.5f
|
* distance + m_kart_width * 0.5f
|
||||||
* > QuadGraph::get()->getNode(*last_node)->getPathWidth() )
|
* > DriveGraph::get()->getNode(*last_node)->getPathWidth() )
|
||||||
*
|
*
|
||||||
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
||||||
* is the distance from the center, i.e. it is half the path width if
|
* is the distance from the center, i.e. it is half the path width if
|
||||||
* the point is at the edge).
|
* the point is at the edge).
|
||||||
* 2. the test:
|
* 2. the test:
|
||||||
*
|
*
|
||||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
* DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
* *last_node );
|
* *last_node );
|
||||||
* in the for loop tests always against distance from the same
|
* in the for loop tests always against distance from the same
|
||||||
* graph node (*last_node), while de-fact the loop will test points
|
* graph node (*last_node), while de-fact the loop will test points
|
||||||
@ -2106,7 +2106,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
m_curve[CURVE_KART]->addPoint(m_kart->getTrans()(forw)+eps);
|
m_curve[CURVE_KART]->addPoint(m_kart->getTrans()(forw)+eps);
|
||||||
#endif
|
#endif
|
||||||
*last_node = m_next_node_index[m_track_node];
|
*last_node = m_next_node_index[m_track_node];
|
||||||
float angle = QuadGraph::get()->getAngleToNext(m_track_node,
|
float angle = DriveGraph::get()->getAngleToNext(m_track_node,
|
||||||
m_successor_index[m_track_node]);
|
m_successor_index[m_track_node]);
|
||||||
int target_sector;
|
int target_sector;
|
||||||
|
|
||||||
@ -2122,7 +2122,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
// target_sector is the sector at the longest distance that we can
|
// target_sector is the sector at the longest distance that we can
|
||||||
// drive to without crashing with the track.
|
// drive to without crashing with the track.
|
||||||
target_sector = m_next_node_index[*last_node];
|
target_sector = m_next_node_index[*last_node];
|
||||||
angle1 = QuadGraph::get()->getAngleToNext(target_sector,
|
angle1 = DriveGraph::get()->getAngleToNext(target_sector,
|
||||||
m_successor_index[target_sector]);
|
m_successor_index[target_sector]);
|
||||||
// In very sharp turns this algorithm tends to aim at off track points,
|
// In very sharp turns this algorithm tends to aim at off track points,
|
||||||
// resulting in hitting a corner. So test for this special case and
|
// resulting in hitting a corner. So test for this special case and
|
||||||
@ -2130,13 +2130,13 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
float diff = normalizeAngle(angle1-angle);
|
float diff = normalizeAngle(angle1-angle);
|
||||||
if(fabsf(diff)>1.5f)
|
if(fabsf(diff)>1.5f)
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
*aim_position = DriveGraph::get()->getNode(target_sector)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//direction is a vector from our kart to the sectors we are testing
|
//direction is a vector from our kart to the sectors we are testing
|
||||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||||
- m_kart->getXYZ();
|
- m_kart->getXYZ();
|
||||||
|
|
||||||
float len=direction.length();
|
float len=direction.length();
|
||||||
@ -2159,16 +2159,16 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
{
|
{
|
||||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||||
|
|
||||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||||
*last_node );
|
*last_node );
|
||||||
|
|
||||||
float distance = fabsf(step_track_coord[0]);
|
float distance = fabsf(step_track_coord[0]);
|
||||||
|
|
||||||
//If we are outside, the previous node is what we are looking for
|
//If we are outside, the previous node is what we are looking for
|
||||||
if ( distance + m_kart_width * 0.5f
|
if ( distance + m_kart_width * 0.5f
|
||||||
> QuadGraph::get()->getNode(*last_node)->getPathWidth() )
|
> DriveGraph::get()->getNode(*last_node)->getPathWidth() )
|
||||||
{
|
{
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
*aim_position = DriveGraph::get()->getNode(*last_node)
|
||||||
->getCenter();
|
->getCenter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2176,7 +2176,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
angle = angle1;
|
angle = angle1;
|
||||||
*last_node = target_sector;
|
*last_node = target_sector;
|
||||||
} // for i<100
|
} // for i<100
|
||||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||||
} // findNonCrashingPoint
|
} // findNonCrashingPoint
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2185,7 +2185,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
|||||||
*/
|
*/
|
||||||
void SkiddingAI::determineTrackDirection()
|
void SkiddingAI::determineTrackDirection()
|
||||||
{
|
{
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
unsigned int succ = m_successor_index[m_track_node];
|
unsigned int succ = m_successor_index[m_track_node];
|
||||||
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
||||||
|
|
||||||
@ -2214,7 +2214,7 @@ void SkiddingAI::determineTrackDirection()
|
|||||||
// quicker be aligned with the track again).
|
// quicker be aligned with the track again).
|
||||||
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
||||||
{
|
{
|
||||||
m_current_track_direction = GraphNode::DIR_UNDEFINED;
|
m_current_track_direction = DriveNode::DIR_UNDEFINED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2230,8 +2230,8 @@ void SkiddingAI::determineTrackDirection()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||||
{
|
{
|
||||||
handleCurve();
|
handleCurve();
|
||||||
} // if(m_current_track_direction == DIR_LEFT || DIR_RIGHT )
|
} // if(m_current_track_direction == DIR_LEFT || DIR_RIGHT )
|
||||||
@ -2256,7 +2256,7 @@ void SkiddingAI::handleCurve()
|
|||||||
// kart will already point towards the direction of the circle), and
|
// kart will already point towards the direction of the circle), and
|
||||||
// the case that the kart is facing wrong was already tested for before
|
// the case that the kart is facing wrong was already tested for before
|
||||||
|
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
Vec3 xyz = m_kart->getXYZ();
|
Vec3 xyz = m_kart->getXYZ();
|
||||||
Vec3 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
Vec3 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
||||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||||
@ -2276,7 +2276,7 @@ void SkiddingAI::handleCurve()
|
|||||||
{
|
{
|
||||||
i = m_next_node_index[i];
|
i = m_next_node_index[i];
|
||||||
// Pick either the lower left or right point:
|
// Pick either the lower left or right point:
|
||||||
int index = m_current_track_direction==GraphNode::DIR_LEFT
|
int index = m_current_track_direction==DriveNode::DIR_LEFT
|
||||||
? 0 : 1;
|
? 0 : 1;
|
||||||
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
||||||
if(m_current_curve_radius < r)
|
if(m_current_curve_radius < r)
|
||||||
@ -2335,8 +2335,8 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No skidding on straights
|
// No skidding on straights
|
||||||
if(m_current_track_direction==GraphNode::DIR_STRAIGHT ||
|
if(m_current_track_direction==DriveNode::DIR_STRAIGHT ||
|
||||||
m_current_track_direction==GraphNode::DIR_UNDEFINED )
|
m_current_track_direction==DriveNode::DIR_UNDEFINED )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(m_controls->m_skid && m_ai_debug)
|
if(m_controls->m_skid && m_ai_debug)
|
||||||
@ -2350,7 +2350,7 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float MIN_SKID_SPEED = 5.0f;
|
const float MIN_SKID_SPEED = 5.0f;
|
||||||
const QuadGraph *qg = QuadGraph::get();
|
const DriveGraph *qg = DriveGraph::get();
|
||||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||||
|
|
||||||
// Only try skidding when a certain minimum speed is reached.
|
// Only try skidding when a certain minimum speed is reached.
|
||||||
@ -2361,7 +2361,7 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
Vec3 diff_last = last_xyz - m_curve_center;
|
Vec3 diff_last = last_xyz - m_curve_center;
|
||||||
float angle_kart = atan2(diff_kart.getX(), diff_kart.getZ());
|
float angle_kart = atan2(diff_kart.getX(), diff_kart.getZ());
|
||||||
float angle_last = atan2(diff_last.getX(), diff_last.getZ());
|
float angle_last = atan2(diff_last.getX(), diff_last.getZ());
|
||||||
float angle = m_current_track_direction == GraphNode::DIR_RIGHT
|
float angle = m_current_track_direction == DriveNode::DIR_RIGHT
|
||||||
? angle_last - angle_kart
|
? angle_last - angle_kart
|
||||||
: angle_kart - angle_last;
|
: angle_kart - angle_last;
|
||||||
angle = normalizeAngle(angle);
|
angle = normalizeAngle(angle);
|
||||||
@ -2388,9 +2388,9 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
|||||||
// left turn steer right to avoid getting too close to the left
|
// left turn steer right to avoid getting too close to the left
|
||||||
// vorder). In this case skidding will be useless.
|
// vorder). In this case skidding will be useless.
|
||||||
else if( (steer_fraction > 0 &&
|
else if( (steer_fraction > 0 &&
|
||||||
m_current_track_direction==GraphNode::DIR_LEFT) ||
|
m_current_track_direction==DriveNode::DIR_LEFT) ||
|
||||||
(steer_fraction < 0 &&
|
(steer_fraction < 0 &&
|
||||||
m_current_track_direction==GraphNode::DIR_RIGHT) )
|
m_current_track_direction==DriveNode::DIR_RIGHT) )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(m_controls->m_skid && m_ai_debug)
|
if(m_controls->m_skid && m_ai_debug)
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include "karts/controller/ai_base_lap_controller.hpp"
|
#include "karts/controller/ai_base_lap_controller.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "utils/random_generator.hpp"
|
#include "utils/random_generator.hpp"
|
||||||
|
|
||||||
#ifdef AI_DEBUG
|
#ifdef AI_DEBUG
|
||||||
@ -111,7 +111,7 @@ private:
|
|||||||
int m_start_kart_crash_direction;
|
int m_start_kart_crash_direction;
|
||||||
|
|
||||||
/** The direction of the track where the kart is on atm. */
|
/** The direction of the track where the kart is on atm. */
|
||||||
GraphNode::DirectionType m_current_track_direction;
|
DriveNode::DirectionType m_current_track_direction;
|
||||||
|
|
||||||
/** The radius of the curve the kart is currently driving. Undefined
|
/** The radius of the curve the kart is currently driving. Undefined
|
||||||
* when being on a straigt section. */
|
* when being on a straigt section. */
|
||||||
|
@ -64,8 +64,8 @@
|
|||||||
#include "physics/physics.hpp"
|
#include "physics/physics.hpp"
|
||||||
#include "race/history.hpp"
|
#include "race/history.hpp"
|
||||||
#include "tracks/terrain_info.hpp"
|
#include "tracks/terrain_info.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "tracks/track_manager.hpp"
|
#include "tracks/track_manager.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
@ -1296,14 +1296,14 @@ void Kart::update(float dt)
|
|||||||
|
|
||||||
// To be used later
|
// To be used later
|
||||||
float dist_to_sector = 0.0f;
|
float dist_to_sector = 0.0f;
|
||||||
if (QuadGraph::get())
|
if (DriveGraph::get())
|
||||||
{
|
{
|
||||||
const int sector = ((LinearWorld*)World::getWorld())
|
const int sector = ((LinearWorld*)World::getWorld())
|
||||||
->getTrackSector(getWorldKartId()).getCurrentGraphNode();
|
->getTrackSector(getWorldKartId()).getCurrentGraphNode();
|
||||||
dist_to_sector = getXYZ().distance
|
dist_to_sector = getXYZ().distance
|
||||||
(QuadGraph::get()->getNode(sector)->getCenter());
|
(DriveGraph::get()->getNode(sector)->getCenter());
|
||||||
|
|
||||||
const Vec3& quad_normal = QuadGraph::get()->getNode(sector)
|
const Vec3& quad_normal = DriveGraph::get()->getNode(sector)
|
||||||
->getNormal();
|
->getNormal();
|
||||||
const btQuaternion& q = getTrans().getRotation();
|
const btQuaternion& q = getTrans().getRotation();
|
||||||
const float roll = quad_normal.angle
|
const float roll = quad_normal.angle
|
||||||
@ -1941,13 +1941,13 @@ void Kart::crashed(const Material *m, const Vec3 &normal)
|
|||||||
World::getWorld()->getTrack()->isPushBackEnabled())
|
World::getWorld()->getTrack()->isPushBackEnabled())
|
||||||
{
|
{
|
||||||
int sector = lw->getSectorForKart(this);
|
int sector = lw->getSectorForKart(this);
|
||||||
if(sector!=QuadGraph::UNKNOWN_SECTOR)
|
if(sector!=Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
// Use the first predecessor node, which is the most
|
// Use the first predecessor node, which is the most
|
||||||
// natural one (i.e. the one on the main driveline).
|
// natural one (i.e. the one on the main driveline).
|
||||||
const GraphNode* gn = QuadGraph::get()->getNode(
|
const DriveNode* dn = DriveGraph::get()->getNode(
|
||||||
QuadGraph::get()->getNode(sector)->getPredecessor(0));
|
DriveGraph::get()->getNode(sector)->getPredecessor(0));
|
||||||
Vec3 impulse = gn->getCenter() - getXYZ();
|
Vec3 impulse = dn->getCenter() - getXYZ();
|
||||||
impulse.setY(0);
|
impulse.setY(0);
|
||||||
if(impulse.getX() || impulse.getZ())
|
if(impulse.getX() || impulse.getZ())
|
||||||
impulse.normalize();
|
impulse.normalize();
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include "physics/physics.hpp"
|
#include "physics/physics.hpp"
|
||||||
#include "race/history.hpp"
|
#include "race/history.hpp"
|
||||||
#include "states_screens/race_gui_base.hpp"
|
#include "states_screens/race_gui_base.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track_sector.hpp"
|
#include "tracks/track_sector.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
@ -393,7 +393,7 @@ void LinearWorld::newLap(unsigned int kart_index)
|
|||||||
int LinearWorld::getSectorForKart(const AbstractKart *kart) const
|
int LinearWorld::getSectorForKart(const AbstractKart *kart) const
|
||||||
{
|
{
|
||||||
if(kart->getWorldKartId()>=m_kart_info.size())
|
if(kart->getWorldKartId()>=m_kart_info.size())
|
||||||
return QuadGraph::UNKNOWN_SECTOR;
|
return Graph::UNKNOWN_SECTOR;
|
||||||
return m_kart_info[kart->getWorldKartId()].getTrackSector()
|
return m_kart_info[kart->getWorldKartId()].getTrackSector()
|
||||||
->getCurrentGraphNode();
|
->getCurrentGraphNode();
|
||||||
} // getSectorForKart
|
} // getSectorForKart
|
||||||
@ -629,7 +629,7 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
|
|||||||
*/
|
*/
|
||||||
unsigned int LinearWorld::getNumberOfRescuePositions() const
|
unsigned int LinearWorld::getNumberOfRescuePositions() const
|
||||||
{
|
{
|
||||||
return QuadGraph::get()->getNumNodes();
|
return DriveGraph::get()->getNumNodes();
|
||||||
} // getNumberOfRescuePositions
|
} // getNumberOfRescuePositions
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -647,8 +647,8 @@ unsigned int LinearWorld::getRescuePositionIndex(AbstractKart *kart)
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
btTransform LinearWorld::getRescueTransform(unsigned int index) const
|
btTransform LinearWorld::getRescueTransform(unsigned int index) const
|
||||||
{
|
{
|
||||||
const Vec3 &xyz = QuadGraph::get()->getNode(index)->getCenter();
|
const Vec3 &xyz = DriveGraph::get()->getNode(index)->getCenter();
|
||||||
const Vec3 &normal = QuadGraph::get()->getNode(index)->getNormal();
|
const Vec3 &normal = DriveGraph::get()->getNode(index)->getNormal();
|
||||||
btTransform pos;
|
btTransform pos;
|
||||||
pos.setOrigin(xyz);
|
pos.setOrigin(xyz);
|
||||||
|
|
||||||
@ -866,11 +866,11 @@ void LinearWorld::checkForWrongDirection(unsigned int i, float dt)
|
|||||||
// will be one direction in which it isn't going backwards anyway.
|
// will be one direction in which it isn't going backwards anyway.
|
||||||
int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode();
|
int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode();
|
||||||
|
|
||||||
if (QuadGraph::get()->getNumberOfSuccessors(sector) > 1)
|
if (DriveGraph::get()->getNumberOfSuccessors(sector) > 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check if the player is going in the wrong direction
|
// check if the player is going in the wrong direction
|
||||||
const GraphNode* node = QuadGraph::get()->getNode(sector);
|
const DriveNode* node = DriveGraph::get()->getNode(sector);
|
||||||
Vec3 center_line = node->getUpperCenter() - node->getLowerCenter();
|
Vec3 center_line = node->getUpperCenter() - node->getLowerCenter();
|
||||||
float angle_diff = kart->getVelocity().angle(center_line);
|
float angle_diff = kart->getVelocity().angle(center_line);
|
||||||
|
|
||||||
|
@ -49,8 +49,9 @@ ArenaGraph::ArenaGraph(const std::string &navmesh, const XMLNode *node)
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
ArenaNode* ArenaGraph::getNode(unsigned int i) const
|
ArenaNode* ArenaGraph::getNode(unsigned int i) const
|
||||||
{
|
{
|
||||||
|
assert(i < m_all_nodes.size());
|
||||||
ArenaNode* n = dynamic_cast<ArenaNode*>(m_all_nodes[i]);
|
ArenaNode* n = dynamic_cast<ArenaNode*>(m_all_nodes[i]);
|
||||||
assert(n!= NULL);
|
assert(n != NULL);
|
||||||
return n;
|
return n;
|
||||||
} // getNode
|
} // getNode
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ class ArenaNode;
|
|||||||
class XMLNode;
|
class XMLNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* \brief A graph made from navmesh
|
||||||
* \ingroup tracks
|
* \ingroup tracks
|
||||||
*/
|
*/
|
||||||
class ArenaGraph : public Graph
|
class ArenaGraph : public Graph
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include "tracks/check_lap.hpp"
|
#include "tracks/check_lap.hpp"
|
||||||
#include "tracks/check_line.hpp"
|
#include "tracks/check_line.hpp"
|
||||||
#include "tracks/check_structure.hpp"
|
#include "tracks/check_structure.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
CheckManager *CheckManager::m_check_manager = NULL;
|
CheckManager *CheckManager::m_check_manager = NULL;
|
||||||
@ -85,7 +85,7 @@ void CheckManager::load(const XMLNode &node)
|
|||||||
for(it=check_structures_to_change_state.begin();
|
for(it=check_structures_to_change_state.begin();
|
||||||
it != check_structures_to_change_state.end(); it++)
|
it != check_structures_to_change_state.end(); it++)
|
||||||
{
|
{
|
||||||
if(QuadGraph::get()->isReverse())
|
if(DriveGraph::get()->isReverse())
|
||||||
m_all_checks[*it]->addSuccessor(i);
|
m_all_checks[*it]->addSuccessor(i);
|
||||||
else
|
else
|
||||||
m_all_checks[i]->addSuccessor(*it);
|
m_all_checks[i]->addSuccessor(*it);
|
||||||
|
@ -16,64 +16,17 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||||
|
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
|
|
||||||
#include "LinearMath/btTransform.h"
|
|
||||||
|
|
||||||
#include <IMesh.h>
|
|
||||||
#include <ICameraSceneNode.h>
|
|
||||||
#include "graphics/central_settings.hpp"
|
|
||||||
#include "config/user_config.hpp"
|
#include "config/user_config.hpp"
|
||||||
#include "graphics/callbacks.hpp"
|
|
||||||
#include "graphics/irr_driver.hpp"
|
|
||||||
#include "graphics/screen_quad.hpp"
|
|
||||||
#include "graphics/shaders.hpp"
|
|
||||||
#include "graphics/rtts.hpp"
|
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "tracks/check_lap.hpp"
|
#include "tracks/check_lap.hpp"
|
||||||
#include "tracks/check_line.hpp"
|
#include "tracks/check_line.hpp"
|
||||||
#include "tracks/check_manager.hpp"
|
#include "tracks/check_manager.hpp"
|
||||||
#include "tracks/node_2d.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/node_3d.hpp"
|
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "graphics/glwrap.hpp"
|
|
||||||
|
|
||||||
const int QuadGraph::UNKNOWN_SECTOR = -1;
|
|
||||||
QuadGraph *QuadGraph::m_quad_graph = NULL;
|
|
||||||
|
|
||||||
/** Factory method to dynamic create 2d / 3d node */
|
|
||||||
GraphNode* createNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|
||||||
const Vec3 &p3, unsigned int node_index,
|
|
||||||
bool invisible, bool ai_ignore)
|
|
||||||
{
|
|
||||||
// Find the normal of this node by computing the normal of two triangles
|
|
||||||
// and taking their average.
|
|
||||||
core::triangle3df tri1(p0.toIrrVector(), p1.toIrrVector(),
|
|
||||||
p2.toIrrVector());
|
|
||||||
core::triangle3df tri2(p0.toIrrVector(), p2.toIrrVector(),
|
|
||||||
p3.toIrrVector());
|
|
||||||
Vec3 normal1 = tri1.getNormal();
|
|
||||||
Vec3 normal2 = tri2.getNormal();
|
|
||||||
Vec3 normal = -0.5f * (normal1 + normal2);
|
|
||||||
normal.normalize();
|
|
||||||
|
|
||||||
// Use the angle between the normal and an up vector to choose 3d/2d node
|
|
||||||
const float angle = normal.angle(Vec3(0, 1, 0));
|
|
||||||
if (angle > 0.5f)
|
|
||||||
{
|
|
||||||
Log::debug("TrackNode", "3d node created, normal: %f, %f, %f",
|
|
||||||
normal.x(), normal.y(), normal.z());
|
|
||||||
return new Node3D(p0, p1, p2, p3, normal, node_index, invisible,
|
|
||||||
ai_ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::debug("TrackNode", "2d node created, normal: %f, %f, %f",
|
|
||||||
normal.x(), normal.y(), normal.z());
|
|
||||||
return new Node2D(p0, p1, p2, p3, normal, node_index, invisible,
|
|
||||||
ai_ignore);
|
|
||||||
} // createNode
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Constructor, loads the graph information for a given set of quads
|
/** Constructor, loads the graph information for a given set of quads
|
||||||
@ -81,36 +34,23 @@ GraphNode* createNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|||||||
* \param quad_file_name Name of the file of all quads
|
* \param quad_file_name Name of the file of all quads
|
||||||
* \param graph_file_name Name of the file describing the actual graph
|
* \param graph_file_name Name of the file describing the actual graph
|
||||||
*/
|
*/
|
||||||
QuadGraph::QuadGraph(const std::string &quad_file_name,
|
DriveGraph::DriveGraph(const std::string &quad_file_name,
|
||||||
const std::string &graph_file_name,
|
const std::string &graph_file_name,
|
||||||
const bool reverse) : m_reverse(reverse)
|
const bool reverse) : m_reverse(reverse)
|
||||||
{
|
{
|
||||||
m_lap_length = 0;
|
m_lap_length = 0;
|
||||||
m_quad_filename = quad_file_name;
|
m_quad_filename = quad_file_name;
|
||||||
m_quad_graph = this;
|
Graph::setGraph(this);
|
||||||
load(quad_file_name, graph_file_name);
|
load(quad_file_name, graph_file_name);
|
||||||
} // QuadGraph
|
} // DriveGraph
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Destructor, removes all nodes of the graph. */
|
void DriveGraph::addSuccessor(unsigned int from, unsigned int to)
|
||||||
QuadGraph::~QuadGraph()
|
|
||||||
{
|
|
||||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
|
||||||
{
|
|
||||||
delete m_all_nodes[i];
|
|
||||||
}
|
|
||||||
if(UserConfigParams::m_track_debug)
|
|
||||||
cleanupDebugMesh();
|
|
||||||
GraphStructure::destroyRTT();
|
|
||||||
} // ~QuadGraph
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void QuadGraph::addSuccessor(unsigned int from, unsigned int to)
|
|
||||||
{
|
{
|
||||||
if(m_reverse)
|
if(m_reverse)
|
||||||
m_all_nodes[to]->addSuccessor(from);
|
getNode(to)->addSuccessor(from);
|
||||||
else
|
else
|
||||||
m_all_nodes[from]->addSuccessor(to);
|
getNode(from)->addSuccessor(to);
|
||||||
|
|
||||||
} // addSuccessor
|
} // addSuccessor
|
||||||
|
|
||||||
@ -120,8 +60,9 @@ void QuadGraph::addSuccessor(unsigned int from, unsigned int to)
|
|||||||
p1="n:p" : get point p from square n (n, p integers)
|
p1="n:p" : get point p from square n (n, p integers)
|
||||||
p1="p1,p2,p3" : make a 3d point out of these 3 floating point values
|
p1="p1,p2,p3" : make a 3d point out of these 3 floating point values
|
||||||
*/
|
*/
|
||||||
void QuadGraph::getPoint(const XMLNode *xml, const std::string &attribute_name,
|
void DriveGraph::getPoint(const XMLNode *xml,
|
||||||
Vec3* result) const
|
const std::string &attribute_name,
|
||||||
|
Vec3* result) const
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
xml->get(attribute_name, &s);
|
xml->get(attribute_name, &s);
|
||||||
@ -141,30 +82,28 @@ void QuadGraph::getPoint(const XMLNode *xml, const std::string &attribute_name,
|
|||||||
} // getPoint
|
} // getPoint
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Loads a quad graph from a file.
|
/** Loads a drive graph from a file.
|
||||||
* \param filename Name of the quad file to load.
|
* \param filename Name of the quad file to load.
|
||||||
* \param filename Name of the graph file to load.
|
* \param filename Name of the graph file to load.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::load(const std::string &quad_file_name,
|
void DriveGraph::load(const std::string &quad_file_name,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
{
|
{
|
||||||
XMLNode *quad = file_manager->createXMLTree(quad_file_name);
|
XMLNode *quad = file_manager->createXMLTree(quad_file_name);
|
||||||
if (!quad || quad->getName() != "quads")
|
if (!quad || quad->getName() != "quads")
|
||||||
{
|
{
|
||||||
Log::error("Quad Graph : Quad xml '%s' not found.", filename.c_str());
|
Log::error("DriveGraph : Quad xml '%s' not found.", filename.c_str());
|
||||||
delete quad;
|
delete quad;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_min = Vec3( 99999, 99999, 99999);
|
|
||||||
m_max = Vec3(-99999, -99999, -99999);
|
|
||||||
// Each quad is part of the graph exactly once now.
|
// Each quad is part of the graph exactly once now.
|
||||||
for(unsigned int i=0; i<quad->getNumNodes(); i++)
|
for(unsigned int i=0; i<quad->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
const XMLNode *xml_node = quad->getNode(i);
|
const XMLNode *xml_node = quad->getNode(i);
|
||||||
if(xml_node->getName()!="quad")
|
if(xml_node->getName()!="quad")
|
||||||
{
|
{
|
||||||
Log::warn("Quad Graph: Unsupported node type '%s' found in '%s' - ignored.",
|
Log::warn("DriveGraph: Unsupported node type '%s' found in '%s' - ignored.",
|
||||||
xml_node->getName().c_str(), filename.c_str());
|
xml_node->getName().c_str(), filename.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -182,11 +121,10 @@ void QuadGraph::load(const std::string &quad_file_name,
|
|||||||
xml_node->get("invisible", &invisible);
|
xml_node->get("invisible", &invisible);
|
||||||
bool ai_ignore=false;
|
bool ai_ignore=false;
|
||||||
xml_node->get("ai-ignore", &ai_ignore);
|
xml_node->get("ai-ignore", &ai_ignore);
|
||||||
GraphNode* node =
|
createQuad(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore,
|
||||||
createNode(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore);
|
false/*is_arena*/);
|
||||||
m_max.max(p0);m_max.max(p1);m_max.max(p2);m_max.max(p3);
|
m_bb_max.max(p0);m_bb_max.max(p1);m_bb_max.max(p2);m_bb_max.max(p3);
|
||||||
m_min.min(p0);m_min.min(p1);m_min.min(p2);m_min.min(p3);
|
m_bb_min.min(p0);m_bb_min.min(p1);m_bb_min.min(p2);m_bb_min.min(p3);
|
||||||
m_all_nodes.push_back(node);
|
|
||||||
}
|
}
|
||||||
delete quad;
|
delete quad;
|
||||||
|
|
||||||
@ -201,12 +139,12 @@ void QuadGraph::load(const std::string &quad_file_name,
|
|||||||
|
|
||||||
if (m_all_nodes.size() > 0)
|
if (m_all_nodes.size() > 0)
|
||||||
{
|
{
|
||||||
m_lap_length = m_all_nodes[m_all_nodes.size()-1]->getDistanceFromStart()
|
m_lap_length = getNode(m_all_nodes.size()-1)->getDistanceFromStart()
|
||||||
+ m_all_nodes[m_all_nodes.size()-1]->getDistanceToSuccessor(0);
|
+ getNode(m_all_nodes.size()-1)->getDistanceToSuccessor(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log::error("Quad Graph", "No node in driveline graph.");
|
Log::error("DriveGraph", "No node in driveline graph.");
|
||||||
m_lap_length = 10.0f;
|
m_lap_length = 10.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +203,7 @@ void QuadGraph::load(const std::string &quad_file_name,
|
|||||||
} // edge
|
} // edge
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log::error("Quad Graph", "Incorrect specification in '%s': '%s' ignored.",
|
Log::error("DriveGraph", "Incorrect specification in '%s': '%s' ignored.",
|
||||||
filename.c_str(), xml_node->getName().c_str());
|
filename.c_str(), xml_node->getName().c_str());
|
||||||
continue;
|
continue;
|
||||||
} // incorrect specification
|
} // incorrect specification
|
||||||
@ -281,8 +219,8 @@ void QuadGraph::load(const std::string &quad_file_name,
|
|||||||
m_lap_length = -1;
|
m_lap_length = -1;
|
||||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||||
{
|
{
|
||||||
float l = m_all_nodes[i]->getDistanceFromStart()
|
float l = getNode(i)->getDistanceFromStart()
|
||||||
+ m_all_nodes[i]->getDistanceToSuccessor(0);
|
+ getNode(i)->getDistanceToSuccessor(0);
|
||||||
if(l > m_lap_length)
|
if(l > m_lap_length)
|
||||||
m_lap_length = l;
|
m_lap_length = l;
|
||||||
}
|
}
|
||||||
@ -296,18 +234,18 @@ void QuadGraph::load(const std::string &quad_file_name,
|
|||||||
* but in reverse mode (where node 0 is actually the end of the track)
|
* but in reverse mode (where node 0 is actually the end of the track)
|
||||||
* this is 0's successor.
|
* this is 0's successor.
|
||||||
*/
|
*/
|
||||||
unsigned int QuadGraph::getStartNode() const
|
unsigned int DriveGraph::getStartNode() const
|
||||||
{
|
{
|
||||||
return m_reverse ? m_all_nodes[0]->getSuccessor(0)
|
return m_reverse ? getNode(0)->getSuccessor(0)
|
||||||
: 0;
|
: 0;
|
||||||
} // getStartNode
|
} // getStartNode
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Sets the checkline requirements for all nodes in the graph.
|
/** Sets the checkline requirements for all nodes in the graph.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::computeChecklineRequirements()
|
void DriveGraph::computeChecklineRequirements()
|
||||||
{
|
{
|
||||||
computeChecklineRequirements(m_all_nodes[0],
|
computeChecklineRequirements(getNode(0),
|
||||||
CheckManager::get()->getLapLineIndex());
|
CheckManager::get()->getLapLineIndex());
|
||||||
} // computeChecklineRequirements
|
} // computeChecklineRequirements
|
||||||
|
|
||||||
@ -315,8 +253,8 @@ void QuadGraph::computeChecklineRequirements()
|
|||||||
/** Finds which checklines must be visited before driving on this quad
|
/** Finds which checklines must be visited before driving on this quad
|
||||||
* (useful for rescue)
|
* (useful for rescue)
|
||||||
*/
|
*/
|
||||||
void QuadGraph::computeChecklineRequirements(GraphNode* node,
|
void DriveGraph::computeChecklineRequirements(DriveNode* node,
|
||||||
int latest_checkline)
|
int latest_checkline)
|
||||||
{
|
{
|
||||||
for (unsigned int n=0; n<node->getNumberOfSuccessors(); n++)
|
for (unsigned int n=0; n<node->getNumberOfSuccessors(); n++)
|
||||||
{
|
{
|
||||||
@ -325,7 +263,7 @@ void QuadGraph::computeChecklineRequirements(GraphNode* node,
|
|||||||
// warp-around
|
// warp-around
|
||||||
if (succ_id == 0) break;
|
if (succ_id == 0) break;
|
||||||
|
|
||||||
GraphNode* succ = m_all_nodes[succ_id];
|
DriveNode* succ = getNode(succ_id);
|
||||||
int new_latest_checkline =
|
int new_latest_checkline =
|
||||||
CheckManager::get()->getChecklineTriggering(node->getCenter(),
|
CheckManager::get()->getChecklineTriggering(node->getCenter(),
|
||||||
succ->getCenter() );
|
succ->getCenter() );
|
||||||
@ -363,11 +301,11 @@ void QuadGraph::computeChecklineRequirements(GraphNode* node,
|
|||||||
* (since on other graph nodes only one path can be used anyway, this
|
* (since on other graph nodes only one path can be used anyway, this
|
||||||
* saves some memory).
|
* saves some memory).
|
||||||
*/
|
*/
|
||||||
void QuadGraph::setupPaths()
|
void DriveGraph::setupPaths()
|
||||||
{
|
{
|
||||||
for(unsigned int i=0; i<getNumNodes(); i++)
|
for(unsigned int i=0; i<getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
m_all_nodes[i]->setupPathsToNode();
|
getNode(i)->setupPathsToNode();
|
||||||
}
|
}
|
||||||
} // setupPaths
|
} // setupPaths
|
||||||
|
|
||||||
@ -375,18 +313,18 @@ void QuadGraph::setupPaths()
|
|||||||
/** This function sets a default successor for all graph nodes that currently
|
/** This function sets a default successor for all graph nodes that currently
|
||||||
* don't have a successor defined. The default successor of node X is X+1.
|
* don't have a successor defined. The default successor of node X is X+1.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::setDefaultSuccessors()
|
void DriveGraph::setDefaultSuccessors()
|
||||||
{
|
{
|
||||||
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
|
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
|
||||||
if(m_all_nodes[i]->getNumberOfSuccessors()==0) {
|
if(getNode(i)->getNumberOfSuccessors()==0) {
|
||||||
addSuccessor(i,i+1>=m_all_nodes.size() ? 0 : i+1);
|
addSuccessor(i,i+1>=m_all_nodes.size() ? 0 : i+1);
|
||||||
//~ m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1);
|
//~ getNode(i)->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1);
|
||||||
} // if size==0
|
} // if size==0
|
||||||
} // for i<m_allNodes.size()
|
} // for i<m_allNodes.size()
|
||||||
} // setDefaultSuccessors
|
} // setDefaultSuccessors
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
/** Sets all start positions depending on the quad graph. The number of
|
/** Sets all start positions depending on the drive graph. The number of
|
||||||
* entries needed is defined by the size of the start_transform (though all
|
* entries needed is defined by the size of the start_transform (though all
|
||||||
* entries will be overwritten).
|
* entries will be overwritten).
|
||||||
* E.g. the karts will be placed as:
|
* E.g. the karts will be placed as:
|
||||||
@ -406,17 +344,17 @@ void QuadGraph::setDefaultSuccessors()
|
|||||||
* \param sidewards_distance Distance in sidewards (X) direction between
|
* \param sidewards_distance Distance in sidewards (X) direction between
|
||||||
* karts.
|
* karts.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
void DriveGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
||||||
*start_transforms,
|
*start_transforms,
|
||||||
unsigned int karts_per_row,
|
unsigned int karts_per_row,
|
||||||
float forwards_distance,
|
float forwards_distance,
|
||||||
float sidewards_distance,
|
float sidewards_distance,
|
||||||
float upwards_distance) const
|
float upwards_distance) const
|
||||||
{
|
{
|
||||||
// We start just before the start node (which will trigger lap
|
// We start just before the start node (which will trigger lap
|
||||||
// counting when reached). The first predecessor is the one on
|
// counting when reached). The first predecessor is the one on
|
||||||
// the main driveline.
|
// the main driveline.
|
||||||
int current_node = m_all_nodes[getStartNode()]->getPredecessor(0);
|
int current_node = getNode(getStartNode())->getPredecessor(0);
|
||||||
|
|
||||||
float distance_from_start = 0.1f+forwards_distance;
|
float distance_from_start = 0.1f+forwards_distance;
|
||||||
|
|
||||||
@ -443,14 +381,14 @@ void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
|||||||
// Only follow the main driveline, i.e. first predecessor
|
// Only follow the main driveline, i.e. first predecessor
|
||||||
current_node = getNode(current_node)->getPredecessor(0);
|
current_node = getNode(current_node)->getPredecessor(0);
|
||||||
}
|
}
|
||||||
const GraphNode* gn = getNode(current_node);
|
const DriveNode* dn = getNode(current_node);
|
||||||
Vec3 center_line = gn->getLowerCenter() - gn->getUpperCenter();
|
Vec3 center_line = dn->getLowerCenter() - dn->getUpperCenter();
|
||||||
center_line.normalize();
|
center_line.normalize();
|
||||||
|
|
||||||
Vec3 horizontal_line = (*gn)[2] - (*gn)[3];
|
Vec3 horizontal_line = (*dn)[2] - (*dn)[3];
|
||||||
horizontal_line.normalize();
|
horizontal_line.normalize();
|
||||||
|
|
||||||
Vec3 start = gn->getUpperCenter()
|
Vec3 start = dn->getUpperCenter()
|
||||||
+ center_line * distance_from_start
|
+ center_line * distance_from_start
|
||||||
+ horizontal_line * x_pos;
|
+ horizontal_line * x_pos;
|
||||||
// Add a certain epsilon to the height in case that the
|
// Add a certain epsilon to the height in case that the
|
||||||
@ -458,7 +396,7 @@ void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
|||||||
(*start_transforms)[i].setOrigin(start+Vec3(0,upwards_distance,0));
|
(*start_transforms)[i].setOrigin(start+Vec3(0,upwards_distance,0));
|
||||||
(*start_transforms)[i].setRotation(
|
(*start_transforms)[i].setRotation(
|
||||||
btQuaternion(btVector3(0, 1, 0),
|
btQuaternion(btVector3(0, 1, 0),
|
||||||
gn->getAngleToSuccessor(0)));
|
dn->getAngleToSuccessor(0)));
|
||||||
if(x_pos >= max_x_dist-sidewards_distance*0.5f)
|
if(x_pos >= max_x_dist-sidewards_distance*0.5f)
|
||||||
{
|
{
|
||||||
x_pos = -max_x_dist;
|
x_pos = -max_x_dist;
|
||||||
@ -482,17 +420,17 @@ void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
|||||||
* \param succ A vector of ints to which the successors are added.
|
* \param succ A vector of ints to which the successors are added.
|
||||||
* \param for_ai true if only quads accessible by the AI should be returned.
|
* \param for_ai true if only quads accessible by the AI should be returned.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::getSuccessors(int node_number,
|
void DriveGraph::getSuccessors(int node_number,
|
||||||
std::vector<unsigned int>& succ,
|
std::vector<unsigned int>& succ,
|
||||||
bool for_ai) const
|
bool for_ai) const
|
||||||
{
|
{
|
||||||
const GraphNode *gn=m_all_nodes[node_number];
|
const DriveNode *dn=getNode(node_number);
|
||||||
for(unsigned int i=0; i<gn->getNumberOfSuccessors(); i++)
|
for(unsigned int i=0; i<dn->getNumberOfSuccessors(); i++)
|
||||||
{
|
{
|
||||||
// If getSuccessor is called for the AI, only add
|
// If getSuccessor is called for the AI, only add
|
||||||
// quads that are meant for the AI to be used.
|
// quads that are meant for the AI to be used.
|
||||||
if(!for_ai || !gn->ignoreSuccessorForAI(i))
|
if(!for_ai || !dn->ignoreSuccessorForAI(i))
|
||||||
succ.push_back(gn->getSuccessor(i));
|
succ.push_back(dn->getSuccessor(i));
|
||||||
}
|
}
|
||||||
} // getSuccessors
|
} // getSuccessors
|
||||||
|
|
||||||
@ -502,10 +440,10 @@ void QuadGraph::getSuccessors(int node_number,
|
|||||||
* \param node The node index for which to set the distance from start.
|
* \param node The node index for which to set the distance from start.
|
||||||
* \param new_distance The new distance for the specified graph node.
|
* \param new_distance The new distance for the specified graph node.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
void DriveGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
||||||
{
|
{
|
||||||
GraphNode *gn = m_all_nodes[node];
|
DriveNode *dn = getNode(node);
|
||||||
float current_distance = gn->getDistanceFromStart();
|
float current_distance = dn->getDistanceFromStart();
|
||||||
|
|
||||||
// If this node already has a distance defined, check if the new distance
|
// 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
|
// is longer, and if so adjust all following nodes. Without this the
|
||||||
@ -519,25 +457,25 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
|||||||
if(current_distance<new_distance)
|
if(current_distance<new_distance)
|
||||||
{
|
{
|
||||||
float delta = new_distance - current_distance;
|
float delta = new_distance - current_distance;
|
||||||
updateDistancesForAllSuccessors(gn->getNodeIndex(), delta, 0);
|
updateDistancesForAllSuccessors(dn->getIndex(), delta, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise this node has no distance defined yet. Set the new
|
// Otherwise this node has no distance defined yet. Set the new
|
||||||
// distance, and recursively update all following nodes.
|
// distance, and recursively update all following nodes.
|
||||||
gn->setDistanceFromStart(new_distance);
|
dn->setDistanceFromStart(new_distance);
|
||||||
|
|
||||||
for(unsigned int i=0; i<gn->getNumberOfSuccessors(); i++)
|
for(unsigned int i=0; i<dn->getNumberOfSuccessors(); i++)
|
||||||
{
|
{
|
||||||
GraphNode *gn_next = m_all_nodes[gn->getSuccessor(i)];
|
DriveNode *dn_next = getNode(dn->getSuccessor(i));
|
||||||
// The start node (only node with distance 0) is reached again,
|
// The start node (only node with distance 0) is reached again,
|
||||||
// recursion can stop now
|
// recursion can stop now
|
||||||
if(gn_next->getDistanceFromStart()==0)
|
if(dn_next->getDistanceFromStart()==0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
computeDistanceFromStart(gn_next->getNodeIndex(),
|
computeDistanceFromStart(dn_next->getIndex(),
|
||||||
new_distance + gn->getDistanceToSuccessor(i));
|
new_distance + dn->getDistanceToSuccessor(i));
|
||||||
} // for i
|
} // for i
|
||||||
} // computeDistanceFromStart
|
} // computeDistanceFromStart
|
||||||
|
|
||||||
@ -551,35 +489,35 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
|||||||
* \param recursive_count Counts how often this function was called
|
* \param recursive_count Counts how often this function was called
|
||||||
* recursively in order to catch incorrect graphs that contain loops.
|
* recursively in order to catch incorrect graphs that contain loops.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta,
|
void DriveGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta,
|
||||||
unsigned int recursive_count)
|
unsigned int recursive_count)
|
||||||
{
|
{
|
||||||
if(recursive_count>getNumNodes())
|
if(recursive_count>getNumNodes())
|
||||||
{
|
{
|
||||||
Log::error("QuadGraph",
|
Log::error("DriveGraph",
|
||||||
"Quad graph contains a loop (without start node).");
|
"DriveGraph contains a loop (without start node).");
|
||||||
Log::fatal("QuadGraph",
|
Log::fatal("DriveGraph",
|
||||||
"Fix graph, check for directions of all shortcuts etc.");
|
"Fix graph, check for directions of all shortcuts etc.");
|
||||||
}
|
}
|
||||||
recursive_count++;
|
recursive_count++;
|
||||||
|
|
||||||
GraphNode* g = getNode(indx);
|
DriveNode* dn = getNode(indx);
|
||||||
g->setDistanceFromStart(g->getDistanceFromStart()+delta);
|
dn->setDistanceFromStart(dn->getDistanceFromStart()+delta);
|
||||||
for(unsigned int i=0; i<g->getNumberOfSuccessors(); i++)
|
for(unsigned int i=0; i<dn->getNumberOfSuccessors(); i++)
|
||||||
{
|
{
|
||||||
GraphNode* g_next = getNode(g->getSuccessor(i));
|
DriveNode* dn_next = getNode(dn->getSuccessor(i));
|
||||||
// Stop when we reach the start node, i.e. the only node with a
|
// Stop when we reach the start node, i.e. the only node with a
|
||||||
// distance of 0
|
// distance of 0
|
||||||
if(g_next->getDistanceFromStart()==0)
|
if(dn_next->getDistanceFromStart()==0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Only increase the distance from start of a successor node, if
|
// Only increase the distance from start of a successor node, if
|
||||||
// this successor has a distance from start that is smaller then
|
// this successor has a distance from start that is smaller then
|
||||||
// the increased amount.
|
// the increased amount.
|
||||||
if(g->getDistanceFromStart()+g->getDistanceToSuccessor(i) >
|
if(dn->getDistanceFromStart()+dn->getDistanceToSuccessor(i) >
|
||||||
g_next->getDistanceFromStart())
|
dn_next->getDistanceFromStart())
|
||||||
{
|
{
|
||||||
updateDistancesForAllSuccessors(g->getSuccessor(i), delta,
|
updateDistancesForAllSuccessors(dn->getSuccessor(i), delta,
|
||||||
recursive_count);
|
recursive_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,12 +538,12 @@ void QuadGraph::updateDistancesForAllSuccessors(unsigned int indx, float delta,
|
|||||||
* its data constantly, i.e. if it takes a different turn, it will be using
|
* its data constantly, i.e. if it takes a different turn, it will be using
|
||||||
* the new data).
|
* the new data).
|
||||||
*/
|
*/
|
||||||
void QuadGraph::computeDirectionData()
|
void DriveGraph::computeDirectionData()
|
||||||
{
|
{
|
||||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||||
{
|
{
|
||||||
for(unsigned int succ_index=0;
|
for(unsigned int succ_index=0;
|
||||||
succ_index<m_all_nodes[i]->getNumberOfSuccessors();
|
succ_index<getNode(i)->getNumberOfSuccessors();
|
||||||
succ_index++)
|
succ_index++)
|
||||||
{
|
{
|
||||||
determineDirection(i, succ_index);
|
determineDirection(i, succ_index);
|
||||||
@ -617,14 +555,14 @@ void QuadGraph::computeDirectionData()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Adjust the given angle to be in [-PI, PI].
|
/** Adjust the given angle to be in [-PI, PI].
|
||||||
*/
|
*/
|
||||||
float QuadGraph::normalizeAngle(float f)
|
float DriveGraph::normalizeAngle(float f)
|
||||||
{
|
{
|
||||||
if(f>M_PI) f -= 2*M_PI;
|
if(f>M_PI) f -= 2*M_PI;
|
||||||
else if(f<-M_PI) f += 2*M_PI;
|
else if(f<-M_PI) f += 2*M_PI;
|
||||||
return f;
|
return f;
|
||||||
} // normalizeAngle
|
} // normalizeAngle
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Determines the direction of the quad graph when driving to the specified
|
/** Determines the direction of the drive graph when driving to the specified
|
||||||
* successor. It also determines the last graph node that is still following
|
* successor. It also determines the last graph node that is still following
|
||||||
* the given direction. The computed data is saved in the corresponding
|
* the given direction. The computed data is saved in the corresponding
|
||||||
* graph node.
|
* graph node.
|
||||||
@ -640,8 +578,8 @@ float QuadGraph::normalizeAngle(float f)
|
|||||||
* If there should be any other branches later, successor
|
* If there should be any other branches later, successor
|
||||||
* 0 will always be tetsed.
|
* 0 will always be tetsed.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::determineDirection(unsigned int current,
|
void DriveGraph::determineDirection(unsigned int current,
|
||||||
unsigned int succ_index)
|
unsigned int succ_index)
|
||||||
{
|
{
|
||||||
// The maximum angle which is still considered to be straight
|
// The maximum angle which is still considered to be straight
|
||||||
const float max_straight_angle=0.1f;
|
const float max_straight_angle=0.1f;
|
||||||
@ -681,11 +619,11 @@ void QuadGraph::determineDirection(unsigned int current,
|
|||||||
next = getNode(next)->getSuccessor(0);
|
next = getNode(next)->getSuccessor(0);
|
||||||
} // while(1)
|
} // while(1)
|
||||||
|
|
||||||
GraphNode::DirectionType dir =
|
DriveNode::DirectionType dir =
|
||||||
rel_angle==0 ? GraphNode::DIR_STRAIGHT
|
rel_angle==0 ? DriveNode::DIR_STRAIGHT
|
||||||
: (rel_angle>0) ? GraphNode::DIR_RIGHT
|
: (rel_angle>0) ? DriveNode::DIR_RIGHT
|
||||||
: GraphNode::DIR_LEFT;
|
: DriveNode::DIR_LEFT;
|
||||||
m_all_nodes[current]->setDirectionData(succ_index, dir, next);
|
getNode(current)->setDirectionData(succ_index, dir, next);
|
||||||
} // determineDirection
|
} // determineDirection
|
||||||
|
|
||||||
|
|
||||||
@ -699,12 +637,12 @@ void QuadGraph::determineDirection(unsigned int current,
|
|||||||
* \param xyz The position of the kart.
|
* \param xyz The position of the kart.
|
||||||
* \param sector The graph node the position is on.
|
* \param sector The graph node the position is on.
|
||||||
*/
|
*/
|
||||||
void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
void DriveGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
||||||
const int sector) const
|
const int sector) const
|
||||||
{
|
{
|
||||||
if(sector == UNKNOWN_SECTOR )
|
if(sector == UNKNOWN_SECTOR )
|
||||||
{
|
{
|
||||||
Log::warn("Quad Graph", "UNKNOWN_SECTOR in spatialToTrack().");
|
Log::warn("Drive Graph", "UNKNOWN_SECTOR in spatialToTrack().");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,215 +650,47 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
|||||||
} // spatialToTrack
|
} // spatialToTrack
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** findRoadSector returns in which sector on the road the position
|
float DriveGraph::getDistanceToNext(int n, int j) const
|
||||||
* xyz is. If xyz is not on top of the road, it sets UNKNOWN_SECTOR as sector.
|
|
||||||
*
|
|
||||||
* \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 all_sectors If this is not NULL, it is a list of all sectors to
|
|
||||||
* test. This is used by the AI to make sure that it ends up on the
|
|
||||||
* selected way in case of a branch, and also to make sure that it
|
|
||||||
* doesn't skip e.g. a loop (see explanation below for details).
|
|
||||||
*/
|
|
||||||
void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
|
|
||||||
std::vector<int> *all_sectors) const
|
|
||||||
{
|
{
|
||||||
// Most likely the kart will still be on the sector it was before,
|
return getNode(n)->getDistanceToSuccessor(j);
|
||||||
// so this simple case is tested first.
|
|
||||||
if(*sector!=UNKNOWN_SECTOR && getNode(*sector)->pointInside(xyz) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
} // if still on same quad
|
|
||||||
|
|
||||||
// Now we search through all graph nodes, starting with
|
|
||||||
// the current one
|
|
||||||
int indx = *sector;
|
|
||||||
|
|
||||||
// If a current sector is given, and max_lookahead is specify, only test
|
|
||||||
// the next max_lookahead graph nodes instead of testing the whole graph.
|
|
||||||
// This is necessary for the AI: if the track contains a loop, e.g.:
|
|
||||||
// -A--+---B---+----F--------
|
|
||||||
// E C
|
|
||||||
// +---D---+
|
|
||||||
// and the track is supposed to be driven: ABCDEBF, the AI might find
|
|
||||||
// the node on F, and then keep on going straight ahead instead of
|
|
||||||
// using the loop at all.
|
|
||||||
unsigned int max_count = (*sector!=UNKNOWN_SECTOR && all_sectors!=NULL)
|
|
||||||
? (unsigned int)all_sectors->size()
|
|
||||||
: (unsigned int)m_all_nodes.size();
|
|
||||||
*sector = UNKNOWN_SECTOR;
|
|
||||||
for(unsigned int i=0; i<max_count; i++)
|
|
||||||
{
|
|
||||||
if(all_sectors)
|
|
||||||
indx = (*all_sectors)[i];
|
|
||||||
else
|
|
||||||
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
|
|
||||||
const GraphNode* gn = getNode(indx);
|
|
||||||
if(gn->pointInside(xyz))
|
|
||||||
{
|
|
||||||
*sector = indx;
|
|
||||||
}
|
|
||||||
} // for i<m_all_nodes.size()
|
|
||||||
|
|
||||||
return;
|
|
||||||
} // findRoadSector
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/** findOutOfRoadSector finds the sector where XYZ is, but as it name
|
|
||||||
implies, it is more accurate for the outside of the track than the
|
|
||||||
inside, and for STK's needs the accuracy on top of the track is
|
|
||||||
unacceptable; but if this was a 2D function, the accuracy for out
|
|
||||||
of road sectors would be perfect.
|
|
||||||
|
|
||||||
To find the sector we look for the closest line segment from the
|
|
||||||
right and left drivelines, and the number of that segment will be
|
|
||||||
the sector.
|
|
||||||
|
|
||||||
The SIDE argument is used to speed up the function only; if we know
|
|
||||||
that XYZ is on the left or right side of the track, we know that
|
|
||||||
the closest driveline must be the one that matches that condition.
|
|
||||||
In reality, the side used in STK is the one from the previous frame,
|
|
||||||
but in order to move from one side to another a point would go
|
|
||||||
through the middle, that is handled by findRoadSector() which doesn't
|
|
||||||
has speed ups based on the side.
|
|
||||||
|
|
||||||
NOTE: This method of finding the sector outside of the road is *not*
|
|
||||||
perfect: if two line segments have a similar altitude (but enough to
|
|
||||||
let a kart get through) and they are very close on a 2D system,
|
|
||||||
if a kart is on the air it could be closer to the top line segment
|
|
||||||
even if it is supposed to be on the sector of the lower line segment.
|
|
||||||
Probably the best solution would be to construct a quad that reaches
|
|
||||||
until the next higher overlapping line segment, and find the closest
|
|
||||||
one to XYZ.
|
|
||||||
*/
|
|
||||||
int QuadGraph::findOutOfRoadSector(const Vec3& xyz,
|
|
||||||
const int curr_sector,
|
|
||||||
std::vector<int> *all_sectors) const
|
|
||||||
{
|
|
||||||
int count = (all_sectors!=NULL) ? (int) all_sectors->size() : getNumNodes();
|
|
||||||
int current_sector = 0;
|
|
||||||
if(curr_sector != UNKNOWN_SECTOR && !all_sectors)
|
|
||||||
{
|
|
||||||
// We have to test all nodes here: reason is that on track with
|
|
||||||
// shortcuts the n quads of the main drivelines is followed by
|
|
||||||
// the quads of the shortcuts. So after quad n-1 (the last one
|
|
||||||
// before the lap counting line) quad n will not be 0 (the first
|
|
||||||
// quad after the lap counting line), but one of the quads on a
|
|
||||||
// shortcut. If we only tested a limited number of quads to
|
|
||||||
// improve the performance the crossing of a lap might not be
|
|
||||||
// detected (because quad 0 is not tested, only quads on the
|
|
||||||
// shortcuts are tested). If this should become a performance
|
|
||||||
// bottleneck, we need to set up a graph of 'next' quads for each
|
|
||||||
// quad (similar to what the AI does), and only test the quads
|
|
||||||
// in this graph.
|
|
||||||
const int LIMIT = getNumNodes();
|
|
||||||
count = LIMIT;
|
|
||||||
// Start 10 quads before the current quad, so the quads closest
|
|
||||||
// to the current position are tested first.
|
|
||||||
current_sector = curr_sector -10;
|
|
||||||
if(current_sector<0) current_sector += getNumNodes();
|
|
||||||
}
|
|
||||||
|
|
||||||
int min_sector = UNKNOWN_SECTOR;
|
|
||||||
float min_dist_2 = 999999.0f*999999.0f;
|
|
||||||
|
|
||||||
// If a kart is falling and in between (or too far below)
|
|
||||||
// a driveline point it might not fulfill
|
|
||||||
// the height condition. So we run the test twice: first with height
|
|
||||||
// condition, then again without the height condition - just to make sure
|
|
||||||
// it always comes back with some kind of quad.
|
|
||||||
for(int phase=0; phase<2; phase++)
|
|
||||||
{
|
|
||||||
for(int j=0; j<count; j++)
|
|
||||||
{
|
|
||||||
int next_sector;
|
|
||||||
if(all_sectors)
|
|
||||||
next_sector = (*all_sectors)[j];
|
|
||||||
else
|
|
||||||
next_sector = current_sector+1 == (int)getNumNodes()
|
|
||||||
? 0
|
|
||||||
: current_sector+1;
|
|
||||||
|
|
||||||
// A first simple test uses the 2d distance to the center of the quad.
|
|
||||||
float dist_2 = m_all_nodes[next_sector]->getDistance2FromPoint(xyz);
|
|
||||||
if(dist_2<min_dist_2)
|
|
||||||
{
|
|
||||||
const GraphNode* gn = getNode(next_sector);
|
|
||||||
const bool is_3d = (dynamic_cast<const Node3D*>(gn) != NULL);
|
|
||||||
float dist = xyz.getY() - gn->getMinHeight();
|
|
||||||
// While negative distances are unlikely, we allow some small
|
|
||||||
// negative numbers in case that the kart is partly in the
|
|
||||||
// track. Only do the height test in phase==0, in phase==1
|
|
||||||
// accept any point, independent of height, or this node is 3d
|
|
||||||
// which already takes height into account
|
|
||||||
if(phase==1 || (dist < 5.0f && dist>-1.0f) || is_3d)
|
|
||||||
{
|
|
||||||
min_dist_2 = dist_2;
|
|
||||||
min_sector = next_sector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_sector = next_sector;
|
|
||||||
} // for j
|
|
||||||
// Leave in phase 0 if any sector was found.
|
|
||||||
if(min_sector!=UNKNOWN_SECTOR)
|
|
||||||
return min_sector;
|
|
||||||
} // phase
|
|
||||||
|
|
||||||
if(min_sector==UNKNOWN_SECTOR )
|
|
||||||
{
|
|
||||||
Log::info("Quad Graph", "unknown sector found.");
|
|
||||||
}
|
|
||||||
return min_sector;
|
|
||||||
} // findOutOfRoadSector
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void QuadGraph::set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
|
||||||
const video::SColor &color) const
|
|
||||||
{
|
|
||||||
m_all_nodes[i]->getVertices(v, color);
|
|
||||||
} // set3DVerticesOfGraph
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
const bool QuadGraph::isNodeInvisible(int n) const
|
|
||||||
{
|
|
||||||
return m_all_nodes[n]->isInvisible();
|
|
||||||
} // isNodeInvisible
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
float QuadGraph::getDistanceToNext(int n, int j) const
|
|
||||||
{
|
|
||||||
return m_all_nodes[n]->getDistanceToSuccessor(j);
|
|
||||||
} // getDistanceToNext
|
} // getDistanceToNext
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
float QuadGraph::getAngleToNext(int n, int j) const
|
float DriveGraph::getAngleToNext(int n, int j) const
|
||||||
{
|
{
|
||||||
return m_all_nodes[n]->getAngleToSuccessor(j);
|
return getNode(n)->getAngleToSuccessor(j);
|
||||||
} // getAngleToNext
|
} // getAngleToNext
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int QuadGraph::getNumberOfSuccessors(int n) const
|
int DriveGraph::getNumberOfSuccessors(int n) const
|
||||||
{
|
{
|
||||||
return m_all_nodes[n]->getNumberOfSuccessors();
|
return getNode(n)->getNumberOfSuccessors();
|
||||||
} // getNumberOfSuccessors
|
} // getNumberOfSuccessors
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
float QuadGraph::getDistanceFromStart(int j) const
|
float DriveGraph::getDistanceFromStart(int j) const
|
||||||
{
|
{
|
||||||
return m_all_nodes[j]->getDistanceFromStart();
|
return getNode(j)->getDistanceFromStart();
|
||||||
} // getDistanceFromStart
|
} // getDistanceFromStart
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const bool QuadGraph::differentNodeColor(int n, NodeColor* c) const
|
void DriveGraph::differentNodeColor(int n, video::SColor* c) const
|
||||||
{
|
{
|
||||||
if (UserConfigParams::m_track_debug)
|
if (UserConfigParams::m_track_debug)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<Node3D*>(m_all_nodes[n]) != NULL)
|
if (getNode(n)->is3DQuad())
|
||||||
*c = COLOR_GREEN;
|
*c = video::SColor(255, 0, 255, 0);
|
||||||
else
|
else
|
||||||
*c = COLOR_YELLOW;
|
*c = video::SColor(255, 255, 255, 0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return n == 0;
|
|
||||||
} // differentNodeColor
|
} // differentNodeColor
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
DriveNode* DriveGraph::getNode(unsigned int j) const
|
||||||
|
{
|
||||||
|
assert(j < m_all_nodes.size());
|
||||||
|
DriveNode* n = dynamic_cast<DriveNode*>(m_all_nodes[j]);
|
||||||
|
assert(n != NULL);
|
||||||
|
return n;
|
||||||
|
} // getNode
|
125
src/tracks/drive_graph.hpp
Normal file
125
src/tracks/drive_graph.hpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||||
|
|
||||||
|
#ifndef HEADER_DRIVE_GRAPH_HPP
|
||||||
|
#define HEADER_DRIVE_GRAPH_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "tracks/graph.hpp"
|
||||||
|
#include "utils/aligned_array.hpp"
|
||||||
|
#include "utils/cpp2011.hpp"
|
||||||
|
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
|
|
||||||
|
class DriveNode;
|
||||||
|
class XMLNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A graph made from driveline
|
||||||
|
* \ingroup tracks
|
||||||
|
*/
|
||||||
|
class DriveGraph : public Graph
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/** The length of the first loop. */
|
||||||
|
float m_lap_length;
|
||||||
|
|
||||||
|
/** Stores the filename - just used for error messages. */
|
||||||
|
std::string m_quad_filename;
|
||||||
|
|
||||||
|
/** Wether the graph should be reverted or not */
|
||||||
|
bool m_reverse;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setDefaultSuccessors();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void computeChecklineRequirements(DriveNode* node, int latest_checkline);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void computeDirectionData();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void determineDirection(unsigned int current, unsigned int succ_index);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
float normalizeAngle(float f);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void addSuccessor(unsigned int from, unsigned int to);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void load(const std::string &quad_file_name, const std::string &filename);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||||
|
Vec3 *result) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void computeDistanceFromStart(unsigned int start_node, float distance);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
unsigned int getStartNode() const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual bool hasLapLine() const OVERRIDE { return true; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void differentNodeColor(int n, video::SColor* c) const OVERRIDE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static DriveGraph* get() { return dynamic_cast<DriveGraph*>(m_graph); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
DriveGraph(const std::string &quad_file_name,
|
||||||
|
const std::string &graph_file_name, const bool reverse);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual ~DriveGraph() {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void getSuccessors(int node_number, std::vector<unsigned int>& succ,
|
||||||
|
bool for_ai=false) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void spatialToTrack(Vec3 *dst, const Vec3& xyz, const int sector) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setDefaultStartPositions(AlignedArray<btTransform> *start_transforms,
|
||||||
|
unsigned int karts_per_row,
|
||||||
|
float forwards_distance = 1.5f,
|
||||||
|
float sidewards_distance = 1.5f,
|
||||||
|
float upwards_distance=0.0f) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void updateDistancesForAllSuccessors(unsigned int indx, float delta,
|
||||||
|
unsigned int count);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setupPaths();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void computeChecklineRequirements();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Return the distance to the j-th successor of node n. */
|
||||||
|
float getDistanceToNext(int n, int j) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the angle of the line between node n and its j-th.
|
||||||
|
* successor. */
|
||||||
|
float getAngleToNext(int n, int j) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the number of successors of a node n. */
|
||||||
|
int getNumberOfSuccessors(int n) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the quad that belongs to a graph node. */
|
||||||
|
DriveNode* getNode(unsigned int j) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the distance from the start to the beginning of a quad. */
|
||||||
|
float getDistanceFromStart(int j) const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the length of the main driveline. */
|
||||||
|
float getLapLength() const { return m_lap_length; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool isReverse() const { return m_reverse; }
|
||||||
|
|
||||||
|
}; // DriveGraph
|
||||||
|
|
||||||
|
#endif
|
@ -16,25 +16,22 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||||
|
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
|
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "matrix4.h"
|
#include "matrix4.h"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
GraphNode::GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
DriveNode::DriveNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||||
const Vec3 &p3, const Vec3 &normal,
|
const Vec3 &p3, const Vec3 &normal,
|
||||||
unsigned int node_index, bool invisible,
|
unsigned int node_index, bool invisible,
|
||||||
bool ai_ignore)
|
bool ai_ignore)
|
||||||
:Quad(p0, p1, p2, p3)
|
:Quad(p0, p1, p2, p3, normal, node_index, invisible)
|
||||||
{
|
{
|
||||||
m_invisible = invisible;
|
|
||||||
m_ai_ignore = ai_ignore;
|
m_ai_ignore = ai_ignore;
|
||||||
m_normal = normal;
|
|
||||||
m_node_index = node_index;
|
|
||||||
m_distance_from_start = -1.0f;
|
m_distance_from_start = -1.0f;
|
||||||
|
|
||||||
// The following values should depend on the actual orientation
|
// The following values should depend on the actual orientation
|
||||||
@ -48,7 +45,7 @@ GraphNode::GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|||||||
m_width = ( (m_p[1]-m_p[0]).length()
|
m_width = ( (m_p[1]-m_p[0]).length()
|
||||||
+ (m_p[3]-m_p[2]).length() ) * 0.5f;
|
+ (m_p[3]-m_p[2]).length() ) * 0.5f;
|
||||||
|
|
||||||
if(QuadGraph::get()->isReverse())
|
if(DriveGraph::get()->isReverse())
|
||||||
{
|
{
|
||||||
m_lower_center = (m_p[2]+m_p[3]) * 0.5f;
|
m_lower_center = (m_p[2]+m_p[3]) * 0.5f;
|
||||||
m_upper_center = (m_p[0]+m_p[1]) * 0.5f;
|
m_upper_center = (m_p[0]+m_p[1]) * 0.5f;
|
||||||
@ -60,53 +57,53 @@ GraphNode::GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|||||||
m_upper_center = (m_p[2]+m_p[3]) * 0.5f;
|
m_upper_center = (m_p[2]+m_p[3]) * 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // GraphNode
|
} // DriveNode
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Adds a successor to a node. This function will also pre-compute certain
|
/** 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)
|
* values (like distance from this node to the successor, angle (in world)
|
||||||
* between this node and the successor.
|
* between this node and the successor.
|
||||||
* \param to The index of the graph node of the successor.
|
* \param to The index of the drive node of the successor.
|
||||||
*/
|
*/
|
||||||
void GraphNode::addSuccessor(unsigned int to)
|
void DriveNode::addSuccessor(unsigned int to)
|
||||||
{
|
{
|
||||||
m_successor_nodes.push_back(to);
|
m_successor_nodes.push_back(to);
|
||||||
// to is the graph node
|
// to is the drive node
|
||||||
GraphNode* gn_to = QuadGraph::get()->getNode(to);
|
DriveNode* dn_to = DriveGraph::get()->getNode(to);
|
||||||
|
|
||||||
// Note that the first predecessor is (because of the way the quad graph
|
// Note that the first predecessor is (because of the way the drive graph
|
||||||
// is exported) the most 'natural' one, i.e. the one on the main
|
// is exported) the most 'natural' one, i.e. the one on the main
|
||||||
// driveline.
|
// driveline.
|
||||||
gn_to->m_predecessor_nodes.push_back(m_node_index);
|
dn_to->m_predecessor_nodes.push_back(m_index);
|
||||||
|
|
||||||
Vec3 d = m_lower_center - gn_to->m_lower_center;
|
Vec3 d = m_lower_center - dn_to->m_lower_center;
|
||||||
m_distance_to_next.push_back(d.length());
|
m_distance_to_next.push_back(d.length());
|
||||||
|
|
||||||
Vec3 diff = gn_to->getCenter() - getCenter();
|
Vec3 diff = dn_to->getCenter() - getCenter();
|
||||||
|
|
||||||
core::CMatrix4<float> m;
|
core::CMatrix4<float> m;
|
||||||
m.buildRotateFromTo(getNormal().toIrrVector(),
|
m.buildRotateFromTo(getNormal().toIrrVector(),
|
||||||
Vec3(0, 1, 0).toIrrVector());
|
Vec3(0, 1, 0).toIrrVector());
|
||||||
core::vector3df diffRotated;
|
core::vector3df diff_rotated;
|
||||||
m.rotateVect(diffRotated, diff.toIrrVector());
|
m.rotateVect(diff_rotated, diff.toIrrVector());
|
||||||
|
|
||||||
m_angle_to_next.push_back(atan2(diffRotated.X, diffRotated.Z));
|
m_angle_to_next.push_back(atan2(diff_rotated.X, diff_rotated.Z));
|
||||||
|
|
||||||
} // addSuccessor
|
} // addSuccessor
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** If this node has more than one successor, it will set up a vector that
|
/** If this node has more than one successor, it will set up a vector that
|
||||||
* contains the direction to use when a certain graph node X should be
|
* contains the direction to use when a certain drive node X should be
|
||||||
* reached.
|
* reached.
|
||||||
*/
|
*/
|
||||||
void GraphNode::setupPathsToNode()
|
void DriveNode::setupPathsToNode()
|
||||||
{
|
{
|
||||||
if(m_successor_nodes.size()<2) return;
|
if(m_successor_nodes.size()<2) return;
|
||||||
|
|
||||||
const unsigned int num_nodes = QuadGraph::get()->getNumNodes();
|
const unsigned int num_nodes = DriveGraph::get()->getNumNodes();
|
||||||
m_path_to_node.resize(num_nodes);
|
m_path_to_node.resize(num_nodes);
|
||||||
|
|
||||||
// Initialise each graph node with -1, indicating that
|
// Initialise each drive node with -1, indicating that
|
||||||
// it hasn't been reached yet.
|
// it hasn't been reached yet.
|
||||||
for(unsigned int i=0; i<num_nodes; i++)
|
for(unsigned int i=0; i<num_nodes; i++)
|
||||||
m_path_to_node[i] = -1;
|
m_path_to_node[i] = -1;
|
||||||
@ -114,24 +111,24 @@ void GraphNode::setupPathsToNode()
|
|||||||
// Indicate that this node can be reached from this node by following
|
// Indicate that this node can be reached from this node by following
|
||||||
// successor 0 - just a dummy value that might only be used during the
|
// successor 0 - just a dummy value that might only be used during the
|
||||||
// recursion below.
|
// recursion below.
|
||||||
m_path_to_node[m_node_index] = 0;
|
m_path_to_node[m_index] = 0;
|
||||||
|
|
||||||
// A simple depth first search is used to determine which successor to
|
// A simple depth first search is used to determine which successor to
|
||||||
// use to reach a certain graph node. Using Dijkstra's algorithm would
|
// use to reach a certain drive node. Using Dijkstra's algorithm would
|
||||||
// give the shortest way to reach a certain node, but the shortest way
|
// give the shortest way to reach a certain node, but the shortest way
|
||||||
// might involve some shortcuts which are hidden, and should therefore
|
// might involve some shortcuts which are hidden, and should therefore
|
||||||
// not be used.
|
// not be used.
|
||||||
for(unsigned int i=0; i<getNumberOfSuccessors(); i++)
|
for(unsigned int i=0; i<getNumberOfSuccessors(); i++)
|
||||||
{
|
{
|
||||||
GraphNode* gn = QuadGraph::get()->getNode(getSuccessor(i));
|
DriveNode* dn = DriveGraph::get()->getNode(getSuccessor(i));
|
||||||
gn->markAllSuccessorsToUse(i, &m_path_to_node);
|
dn->markAllSuccessorsToUse(i, &m_path_to_node);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for(unsigned int i = 0; i < m_path_to_node.size(); ++i)
|
for(unsigned int i = 0; i < m_path_to_node.size(); ++i)
|
||||||
{
|
{
|
||||||
if(m_path_to_node[i] == -1)
|
if(m_path_to_node[i] == -1)
|
||||||
Log::warn("GraphNode", "No path to node %d found on graph node %d.",
|
Log::warn("DriveNode", "No path to node %d found on drive node %d.",
|
||||||
i, m_node_index);
|
i, m_index);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} // setupPathsToNode
|
} // setupPathsToNode
|
||||||
@ -145,22 +142,22 @@ void GraphNode::setupPathsToNode()
|
|||||||
* \param path_to_node The path-to-node data structure of the node for
|
* \param path_to_node The path-to-node data structure of the node for
|
||||||
* which the paths are currently determined.
|
* which the paths are currently determined.
|
||||||
*/
|
*/
|
||||||
void GraphNode::markAllSuccessorsToUse(unsigned int n,
|
void DriveNode::markAllSuccessorsToUse(unsigned int n,
|
||||||
PathToNodeVector *path_to_node)
|
PathToNodeVector *path_to_node)
|
||||||
{
|
{
|
||||||
// End recursion if the path to this node has already been found.
|
// End recursion if the path to this node has already been found.
|
||||||
if( (*path_to_node)[m_node_index] >-1) return;
|
if( (*path_to_node)[m_index] >-1) return;
|
||||||
|
|
||||||
(*path_to_node)[m_node_index] = n;
|
(*path_to_node)[m_index] = n;
|
||||||
for(unsigned int i=0; i<getNumberOfSuccessors(); i++)
|
for(unsigned int i=0; i<getNumberOfSuccessors(); i++)
|
||||||
{
|
{
|
||||||
GraphNode* gn = QuadGraph::get()->getNode(getSuccessor(i));
|
DriveNode* dn = DriveGraph::get()->getNode(getSuccessor(i));
|
||||||
gn->markAllSuccessorsToUse(n, path_to_node);
|
dn->markAllSuccessorsToUse(n, path_to_node);
|
||||||
}
|
}
|
||||||
} // markAllSuccesorsToUse
|
} // markAllSuccesorsToUse
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GraphNode::setDirectionData(unsigned int successor, DirectionType dir,
|
void DriveNode::setDirectionData(unsigned int successor, DirectionType dir,
|
||||||
unsigned int last_node_index)
|
unsigned int last_node_index)
|
||||||
{
|
{
|
||||||
if(m_direction.size()<successor+1)
|
if(m_direction.size()<successor+1)
|
||||||
@ -173,7 +170,7 @@ void GraphNode::setDirectionData(unsigned int successor, DirectionType dir,
|
|||||||
} // setDirectionData
|
} // setDirectionData
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void GraphNode::setChecklineRequirements(int latest_checkline)
|
void DriveNode::setChecklineRequirements(int latest_checkline)
|
||||||
{
|
{
|
||||||
m_checkline_requirements.push_back(latest_checkline);
|
m_checkline_requirements.push_back(latest_checkline);
|
||||||
} // setChecklineRequirements
|
} // setChecklineRequirements
|
||||||
@ -183,7 +180,7 @@ void GraphNode::setChecklineRequirements(int latest_checkline)
|
|||||||
* is allowed to use.
|
* is allowed to use.
|
||||||
* \param index Index of the successor.
|
* \param index Index of the successor.
|
||||||
*/
|
*/
|
||||||
bool GraphNode::ignoreSuccessorForAI(unsigned int i) const
|
bool DriveNode::ignoreSuccessorForAI(unsigned int i) const
|
||||||
{
|
{
|
||||||
return QuadGraph::get()->getNode(m_successor_nodes[i])->letAIIgnore();
|
return DriveGraph::get()->getNode(m_successor_nodes[i])->letAIIgnore();
|
||||||
} // ignoreSuccessorForAI
|
} // ignoreSuccessorForAI
|
@ -16,19 +16,19 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||||
|
|
||||||
#ifndef HEADER_GRAPH_NODE_HPP
|
#ifndef HEADER_DRIVE_NODE_HPP
|
||||||
#define HEADER_GRAPH_NODE_HPP
|
#define HEADER_DRIVE_NODE_HPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "tracks/quad.hpp"
|
#include "tracks/quad.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief This class stores a node of the graph, i.e. a list of successor
|
* \brief This class stores a node of the drive graph, i.e. a list of
|
||||||
* edges, it can either be 2d or 3d.
|
* successor edges, it can either be 2d or 3d.
|
||||||
* \ingroup tracks
|
* \ingroup tracks
|
||||||
*/
|
*/
|
||||||
class GraphNode : public Quad
|
class DriveNode : public Quad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** To indiciate in which direction the track is going:
|
/** To indiciate in which direction the track is going:
|
||||||
@ -37,29 +37,20 @@ public:
|
|||||||
enum DirectionType {DIR_STRAIGHT, DIR_LEFT, DIR_RIGHT,
|
enum DirectionType {DIR_STRAIGHT, DIR_LEFT, DIR_RIGHT,
|
||||||
DIR_UNDEFINED};
|
DIR_UNDEFINED};
|
||||||
protected:
|
protected:
|
||||||
/** Lower center point of the graph node. */
|
/** Lower center point of the drive node. */
|
||||||
Vec3 m_lower_center;
|
Vec3 m_lower_center;
|
||||||
|
|
||||||
/** Upper center point of the graph node. */
|
/** Upper center point of the drive node. */
|
||||||
Vec3 m_upper_center;
|
Vec3 m_upper_center;
|
||||||
|
|
||||||
/** Distance from the start to the beginning of the graph node. */
|
/** Distance from the start to the beginning of the drive node. */
|
||||||
float m_distance_from_start;
|
float m_distance_from_start;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Normal of the graph node */
|
/** Set to true if this drive node should not be used by the AI. */
|
||||||
Vec3 m_normal;
|
|
||||||
|
|
||||||
/** Set to true if this graph node should not be shown in the minimap. */
|
|
||||||
bool m_invisible;
|
|
||||||
|
|
||||||
/** Set to true if this graph node should not be used by the AI. */
|
|
||||||
bool m_ai_ignore;
|
bool m_ai_ignore;
|
||||||
|
|
||||||
/** Index of this graph node. */
|
/** The list of successor drive nodes. */
|
||||||
unsigned int m_node_index;
|
|
||||||
|
|
||||||
/** The list of successor graph nodes. */
|
|
||||||
std::vector<int> m_successor_nodes;
|
std::vector<int> m_successor_nodes;
|
||||||
|
|
||||||
/** The list of predecessors of a node. */
|
/** The list of predecessors of a node. */
|
||||||
@ -79,18 +70,18 @@ private:
|
|||||||
Vec3 m_center_to_right;
|
Vec3 m_center_to_right;
|
||||||
|
|
||||||
typedef std::vector<int> PathToNodeVector;
|
typedef std::vector<int> PathToNodeVector;
|
||||||
/** This vector is only used if the graph node has more than one
|
/** This vector is only used if the drive node has more than one
|
||||||
* successor. In this case m_path_to_node[X] will contain the index
|
* successor. In this case m_path_to_node[X] will contain the index
|
||||||
* of the successor to use in order to reach graph node X for this
|
* of the successor to use in order to reach drive node X for this
|
||||||
* graph nodes. */
|
* drive nodes. */
|
||||||
PathToNodeVector m_path_to_node;
|
PathToNodeVector m_path_to_node;
|
||||||
|
|
||||||
/** The direction for each of the successors. */
|
/** The direction for each of the successors. */
|
||||||
std::vector<DirectionType> m_direction;
|
std::vector<DirectionType> m_direction;
|
||||||
|
|
||||||
/** Stores for each successor the index of the last graph node that
|
/** Stores for each successor the index of the last drive node that
|
||||||
* has the same direction (i.e. if index 0 curves left, this vector
|
* has the same direction (i.e. if index 0 curves left, this vector
|
||||||
* will store the index of the last graph node that is still turning
|
* will store the index of the last drive node that is still turning
|
||||||
* left. */
|
* left. */
|
||||||
std::vector<unsigned int> m_last_index_same_direction;
|
std::vector<unsigned int> m_last_index_same_direction;
|
||||||
|
|
||||||
@ -105,16 +96,17 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::vector< int > m_checkline_requirements;
|
std::vector< int > m_checkline_requirements;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void markAllSuccessorsToUse(unsigned int n,
|
void markAllSuccessorsToUse(unsigned int n,
|
||||||
PathToNodeVector *m_path_to_node);
|
PathToNodeVector *m_path_to_node);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
DriveNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||||
const Vec3 &p3, const Vec3 &normal,
|
const Vec3 &p3, const Vec3 &normal,
|
||||||
unsigned int node_index, bool invisible,
|
unsigned int node_index, bool invisible,
|
||||||
bool ai_ignore);
|
bool ai_ignore);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual ~GraphNode() {}
|
virtual ~DriveNode() {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void addSuccessor (unsigned int to);
|
void addSuccessor (unsigned int to);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -131,7 +123,7 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the i-th successor node. */
|
/** Returns the i-th successor node. */
|
||||||
unsigned int getSuccessor(unsigned int i) const
|
unsigned int getSuccessor(unsigned int i) const
|
||||||
{ return m_successor_nodes[i]; }
|
{ return m_successor_nodes[i]; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the number of predecessors. */
|
/** Returns the number of predecessors. */
|
||||||
unsigned int getNumberOfPredecessors() const
|
unsigned int getNumberOfPredecessors() const
|
||||||
@ -140,47 +132,41 @@ public:
|
|||||||
/** Returns a predecessor for this node. Note that the first predecessor
|
/** Returns a predecessor for this node. Note that the first predecessor
|
||||||
* is the most 'natural' one, i.e. the one on the main driveline.
|
* is the most 'natural' one, i.e. the one on the main driveline.
|
||||||
*/
|
*/
|
||||||
int getPredecessor(unsigned int i) const {return m_predecessor_nodes[i]; }
|
int getPredecessor(unsigned int i) const { return m_predecessor_nodes[i]; }
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the node index of this node. */
|
|
||||||
unsigned int getNodeIndex() const { return m_node_index; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the normal of this quad */
|
|
||||||
const Vec3& getNormal() const { return m_normal; }
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the distance to the j-th. successor. */
|
/** Returns the distance to the j-th. successor. */
|
||||||
float getDistanceToSuccessor(unsigned int j) const
|
float getDistanceToSuccessor(unsigned int j) const
|
||||||
{ return m_distance_to_next[j]; }
|
{ return m_distance_to_next[j]; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the angle from this node to the j-th. successor. */
|
/** Returns the angle from this node to the j-th. successor. */
|
||||||
float getAngleToSuccessor(unsigned int j) const
|
float getAngleToSuccessor(unsigned int j) const
|
||||||
{ return m_angle_to_next[j]; }
|
{ return m_angle_to_next[j]; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the distance from start. */
|
/** Returns the distance from start. */
|
||||||
float getDistanceFromStart() const
|
float getDistanceFromStart() const
|
||||||
{ return m_distance_from_start; }
|
{ return m_distance_from_start; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets the distance from start for this node. */
|
/** Sets the distance from start for this node. */
|
||||||
void setDistanceFromStart(float d) {m_distance_from_start = d; }
|
void setDistanceFromStart(float d) { m_distance_from_start = d; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the width of the part for this quad. */
|
/** Returns the width of the part for this quad. */
|
||||||
float getPathWidth() const { return m_width; }
|
float getPathWidth() const { return m_width; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the center point of the lower edge of this graph node. */
|
/** Returns the center point of the lower edge of this drive node. */
|
||||||
const Vec3& getLowerCenter() const {return m_lower_center;}
|
const Vec3& getLowerCenter() const { return m_lower_center; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the center point of the upper edge of this graph node. */
|
/** Returns the center point of the upper edge of this drive node. */
|
||||||
const Vec3& getUpperCenter() const {return m_upper_center;}
|
const Vec3& getUpperCenter() const { return m_upper_center; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the length of the quad of this node. */
|
/** Returns the length of the quad of this node. */
|
||||||
float getNodeLength() const
|
float getNodeLength() const
|
||||||
{return (m_lower_center-m_upper_center).length();}
|
{ return (m_lower_center-m_upper_center).length(); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool ignoreSuccessorForAI(unsigned int i) const;
|
bool ignoreSuccessorForAI(unsigned int i) const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns which successor node to use in order to be able to reach the
|
/** Returns which successor node to use in order to be able to reach the
|
||||||
* given node n.
|
* given node n.
|
||||||
* \param n Index of the graph node to reach.
|
* \param n Index of the drive node to reach.
|
||||||
*/
|
*/
|
||||||
int getSuccessorToReach(unsigned int n)
|
int getSuccessorToReach(unsigned int n)
|
||||||
{
|
{
|
||||||
@ -189,7 +175,7 @@ public:
|
|||||||
return m_path_to_node.size()>0 ? m_path_to_node[n] : 0;
|
return m_path_to_node.size()>0 ? m_path_to_node[n] : 0;
|
||||||
} // getSuccesorToReach
|
} // getSuccesorToReach
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the checkline requirements of this graph node. */
|
/** Returns the checkline requirements of this drive node. */
|
||||||
const std::vector<int>& getChecklineRequirements() const
|
const std::vector<int>& getChecklineRequirements() const
|
||||||
{ return m_checkline_requirements; }
|
{ return m_checkline_requirements; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -201,17 +187,13 @@ public:
|
|||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns a unit vector pointing to the right side of the quad. */
|
/** Returns a unit vector pointing to the right side of the quad. */
|
||||||
const Vec3 &getRightUnitVector() const { return m_right_unit_vector; }
|
const Vec3 &getRightUnitVector() const { return m_right_unit_vector; }
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns true of this node is invisible, i.e. not to be shown in
|
|
||||||
* the minimap. */
|
|
||||||
bool isInvisible() const { return m_invisible; }
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** True if this node should be ignored by the AI. */
|
/** True if this node should be ignored by the AI. */
|
||||||
bool letAIIgnore() const { return m_ai_ignore; }
|
bool letAIIgnore() const { return m_ai_ignore; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void getDistances(const Vec3 &xyz, Vec3 *result) const = 0;
|
virtual void getDistances(const Vec3 &xyz, Vec3 *result) const = 0;
|
||||||
|
|
||||||
}; // GraphNode
|
}; // DriveNode
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -16,13 +16,15 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "tracks/node_2d.hpp"
|
#include "tracks/drive_node_2d.hpp"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
Node2D::Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
DriveNode2D::DriveNode2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
const Vec3 &p3, const Vec3 &normal,
|
||||||
bool ai_ignore)
|
unsigned int node_index, bool invisible,
|
||||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
bool ai_ignore)
|
||||||
|
: DriveNode(p0, p1, p2, p3, normal, node_index, invisible,
|
||||||
|
ai_ignore)
|
||||||
{
|
{
|
||||||
m_line = core::line2df(m_upper_center.getX(), m_upper_center.getZ(),
|
m_line = core::line2df(m_upper_center.getX(), m_upper_center.getZ(),
|
||||||
m_lower_center.getX(), m_lower_center.getZ());
|
m_lower_center.getX(), m_lower_center.getZ());
|
||||||
@ -30,7 +32,7 @@ Node2D::Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
|||||||
// Only this 2d point is needed later
|
// Only this 2d point is needed later
|
||||||
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
|
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
|
||||||
m_lower_center.getZ());
|
m_lower_center.getZ());
|
||||||
} // Node2D
|
} // DriveNode2D
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Returns the distance a point has from this node in forward and sidewards
|
/** Returns the distance a point has from this node in forward and sidewards
|
||||||
@ -41,7 +43,7 @@ Node2D::Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
|||||||
* \param result The X coordinate contains the sidewards distance, the
|
* \param result The X coordinate contains the sidewards distance, the
|
||||||
* Z coordinate the forward distance.
|
* Z coordinate the forward distance.
|
||||||
*/
|
*/
|
||||||
void Node2D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
void DriveNode2D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
||||||
{
|
{
|
||||||
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
||||||
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
||||||
@ -61,7 +63,7 @@ void Node2D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
|||||||
* which belongs to this graph node. The value is computed in 2d only!
|
* which belongs to this graph node. The value is computed in 2d only!
|
||||||
* \param xyz The point for which the distance to the line is computed.
|
* \param xyz The point for which the distance to the line is computed.
|
||||||
*/
|
*/
|
||||||
float Node2D::getDistance2FromPoint(const Vec3 &xyz) const
|
float DriveNode2D::getDistance2FromPoint(const Vec3 &xyz) const
|
||||||
{
|
{
|
||||||
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
||||||
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
@ -16,10 +16,10 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef HEADER_NODE_2D_HPP
|
#ifndef HEADER_DRIVE_NODE_2D_HPP
|
||||||
#define HEADER_NODE_2D_HPP
|
#define HEADER_DRIVE_NODE_2D_HPP
|
||||||
|
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "utils/cpp2011.hpp"
|
#include "utils/cpp2011.hpp"
|
||||||
|
|
||||||
#include <line2d.h>
|
#include <line2d.h>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
/**
|
/**
|
||||||
* \ingroup tracks
|
* \ingroup tracks
|
||||||
*/
|
*/
|
||||||
class Node2D : public GraphNode
|
class DriveNode2D : public DriveNode
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** The center point of the lower two points (e.g. points 0 and 1).
|
/** The center point of the lower two points (e.g. points 0 and 1).
|
||||||
@ -43,9 +43,9 @@ private:
|
|||||||
core::line2df m_line;
|
core::line2df m_line;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
DriveNode2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||||
bool ai_ignore);
|
bool ai_ignore);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void getDistances(const Vec3 &xyz, Vec3 *result) const OVERRIDE;
|
virtual void getDistances(const Vec3 &xyz, Vec3 *result) const OVERRIDE;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
@ -16,18 +16,20 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "tracks/node_3d.hpp"
|
#include "tracks/drive_node_3d.hpp"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
Node3D::Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
DriveNode3D::DriveNode3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
const Vec3 &p3, const Vec3 &normal,
|
||||||
bool ai_ignore)
|
unsigned int node_index, bool invisible,
|
||||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
bool ai_ignore)
|
||||||
|
: DriveNode(p0, p1, p2, p3, normal, node_index, invisible,
|
||||||
|
ai_ignore)
|
||||||
{
|
{
|
||||||
BoundingBox3D::init(p0, p1, p2, p3, normal);
|
BoundingBox3D::init(p0, p1, p2, p3, normal);
|
||||||
m_line = core::line3df(m_lower_center.toIrrVector(),
|
m_line = core::line3df(m_lower_center.toIrrVector(),
|
||||||
m_upper_center.toIrrVector());
|
m_upper_center.toIrrVector());
|
||||||
} // Node3D
|
} // DriveNode3D
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Returns the distance a point has from this node in forward and sidewards
|
/** Returns the distance a point has from this node in forward and sidewards
|
||||||
@ -38,7 +40,7 @@ Node3D::Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
|||||||
* \param result The X coordinate contains the sidewards distance, the
|
* \param result The X coordinate contains the sidewards distance, the
|
||||||
* Z coordinate the forward distance.
|
* Z coordinate the forward distance.
|
||||||
*/
|
*/
|
||||||
void Node3D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
void DriveNode3D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
||||||
{
|
{
|
||||||
core::vector3df xyz_irr = xyz.toIrrVector();
|
core::vector3df xyz_irr = xyz.toIrrVector();
|
||||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||||
@ -59,7 +61,7 @@ void Node3D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
|||||||
* which belongs to this node.
|
* which belongs to this node.
|
||||||
* \param xyz The point for which the distance to the line is computed.
|
* \param xyz The point for which the distance to the line is computed.
|
||||||
*/
|
*/
|
||||||
float Node3D::getDistance2FromPoint(const Vec3 &xyz) const
|
float DriveNode3D::getDistance2FromPoint(const Vec3 &xyz) const
|
||||||
{
|
{
|
||||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||||
return (closest-xyz.toIrrVector()).getLengthSQ();
|
return (closest-xyz.toIrrVector()).getLengthSQ();
|
@ -16,18 +16,18 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef HEADER_NODE_3D_HPP
|
#ifndef HEADER_DRIVE_NODE_3D_HPP
|
||||||
#define HEADER_NODE_3D_HPP
|
#define HEADER_DRIVE_NODE_3D_HPP
|
||||||
|
|
||||||
#include "tracks/bounding_box_3d.hpp"
|
#include "tracks/bounding_box_3d.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "utils/cpp2011.hpp"
|
#include "utils/cpp2011.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup tracks
|
* \ingroup tracks
|
||||||
*/
|
*/
|
||||||
class Node3D : public GraphNode,
|
class DriveNode3D : public DriveNode,
|
||||||
public BoundingBox3D
|
public BoundingBox3D
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** Line between lower and upper center, saves computation in
|
/** Line between lower and upper center, saves computation in
|
||||||
@ -36,9 +36,9 @@ private:
|
|||||||
core::line3df m_line;
|
core::line3df m_line;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
DriveNode3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||||
bool ai_ignore);
|
bool ai_ignore);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual bool pointInside(const Vec3& p,
|
virtual bool pointInside(const Vec3& p,
|
||||||
bool ignore_vertical = false) const OVERRIDE
|
bool ignore_vertical = false) const OVERRIDE
|
@ -30,8 +30,8 @@
|
|||||||
#include "graphics/rtts.hpp"
|
#include "graphics/rtts.hpp"
|
||||||
#include "modes/profile_world.hpp"
|
#include "modes/profile_world.hpp"
|
||||||
#include "tracks/arena_node_3d.hpp"
|
#include "tracks/arena_node_3d.hpp"
|
||||||
#include "tracks/node_2d.hpp"
|
#include "tracks/drive_node_2d.hpp"
|
||||||
#include "tracks/node_3d.hpp"
|
#include "tracks/drive_node_3d.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
const int Graph::UNKNOWN_SECTOR = -1;
|
const int Graph::UNKNOWN_SECTOR = -1;
|
||||||
@ -426,7 +426,7 @@ void Graph::createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
q = new Node3D(p0, p1, p2, p3, normal, node_index, invisible,
|
q = new DriveNode3D(p0, p1, p2, p3, normal, node_index, invisible,
|
||||||
ai_ignore);
|
ai_ignore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -440,7 +440,7 @@ void Graph::createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
q = new Node2D(p0, p1, p2, p3, normal, node_index, invisible,
|
q = new DriveNode2D(p0, p1, p2, p3, normal, node_index, invisible,
|
||||||
ai_ignore);
|
ai_ignore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,5 +614,3 @@ int Graph::findOutOfRoadSector(const Vec3& xyz, const int curr_sector,
|
|||||||
}
|
}
|
||||||
return min_sector;
|
return min_sector;
|
||||||
} // findOutOfRoadSector
|
} // findOutOfRoadSector
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
@ -40,8 +40,15 @@ class Quad;
|
|||||||
class RTT;
|
class RTT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \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. arena without navmesh). So
|
||||||
|
* get() returns NULL in this case, and this is tested where necessary.
|
||||||
|
* \ingroup tracks
|
||||||
|
*/
|
||||||
class Graph : public NoCopy
|
class Graph : public NoCopy
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -55,7 +62,8 @@ protected:
|
|||||||
Vec3 m_bb_max;
|
Vec3 m_bb_max;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Factory method to dynamic create 2d / 3d quad. */
|
/** Factory method to dynamic create 2d / 3d quad for drive and arena
|
||||||
|
* graph. */
|
||||||
void createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
void createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||||
const Vec3 &p3, unsigned int node_index,
|
const Vec3 &p3, unsigned int node_index,
|
||||||
bool invisible, bool ai_ignore, bool is_arena);
|
bool invisible, bool ai_ignore, bool is_arena);
|
||||||
@ -90,11 +98,11 @@ public:
|
|||||||
static const int UNKNOWN_SECTOR;
|
static const int UNKNOWN_SECTOR;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the one instance of this object. It is possible that there
|
/** Returns the one instance of this object. It is possible that there
|
||||||
* is no instance created (e.g. battle mode without navmesh) so we don't
|
* is no instance created (e.g. arena without navmesh) so we don't assert
|
||||||
* assert that an instance exist. */
|
* that an instance exist. */
|
||||||
static Graph* get() { return m_graph; }
|
static Graph* get() { return m_graph; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Set the graph (either driveline or arena graph for now). */
|
/** Set the graph (either drive or arena graph for now). */
|
||||||
static void setGraph(Graph* graph)
|
static void setGraph(Graph* graph)
|
||||||
{
|
{
|
||||||
assert(m_graph == NULL);
|
assert(m_graph == NULL);
|
||||||
@ -102,8 +110,8 @@ public:
|
|||||||
} // create
|
} // create
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Cleans up the graph. It is possible that this function is called even
|
/** Cleans up the graph. It is possible that this function is called even
|
||||||
* if no instance exists (e.g. in battle mode without navmesh). So it is
|
* if no instance exists (e.g. arena without navmesh). So it is not an
|
||||||
* not an error if there is no instance. */
|
* error if there is no instance. */
|
||||||
static void destroy()
|
static void destroy()
|
||||||
{
|
{
|
||||||
if (m_graph)
|
if (m_graph)
|
||||||
|
@ -1,386 +0,0 @@
|
|||||||
//
|
|
||||||
// SuperTuxKart - a fun racing game with go-kart
|
|
||||||
// Copyright (C) 2015 SuperTuxKart Team
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 3
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#include "tracks/graph_structure.hpp"
|
|
||||||
|
|
||||||
#include <ICameraSceneNode.h>
|
|
||||||
#include <IMesh.h>
|
|
||||||
#include <IMeshSceneNode.h>
|
|
||||||
#include <ISceneManager.h>
|
|
||||||
|
|
||||||
#include "graphics/irr_driver.hpp"
|
|
||||||
#include "graphics/glwrap.hpp"
|
|
||||||
#include "graphics/shaders.hpp"
|
|
||||||
#include "graphics/rtts.hpp"
|
|
||||||
#include "modes/world.hpp"
|
|
||||||
#include "modes/profile_world.hpp"
|
|
||||||
#include "utils/log.hpp"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
GraphStructure::GraphStructure()
|
|
||||||
{
|
|
||||||
m_min_coord = 0;
|
|
||||||
m_scaling = 0;
|
|
||||||
m_node = NULL;
|
|
||||||
m_mesh = NULL;
|
|
||||||
m_mesh_buffer = NULL;
|
|
||||||
m_new_rtt = NULL;
|
|
||||||
} // GraphStructure
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void GraphStructure::destroyRTT()
|
|
||||||
{
|
|
||||||
if (m_new_rtt != NULL)
|
|
||||||
{
|
|
||||||
delete m_new_rtt;
|
|
||||||
m_new_rtt = NULL;
|
|
||||||
}
|
|
||||||
} // destroyRTT
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Cleans up the debug mesh */
|
|
||||||
void GraphStructure::cleanupDebugMesh()
|
|
||||||
{
|
|
||||||
if (m_node != NULL)
|
|
||||||
irr_driver->removeNode(m_node);
|
|
||||||
|
|
||||||
m_node = NULL;
|
|
||||||
// No need to call irr_driber->removeMeshFromCache, since the mesh
|
|
||||||
// was manually made and so never added to the mesh cache.
|
|
||||||
m_mesh->drop();
|
|
||||||
m_mesh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Creates the debug mesh to display the graph on top of the track
|
|
||||||
* model. */
|
|
||||||
void GraphStructure::createDebugMesh()
|
|
||||||
{
|
|
||||||
if (getNumNodes() <= 0) return; // no debug output if not graph
|
|
||||||
|
|
||||||
createMesh(/*show_invisible*/true,
|
|
||||||
/*enable_transparency*/true);
|
|
||||||
|
|
||||||
video::S3DVertex *v = (video::S3DVertex*)m_mesh_buffer->getVertices();
|
|
||||||
for (unsigned int i = 0; i < m_mesh_buffer->getVertexCount(); i++)
|
|
||||||
{
|
|
||||||
// Swap the alpha and back
|
|
||||||
v[i].Color.setAlpha((i%2) ? 64 : 255);
|
|
||||||
}
|
|
||||||
m_node = irr_driver->addMesh(m_mesh, "track-debug-mesh");
|
|
||||||
#ifdef DEBUG
|
|
||||||
m_node->setName("track-debug-mesh");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // createDebugMesh
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */
|
|
||||||
void GraphStructure::createMesh(bool show_invisible,
|
|
||||||
bool enable_transparency,
|
|
||||||
const video::SColor *track_color)
|
|
||||||
{
|
|
||||||
// The debug track will not be lighted or culled.
|
|
||||||
video::SMaterial m;
|
|
||||||
m.BackfaceCulling = false;
|
|
||||||
m.Lighting = false;
|
|
||||||
if (enable_transparency)
|
|
||||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
||||||
m.setTexture(0, getUnicolorTexture(video::SColor(255, 255, 255, 255)));
|
|
||||||
m.setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
|
||||||
m.setTexture(7, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
|
||||||
m_mesh = irr_driver->createQuadMesh(&m);
|
|
||||||
m_mesh_buffer = m_mesh->getMeshBuffer(0);
|
|
||||||
assert(m_mesh_buffer->getVertexType()==video::EVT_STANDARD);
|
|
||||||
|
|
||||||
unsigned int n = 0;
|
|
||||||
const unsigned int total_nodes = getNumNodes();
|
|
||||||
|
|
||||||
// Count the number of quads to display (some quads might be invisible)
|
|
||||||
for (unsigned int i = 0; i < total_nodes; i++)
|
|
||||||
{
|
|
||||||
if (show_invisible || !isNodeInvisible(i))
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Four vertices for each of the n-1 remaining quads
|
|
||||||
video::S3DVertex *new_v = new video::S3DVertex[4*n];
|
|
||||||
// Each quad consists of 2 triangles with 3 elements, so
|
|
||||||
// we need 2*3 indices for each quad.
|
|
||||||
irr::u16 *ind = new irr::u16[6*n];
|
|
||||||
video::SColor c(255, 255, 0, 0);
|
|
||||||
|
|
||||||
if (track_color)
|
|
||||||
c = *track_color;
|
|
||||||
|
|
||||||
// Now add all quads
|
|
||||||
int i = 0;
|
|
||||||
for (unsigned int count = 0; count < total_nodes; count++)
|
|
||||||
{
|
|
||||||
// Ignore invisible quads
|
|
||||||
if (!show_invisible && isNodeInvisible(count))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Swap the colours from red to blue and back
|
|
||||||
if (!track_color)
|
|
||||||
{
|
|
||||||
c.setRed ((i%2) ? 255 : 0);
|
|
||||||
c.setBlue((i%2) ? 0 : 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeColor nc = COLOR_RED;
|
|
||||||
const bool different_color = differentNodeColor(count, &nc);
|
|
||||||
// Transfer the 4 points of the current quad to the list of vertices
|
|
||||||
set3DVerticesOfGraph(count, new_v+4*i, (different_color ?
|
|
||||||
(nc == COLOR_RED ? video::SColor(255, 255, 0, 0) :
|
|
||||||
nc == COLOR_GREEN ? video::SColor(255, 0, 255, 0) :
|
|
||||||
nc == COLOR_BLUE ? video::SColor(255, 0, 0, 255) :
|
|
||||||
video::SColor(255, 255, 255, 0)) : c));
|
|
||||||
|
|
||||||
// Set up the indices for the triangles
|
|
||||||
// (note, afaik with opengl we could use quads directly, but the code
|
|
||||||
// would not be portable to directx anymore).
|
|
||||||
ind[6*i ] = 4*i+2; // First triangle: vertex 0, 1, 2
|
|
||||||
ind[6*i+1] = 4*i+1;
|
|
||||||
ind[6*i+2] = 4*i;
|
|
||||||
ind[6*i+3] = 4*i+3; // second triangle: vertex 0, 1, 3
|
|
||||||
ind[6*i+4] = 4*i+2;
|
|
||||||
ind[6*i+5] = 4*i;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_mesh_buffer->append(new_v, n*4, ind, n*6);
|
|
||||||
|
|
||||||
if (0)
|
|
||||||
{
|
|
||||||
video::S3DVertex lap_v[4];
|
|
||||||
irr::u16 lap_ind[6];
|
|
||||||
video::SColor lap_color(128, 255, 0, 0);
|
|
||||||
set3DVerticesOfGraph(0, lap_v, lap_color);
|
|
||||||
|
|
||||||
// Now scale the length (distance between vertix 0 and 3
|
|
||||||
// and between 1 and 2) to be 'length':
|
|
||||||
Vec3 bb_min, bb_max;
|
|
||||||
getGraphBoundingBox(&bb_min, &bb_max);
|
|
||||||
// Length of the lap line about 3% of the 'height'
|
|
||||||
// of the track.
|
|
||||||
const float length = (bb_max.getZ()-bb_min.getZ())*0.03f;
|
|
||||||
|
|
||||||
core::vector3df dl = lap_v[3].Pos-lap_v[0].Pos;
|
|
||||||
float ll2 = dl.getLengthSQ();
|
|
||||||
if (ll2 < 0.001)
|
|
||||||
lap_v[3].Pos = lap_v[0].Pos+core::vector3df(0, 0, 1);
|
|
||||||
else
|
|
||||||
lap_v[3].Pos = lap_v[0].Pos+dl*length/sqrt(ll2);
|
|
||||||
|
|
||||||
core::vector3df dr = lap_v[2].Pos-lap_v[1].Pos;
|
|
||||||
float lr2 = dr.getLengthSQ();
|
|
||||||
if (lr2 < 0.001)
|
|
||||||
lap_v[2].Pos = lap_v[1].Pos+core::vector3df(0, 0, 1);
|
|
||||||
else
|
|
||||||
lap_v[2].Pos = lap_v[1].Pos+dr*length/sqrt(lr2);
|
|
||||||
lap_ind[0] = 2;
|
|
||||||
lap_ind[1] = 1;
|
|
||||||
lap_ind[2] = 0;
|
|
||||||
lap_ind[3] = 3;
|
|
||||||
lap_ind[4] = 2;
|
|
||||||
lap_ind[5] = 0;
|
|
||||||
// Set it a bit higher to avoid issued with z fighting,
|
|
||||||
// i.e. part of the lap line might not be visible.
|
|
||||||
for (unsigned int i = 0; i < 4; i++)
|
|
||||||
lap_v[i].Pos.Y += 0.1f;
|
|
||||||
#ifndef USE_TEXTURED_LINE
|
|
||||||
m_mesh_buffer->append(lap_v, 4, lap_ind, 6);
|
|
||||||
#else
|
|
||||||
lap_v[0].TCoords = core::vector2df(0,0);
|
|
||||||
lap_v[1].TCoords = core::vector2df(3,0);
|
|
||||||
lap_v[2].TCoords = core::vector2df(3,1);
|
|
||||||
lap_v[3].TCoords = core::vector2df(0,1);
|
|
||||||
m_mesh_buffer->append(lap_v, 4, lap_ind, 6);
|
|
||||||
video::SMaterial &m = m_mesh_buffer->getMaterial();
|
|
||||||
video::ITexture *t = irr_driver->getTexture("chess.png");
|
|
||||||
m.setTexture(0, t);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instead of setting the bounding boxes, we could just disable culling,
|
|
||||||
// since the debug track should always be drawn.
|
|
||||||
//m_node->setAutomaticCulling(scene::EAC_OFF);
|
|
||||||
m_mesh_buffer->recalculateBoundingBox();
|
|
||||||
m_mesh->setBoundingBox(m_mesh_buffer->getBoundingBox());
|
|
||||||
|
|
||||||
m_mesh_buffer->getMaterial().setTexture(0, irr_driver->getTexture("unlit.png"));
|
|
||||||
|
|
||||||
delete[] ind;
|
|
||||||
delete[] new_v;
|
|
||||||
} // createMesh
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Takes a snapshot of the graph so they can be used as minimap.
|
|
||||||
*/
|
|
||||||
void GraphStructure::makeMiniMap(const core::dimension2du &dimension,
|
|
||||||
const std::string &name,
|
|
||||||
const video::SColor &fill_color,
|
|
||||||
video::ITexture** oldRttMinimap,
|
|
||||||
FrameBuffer** newRttMinimap)
|
|
||||||
{
|
|
||||||
// Skip minimap when profiling
|
|
||||||
if (ProfileWorld::isNoGraphics()) return;
|
|
||||||
|
|
||||||
const video::SColor oldClearColor = World::getWorld()->getClearColor();
|
|
||||||
World::getWorld()->setClearbackBufferColor(video::SColor(0, 255, 255, 255));
|
|
||||||
World::getWorld()->forceFogDisabled(true);
|
|
||||||
*oldRttMinimap = NULL;
|
|
||||||
*newRttMinimap = NULL;
|
|
||||||
|
|
||||||
RTT* newRttProvider = NULL;
|
|
||||||
IrrDriver::RTTProvider* oldRttProvider = NULL;
|
|
||||||
if (CVS->isGLSL())
|
|
||||||
{
|
|
||||||
m_new_rtt = newRttProvider = new RTT(dimension.Width, dimension.Height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oldRttProvider = new IrrDriver::RTTProvider(dimension, name, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 255, 255, 255));
|
|
||||||
|
|
||||||
createMesh(/*show_invisible part of the track*/ false,
|
|
||||||
/*enable_transparency*/ false,
|
|
||||||
/*track_color*/ &fill_color);
|
|
||||||
|
|
||||||
m_node = irr_driver->addMesh(m_mesh, "mini_map");
|
|
||||||
#ifdef DEBUG
|
|
||||||
m_node->setName("minimap-mesh");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_node->setAutomaticCulling(0);
|
|
||||||
m_node->setMaterialFlag(video::EMF_LIGHTING, false);
|
|
||||||
|
|
||||||
// Add the camera:
|
|
||||||
// ---------------
|
|
||||||
scene::ICameraSceneNode *camera = irr_driver->addCameraSceneNode();
|
|
||||||
Vec3 bb_min, bb_max;
|
|
||||||
getGraphBoundingBox(&bb_min, &bb_max);
|
|
||||||
Vec3 center = (bb_max+bb_min)*0.5f;
|
|
||||||
|
|
||||||
float dx = bb_max.getX()-bb_min.getX();
|
|
||||||
float dz = bb_max.getZ()-bb_min.getZ();
|
|
||||||
|
|
||||||
// Set the scaling correctly. Also the center point (which is used
|
|
||||||
// as the camera position) needs to be adjusted: the track must
|
|
||||||
// be aligned to the left/top of the texture which is used (otherwise
|
|
||||||
// mapPoint2MiniMap doesn't work), so adjust the camera position
|
|
||||||
// that the track is properly aligned (view from the side):
|
|
||||||
// c camera
|
|
||||||
// / \ .
|
|
||||||
// / \ <--- camera angle
|
|
||||||
// / \ .
|
|
||||||
// { [-] } <--- track flat (viewed from the side)
|
|
||||||
// If [-] is the shorter side of the track, then the camera will
|
|
||||||
// actually render the area in { } - which is the length of the
|
|
||||||
// longer side of the track.
|
|
||||||
// To align the [-] side to the left, the camera must be moved
|
|
||||||
// the distance betwwen '{' and '[' to the right. This distance
|
|
||||||
// is exacly (longer_side - shorter_side) / 2.
|
|
||||||
// So, adjust the center point by this amount:
|
|
||||||
if (dz > dx)
|
|
||||||
{
|
|
||||||
center.setX(center.getX() + (dz-dx)*0.5f);
|
|
||||||
m_scaling = dimension.Width / dz;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
center.setZ(center.getZ() + (dx-dz)*0.5f);
|
|
||||||
m_scaling = dimension.Width / dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
float range = (dx>dz) ? dx : dz;
|
|
||||||
|
|
||||||
core::matrix4 projection;
|
|
||||||
projection.buildProjectionMatrixOrthoLH(range /* width */,
|
|
||||||
range /* height */,
|
|
||||||
-1, bb_max.getY()-bb_min.getY()+1);
|
|
||||||
camera->setProjectionMatrix(projection, true);
|
|
||||||
|
|
||||||
irr_driver->suppressSkyBox();
|
|
||||||
irr_driver->clearLights();
|
|
||||||
|
|
||||||
// Adjust Y position by +1 for max, -1 for min - this helps in case that
|
|
||||||
// the maximum Y coordinate is negative (otherwise the minimap is mirrored)
|
|
||||||
// and avoids problems for tracks which have a flat (max Y = min Y) minimap.
|
|
||||||
camera->setPosition(core::vector3df(center.getX(), bb_min.getY() + 1.0f, center.getZ()));
|
|
||||||
//camera->setPosition(core::vector3df(center.getX() - 5.0f, bb_min.getY() - 1 - 5.0f, center.getZ() - 15.0f));
|
|
||||||
camera->setUpVector(core::vector3df(0, 0, 1));
|
|
||||||
camera->setTarget(core::vector3df(center.getX(),bb_min.getY()-1,center.getZ()));
|
|
||||||
//camera->setAspectRatio(1.0f);
|
|
||||||
camera->updateAbsolutePosition();
|
|
||||||
|
|
||||||
video::ITexture* texture = NULL;
|
|
||||||
FrameBuffer* frame_buffer = NULL;
|
|
||||||
|
|
||||||
if (CVS->isGLSL())
|
|
||||||
{
|
|
||||||
frame_buffer = newRttProvider->render(camera, GUIEngine::getLatestDt());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
texture = oldRttProvider->renderToTexture();
|
|
||||||
delete oldRttProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupDebugMesh();
|
|
||||||
irr_driver->removeCameraSceneNode(camera);
|
|
||||||
m_min_coord = bb_min;
|
|
||||||
|
|
||||||
|
|
||||||
if (texture == NULL && frame_buffer == NULL)
|
|
||||||
{
|
|
||||||
Log::error("Graph Structure", "[makeMiniMap] WARNING: RTT does not"
|
|
||||||
"appear to work, mini-map will not be available.");
|
|
||||||
}
|
|
||||||
|
|
||||||
*oldRttMinimap = texture;
|
|
||||||
*newRttMinimap = frame_buffer;
|
|
||||||
World::getWorld()->setClearbackBufferColor(oldClearColor);
|
|
||||||
World::getWorld()->forceFogDisabled(false);
|
|
||||||
|
|
||||||
irr_driver->getSceneManager()->clear();
|
|
||||||
VAOManager::kill();
|
|
||||||
irr_driver->clearGlowingNodes();
|
|
||||||
irr_driver->clearLights();
|
|
||||||
irr_driver->clearForcedBloom();
|
|
||||||
irr_driver->clearBackgroundNodes();
|
|
||||||
} // makeMiniMap
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Returns the 2d coordinates of a point when drawn on the mini map
|
|
||||||
* texture.
|
|
||||||
* \param xyz Coordinates of the point to map.
|
|
||||||
* \param draw_at The coordinates in pixel on the mini map of the point,
|
|
||||||
* only the first two coordinates will be used.
|
|
||||||
*/
|
|
||||||
void GraphStructure::mapPoint2MiniMap(const Vec3 &xyz,Vec3 *draw_at) const
|
|
||||||
{
|
|
||||||
draw_at->setX((xyz.getX()-m_min_coord.getX())*m_scaling);
|
|
||||||
draw_at->setY((xyz.getZ()-m_min_coord.getZ())*m_scaling);
|
|
||||||
|
|
||||||
} // mapPoint
|
|
@ -1,104 +0,0 @@
|
|||||||
//
|
|
||||||
// SuperTuxKart - a fun racing game with go-kart
|
|
||||||
// Copyright (C) 2015 SuperTuxKart Team
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 3
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#ifndef HEADER_GRAPH_STRUCTURE_HPP
|
|
||||||
#define HEADER_GRAPH_STRUCTURE_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <dimension2d.h>
|
|
||||||
#include <SColor.h>
|
|
||||||
#include "utils/vec3.hpp"
|
|
||||||
#include "utils/no_copy.hpp"
|
|
||||||
|
|
||||||
namespace irr
|
|
||||||
{
|
|
||||||
namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; }
|
|
||||||
namespace video { class ITexture; struct S3DVertex; }
|
|
||||||
}
|
|
||||||
using namespace irr;
|
|
||||||
|
|
||||||
class FrameBuffer;
|
|
||||||
class RTT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Virtual base class for a graph structure.
|
|
||||||
* This is mainly used for drawing minimap in game.
|
|
||||||
*
|
|
||||||
* \ingroup tracks
|
|
||||||
*/
|
|
||||||
class GraphStructure : public NoCopy
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/** Used by soccer field with navmesh to draw goal line,
|
|
||||||
* or to determine 2d/3d nodes in driveline graph. */
|
|
||||||
enum NodeColor
|
|
||||||
{
|
|
||||||
COLOR_BLUE,
|
|
||||||
COLOR_GREEN,
|
|
||||||
COLOR_RED,
|
|
||||||
COLOR_YELLOW
|
|
||||||
};
|
|
||||||
|
|
||||||
void cleanupDebugMesh();
|
|
||||||
void destroyRTT();
|
|
||||||
|
|
||||||
private:
|
|
||||||
RTT* m_new_rtt;
|
|
||||||
|
|
||||||
/** The node of the graph mesh. */
|
|
||||||
scene::ISceneNode *m_node;
|
|
||||||
|
|
||||||
/** The mesh of the graph mesh. */
|
|
||||||
scene::IMesh *m_mesh;
|
|
||||||
|
|
||||||
/** The actual mesh buffer storing the graph. */
|
|
||||||
scene::IMeshBuffer *m_mesh_buffer;
|
|
||||||
|
|
||||||
/** The minimum coordinates of the graph. */
|
|
||||||
Vec3 m_min_coord;
|
|
||||||
|
|
||||||
/** Scaling for mini map. */
|
|
||||||
float m_scaling;
|
|
||||||
|
|
||||||
void createMesh(bool show_invisible=true,
|
|
||||||
bool enable_transparency=false,
|
|
||||||
const video::SColor *track_color=NULL);
|
|
||||||
|
|
||||||
virtual void set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
|
||||||
const video::SColor &color) const = 0;
|
|
||||||
virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const = 0;
|
|
||||||
virtual const bool isNodeInvisible(int n) const = 0;
|
|
||||||
virtual const bool hasLapLine() const = 0;
|
|
||||||
virtual const bool differentNodeColor(int n, NodeColor* c) const = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GraphStructure();
|
|
||||||
virtual ~GraphStructure() {};
|
|
||||||
void createDebugMesh();
|
|
||||||
void makeMiniMap(const core::dimension2du &where,
|
|
||||||
const std::string &name,
|
|
||||||
const video::SColor &fill_color,
|
|
||||||
video::ITexture** oldRttMinimap,
|
|
||||||
FrameBuffer** newRttMinimap);
|
|
||||||
void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const;
|
|
||||||
virtual const unsigned int getNumNodes() const = 0;
|
|
||||||
}; // GraphStructure
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,182 +0,0 @@
|
|||||||
//
|
|
||||||
// SuperTuxKart - a fun racing game with go-kart
|
|
||||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 3
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
|
||||||
|
|
||||||
#ifndef HEADER_QUAD_GRAPH_HPP
|
|
||||||
#define HEADER_QUAD_GRAPH_HPP
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "tracks/graph_structure.hpp"
|
|
||||||
#include "utils/aligned_array.hpp"
|
|
||||||
|
|
||||||
#include "LinearMath/btTransform.h"
|
|
||||||
|
|
||||||
class GraphNode;
|
|
||||||
class XMLNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \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 GraphStructure
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
static QuadGraph *m_quad_graph;
|
|
||||||
|
|
||||||
/** The 2d bounding box, used for hashing. */
|
|
||||||
Vec3 m_min;
|
|
||||||
Vec3 m_max;
|
|
||||||
|
|
||||||
/** The actual graph data structure. */
|
|
||||||
std::vector<GraphNode*> m_all_nodes;
|
|
||||||
|
|
||||||
/** The length of the first loop. */
|
|
||||||
float m_lap_length;
|
|
||||||
|
|
||||||
/** Stores the filename - just used for error messages. */
|
|
||||||
std::string m_quad_filename;
|
|
||||||
|
|
||||||
/** Wether the graph should be reverted or not */
|
|
||||||
bool m_reverse;
|
|
||||||
|
|
||||||
void setDefaultSuccessors();
|
|
||||||
void computeChecklineRequirements(GraphNode* node, int latest_checkline);
|
|
||||||
void computeDirectionData();
|
|
||||||
void determineDirection(unsigned int current, unsigned int succ_index);
|
|
||||||
float normalizeAngle(float f);
|
|
||||||
|
|
||||||
void addSuccessor(unsigned int from, unsigned int to);
|
|
||||||
void load(const std::string &quad_file_name, const std::string &filename);
|
|
||||||
void getPoint(const XMLNode *xml, const std::string &attribute_name,
|
|
||||||
Vec3 *result) const;
|
|
||||||
void computeDistanceFromStart(unsigned int start_node, float distance);
|
|
||||||
unsigned int getStartNode() const;
|
|
||||||
QuadGraph(const std::string &quad_file_name,
|
|
||||||
const std::string &graph_file_name,
|
|
||||||
const bool reverse);
|
|
||||||
~QuadGraph();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
|
||||||
const video::SColor &color) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const
|
|
||||||
{ *min = m_min; *max = m_max; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual const bool isNodeInvisible(int n) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual const bool hasLapLine() const
|
|
||||||
{ return true; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual const bool differentNodeColor(int n, NodeColor* c) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const int UNKNOWN_SECTOR;
|
|
||||||
|
|
||||||
void getSuccessors(int node_number,
|
|
||||||
std::vector<unsigned int>& succ,
|
|
||||||
bool for_ai=false) const;
|
|
||||||
void spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
|
||||||
const int sector) const;
|
|
||||||
void findRoadSector(const Vec3& XYZ, int *sector,
|
|
||||||
std::vector<int> *all_sectors=NULL) const;
|
|
||||||
int findOutOfRoadSector(const Vec3& xyz,
|
|
||||||
const int curr_sector=UNKNOWN_SECTOR,
|
|
||||||
std::vector<int> *all_sectors=NULL
|
|
||||||
) const;
|
|
||||||
void setDefaultStartPositions(AlignedArray<btTransform>
|
|
||||||
*start_transforms,
|
|
||||||
unsigned int karts_per_row,
|
|
||||||
float forwards_distance=1.5f,
|
|
||||||
float sidewards_distance=1.5f,
|
|
||||||
float upwards_distance=0.0f) const;
|
|
||||||
void updateDistancesForAllSuccessors(unsigned int indx,
|
|
||||||
float delta,
|
|
||||||
unsigned int count);
|
|
||||||
void setupPaths();
|
|
||||||
void computeChecklineRequirements();
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** 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,
|
|
||||||
const bool reverse)
|
|
||||||
{
|
|
||||||
assert(m_quad_graph==NULL);
|
|
||||||
// assignment to m_quad_graph is done in the constructor, since
|
|
||||||
// functions called from the constructor need it to be defined.
|
|
||||||
new QuadGraph(quad_file_name, graph_file_name, reverse);
|
|
||||||
} // 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. */
|
|
||||||
virtual const unsigned int getNumNodes() const
|
|
||||||
{ return m_all_nodes.size(); }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Return the distance to the j-th successor of node n. */
|
|
||||||
float getDistanceToNext(int n, int j) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the angle of the line between node n and its j-th.
|
|
||||||
* successor. */
|
|
||||||
float getAngleToNext(int n, int j) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the number of successors of a node n. */
|
|
||||||
int getNumberOfSuccessors(int n) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the quad that belongs to a graph node. */
|
|
||||||
GraphNode* getNode(unsigned int j) { return m_all_nodes[j]; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the quad that belongs to a graph node (const version). */
|
|
||||||
const GraphNode* getNode(unsigned int j) const { return m_all_nodes[j]; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the distance from the start to the beginning of a quad. */
|
|
||||||
float getDistanceFromStart(int j) const;
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Returns the length of the main driveline. */
|
|
||||||
float getLapLength() const { return m_lap_length; }
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
bool isReverse() const { return m_reverse; }
|
|
||||||
|
|
||||||
}; // QuadGraph
|
|
||||||
|
|
||||||
#endif
|
|
@ -56,9 +56,9 @@
|
|||||||
#include "tracks/arena_graph.hpp"
|
#include "tracks/arena_graph.hpp"
|
||||||
#include "tracks/bezier_curve.hpp"
|
#include "tracks/bezier_curve.hpp"
|
||||||
#include "tracks/check_manager.hpp"
|
#include "tracks/check_manager.hpp"
|
||||||
|
#include "tracks/drive_graph.hpp"
|
||||||
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/model_definition_loader.hpp"
|
#include "tracks/model_definition_loader.hpp"
|
||||||
#include "tracks/node_3d.hpp"
|
|
||||||
#include "tracks/quad_graph.hpp"
|
|
||||||
#include "tracks/track_manager.hpp"
|
#include "tracks/track_manager.hpp"
|
||||||
#include "tracks/track_object_manager.hpp"
|
#include "tracks/track_object_manager.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
@ -277,7 +277,6 @@ void Track::reset()
|
|||||||
*/
|
*/
|
||||||
void Track::cleanup()
|
void Track::cleanup()
|
||||||
{
|
{
|
||||||
QuadGraph::destroy();
|
|
||||||
Graph::destroy();
|
Graph::destroy();
|
||||||
ItemManager::destroy();
|
ItemManager::destroy();
|
||||||
VAOManager::kill();
|
VAOManager::kill();
|
||||||
@ -374,7 +373,7 @@ void Track::cleanup()
|
|||||||
}
|
}
|
||||||
if (m_new_rtt_mini_map)
|
if (m_new_rtt_mini_map)
|
||||||
{
|
{
|
||||||
m_new_rtt_mini_map = NULL; // already deleted by QuadGraph::~QuadGraph
|
m_new_rtt_mini_map = NULL; // already deleted by Graph::~Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i=0; i<m_sky_textures.size(); i++)
|
for(unsigned int i=0; i<m_sky_textures.size(); i++)
|
||||||
@ -715,24 +714,25 @@ btQuaternion Track::getArenaStartRotation(const Vec3& xyz, float heading)
|
|||||||
} // getArenaStartRotation
|
} // getArenaStartRotation
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Loads the quad graph, i.e. the definition of all quads, and the way
|
/** Loads the drive graph, i.e. the definition of all quads, and the way
|
||||||
* they are connected to each other.
|
* they are connected to each other.
|
||||||
*/
|
*/
|
||||||
void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
void Track::loadDriveGraph(unsigned int mode_id, const bool reverse)
|
||||||
{
|
{
|
||||||
QuadGraph::create(m_root+m_all_modes[mode_id].m_quad_name,
|
new DriveGraph(m_root+m_all_modes[mode_id].m_quad_name,
|
||||||
m_root+m_all_modes[mode_id].m_graph_name,
|
m_root+m_all_modes[mode_id].m_graph_name, reverse);
|
||||||
reverse);
|
|
||||||
|
|
||||||
QuadGraph::get()->setupPaths();
|
// setGraph is done in DriveGraph constructor
|
||||||
|
assert(DriveGraph::get());
|
||||||
|
DriveGraph::get()->setupPaths();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
assert(QuadGraph::get()->getNode(i)->getPredecessor(0)!=-1);
|
assert(DriveGraph::get()->getNode(i)->getPredecessor(0)!=-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(QuadGraph::get()->getNumNodes()==0)
|
if(DriveGraph::get()->getNumNodes()==0)
|
||||||
{
|
{
|
||||||
Log::warn("track", "No graph nodes defined for track '%s'\n",
|
Log::warn("track", "No graph nodes defined for track '%s'\n",
|
||||||
m_filename.c_str());
|
m_filename.c_str());
|
||||||
@ -746,16 +746,13 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
|||||||
{
|
{
|
||||||
loadMinimap();
|
loadMinimap();
|
||||||
}
|
}
|
||||||
} // loadQuadGraph
|
} // loadDriveGraph
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const
|
void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const
|
||||||
{
|
{
|
||||||
if ((m_is_arena || m_is_soccer) && m_has_navmesh)
|
Graph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||||
Graph::get()->mapPoint2MiniMap(xyz, draw_at);
|
|
||||||
else
|
|
||||||
QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
|
||||||
draw_at->setX(draw_at->getX() * m_minimap_x_scale);
|
draw_at->setX(draw_at->getX() * m_minimap_x_scale);
|
||||||
draw_at->setY(draw_at->getY() * m_minimap_y_scale);
|
draw_at->setY(draw_at->getY() * m_minimap_y_scale);
|
||||||
}
|
}
|
||||||
@ -1058,16 +1055,8 @@ void Track::loadMinimap()
|
|||||||
core::dimension2du size = m_mini_map_size
|
core::dimension2du size = m_mini_map_size
|
||||||
.getOptimalSize(!nonpower,!nonsquare);
|
.getOptimalSize(!nonpower,!nonsquare);
|
||||||
|
|
||||||
if ((m_is_arena || m_is_soccer) && m_has_navmesh)
|
Graph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255),
|
||||||
{
|
&m_old_rtt_mini_map, &m_new_rtt_mini_map);
|
||||||
Graph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255),
|
|
||||||
&m_old_rtt_mini_map, &m_new_rtt_mini_map);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QuadGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255),
|
|
||||||
&m_old_rtt_mini_map, &m_new_rtt_mini_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_old_rtt_mini_map)
|
if (m_old_rtt_mini_map)
|
||||||
{
|
{
|
||||||
@ -1686,7 +1675,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
|||||||
// the race gui was created. The race gui is needed since it stores
|
// the race gui was created. The race gui is needed since it stores
|
||||||
// the information about the size of the texture to render the mini
|
// the information about the size of the texture to render the mini
|
||||||
// map to.
|
// map to.
|
||||||
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadDriveGraph(mode_id, reverse_track);
|
||||||
else if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh)
|
else if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh)
|
||||||
loadArenaGraph(*root);
|
loadArenaGraph(*root);
|
||||||
|
|
||||||
@ -1718,7 +1707,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_start_transforms.resize(race_manager->getNumberOfKarts());
|
m_start_transforms.resize(race_manager->getNumberOfKarts());
|
||||||
QuadGraph::get()->setDefaultStartPositions(&m_start_transforms,
|
DriveGraph::get()->setDefaultStartPositions(&m_start_transforms,
|
||||||
karts_per_row,
|
karts_per_row,
|
||||||
forwards_distance,
|
forwards_distance,
|
||||||
sidewards_distance,
|
sidewards_distance,
|
||||||
@ -1929,7 +1918,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
|||||||
World *world = World::getWorld();
|
World *world = World::getWorld();
|
||||||
if (world->useChecklineRequirements())
|
if (world->useChecklineRequirements())
|
||||||
{
|
{
|
||||||
QuadGraph::get()->computeChecklineRequirements();
|
DriveGraph::get()->computeChecklineRequirements();
|
||||||
}
|
}
|
||||||
|
|
||||||
EasterEggHunt *easter_world = dynamic_cast<EasterEggHunt*>(world);
|
EasterEggHunt *easter_world = dynamic_cast<EasterEggHunt*>(world);
|
||||||
@ -2282,30 +2271,26 @@ void Track::itemCommand(const XMLNode *node)
|
|||||||
// Test if the item lies on a 3d node, if so adjust the normal
|
// Test if the item lies on a 3d node, if so adjust the normal
|
||||||
// Also do a raycast if drop item is given
|
// Also do a raycast if drop item is given
|
||||||
Vec3 normal(0, 1, 0);
|
Vec3 normal(0, 1, 0);
|
||||||
|
Vec3 quad_normal = normal;
|
||||||
Vec3 hit_point = loc;
|
Vec3 hit_point = loc;
|
||||||
Node3D* node_3d = NULL;
|
if (Graph::get())
|
||||||
if (QuadGraph::get())
|
|
||||||
{
|
{
|
||||||
int road_sector = QuadGraph::UNKNOWN_SECTOR;
|
int road_sector = Graph::UNKNOWN_SECTOR;
|
||||||
QuadGraph::get()->findRoadSector(xyz, &road_sector);
|
Graph::get()->findRoadSector(xyz, &road_sector);
|
||||||
// Only do custom direction of raycast if item is on quad graph
|
// Only do custom direction of raycast if item is on quad graph
|
||||||
if (road_sector != QuadGraph::UNKNOWN_SECTOR)
|
if (road_sector != Graph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
node_3d =
|
quad_normal = Graph::get()->getQuad(road_sector)->getNormal();
|
||||||
dynamic_cast<Node3D*>(QuadGraph::get()->getNode(road_sector));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 quad_normal = node_3d ? node_3d->getNormal() : Vec3(0, 1, 0);
|
if (drop)
|
||||||
if (node_3d || drop)
|
|
||||||
{
|
{
|
||||||
const Material *m;
|
const Material *m;
|
||||||
// If raycast is used, increase the start position slightly
|
// If raycast is used, increase the start position slightly
|
||||||
// in case that the point is too close to the actual surface
|
// in case that the point is too close to the actual surface
|
||||||
// (e.g. floating point errors can cause a problem here).
|
// (e.g. floating point errors can cause a problem here).
|
||||||
// Only do so for 2d node
|
loc += quad_normal * 0.1;
|
||||||
if (node_3d == NULL)
|
|
||||||
loc += Vec3(0.0f, 0.1f, 0.0f);
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
m_track_mesh->castRay(loc, loc + (-10000 * quad_normal), &hit_point,
|
m_track_mesh->castRay(loc, loc + (-10000 * quad_normal), &hit_point,
|
||||||
@ -2323,8 +2308,7 @@ void Track::itemCommand(const XMLNode *node)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemManager::get()->newItem(type, drop ? hit_point : loc,
|
ItemManager::get()->newItem(type, drop ? hit_point : loc, normal);
|
||||||
node_3d ? normal : Vec3(0, 1, 0));
|
|
||||||
} // itemCommand
|
} // itemCommand
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -2434,11 +2418,11 @@ bool Track::findGround(AbstractKart *kart)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
float Track::getTrackLength() const
|
float Track::getTrackLength() const
|
||||||
{
|
{
|
||||||
return QuadGraph::get()->getLapLength();
|
return DriveGraph::get()->getLapLength();
|
||||||
} // getTrackLength
|
} // getTrackLength
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
float Track::getAngle(int n) const
|
float Track::getAngle(int n) const
|
||||||
{
|
{
|
||||||
return QuadGraph::get()->getAngleToNext(n, 0);
|
return DriveGraph::get()->getAngleToNext(n, 0);
|
||||||
} // getAngle
|
} // getAngle
|
||||||
|
@ -373,7 +373,7 @@ private:
|
|||||||
int m_actual_number_of_laps;
|
int m_actual_number_of_laps;
|
||||||
|
|
||||||
void loadTrackInfo();
|
void loadTrackInfo();
|
||||||
void loadQuadGraph(unsigned int mode_id, const bool reverse);
|
void loadDriveGraph(unsigned int mode_id, const bool reverse);
|
||||||
void loadArenaGraph(const XMLNode &node);
|
void loadArenaGraph(const XMLNode &node);
|
||||||
btQuaternion getArenaStartRotation(const Vec3& xyz, float heading);
|
btQuaternion getArenaStartRotation(const Vec3& xyz, float heading);
|
||||||
void convertTrackToBullet(scene::ISceneNode *node);
|
void convertTrackToBullet(scene::ISceneNode *node);
|
||||||
|
@ -16,15 +16,16 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "tracks/track_sector.hpp"
|
||||||
|
|
||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "tracks/check_manager.hpp"
|
#include "tracks/check_manager.hpp"
|
||||||
#include "tracks/check_structure.hpp"
|
#include "tracks/check_structure.hpp"
|
||||||
#include "tracks/track_sector.hpp"
|
|
||||||
#include "tracks/arena_graph.hpp"
|
#include "tracks/arena_graph.hpp"
|
||||||
#include "tracks/arena_node.hpp"
|
#include "tracks/arena_node.hpp"
|
||||||
#include "tracks/quad_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/graph_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Initialises the object, and sets the current graph node to be undefined.
|
/** Initialises the object, and sets the current graph node to be undefined.
|
||||||
@ -37,8 +38,8 @@ TrackSector::TrackSector()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void TrackSector::reset()
|
void TrackSector::reset()
|
||||||
{
|
{
|
||||||
m_current_graph_node = QuadGraph::UNKNOWN_SECTOR;
|
m_current_graph_node = Graph::UNKNOWN_SECTOR;
|
||||||
m_last_valid_graph_node = QuadGraph::UNKNOWN_SECTOR;
|
m_last_valid_graph_node = Graph::UNKNOWN_SECTOR;
|
||||||
m_on_road = false;
|
m_on_road = false;
|
||||||
m_last_triggered_checkline = -1;
|
m_last_triggered_checkline = -1;
|
||||||
} // reset
|
} // reset
|
||||||
@ -79,8 +80,8 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical)
|
|||||||
if (ag) return;
|
if (ag) return;
|
||||||
// keep the current quad as the latest valid one IF the player has one
|
// keep the current quad as the latest valid one IF the player has one
|
||||||
// of the required checklines
|
// of the required checklines
|
||||||
const GraphNode* gn = QuadGraph::get()->getNode(m_current_graph_node);
|
const DriveNode* dn = DriveGraph::get()->getNode(m_current_graph_node);
|
||||||
const std::vector<int>& checkline_requirements = gn->getChecklineRequirements();
|
const std::vector<int>& checkline_requirements = dn->getChecklineRequirements();
|
||||||
|
|
||||||
if (checkline_requirements.size() == 0)
|
if (checkline_requirements.size() == 0)
|
||||||
{
|
{
|
||||||
@ -107,8 +108,8 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical)
|
|||||||
|
|
||||||
// Now determine the 'track' coords, i.e. ow far from the start of the
|
// Now determine the 'track' coords, i.e. ow far from the start of the
|
||||||
// track, and how far to the left or right of the center driveline.
|
// track, and how far to the left or right of the center driveline.
|
||||||
QuadGraph::get()->spatialToTrack(&m_current_track_coords, xyz,
|
DriveGraph::get()->spatialToTrack(&m_current_track_coords, xyz,
|
||||||
m_current_graph_node);
|
m_current_graph_node);
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -116,7 +117,7 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical)
|
|||||||
*/
|
*/
|
||||||
void TrackSector::rescue()
|
void TrackSector::rescue()
|
||||||
{
|
{
|
||||||
if (m_last_valid_graph_node != QuadGraph::UNKNOWN_SECTOR)
|
if (m_last_valid_graph_node != Graph::UNKNOWN_SECTOR)
|
||||||
m_current_graph_node = m_last_valid_graph_node;
|
m_current_graph_node = m_last_valid_graph_node;
|
||||||
|
|
||||||
// Using the predecessor has the additional advantage (besides punishing
|
// Using the predecessor has the additional advantage (besides punishing
|
||||||
@ -124,10 +125,10 @@ void TrackSector::rescue()
|
|||||||
// rescue loop since the kart moves back on each attempt. At this stage
|
// rescue loop since the kart moves back on each attempt. At this stage
|
||||||
// STK does not keep track of where the kart is coming from, so always
|
// STK does not keep track of where the kart is coming from, so always
|
||||||
// use the first predecessor, which is the one on the main driveline.
|
// use the first predecessor, which is the one on the main driveline.
|
||||||
m_current_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
|
m_current_graph_node = DriveGraph::get()->getNode(m_current_graph_node)
|
||||||
->getPredecessor(0);
|
->getPredecessor(0);
|
||||||
m_last_valid_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
|
m_last_valid_graph_node = DriveGraph::get()->getNode(m_current_graph_node)
|
||||||
->getPredecessor(0);
|
->getPredecessor(0);
|
||||||
} // rescue
|
} // rescue
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -137,7 +138,7 @@ void TrackSector::rescue()
|
|||||||
*/
|
*/
|
||||||
float TrackSector::getRelativeDistanceToCenter() const
|
float TrackSector::getRelativeDistanceToCenter() const
|
||||||
{
|
{
|
||||||
float w = QuadGraph::get()->getNode(m_current_graph_node)->getPathWidth();
|
float w = DriveGraph::get()->getNode(m_current_graph_node)->getPathWidth();
|
||||||
// w * 0.5 is the distance from center of the quad to the left or right
|
// w * 0.5 is the distance from center of the quad to the left or right
|
||||||
// This way we get a value between -1 and 1.
|
// This way we get a value between -1 and 1.
|
||||||
float ratio = getDistanceToCenter()/(w*0.5f);
|
float ratio = getDistanceToCenter()/(w*0.5f);
|
||||||
|
Loading…
Reference in New Issue
Block a user