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/kart_properties.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
@ -62,7 +62,7 @@ void CameraEnd::readEndCamera(const XMLNode &root)
|
||||
unsigned int index = i;
|
||||
// In reverse mode, reverse the order in which the
|
||||
// end cameras are read.
|
||||
if(QuadGraph::get()->isReverse())
|
||||
if(DriveGraph::get()->isReverse())
|
||||
index = root.getNumNodes() - 1 - i;
|
||||
const XMLNode *node = root.getNode(index);
|
||||
EndCameraInformation eci;
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/linear_world.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
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include "modes/three_strikes_battle.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/arena_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
@ -145,15 +145,15 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
{
|
||||
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)
|
||||
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();
|
||||
const GraphNode* gn = QuadGraph::get()->getNode(m_graph_node);
|
||||
const Vec3& right = gn->getRightUnitVector();
|
||||
const DriveNode* dn = DriveGraph::get()->getNode(m_graph_node);
|
||||
const Vec3& right = dn->getRightUnitVector();
|
||||
// Give it 10% more space, since the kart will not always come
|
||||
// parallel to the drive line.
|
||||
Vec3 delta = right * sqrt(m_distance_2) * 1.3f;
|
||||
|
@ -225,7 +225,7 @@ void ItemManager::insertItem(Item *item)
|
||||
if(m_items_in_quads)
|
||||
{
|
||||
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)
|
||||
{
|
||||
(*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]
|
||||
* 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;
|
||||
|
||||
/** What item this item is switched to. */
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
@ -100,7 +100,7 @@ RubberBall::RubberBall(AbstractKart *kart)
|
||||
// initialises the current graph node
|
||||
TrackSector::update(getXYZ());
|
||||
const Vec3& normal =
|
||||
QuadGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
||||
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
||||
TerrainInfo::update(getXYZ(), -normal);
|
||||
initializeControlPoints(m_owner->getXYZ());
|
||||
|
||||
@ -136,7 +136,7 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
|
||||
// left or right when firing the ball off track.
|
||||
getNextControlPoint();
|
||||
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]
|
||||
getNextControlPoint();
|
||||
@ -201,12 +201,12 @@ unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index,
|
||||
|
||||
unsigned int sect =
|
||||
lin_world->getSectorForKart(m_target);
|
||||
succ = QuadGraph::get()->getNode(node_index)->getSuccessorToReach(sect);
|
||||
succ = DriveGraph::get()->getNode(node_index)->getSuccessorToReach(sect);
|
||||
|
||||
if(dist)
|
||||
*dist += QuadGraph::get()->getNode(node_index)
|
||||
*dist += DriveGraph::get()->getNode(node_index)
|
||||
->getDistanceToSuccessor(succ);
|
||||
return QuadGraph::get()->getNode(node_index)->getSuccessor(succ);
|
||||
return DriveGraph::get()->getNode(node_index)->getSuccessor(succ);
|
||||
} // getSuccessorToHitTarget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -224,21 +224,21 @@ void RubberBall::getNextControlPoint()
|
||||
// spline between the control points.
|
||||
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);
|
||||
float d = QuadGraph::get()->getDistanceFromStart(next)-f;
|
||||
float d = DriveGraph::get()->getDistanceFromStart(next)-f;
|
||||
while(d<m_st_min_interpolation_distance && d>=0)
|
||||
{
|
||||
next = getSuccessorToHitTarget(next, &dist);
|
||||
d = QuadGraph::get()->getDistanceFromStart(next)-f;
|
||||
d = DriveGraph::get()->getDistanceFromStart(next)-f;
|
||||
}
|
||||
|
||||
m_last_aimed_graph_node = next;
|
||||
m_length_cp_2_3 = dist;
|
||||
const GraphNode* gn =
|
||||
QuadGraph::get()->getNode(m_last_aimed_graph_node);
|
||||
m_control_points[3] = gn->getCenter();
|
||||
const DriveNode* dn =
|
||||
DriveGraph::get()->getNode(m_last_aimed_graph_node);
|
||||
m_control_points[3] = dn->getCenter();
|
||||
} // getNextControlPoint
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "tracks/track_sector.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
class QuadGraph;
|
||||
class SFXBase;
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/controller/ai_properties.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.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.
|
||||
|
||||
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
|
||||
or forks in the road).
|
||||
|
||||
@ -139,14 +139,14 @@ void AIBaseLapController::newLap(int lap)
|
||||
*/
|
||||
void AIBaseLapController::computePath()
|
||||
{
|
||||
m_next_node_index.resize(QuadGraph::get()->getNumNodes());
|
||||
m_successor_index.resize(QuadGraph::get()->getNumNodes());
|
||||
m_next_node_index.resize(DriveGraph::get()->getNumNodes());
|
||||
m_successor_index.resize(DriveGraph::get()->getNumNodes());
|
||||
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();
|
||||
// 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
|
||||
// might not have a successor (since the first and last edge of
|
||||
// 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
|
||||
// the non-AI successors of that node in this case.
|
||||
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
|
||||
// race. Long term statistics might be gathered to determine the
|
||||
// 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'
|
||||
// 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
|
||||
// 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
|
||||
// be computed recursively, but since the AI for now is using only
|
||||
// (randomly picked) path this is fine
|
||||
m_all_look_aheads.resize(QuadGraph::get()->getNumNodes());
|
||||
for(unsigned int i=0; i<QuadGraph::get()->getNumNodes(); i++)
|
||||
m_all_look_aheads.resize(DriveGraph::get()->getNumNodes());
|
||||
for(unsigned int i=0; i<DriveGraph::get()->getNumNodes(); i++)
|
||||
{
|
||||
std::vector<int> l;
|
||||
int current = i;
|
||||
@ -199,24 +199,24 @@ void AIBaseLapController::computePath()
|
||||
void AIBaseLapController::update(float dt)
|
||||
{
|
||||
AIBaseController::update(dt);
|
||||
if(QuadGraph::get())
|
||||
if(DriveGraph::get())
|
||||
{
|
||||
// Update the current 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]);
|
||||
}
|
||||
// If we can't find a proper place on the track, to a broader search
|
||||
// on off-track locations.
|
||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||
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
|
||||
// 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_track_node = old_node;
|
||||
}
|
||||
@ -233,7 +233,7 @@ void AIBaseLapController::update(float dt)
|
||||
unsigned int AIBaseLapController::getNextSector(unsigned int index)
|
||||
{
|
||||
std::vector<unsigned int> successors;
|
||||
QuadGraph::get()->getSuccessors(index, successors);
|
||||
DriveGraph::get()->getSuccessors(index, successors);
|
||||
return successors[0];
|
||||
} // getNextSector
|
||||
|
||||
@ -245,8 +245,8 @@ unsigned int AIBaseLapController::getNextSector(unsigned int index)
|
||||
float AIBaseLapController::steerToAngle(const unsigned int sector,
|
||||
const float add_angle)
|
||||
{
|
||||
float angle = QuadGraph::get()->getAngleToNext(sector,
|
||||
getNextSector(sector));
|
||||
float angle = DriveGraph::get()->getAngleToNext(sector,
|
||||
getNextSector(sector));
|
||||
|
||||
//Desired angle minus current angle equals how many angles to turn
|
||||
float steer_angle = angle - m_kart->getHeading();
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
class AIProperties;
|
||||
class LinearWorld;
|
||||
class QuadGraph;
|
||||
class Track;
|
||||
class Vec3;
|
||||
|
||||
|
@ -45,8 +45,8 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/race_result_gui.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.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
|
||||
// the main driveline).
|
||||
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
|
||||
// up by accident on a non-selected path, it will keep on working.
|
||||
m_successor_index[i] = 0;
|
||||
|
||||
next.clear();
|
||||
QuadGraph::get()->getSuccessors(i, next);
|
||||
DriveGraph::get()->getSuccessors(i, next);
|
||||
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'
|
||||
// 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
|
||||
// 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
|
||||
// be computed recursively, but since the AI for now is using only
|
||||
// (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;
|
||||
int current = i;
|
||||
@ -95,7 +95,7 @@ EndController::EndController(AbstractKart *kart,
|
||||
}
|
||||
} // 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();
|
||||
|
||||
m_max_handicap_accel = 1.0f;
|
||||
@ -130,18 +130,18 @@ void EndController::reset()
|
||||
m_crash_time = 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
|
||||
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
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
|
||||
// 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
|
||||
@ -212,10 +212,10 @@ void EndController::handleSteering(float dt)
|
||||
*/
|
||||
//Reaction to being outside of the road
|
||||
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];
|
||||
target_point = QuadGraph::get()->getNode(next)->getCenter();
|
||||
target_point = DriveGraph::get()->getNode(next)->getCenter();
|
||||
#ifdef AI_DEBUG
|
||||
Log::debug("end_controller.cpp", "- Outside of road: steer to center point.");
|
||||
#endif
|
||||
@ -275,7 +275,7 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
||||
target_sector = m_next_node_index[sector];
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getNode(target_sector)->getCenter()
|
||||
direction = DriveGraph::get()->getNode(target_sector)->getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
float len=direction.length();
|
||||
@ -293,16 +293,16 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
||||
{
|
||||
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 );
|
||||
|
||||
distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous sector is what we are looking for
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> 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;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
class Camera;
|
||||
class LinearWorld;
|
||||
class QuadGraph;
|
||||
class Track;
|
||||
class Vec3;
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp"
|
||||
@ -171,22 +171,22 @@ void SkiddingAI::reset()
|
||||
m_distance_behind = 0.0f;
|
||||
m_current_curve_radius = 0.0f;
|
||||
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_avoid_item_close = false;
|
||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||
m_last_item_random = NULL;
|
||||
|
||||
AIBaseLapController::reset();
|
||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||
{
|
||||
Log::error(getControllerName().c_str(),
|
||||
"Invalid starting position for '%s' - not on track"
|
||||
" - can be ignored.",
|
||||
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();
|
||||
@ -414,7 +414,7 @@ void SkiddingAI::handleBraking()
|
||||
|
||||
// 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.
|
||||
if(m_current_track_direction==GraphNode::DIR_UNDEFINED &&
|
||||
if(m_current_track_direction==DriveNode::DIR_UNDEFINED &&
|
||||
m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -426,8 +426,8 @@ void SkiddingAI::handleBraking()
|
||||
m_controls->m_brake = true;
|
||||
return;
|
||||
}
|
||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
||||
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||
{
|
||||
float max_turn_speed =
|
||||
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
||||
@ -476,13 +476,13 @@ void SkiddingAI::handleSteering(float dt)
|
||||
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
||||
|
||||
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());
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
||||
m_debug_sphere[0]->setPosition(DriveGraph::get()->getNode(next)
|
||||
->getCenter().toIrrVector());
|
||||
Log::debug(getControllerName().c_str(),
|
||||
"Outside of road: steer to center point.");
|
||||
@ -530,7 +530,7 @@ void SkiddingAI::handleSteering(float dt)
|
||||
{
|
||||
m_start_kart_crash_direction = 0;
|
||||
Vec3 aim_point;
|
||||
int last_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
int last_node = Graph::UNKNOWN_SECTOR;
|
||||
|
||||
switch(m_point_selection_algorithm)
|
||||
{
|
||||
@ -623,7 +623,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||
|
||||
// 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];
|
||||
|
||||
int node = m_track_node;
|
||||
@ -636,7 +636,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
const float max_item_lookahead_distance = 30.f;
|
||||
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 =
|
||||
ItemManager::get()->getItemsInQuads(n_index);
|
||||
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,
|
||||
&items_to_avoid, &items_to_collect);
|
||||
} // for i<items_ahead;
|
||||
distance += QuadGraph::get()->getDistanceToNext(node,
|
||||
distance += DriveGraph::get()->getDistanceToNext(node,
|
||||
m_successor_index[node]);
|
||||
node = m_next_node_index[node];
|
||||
// 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.
|
||||
Vec3 xyz = item_to_collect->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();
|
||||
float dist_to_plane = item_direction.dot(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.
|
||||
const Vec3 &xyz = m_item_to_collect->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);
|
||||
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.
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
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,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
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());
|
||||
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,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
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.
|
||||
const Vec3 &xyz = item->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);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
@ -1714,14 +1714,14 @@ void SkiddingAI::handleNitroAndZipper()
|
||||
m_kart->getSpeed()>1.0f &&
|
||||
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
||||
{
|
||||
GraphNode::DirectionType dir;
|
||||
DriveNode::DirectionType dir;
|
||||
unsigned int last;
|
||||
const GraphNode* gn = QuadGraph::get()->getNode(m_track_node);
|
||||
gn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||
if(dir==GraphNode::DIR_STRAIGHT)
|
||||
const DriveNode* dn = DriveGraph::get()->getNode(m_track_node);
|
||||
dn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||
if(dir==DriveNode::DIR_STRAIGHT)
|
||||
{
|
||||
float diff = QuadGraph::get()->getDistanceFromStart(last)
|
||||
- QuadGraph::get()->getDistanceFromStart(m_track_node);
|
||||
float diff = DriveGraph::get()->getDistanceFromStart(last)
|
||||
- DriveGraph::get()->getDistanceFromStart(m_track_node);
|
||||
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
||||
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
||||
m_controls->m_fire = true;
|
||||
@ -1812,12 +1812,12 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
||||
}
|
||||
|
||||
/*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)
|
||||
QuadGraph::get()->findRoadSector(step_coord, ¤t_node,
|
||||
DriveGraph::get()->findRoadSector(step_coord, ¤t_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;
|
||||
return;
|
||||
@ -1865,23 +1865,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
*last_node = m_next_node_index[m_track_node];
|
||||
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.
|
||||
const unsigned int LEFT_END_POINT = 0;
|
||||
const unsigned int RIGHT_END_POINT = 1;
|
||||
core::line2df left (xz, (*g)[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, (*g)[RIGHT_END_POINT].toIrrVector2d());
|
||||
core::line2df left (xz, (*dn)[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, (*dn)[RIGHT_END_POINT].toIrrVector2d());
|
||||
|
||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
const Vec3 eps1(0,0.5f,0);
|
||||
m_curve[CURVE_LEFT]->clear();
|
||||
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_RIGHT]->clear();
|
||||
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);
|
||||
#endif
|
||||
#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)
|
||||
{
|
||||
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
|
||||
// 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 )
|
||||
{
|
||||
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
|
||||
if(right.getPointOrientation(p)<0)
|
||||
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
|
||||
// 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 )
|
||||
{
|
||||
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
|
||||
if(left.getPointOrientation(p)>0)
|
||||
break;
|
||||
@ -1941,7 +1941,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
// 0.5f*(left.end.Y+right.end.Y));
|
||||
//*result = ppp;
|
||||
|
||||
*result = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*result = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPointNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1978,7 +1978,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
target_sector = m_next_node_index[*last_node];
|
||||
|
||||
//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();
|
||||
|
||||
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);
|
||||
|
||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
*last_node );
|
||||
|
||||
float distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous node is what we are looking for
|
||||
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();
|
||||
return;
|
||||
}
|
||||
}
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPointFixed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2025,14 +2025,14 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
* 1. the test:
|
||||
*
|
||||
* 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 the distance from the center, i.e. it is half the path width if
|
||||
* the point is at the edge).
|
||||
* 2. the test:
|
||||
*
|
||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* *last_node );
|
||||
* in the for loop tests always against distance from the same
|
||||
* 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);
|
||||
#endif
|
||||
*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]);
|
||||
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
|
||||
// drive to without crashing with the track.
|
||||
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]);
|
||||
// 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
|
||||
@ -2081,13 +2081,13 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
float diff = normalizeAngle(angle1-angle);
|
||||
if(fabsf(diff)>1.5f)
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
||||
*aim_position = DriveGraph::get()->getNode(target_sector)
|
||||
->getCenter();
|
||||
return;
|
||||
}
|
||||
|
||||
//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();
|
||||
|
||||
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);
|
||||
|
||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
*last_node );
|
||||
|
||||
float distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous node is what we are looking for
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -2127,7 +2127,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
angle = angle1;
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2136,7 +2136,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
*/
|
||||
void SkiddingAI::determineTrackDirection()
|
||||
{
|
||||
const QuadGraph *qg = QuadGraph::get();
|
||||
const DriveGraph *qg = DriveGraph::get();
|
||||
unsigned int succ = m_successor_index[m_track_node];
|
||||
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
||||
|
||||
@ -2165,7 +2165,7 @@ void SkiddingAI::determineTrackDirection()
|
||||
// quicker be aligned with the track again).
|
||||
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
||||
{
|
||||
m_current_track_direction = GraphNode::DIR_UNDEFINED;
|
||||
m_current_track_direction = DriveNode::DIR_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2181,8 +2181,8 @@ void SkiddingAI::determineTrackDirection()
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
||||
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||
{
|
||||
handleCurve();
|
||||
} // 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
|
||||
// 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 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||
@ -2227,7 +2227,7 @@ void SkiddingAI::handleCurve()
|
||||
{
|
||||
i = m_next_node_index[i];
|
||||
// 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;
|
||||
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
||||
if(m_current_curve_radius < r)
|
||||
@ -2286,8 +2286,8 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
||||
}
|
||||
|
||||
// No skidding on straights
|
||||
if(m_current_track_direction==GraphNode::DIR_STRAIGHT ||
|
||||
m_current_track_direction==GraphNode::DIR_UNDEFINED )
|
||||
if(m_current_track_direction==DriveNode::DIR_STRAIGHT ||
|
||||
m_current_track_direction==DriveNode::DIR_UNDEFINED )
|
||||
{
|
||||
#ifdef 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 QuadGraph *qg = QuadGraph::get();
|
||||
const DriveGraph *qg = DriveGraph::get();
|
||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||
|
||||
// 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;
|
||||
float angle_kart = atan2(diff_kart.getX(), diff_kart.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_kart - angle_last;
|
||||
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
|
||||
// vorder). In this case skidding will be useless.
|
||||
else if( (steer_fraction > 0 &&
|
||||
m_current_track_direction==GraphNode::DIR_LEFT) ||
|
||||
m_current_track_direction==DriveNode::DIR_LEFT) ||
|
||||
(steer_fraction < 0 &&
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT) )
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(m_controls->m_skid && m_ai_debug)
|
||||
|
@ -45,11 +45,11 @@
|
||||
|
||||
#include "karts/controller/ai_base_lap_controller.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
class LinearWorld;
|
||||
class QuadGraph;
|
||||
class DriveGraph;
|
||||
class ShowCurve;
|
||||
class Track;
|
||||
|
||||
@ -155,7 +155,7 @@ private:
|
||||
int m_start_kart_crash_direction;
|
||||
|
||||
/** 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
|
||||
* when being on a straigt section. */
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp"
|
||||
@ -177,22 +177,22 @@ void SkiddingAI::reset()
|
||||
m_distance_behind = 0.0f;
|
||||
m_current_curve_radius = 0.0f;
|
||||
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_avoid_item_close = false;
|
||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||
m_last_item_random = NULL;
|
||||
|
||||
AIBaseLapController::reset();
|
||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||
m_track_node = Graph::UNKNOWN_SECTOR;
|
||||
DriveGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||
if(m_track_node==Graph::UNKNOWN_SECTOR)
|
||||
{
|
||||
Log::error(getControllerName().c_str(),
|
||||
"Invalid starting position for '%s' - not on track"
|
||||
" - can be ignored.",
|
||||
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();
|
||||
@ -420,7 +420,7 @@ void SkiddingAI::handleBraking()
|
||||
|
||||
// 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.
|
||||
if(m_current_track_direction==GraphNode::DIR_UNDEFINED &&
|
||||
if(m_current_track_direction==DriveNode::DIR_UNDEFINED &&
|
||||
m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -432,8 +432,8 @@ void SkiddingAI::handleBraking()
|
||||
m_controls->m_brake = true;
|
||||
return;
|
||||
}
|
||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
||||
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||
{
|
||||
float max_turn_speed =
|
||||
m_kart->getSpeedForTurnRadius(m_current_curve_radius);
|
||||
@ -482,13 +482,13 @@ void SkiddingAI::handleSteering(float dt)
|
||||
m_world->getDistanceToCenterForKart( m_kart->getWorldKartId() );
|
||||
|
||||
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());
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
||||
m_debug_sphere[0]->setPosition(DriveGraph::get()->getNode(next)
|
||||
->getCenter().toIrrVector());
|
||||
Log::debug(getControllerName().c_str(),
|
||||
"Outside of road: steer to center point.");
|
||||
@ -536,7 +536,7 @@ void SkiddingAI::handleSteering(float dt)
|
||||
{
|
||||
m_start_kart_crash_direction = 0;
|
||||
Vec3 aim_point;
|
||||
int last_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
int last_node = Graph::UNKNOWN_SECTOR;
|
||||
|
||||
switch(m_point_selection_algorithm)
|
||||
{
|
||||
@ -629,7 +629,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||
|
||||
// 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];
|
||||
|
||||
int node = m_track_node;
|
||||
@ -642,7 +642,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
const float max_item_lookahead_distance = 30.f;
|
||||
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 =
|
||||
ItemManager::get()->getItemsInQuads(n_index);
|
||||
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,
|
||||
&items_to_avoid, &items_to_collect);
|
||||
} // for i<items_ahead;
|
||||
distance += QuadGraph::get()->getDistanceToNext(node,
|
||||
distance += DriveGraph::get()->getDistanceToNext(node,
|
||||
m_successor_index[node]);
|
||||
node = m_next_node_index[node];
|
||||
// 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.
|
||||
Vec3 xyz = item_to_collect->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();
|
||||
float dist_to_plane = item_direction.dot(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.
|
||||
const Vec3 &xyz = m_item_to_collect->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);
|
||||
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.
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
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,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
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());
|
||||
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,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
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.
|
||||
const Vec3 &xyz = item->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);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
@ -1763,14 +1763,14 @@ void SkiddingAI::handleNitroAndZipper()
|
||||
m_kart->getSpeed()>1.0f &&
|
||||
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
|
||||
{
|
||||
GraphNode::DirectionType dir;
|
||||
DriveNode::DirectionType dir;
|
||||
unsigned int last;
|
||||
const GraphNode* gn = QuadGraph::get()->getNode(m_track_node);
|
||||
gn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||
if(dir==GraphNode::DIR_STRAIGHT)
|
||||
const DriveNode* dn = DriveGraph::get()->getNode(m_track_node);
|
||||
dn->getDirectionData(m_successor_index[m_track_node], &dir, &last);
|
||||
if(dir==DriveNode::DIR_STRAIGHT)
|
||||
{
|
||||
float diff = QuadGraph::get()->getDistanceFromStart(last)
|
||||
- QuadGraph::get()->getDistanceFromStart(m_track_node);
|
||||
float diff = DriveGraph::get()->getDistanceFromStart(last)
|
||||
- DriveGraph::get()->getDistanceFromStart(m_track_node);
|
||||
if(diff<0) diff+=World::getWorld()->getTrack()->getTrackLength();
|
||||
if(diff>m_ai_properties->m_straight_length_for_zipper)
|
||||
m_controls->m_fire = true;
|
||||
@ -1861,12 +1861,12 @@ void SkiddingAI::checkCrashes(const Vec3& pos )
|
||||
}
|
||||
|
||||
/*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)
|
||||
QuadGraph::get()->findRoadSector(step_coord, ¤t_node,
|
||||
DriveGraph::get()->findRoadSector(step_coord, ¤t_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;
|
||||
return;
|
||||
@ -1914,23 +1914,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
*last_node = m_next_node_index[m_track_node];
|
||||
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.
|
||||
const unsigned int LEFT_END_POINT = 0;
|
||||
const unsigned int RIGHT_END_POINT = 1;
|
||||
core::line2df left (xz, (*g)[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, (*g)[RIGHT_END_POINT].toIrrVector2d());
|
||||
core::line2df left (xz, (*dn)[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, (*dn)[RIGHT_END_POINT].toIrrVector2d());
|
||||
|
||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
const Vec3 eps1(0,0.5f,0);
|
||||
m_curve[CURVE_LEFT]->clear();
|
||||
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_RIGHT]->clear();
|
||||
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);
|
||||
#endif
|
||||
#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)
|
||||
{
|
||||
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
|
||||
// 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 )
|
||||
{
|
||||
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
|
||||
if(right.getPointOrientation(p)<0)
|
||||
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
|
||||
// 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 )
|
||||
{
|
||||
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
|
||||
if(left.getPointOrientation(p)>0)
|
||||
break;
|
||||
@ -1990,7 +1990,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
// 0.5f*(left.end.Y+right.end.Y));
|
||||
//*result = ppp;
|
||||
|
||||
*result = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*result = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPointNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2027,7 +2027,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
target_sector = m_next_node_index[*last_node];
|
||||
|
||||
//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();
|
||||
|
||||
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);
|
||||
|
||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
*last_node );
|
||||
|
||||
float distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous node is what we are looking for
|
||||
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();
|
||||
return;
|
||||
}
|
||||
}
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPointFixed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2074,14 +2074,14 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
* 1. the test:
|
||||
*
|
||||
* 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 the distance from the center, i.e. it is half the path width if
|
||||
* the point is at the edge).
|
||||
* 2. the test:
|
||||
*
|
||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* *last_node );
|
||||
* in the for loop tests always against distance from the same
|
||||
* 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);
|
||||
#endif
|
||||
*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]);
|
||||
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
|
||||
// drive to without crashing with the track.
|
||||
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]);
|
||||
// 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
|
||||
@ -2130,13 +2130,13 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
float diff = normalizeAngle(angle1-angle);
|
||||
if(fabsf(diff)>1.5f)
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
||||
*aim_position = DriveGraph::get()->getNode(target_sector)
|
||||
->getCenter();
|
||||
return;
|
||||
}
|
||||
|
||||
//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();
|
||||
|
||||
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);
|
||||
|
||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
DriveGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
*last_node );
|
||||
|
||||
float distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous node is what we are looking for
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -2176,7 +2176,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
angle = angle1;
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)->getCenter();
|
||||
*aim_position = DriveGraph::get()->getNode(*last_node)->getCenter();
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2185,7 +2185,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
*/
|
||||
void SkiddingAI::determineTrackDirection()
|
||||
{
|
||||
const QuadGraph *qg = QuadGraph::get();
|
||||
const DriveGraph *qg = DriveGraph::get();
|
||||
unsigned int succ = m_successor_index[m_track_node];
|
||||
unsigned int next = qg->getNode(m_track_node)->getSuccessor(succ);
|
||||
|
||||
@ -2214,7 +2214,7 @@ void SkiddingAI::determineTrackDirection()
|
||||
// quicker be aligned with the track again).
|
||||
if(fabsf(angle_to_track) > 0.22222f * M_PI)
|
||||
{
|
||||
m_current_track_direction = GraphNode::DIR_UNDEFINED;
|
||||
m_current_track_direction = DriveNode::DIR_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2230,8 +2230,8 @@ void SkiddingAI::determineTrackDirection()
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_current_track_direction==GraphNode::DIR_LEFT ||
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT )
|
||||
if(m_current_track_direction==DriveNode::DIR_LEFT ||
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT )
|
||||
{
|
||||
handleCurve();
|
||||
} // 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
|
||||
// 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 tangent = m_kart->getTrans()(Vec3(0,0,1)) - xyz;
|
||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||
@ -2276,7 +2276,7 @@ void SkiddingAI::handleCurve()
|
||||
{
|
||||
i = m_next_node_index[i];
|
||||
// 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;
|
||||
float r = (m_curve_center - *(qg->getNode(i))[index]).length();
|
||||
if(m_current_curve_radius < r)
|
||||
@ -2335,8 +2335,8 @@ bool SkiddingAI::canSkid(float steer_fraction)
|
||||
}
|
||||
|
||||
// No skidding on straights
|
||||
if(m_current_track_direction==GraphNode::DIR_STRAIGHT ||
|
||||
m_current_track_direction==GraphNode::DIR_UNDEFINED )
|
||||
if(m_current_track_direction==DriveNode::DIR_STRAIGHT ||
|
||||
m_current_track_direction==DriveNode::DIR_UNDEFINED )
|
||||
{
|
||||
#ifdef 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 QuadGraph *qg = QuadGraph::get();
|
||||
const DriveGraph *qg = DriveGraph::get();
|
||||
Vec3 last_xyz = qg->getNode(m_last_direction_node)->getCenter();
|
||||
|
||||
// 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;
|
||||
float angle_kart = atan2(diff_kart.getX(), diff_kart.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_kart - angle_last;
|
||||
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
|
||||
// vorder). In this case skidding will be useless.
|
||||
else if( (steer_fraction > 0 &&
|
||||
m_current_track_direction==GraphNode::DIR_LEFT) ||
|
||||
m_current_track_direction==DriveNode::DIR_LEFT) ||
|
||||
(steer_fraction < 0 &&
|
||||
m_current_track_direction==GraphNode::DIR_RIGHT) )
|
||||
m_current_track_direction==DriveNode::DIR_RIGHT) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(m_controls->m_skid && m_ai_debug)
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
#include "karts/controller/ai_base_lap_controller.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
@ -111,7 +111,7 @@ private:
|
||||
int m_start_kart_crash_direction;
|
||||
|
||||
/** 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
|
||||
* when being on a straigt section. */
|
||||
|
@ -64,8 +64,8 @@
|
||||
#include "physics/physics.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "tracks/terrain_info.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -1296,14 +1296,14 @@ void Kart::update(float dt)
|
||||
|
||||
// To be used later
|
||||
float dist_to_sector = 0.0f;
|
||||
if (QuadGraph::get())
|
||||
if (DriveGraph::get())
|
||||
{
|
||||
const int sector = ((LinearWorld*)World::getWorld())
|
||||
->getTrackSector(getWorldKartId()).getCurrentGraphNode();
|
||||
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();
|
||||
const btQuaternion& q = getTrans().getRotation();
|
||||
const float roll = quad_normal.angle
|
||||
@ -1941,13 +1941,13 @@ void Kart::crashed(const Material *m, const Vec3 &normal)
|
||||
World::getWorld()->getTrack()->isPushBackEnabled())
|
||||
{
|
||||
int sector = lw->getSectorForKart(this);
|
||||
if(sector!=QuadGraph::UNKNOWN_SECTOR)
|
||||
if(sector!=Graph::UNKNOWN_SECTOR)
|
||||
{
|
||||
// Use the first predecessor node, which is the most
|
||||
// natural one (i.e. the one on the main driveline).
|
||||
const GraphNode* gn = QuadGraph::get()->getNode(
|
||||
QuadGraph::get()->getNode(sector)->getPredecessor(0));
|
||||
Vec3 impulse = gn->getCenter() - getXYZ();
|
||||
const DriveNode* dn = DriveGraph::get()->getNode(
|
||||
DriveGraph::get()->getNode(sector)->getPredecessor(0));
|
||||
Vec3 impulse = dn->getCenter() - getXYZ();
|
||||
impulse.setY(0);
|
||||
if(impulse.getX() || impulse.getZ())
|
||||
impulse.normalize();
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include "physics/physics.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "tracks/track_sector.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -393,7 +393,7 @@ void LinearWorld::newLap(unsigned int kart_index)
|
||||
int LinearWorld::getSectorForKart(const AbstractKart *kart) const
|
||||
{
|
||||
if(kart->getWorldKartId()>=m_kart_info.size())
|
||||
return QuadGraph::UNKNOWN_SECTOR;
|
||||
return Graph::UNKNOWN_SECTOR;
|
||||
return m_kart_info[kart->getWorldKartId()].getTrackSector()
|
||||
->getCurrentGraphNode();
|
||||
} // getSectorForKart
|
||||
@ -629,7 +629,7 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
|
||||
*/
|
||||
unsigned int LinearWorld::getNumberOfRescuePositions() const
|
||||
{
|
||||
return QuadGraph::get()->getNumNodes();
|
||||
return DriveGraph::get()->getNumNodes();
|
||||
} // getNumberOfRescuePositions
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -647,8 +647,8 @@ unsigned int LinearWorld::getRescuePositionIndex(AbstractKart *kart)
|
||||
// ------------------------------------------------------------------------
|
||||
btTransform LinearWorld::getRescueTransform(unsigned int index) const
|
||||
{
|
||||
const Vec3 &xyz = QuadGraph::get()->getNode(index)->getCenter();
|
||||
const Vec3 &normal = QuadGraph::get()->getNode(index)->getNormal();
|
||||
const Vec3 &xyz = DriveGraph::get()->getNode(index)->getCenter();
|
||||
const Vec3 &normal = DriveGraph::get()->getNode(index)->getNormal();
|
||||
btTransform pos;
|
||||
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.
|
||||
int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode();
|
||||
|
||||
if (QuadGraph::get()->getNumberOfSuccessors(sector) > 1)
|
||||
if (DriveGraph::get()->getNumberOfSuccessors(sector) > 1)
|
||||
return;
|
||||
|
||||
// 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();
|
||||
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
|
||||
{
|
||||
assert(i < m_all_nodes.size());
|
||||
ArenaNode* n = dynamic_cast<ArenaNode*>(m_all_nodes[i]);
|
||||
assert(n!= NULL);
|
||||
assert(n != NULL);
|
||||
return n;
|
||||
} // getNode
|
||||
|
||||
|
@ -28,6 +28,7 @@ class ArenaNode;
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \brief A graph made from navmesh
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class ArenaGraph : public Graph
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_line.hpp"
|
||||
#include "tracks/check_structure.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
CheckManager *CheckManager::m_check_manager = NULL;
|
||||
@ -85,7 +85,7 @@ void CheckManager::load(const XMLNode &node)
|
||||
for(it=check_structures_to_change_state.begin();
|
||||
it != check_structures_to_change_state.end(); it++)
|
||||
{
|
||||
if(QuadGraph::get()->isReverse())
|
||||
if(DriveGraph::get()->isReverse())
|
||||
m_all_checks[*it]->addSuccessor(i);
|
||||
else
|
||||
m_all_checks[i]->addSuccessor(*it);
|
||||
|
@ -16,64 +16,17 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// 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 "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/xml_node.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_line.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/node_2d.hpp"
|
||||
#include "tracks/node_3d.hpp"
|
||||
#include "tracks/drive_node.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
|
||||
@ -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 graph_file_name Name of the file describing the actual graph
|
||||
*/
|
||||
QuadGraph::QuadGraph(const std::string &quad_file_name,
|
||||
const std::string &graph_file_name,
|
||||
const bool reverse) : m_reverse(reverse)
|
||||
DriveGraph::DriveGraph(const std::string &quad_file_name,
|
||||
const std::string &graph_file_name,
|
||||
const bool reverse) : m_reverse(reverse)
|
||||
{
|
||||
m_lap_length = 0;
|
||||
m_quad_filename = quad_file_name;
|
||||
m_quad_graph = this;
|
||||
m_lap_length = 0;
|
||||
m_quad_filename = quad_file_name;
|
||||
Graph::setGraph(this);
|
||||
load(quad_file_name, graph_file_name);
|
||||
} // QuadGraph
|
||||
} // DriveGraph
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor, removes all nodes of the graph. */
|
||||
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)
|
||||
void DriveGraph::addSuccessor(unsigned int from, unsigned int to)
|
||||
{
|
||||
if(m_reverse)
|
||||
m_all_nodes[to]->addSuccessor(from);
|
||||
getNode(to)->addSuccessor(from);
|
||||
else
|
||||
m_all_nodes[from]->addSuccessor(to);
|
||||
getNode(from)->addSuccessor(to);
|
||||
|
||||
} // 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="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,
|
||||
Vec3* result) const
|
||||
void DriveGraph::getPoint(const XMLNode *xml,
|
||||
const std::string &attribute_name,
|
||||
Vec3* result) const
|
||||
{
|
||||
std::string s;
|
||||
xml->get(attribute_name, &s);
|
||||
@ -141,30 +82,28 @@ void QuadGraph::getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||
} // 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 graph file to load.
|
||||
*/
|
||||
void QuadGraph::load(const std::string &quad_file_name,
|
||||
const std::string &filename)
|
||||
void DriveGraph::load(const std::string &quad_file_name,
|
||||
const std::string &filename)
|
||||
{
|
||||
XMLNode *quad = file_manager->createXMLTree(quad_file_name);
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
m_min = Vec3( 99999, 99999, 99999);
|
||||
m_max = Vec3(-99999, -99999, -99999);
|
||||
// Each quad is part of the graph exactly once now.
|
||||
for(unsigned int i=0; i<quad->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node = quad->getNode(i);
|
||||
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());
|
||||
continue;
|
||||
}
|
||||
@ -182,11 +121,10 @@ void QuadGraph::load(const std::string &quad_file_name,
|
||||
xml_node->get("invisible", &invisible);
|
||||
bool ai_ignore=false;
|
||||
xml_node->get("ai-ignore", &ai_ignore);
|
||||
GraphNode* node =
|
||||
createNode(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore);
|
||||
m_max.max(p0);m_max.max(p1);m_max.max(p2);m_max.max(p3);
|
||||
m_min.min(p0);m_min.min(p1);m_min.min(p2);m_min.min(p3);
|
||||
m_all_nodes.push_back(node);
|
||||
createQuad(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore,
|
||||
false/*is_arena*/);
|
||||
m_bb_max.max(p0);m_bb_max.max(p1);m_bb_max.max(p2);m_bb_max.max(p3);
|
||||
m_bb_min.min(p0);m_bb_min.min(p1);m_bb_min.min(p2);m_bb_min.min(p3);
|
||||
}
|
||||
delete quad;
|
||||
|
||||
@ -201,12 +139,12 @@ void QuadGraph::load(const std::string &quad_file_name,
|
||||
|
||||
if (m_all_nodes.size() > 0)
|
||||
{
|
||||
m_lap_length = m_all_nodes[m_all_nodes.size()-1]->getDistanceFromStart()
|
||||
+ m_all_nodes[m_all_nodes.size()-1]->getDistanceToSuccessor(0);
|
||||
m_lap_length = getNode(m_all_nodes.size()-1)->getDistanceFromStart()
|
||||
+ getNode(m_all_nodes.size()-1)->getDistanceToSuccessor(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Quad Graph", "No node in driveline graph.");
|
||||
Log::error("DriveGraph", "No node in driveline graph.");
|
||||
m_lap_length = 10.0f;
|
||||
}
|
||||
|
||||
@ -265,7 +203,7 @@ void QuadGraph::load(const std::string &quad_file_name,
|
||||
} // edge
|
||||
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());
|
||||
continue;
|
||||
} // incorrect specification
|
||||
@ -281,8 +219,8 @@ void QuadGraph::load(const std::string &quad_file_name,
|
||||
m_lap_length = -1;
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||
{
|
||||
float l = m_all_nodes[i]->getDistanceFromStart()
|
||||
+ m_all_nodes[i]->getDistanceToSuccessor(0);
|
||||
float l = getNode(i)->getDistanceFromStart()
|
||||
+ getNode(i)->getDistanceToSuccessor(0);
|
||||
if(l > m_lap_length)
|
||||
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)
|
||||
* 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;
|
||||
} // getStartNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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());
|
||||
} // computeChecklineRequirements
|
||||
|
||||
@ -315,8 +253,8 @@ void QuadGraph::computeChecklineRequirements()
|
||||
/** Finds which checklines must be visited before driving on this quad
|
||||
* (useful for rescue)
|
||||
*/
|
||||
void QuadGraph::computeChecklineRequirements(GraphNode* node,
|
||||
int latest_checkline)
|
||||
void DriveGraph::computeChecklineRequirements(DriveNode* node,
|
||||
int latest_checkline)
|
||||
{
|
||||
for (unsigned int n=0; n<node->getNumberOfSuccessors(); n++)
|
||||
{
|
||||
@ -325,7 +263,7 @@ void QuadGraph::computeChecklineRequirements(GraphNode* node,
|
||||
// warp-around
|
||||
if (succ_id == 0) break;
|
||||
|
||||
GraphNode* succ = m_all_nodes[succ_id];
|
||||
DriveNode* succ = getNode(succ_id);
|
||||
int new_latest_checkline =
|
||||
CheckManager::get()->getChecklineTriggering(node->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
|
||||
* saves some memory).
|
||||
*/
|
||||
void QuadGraph::setupPaths()
|
||||
void DriveGraph::setupPaths()
|
||||
{
|
||||
for(unsigned int i=0; i<getNumNodes(); i++)
|
||||
{
|
||||
m_all_nodes[i]->setupPathsToNode();
|
||||
getNode(i)->setupPathsToNode();
|
||||
}
|
||||
} // setupPaths
|
||||
|
||||
@ -375,18 +313,18 @@ void QuadGraph::setupPaths()
|
||||
/** 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.
|
||||
*/
|
||||
void QuadGraph::setDefaultSuccessors()
|
||||
void DriveGraph::setDefaultSuccessors()
|
||||
{
|
||||
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);
|
||||
//~ 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
|
||||
} // for i<m_allNodes.size()
|
||||
} // 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 will be overwritten).
|
||||
* E.g. the karts will be placed as:
|
||||
@ -406,17 +344,17 @@ void QuadGraph::setDefaultSuccessors()
|
||||
* \param sidewards_distance Distance in sidewards (X) direction between
|
||||
* karts.
|
||||
*/
|
||||
void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
||||
void DriveGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
||||
*start_transforms,
|
||||
unsigned int karts_per_row,
|
||||
float forwards_distance,
|
||||
float sidewards_distance,
|
||||
float upwards_distance) const
|
||||
unsigned int karts_per_row,
|
||||
float forwards_distance,
|
||||
float sidewards_distance,
|
||||
float upwards_distance) const
|
||||
{
|
||||
// We start just before the start node (which will trigger lap
|
||||
// counting when reached). The first predecessor is the one on
|
||||
// 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;
|
||||
|
||||
@ -443,14 +381,14 @@ void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
|
||||
// Only follow the main driveline, i.e. first predecessor
|
||||
current_node = getNode(current_node)->getPredecessor(0);
|
||||
}
|
||||
const GraphNode* gn = getNode(current_node);
|
||||
Vec3 center_line = gn->getLowerCenter() - gn->getUpperCenter();
|
||||
const DriveNode* dn = getNode(current_node);
|
||||
Vec3 center_line = dn->getLowerCenter() - dn->getUpperCenter();
|
||||
center_line.normalize();
|
||||
|
||||
Vec3 horizontal_line = (*gn)[2] - (*gn)[3];
|
||||
Vec3 horizontal_line = (*dn)[2] - (*dn)[3];
|
||||
horizontal_line.normalize();
|
||||
|
||||
Vec3 start = gn->getUpperCenter()
|
||||
Vec3 start = dn->getUpperCenter()
|
||||
+ center_line * distance_from_start
|
||||
+ horizontal_line * x_pos;
|
||||
// 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].setRotation(
|
||||
btQuaternion(btVector3(0, 1, 0),
|
||||
gn->getAngleToSuccessor(0)));
|
||||
dn->getAngleToSuccessor(0)));
|
||||
if(x_pos >= max_x_dist-sidewards_distance*0.5f)
|
||||
{
|
||||
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 for_ai true if only quads accessible by the AI should be returned.
|
||||
*/
|
||||
void QuadGraph::getSuccessors(int node_number,
|
||||
std::vector<unsigned int>& succ,
|
||||
bool for_ai) const
|
||||
void DriveGraph::getSuccessors(int node_number,
|
||||
std::vector<unsigned int>& succ,
|
||||
bool for_ai) const
|
||||
{
|
||||
const GraphNode *gn=m_all_nodes[node_number];
|
||||
for(unsigned int i=0; i<gn->getNumberOfSuccessors(); i++)
|
||||
const DriveNode *dn=getNode(node_number);
|
||||
for(unsigned int i=0; i<dn->getNumberOfSuccessors(); i++)
|
||||
{
|
||||
// If getSuccessor is called for the AI, only add
|
||||
// quads that are meant for the AI to be used.
|
||||
if(!for_ai || !gn->ignoreSuccessorForAI(i))
|
||||
succ.push_back(gn->getSuccessor(i));
|
||||
if(!for_ai || !dn->ignoreSuccessorForAI(i))
|
||||
succ.push_back(dn->getSuccessor(i));
|
||||
}
|
||||
} // 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 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];
|
||||
float current_distance = gn->getDistanceFromStart();
|
||||
DriveNode *dn = getNode(node);
|
||||
float current_distance = dn->getDistanceFromStart();
|
||||
|
||||
// If this node already has a distance defined, check if the new distance
|
||||
// is longer, and if so adjust all following nodes. Without this the
|
||||
@ -519,25 +457,25 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
||||
if(current_distance<new_distance)
|
||||
{
|
||||
float delta = new_distance - current_distance;
|
||||
updateDistancesForAllSuccessors(gn->getNodeIndex(), delta, 0);
|
||||
updateDistancesForAllSuccessors(dn->getIndex(), delta, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise this node has no distance defined yet. Set the new
|
||||
// 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,
|
||||
// recursion can stop now
|
||||
if(gn_next->getDistanceFromStart()==0)
|
||||
if(dn_next->getDistanceFromStart()==0)
|
||||
continue;
|
||||
|
||||
computeDistanceFromStart(gn_next->getNodeIndex(),
|
||||
new_distance + gn->getDistanceToSuccessor(i));
|
||||
computeDistanceFromStart(dn_next->getIndex(),
|
||||
new_distance + dn->getDistanceToSuccessor(i));
|
||||
} // for i
|
||||
} // computeDistanceFromStart
|
||||
|
||||
@ -551,35 +489,35 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
||||
* \param recursive_count Counts how often this function was called
|
||||
* 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)
|
||||
{
|
||||
if(recursive_count>getNumNodes())
|
||||
{
|
||||
Log::error("QuadGraph",
|
||||
"Quad graph contains a loop (without start node).");
|
||||
Log::fatal("QuadGraph",
|
||||
Log::error("DriveGraph",
|
||||
"DriveGraph contains a loop (without start node).");
|
||||
Log::fatal("DriveGraph",
|
||||
"Fix graph, check for directions of all shortcuts etc.");
|
||||
}
|
||||
recursive_count++;
|
||||
|
||||
GraphNode* g = getNode(indx);
|
||||
g->setDistanceFromStart(g->getDistanceFromStart()+delta);
|
||||
for(unsigned int i=0; i<g->getNumberOfSuccessors(); i++)
|
||||
DriveNode* dn = getNode(indx);
|
||||
dn->setDistanceFromStart(dn->getDistanceFromStart()+delta);
|
||||
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
|
||||
// distance of 0
|
||||
if(g_next->getDistanceFromStart()==0)
|
||||
if(dn_next->getDistanceFromStart()==0)
|
||||
continue;
|
||||
|
||||
// Only increase the distance from start of a successor node, if
|
||||
// this successor has a distance from start that is smaller then
|
||||
// the increased amount.
|
||||
if(g->getDistanceFromStart()+g->getDistanceToSuccessor(i) >
|
||||
g_next->getDistanceFromStart())
|
||||
if(dn->getDistanceFromStart()+dn->getDistanceToSuccessor(i) >
|
||||
dn_next->getDistanceFromStart())
|
||||
{
|
||||
updateDistancesForAllSuccessors(g->getSuccessor(i), delta,
|
||||
updateDistancesForAllSuccessors(dn->getSuccessor(i), delta,
|
||||
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
|
||||
* the new data).
|
||||
*/
|
||||
void QuadGraph::computeDirectionData()
|
||||
void DriveGraph::computeDirectionData()
|
||||
{
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||
{
|
||||
for(unsigned int succ_index=0;
|
||||
succ_index<m_all_nodes[i]->getNumberOfSuccessors();
|
||||
succ_index<getNode(i)->getNumberOfSuccessors();
|
||||
succ_index++)
|
||||
{
|
||||
determineDirection(i, succ_index);
|
||||
@ -617,14 +555,14 @@ void QuadGraph::computeDirectionData()
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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;
|
||||
else if(f<-M_PI) f += 2*M_PI;
|
||||
return f;
|
||||
} // 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
|
||||
* the given direction. The computed data is saved in the corresponding
|
||||
* graph node.
|
||||
@ -640,8 +578,8 @@ float QuadGraph::normalizeAngle(float f)
|
||||
* If there should be any other branches later, successor
|
||||
* 0 will always be tetsed.
|
||||
*/
|
||||
void QuadGraph::determineDirection(unsigned int current,
|
||||
unsigned int succ_index)
|
||||
void DriveGraph::determineDirection(unsigned int current,
|
||||
unsigned int succ_index)
|
||||
{
|
||||
// The maximum angle which is still considered to be straight
|
||||
const float max_straight_angle=0.1f;
|
||||
@ -681,11 +619,11 @@ void QuadGraph::determineDirection(unsigned int current,
|
||||
next = getNode(next)->getSuccessor(0);
|
||||
} // while(1)
|
||||
|
||||
GraphNode::DirectionType dir =
|
||||
rel_angle==0 ? GraphNode::DIR_STRAIGHT
|
||||
: (rel_angle>0) ? GraphNode::DIR_RIGHT
|
||||
: GraphNode::DIR_LEFT;
|
||||
m_all_nodes[current]->setDirectionData(succ_index, dir, next);
|
||||
DriveNode::DirectionType dir =
|
||||
rel_angle==0 ? DriveNode::DIR_STRAIGHT
|
||||
: (rel_angle>0) ? DriveNode::DIR_RIGHT
|
||||
: DriveNode::DIR_LEFT;
|
||||
getNode(current)->setDirectionData(succ_index, dir, next);
|
||||
} // determineDirection
|
||||
|
||||
|
||||
@ -699,12 +637,12 @@ void QuadGraph::determineDirection(unsigned int current,
|
||||
* \param xyz The position of the kart.
|
||||
* \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
|
||||
{
|
||||
if(sector == UNKNOWN_SECTOR )
|
||||
{
|
||||
Log::warn("Quad Graph", "UNKNOWN_SECTOR in spatialToTrack().");
|
||||
Log::warn("Drive Graph", "UNKNOWN_SECTOR in spatialToTrack().");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -712,215 +650,47 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
||||
} // spatialToTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** findRoadSector returns in which sector on the road the position
|
||||
* 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
|
||||
float DriveGraph::getDistanceToNext(int n, int j) const
|
||||
{
|
||||
// Most likely the kart will still be on the sector it was before,
|
||||
// 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);
|
||||
return getNode(n)->getDistanceToSuccessor(j);
|
||||
} // 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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int QuadGraph::getNumberOfSuccessors(int n) const
|
||||
int DriveGraph::getNumberOfSuccessors(int n) const
|
||||
{
|
||||
return m_all_nodes[n]->getNumberOfSuccessors();
|
||||
return getNode(n)->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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const bool QuadGraph::differentNodeColor(int n, NodeColor* c) const
|
||||
// -----------------------------------------------------------------------------
|
||||
void DriveGraph::differentNodeColor(int n, video::SColor* c) const
|
||||
{
|
||||
if (UserConfigParams::m_track_debug)
|
||||
{
|
||||
if (dynamic_cast<Node3D*>(m_all_nodes[n]) != NULL)
|
||||
*c = COLOR_GREEN;
|
||||
if (getNode(n)->is3DQuad())
|
||||
*c = video::SColor(255, 0, 255, 0);
|
||||
else
|
||||
*c = COLOR_YELLOW;
|
||||
return true;
|
||||
*c = video::SColor(255, 255, 255, 0);
|
||||
}
|
||||
return n == 0;
|
||||
|
||||
} // 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
|
||||
// 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/xml_node.hpp"
|
||||
#include "matrix4.h"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.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,
|
||||
unsigned int node_index, bool invisible,
|
||||
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_normal = normal;
|
||||
m_node_index = node_index;
|
||||
m_distance_from_start = -1.0f;
|
||||
|
||||
// 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_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_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;
|
||||
}
|
||||
|
||||
} // GraphNode
|
||||
} // DriveNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a successor to a node. This function will also pre-compute certain
|
||||
* values (like distance from this node to the successor, angle (in world)
|
||||
* between this node and the successor.
|
||||
* \param to The index of the 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);
|
||||
// to is the graph node
|
||||
GraphNode* gn_to = QuadGraph::get()->getNode(to);
|
||||
// to is the drive node
|
||||
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
|
||||
// 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());
|
||||
|
||||
Vec3 diff = gn_to->getCenter() - getCenter();
|
||||
Vec3 diff = dn_to->getCenter() - getCenter();
|
||||
|
||||
core::CMatrix4<float> m;
|
||||
m.buildRotateFromTo(getNormal().toIrrVector(),
|
||||
Vec3(0, 1, 0).toIrrVector());
|
||||
core::vector3df diffRotated;
|
||||
m.rotateVect(diffRotated, diff.toIrrVector());
|
||||
core::vector3df diff_rotated;
|
||||
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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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.
|
||||
*/
|
||||
void GraphNode::setupPathsToNode()
|
||||
void DriveNode::setupPathsToNode()
|
||||
{
|
||||
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);
|
||||
|
||||
// Initialise each graph node with -1, indicating that
|
||||
// Initialise each drive node with -1, indicating that
|
||||
// it hasn't been reached yet.
|
||||
for(unsigned int i=0; i<num_nodes; i++)
|
||||
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
|
||||
// successor 0 - just a dummy value that might only be used during the
|
||||
// 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
|
||||
// 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
|
||||
// might involve some shortcuts which are hidden, and should therefore
|
||||
// not be used.
|
||||
for(unsigned int i=0; i<getNumberOfSuccessors(); i++)
|
||||
{
|
||||
GraphNode* gn = QuadGraph::get()->getNode(getSuccessor(i));
|
||||
gn->markAllSuccessorsToUse(i, &m_path_to_node);
|
||||
DriveNode* dn = DriveGraph::get()->getNode(getSuccessor(i));
|
||||
dn->markAllSuccessorsToUse(i, &m_path_to_node);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
for(unsigned int i = 0; i < m_path_to_node.size(); ++i)
|
||||
{
|
||||
if(m_path_to_node[i] == -1)
|
||||
Log::warn("GraphNode", "No path to node %d found on graph node %d.",
|
||||
i, m_node_index);
|
||||
Log::warn("DriveNode", "No path to node %d found on drive node %d.",
|
||||
i, m_index);
|
||||
}
|
||||
#endif
|
||||
} // setupPathsToNode
|
||||
@ -145,22 +142,22 @@ void GraphNode::setupPathsToNode()
|
||||
* \param path_to_node The path-to-node data structure of the node for
|
||||
* which the paths are currently determined.
|
||||
*/
|
||||
void GraphNode::markAllSuccessorsToUse(unsigned int n,
|
||||
void DriveNode::markAllSuccessorsToUse(unsigned int n,
|
||||
PathToNodeVector *path_to_node)
|
||||
{
|
||||
// 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++)
|
||||
{
|
||||
GraphNode* gn = QuadGraph::get()->getNode(getSuccessor(i));
|
||||
gn->markAllSuccessorsToUse(n, path_to_node);
|
||||
DriveNode* dn = DriveGraph::get()->getNode(getSuccessor(i));
|
||||
dn->markAllSuccessorsToUse(n, path_to_node);
|
||||
}
|
||||
} // markAllSuccesorsToUse
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GraphNode::setDirectionData(unsigned int successor, DirectionType dir,
|
||||
void DriveNode::setDirectionData(unsigned int successor, DirectionType dir,
|
||||
unsigned int last_node_index)
|
||||
{
|
||||
if(m_direction.size()<successor+1)
|
||||
@ -173,7 +170,7 @@ void GraphNode::setDirectionData(unsigned int successor, DirectionType dir,
|
||||
} // setDirectionData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GraphNode::setChecklineRequirements(int latest_checkline)
|
||||
void DriveNode::setChecklineRequirements(int latest_checkline)
|
||||
{
|
||||
m_checkline_requirements.push_back(latest_checkline);
|
||||
} // setChecklineRequirements
|
||||
@ -183,7 +180,7 @@ void GraphNode::setChecklineRequirements(int latest_checkline)
|
||||
* is allowed to use.
|
||||
* \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
|
@ -16,19 +16,19 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||
|
||||
#ifndef HEADER_GRAPH_NODE_HPP
|
||||
#define HEADER_GRAPH_NODE_HPP
|
||||
#ifndef HEADER_DRIVE_NODE_HPP
|
||||
#define HEADER_DRIVE_NODE_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "tracks/quad.hpp"
|
||||
|
||||
/**
|
||||
* \brief This class stores a node of the graph, i.e. a list of successor
|
||||
* edges, it can either be 2d or 3d.
|
||||
* \brief This class stores a node of the drive graph, i.e. a list of
|
||||
* successor edges, it can either be 2d or 3d.
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class GraphNode : public Quad
|
||||
class DriveNode : public Quad
|
||||
{
|
||||
public:
|
||||
/** To indiciate in which direction the track is going:
|
||||
@ -37,29 +37,20 @@ public:
|
||||
enum DirectionType {DIR_STRAIGHT, DIR_LEFT, DIR_RIGHT,
|
||||
DIR_UNDEFINED};
|
||||
protected:
|
||||
/** Lower center point of the graph node. */
|
||||
/** Lower center point of the drive node. */
|
||||
Vec3 m_lower_center;
|
||||
|
||||
/** Upper center point of the graph node. */
|
||||
/** Upper center point of the drive node. */
|
||||
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;
|
||||
|
||||
private:
|
||||
/** Normal of the graph node */
|
||||
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. */
|
||||
/** Set to true if this drive node should not be used by the AI. */
|
||||
bool m_ai_ignore;
|
||||
|
||||
/** Index of this graph node. */
|
||||
unsigned int m_node_index;
|
||||
|
||||
/** The list of successor graph nodes. */
|
||||
/** The list of successor drive nodes. */
|
||||
std::vector<int> m_successor_nodes;
|
||||
|
||||
/** The list of predecessors of a node. */
|
||||
@ -79,18 +70,18 @@ private:
|
||||
Vec3 m_center_to_right;
|
||||
|
||||
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
|
||||
* of the successor to use in order to reach graph node X for this
|
||||
* graph nodes. */
|
||||
* of the successor to use in order to reach drive node X for this
|
||||
* drive nodes. */
|
||||
PathToNodeVector m_path_to_node;
|
||||
|
||||
/** The direction for each of the successors. */
|
||||
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
|
||||
* 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. */
|
||||
std::vector<unsigned int> m_last_index_same_direction;
|
||||
|
||||
@ -105,16 +96,17 @@ private:
|
||||
*/
|
||||
std::vector< int > m_checkline_requirements;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void markAllSuccessorsToUse(unsigned int n,
|
||||
PathToNodeVector *m_path_to_node);
|
||||
|
||||
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,
|
||||
unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~GraphNode() {}
|
||||
virtual ~DriveNode() {}
|
||||
// ------------------------------------------------------------------------
|
||||
void addSuccessor (unsigned int to);
|
||||
// ------------------------------------------------------------------------
|
||||
@ -131,7 +123,7 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the i-th successor node. */
|
||||
unsigned int getSuccessor(unsigned int i) const
|
||||
{ return m_successor_nodes[i]; }
|
||||
{ return m_successor_nodes[i]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of predecessors. */
|
||||
unsigned int getNumberOfPredecessors() const
|
||||
@ -140,47 +132,41 @@ public:
|
||||
/** Returns a predecessor for this node. Note that the first predecessor
|
||||
* is the most 'natural' one, i.e. the one on the main driveline.
|
||||
*/
|
||||
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; }
|
||||
int getPredecessor(unsigned int i) const { return m_predecessor_nodes[i]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance to the j-th. successor. */
|
||||
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. */
|
||||
float getAngleToSuccessor(unsigned int j) const
|
||||
{ return m_angle_to_next[j]; }
|
||||
{ return m_angle_to_next[j]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance from start. */
|
||||
float getDistanceFromStart() const
|
||||
{ return m_distance_from_start; }
|
||||
{ return m_distance_from_start; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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. */
|
||||
float getPathWidth() const { return m_width; }
|
||||
float getPathWidth() const { return m_width; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center point of the lower edge of this graph node. */
|
||||
const Vec3& getLowerCenter() const {return m_lower_center;}
|
||||
/** Returns the center point of the lower edge of this drive node. */
|
||||
const Vec3& getLowerCenter() const { return m_lower_center; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center point of the upper edge of this graph node. */
|
||||
const Vec3& getUpperCenter() const {return m_upper_center;}
|
||||
/** Returns the center point of the upper edge of this drive node. */
|
||||
const Vec3& getUpperCenter() const { return m_upper_center; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the length of the quad of this node. */
|
||||
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;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns which successor node to use in order to be able to reach the
|
||||
* 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)
|
||||
{
|
||||
@ -189,7 +175,7 @@ public:
|
||||
return m_path_to_node.size()>0 ? m_path_to_node[n] : 0;
|
||||
} // getSuccesorToReach
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the checkline requirements of this graph node. */
|
||||
/** Returns the checkline requirements of this drive node. */
|
||||
const std::vector<int>& getChecklineRequirements() const
|
||||
{ return m_checkline_requirements; }
|
||||
// ------------------------------------------------------------------------
|
||||
@ -201,17 +187,13 @@ public:
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a unit vector pointing to the right side of the quad. */
|
||||
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; }
|
||||
const Vec3 &getRightUnitVector() const { return m_right_unit_vector; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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;
|
||||
|
||||
}; // GraphNode
|
||||
}; // DriveNode
|
||||
|
||||
#endif
|
@ -16,13 +16,15 @@
|
||||
// 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/node_2d.hpp"
|
||||
#include "tracks/drive_node_2d.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Node2D::Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
||||
DriveNode2D::DriveNode2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
const Vec3 &p3, const Vec3 &normal,
|
||||
unsigned int node_index, bool invisible,
|
||||
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_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
|
||||
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
|
||||
m_lower_center.getZ());
|
||||
} // Node2D
|
||||
} // DriveNode2D
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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
|
||||
* 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 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!
|
||||
* \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 closest = m_line.getClosestPoint(xyz2d);
|
@ -16,10 +16,10 @@
|
||||
// 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_NODE_2D_HPP
|
||||
#define HEADER_NODE_2D_HPP
|
||||
#ifndef HEADER_DRIVE_NODE_2D_HPP
|
||||
#define HEADER_DRIVE_NODE_2D_HPP
|
||||
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include <line2d.h>
|
||||
@ -27,7 +27,7 @@
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class Node2D : public GraphNode
|
||||
class DriveNode2D : public DriveNode
|
||||
{
|
||||
private:
|
||||
/** The center point of the lower two points (e.g. points 0 and 1).
|
||||
@ -43,9 +43,9 @@ private:
|
||||
core::line2df m_line;
|
||||
|
||||
public:
|
||||
Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
DriveNode2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
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
|
||||
// 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,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
||||
DriveNode3D::DriveNode3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
const Vec3 &p3, const Vec3 &normal,
|
||||
unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
: DriveNode(p0, p1, p2, p3, normal, node_index, invisible,
|
||||
ai_ignore)
|
||||
{
|
||||
BoundingBox3D::init(p0, p1, p2, p3, normal);
|
||||
m_line = core::line3df(m_lower_center.toIrrVector(),
|
||||
m_upper_center.toIrrVector());
|
||||
} // Node3D
|
||||
} // DriveNode3D
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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
|
||||
* 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 closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||
@ -59,7 +61,7 @@ void Node3D::getDistances(const Vec3 &xyz, Vec3 *result) const
|
||||
* which belongs to this node.
|
||||
* \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());
|
||||
return (closest-xyz.toIrrVector()).getLengthSQ();
|
@ -16,18 +16,18 @@
|
||||
// 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_NODE_3D_HPP
|
||||
#define HEADER_NODE_3D_HPP
|
||||
#ifndef HEADER_DRIVE_NODE_3D_HPP
|
||||
#define HEADER_DRIVE_NODE_3D_HPP
|
||||
|
||||
#include "tracks/bounding_box_3d.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class Node3D : public GraphNode,
|
||||
public BoundingBox3D
|
||||
class DriveNode3D : public DriveNode,
|
||||
public BoundingBox3D
|
||||
{
|
||||
private:
|
||||
/** Line between lower and upper center, saves computation in
|
||||
@ -36,9 +36,9 @@ private:
|
||||
core::line3df m_line;
|
||||
|
||||
public:
|
||||
Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
DriveNode3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool pointInside(const Vec3& p,
|
||||
bool ignore_vertical = false) const OVERRIDE
|
@ -30,8 +30,8 @@
|
||||
#include "graphics/rtts.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "tracks/arena_node_3d.hpp"
|
||||
#include "tracks/node_2d.hpp"
|
||||
#include "tracks/node_3d.hpp"
|
||||
#include "tracks/drive_node_2d.hpp"
|
||||
#include "tracks/drive_node_3d.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
const int Graph::UNKNOWN_SECTOR = -1;
|
||||
@ -426,7 +426,7 @@ void Graph::createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -440,7 +440,7 @@ void Graph::createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -614,5 +614,3 @@ int Graph::findOutOfRoadSector(const Vec3& xyz, const int curr_sector,
|
||||
}
|
||||
return min_sector;
|
||||
} // findOutOfRoadSector
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -40,8 +40,15 @@ class Quad;
|
||||
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
|
||||
{
|
||||
protected:
|
||||
@ -55,7 +62,8 @@ protected:
|
||||
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,
|
||||
const Vec3 &p3, unsigned int node_index,
|
||||
bool invisible, bool ai_ignore, bool is_arena);
|
||||
@ -90,11 +98,11 @@ public:
|
||||
static const int UNKNOWN_SECTOR;
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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
|
||||
* assert that an instance exist. */
|
||||
* is no instance created (e.g. arena without navmesh) so we don't assert
|
||||
* that an instance exist. */
|
||||
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)
|
||||
{
|
||||
assert(m_graph == NULL);
|
||||
@ -102,8 +110,8 @@ public:
|
||||
} // create
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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
|
||||
* not an error if there is no instance. */
|
||||
* if no instance exists (e.g. arena without navmesh). So it is not an
|
||||
* error if there is no instance. */
|
||||
static void destroy()
|
||||
{
|
||||
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/bezier_curve.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.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_object_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -277,7 +277,6 @@ void Track::reset()
|
||||
*/
|
||||
void Track::cleanup()
|
||||
{
|
||||
QuadGraph::destroy();
|
||||
Graph::destroy();
|
||||
ItemManager::destroy();
|
||||
VAOManager::kill();
|
||||
@ -374,7 +373,7 @@ void Track::cleanup()
|
||||
}
|
||||
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++)
|
||||
@ -715,24 +714,25 @@ btQuaternion Track::getArenaStartRotation(const Vec3& xyz, float heading)
|
||||
} // 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.
|
||||
*/
|
||||
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,
|
||||
m_root+m_all_modes[mode_id].m_graph_name,
|
||||
reverse);
|
||||
new DriveGraph(m_root+m_all_modes[mode_id].m_quad_name,
|
||||
m_root+m_all_modes[mode_id].m_graph_name, reverse);
|
||||
|
||||
QuadGraph::get()->setupPaths();
|
||||
// setGraph is done in DriveGraph constructor
|
||||
assert(DriveGraph::get());
|
||||
DriveGraph::get()->setupPaths();
|
||||
#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
|
||||
|
||||
if(QuadGraph::get()->getNumNodes()==0)
|
||||
if(DriveGraph::get()->getNumNodes()==0)
|
||||
{
|
||||
Log::warn("track", "No graph nodes defined for track '%s'\n",
|
||||
m_filename.c_str());
|
||||
@ -746,16 +746,13 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
||||
{
|
||||
loadMinimap();
|
||||
}
|
||||
} // loadQuadGraph
|
||||
} // loadDriveGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
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);
|
||||
else
|
||||
QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
Graph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
draw_at->setX(draw_at->getX() * m_minimap_x_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
|
||||
.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
QuadGraph::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);
|
||||
|
||||
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 information about the size of the texture to render the mini
|
||||
// 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)
|
||||
loadArenaGraph(*root);
|
||||
|
||||
@ -1718,7 +1707,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
}
|
||||
else
|
||||
m_start_transforms.resize(race_manager->getNumberOfKarts());
|
||||
QuadGraph::get()->setDefaultStartPositions(&m_start_transforms,
|
||||
DriveGraph::get()->setDefaultStartPositions(&m_start_transforms,
|
||||
karts_per_row,
|
||||
forwards_distance,
|
||||
sidewards_distance,
|
||||
@ -1929,7 +1918,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
World *world = World::getWorld();
|
||||
if (world->useChecklineRequirements())
|
||||
{
|
||||
QuadGraph::get()->computeChecklineRequirements();
|
||||
DriveGraph::get()->computeChecklineRequirements();
|
||||
}
|
||||
|
||||
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
|
||||
// Also do a raycast if drop item is given
|
||||
Vec3 normal(0, 1, 0);
|
||||
Vec3 quad_normal = normal;
|
||||
Vec3 hit_point = loc;
|
||||
Node3D* node_3d = NULL;
|
||||
if (QuadGraph::get())
|
||||
if (Graph::get())
|
||||
{
|
||||
int road_sector = QuadGraph::UNKNOWN_SECTOR;
|
||||
QuadGraph::get()->findRoadSector(xyz, &road_sector);
|
||||
int road_sector = Graph::UNKNOWN_SECTOR;
|
||||
Graph::get()->findRoadSector(xyz, &road_sector);
|
||||
// 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 =
|
||||
dynamic_cast<Node3D*>(QuadGraph::get()->getNode(road_sector));
|
||||
quad_normal = Graph::get()->getQuad(road_sector)->getNormal();
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 quad_normal = node_3d ? node_3d->getNormal() : Vec3(0, 1, 0);
|
||||
if (node_3d || drop)
|
||||
if (drop)
|
||||
{
|
||||
const Material *m;
|
||||
// If raycast is used, increase the start position slightly
|
||||
// in case that the point is too close to the actual surface
|
||||
// (e.g. floating point errors can cause a problem here).
|
||||
// Only do so for 2d node
|
||||
if (node_3d == NULL)
|
||||
loc += Vec3(0.0f, 0.1f, 0.0f);
|
||||
loc += quad_normal * 0.1;
|
||||
|
||||
#ifndef DEBUG
|
||||
m_track_mesh->castRay(loc, loc + (-10000 * quad_normal), &hit_point,
|
||||
@ -2323,8 +2308,7 @@ void Track::itemCommand(const XMLNode *node)
|
||||
#endif
|
||||
}
|
||||
|
||||
ItemManager::get()->newItem(type, drop ? hit_point : loc,
|
||||
node_3d ? normal : Vec3(0, 1, 0));
|
||||
ItemManager::get()->newItem(type, drop ? hit_point : loc, normal);
|
||||
} // itemCommand
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -2434,11 +2418,11 @@ bool Track::findGround(AbstractKart *kart)
|
||||
//-----------------------------------------------------------------------------
|
||||
float Track::getTrackLength() const
|
||||
{
|
||||
return QuadGraph::get()->getLapLength();
|
||||
return DriveGraph::get()->getLapLength();
|
||||
} // getTrackLength
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float Track::getAngle(int n) const
|
||||
{
|
||||
return QuadGraph::get()->getAngleToNext(n, 0);
|
||||
return DriveGraph::get()->getAngleToNext(n, 0);
|
||||
} // getAngle
|
||||
|
@ -373,7 +373,7 @@ private:
|
||||
int m_actual_number_of_laps;
|
||||
|
||||
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);
|
||||
btQuaternion getArenaStartRotation(const Vec3& xyz, float heading);
|
||||
void convertTrackToBullet(scene::ISceneNode *node);
|
||||
|
@ -16,15 +16,16 @@
|
||||
// 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/track_sector.hpp"
|
||||
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/check_structure.hpp"
|
||||
#include "tracks/track_sector.hpp"
|
||||
#include "tracks/arena_graph.hpp"
|
||||
#include "tracks/arena_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "tracks/drive_node.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the object, and sets the current graph node to be undefined.
|
||||
@ -37,8 +38,8 @@ TrackSector::TrackSector()
|
||||
// ----------------------------------------------------------------------------
|
||||
void TrackSector::reset()
|
||||
{
|
||||
m_current_graph_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
m_last_valid_graph_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
m_current_graph_node = Graph::UNKNOWN_SECTOR;
|
||||
m_last_valid_graph_node = Graph::UNKNOWN_SECTOR;
|
||||
m_on_road = false;
|
||||
m_last_triggered_checkline = -1;
|
||||
} // reset
|
||||
@ -79,8 +80,8 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical)
|
||||
if (ag) return;
|
||||
// keep the current quad as the latest valid one IF the player has one
|
||||
// of the required checklines
|
||||
const GraphNode* gn = QuadGraph::get()->getNode(m_current_graph_node);
|
||||
const std::vector<int>& checkline_requirements = gn->getChecklineRequirements();
|
||||
const DriveNode* dn = DriveGraph::get()->getNode(m_current_graph_node);
|
||||
const std::vector<int>& checkline_requirements = dn->getChecklineRequirements();
|
||||
|
||||
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
|
||||
// track, and how far to the left or right of the center driveline.
|
||||
QuadGraph::get()->spatialToTrack(&m_current_track_coords, xyz,
|
||||
m_current_graph_node);
|
||||
DriveGraph::get()->spatialToTrack(&m_current_track_coords, xyz,
|
||||
m_current_graph_node);
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -116,7 +117,7 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical)
|
||||
*/
|
||||
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;
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
m_current_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
|
||||
->getPredecessor(0);
|
||||
m_last_valid_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
|
||||
->getPredecessor(0);
|
||||
m_current_graph_node = DriveGraph::get()->getNode(m_current_graph_node)
|
||||
->getPredecessor(0);
|
||||
m_last_valid_graph_node = DriveGraph::get()->getNode(m_current_graph_node)
|
||||
->getPredecessor(0);
|
||||
} // rescue
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -137,7 +138,7 @@ void TrackSector::rescue()
|
||||
*/
|
||||
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
|
||||
// This way we get a value between -1 and 1.
|
||||
float ratio = getDistanceToCenter()/(w*0.5f);
|
||||
|
Loading…
Reference in New Issue
Block a user