Port all function from battle graph to new graph interface
This commit is contained in:
@@ -145,7 +145,7 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
{
|
||||
Graph::get()->findRoadSector(xyz, &m_graph_node);
|
||||
}
|
||||
else if (!ArenaGraph::get()) // Todo replace with driveline graph
|
||||
if (Graph::get() && !ArenaGraph::get()) // Todo replace with driveline graph
|
||||
{
|
||||
// Item is on quad graph. Pre-compute the distance from center
|
||||
// of this item, which is used by the AI (mostly for avoiding items)
|
||||
|
||||
@@ -32,10 +32,9 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/arena_graph.hpp"
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "tracks/graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/arena_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
@@ -426,7 +425,6 @@ void ItemManager::deleteItem(Item *item)
|
||||
// First check if the item needs to be removed from the items-in-quad list
|
||||
if(m_items_in_quads)
|
||||
{
|
||||
const Vec3 &xyz = item->getXYZ();
|
||||
int sector = item->getGraphNode();
|
||||
unsigned int indx = sector==Graph::UNKNOWN_SECTOR
|
||||
? (unsigned int) m_items_in_quads->size()-1
|
||||
@@ -480,40 +478,41 @@ void ItemManager::switchItems()
|
||||
bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
{
|
||||
if (!UserConfigParams::m_random_arena_item) return false;
|
||||
if (!BattleGraph::get()) return false;
|
||||
if (!ArenaGraph::get()) return false;
|
||||
|
||||
const ArenaGraph* ag = ArenaGraph::get();
|
||||
std::vector<int> used_location;
|
||||
std::vector<int> invalid_location;
|
||||
for (unsigned int i = 0; i < pos.size(); i++)
|
||||
{
|
||||
// Load all starting positions of arena, so no items will be near them
|
||||
int node = BattleGraph::get()->pointToNode(/*cur_node*/-1,
|
||||
Vec3(pos[i].getOrigin()), /*ignore_vertical*/true);
|
||||
int node = -1;
|
||||
ag->findRoadSector(pos[i].getOrigin(), &node, NULL, true);
|
||||
assert(node != -1);
|
||||
used_location.push_back(node);
|
||||
invalid_location.push_back(node);
|
||||
}
|
||||
|
||||
RandomGenerator random;
|
||||
const unsigned int MIN_DIST = int(sqrt(BattleGraph::get()->getNumNodes()));
|
||||
const unsigned int ALL_NODES = ag->getNumNodes();
|
||||
const unsigned int MIN_DIST = int(sqrt(ALL_NODES));
|
||||
const unsigned int TOTAL_ITEM = MIN_DIST / 2;
|
||||
|
||||
Log::info("[ItemManager]","Creating %d random items for arena", TOTAL_ITEM);
|
||||
for (unsigned int i = 0; i < TOTAL_ITEM; i++)
|
||||
{
|
||||
int chosen_node = -1;
|
||||
const unsigned int total_node = BattleGraph::get()->getNumNodes();
|
||||
while(true)
|
||||
{
|
||||
if (used_location.size() - pos.size() +
|
||||
invalid_location.size() == total_node)
|
||||
invalid_location.size() == ALL_NODES)
|
||||
{
|
||||
Log::warn("[ItemManager]","Can't place more random items! "
|
||||
"Use default item location.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const int node = random.get(total_node);
|
||||
const int node = random.get(ALL_NODES);
|
||||
|
||||
// Check if tried
|
||||
std::vector<int>::iterator it = std::find(invalid_location.begin(),
|
||||
@@ -522,7 +521,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
continue;
|
||||
|
||||
// Check if near edge
|
||||
if (BattleGraph::get()->isNearEdge(node))
|
||||
if (ag->getNode(node)->isNearEdge())
|
||||
{
|
||||
invalid_location.push_back(node);
|
||||
continue;
|
||||
@@ -532,8 +531,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
for (unsigned int j = 0; j < used_location.size(); j++)
|
||||
{
|
||||
if (!found) continue;
|
||||
float test_distance = BattleGraph::get()
|
||||
->getDistance(used_location[j], node);
|
||||
float test_distance = ag->getDistance(used_location[j], node);
|
||||
found = test_distance > MIN_DIST;
|
||||
}
|
||||
if (found)
|
||||
@@ -566,10 +564,31 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
Item::ItemType type = (j > BONUS_BOX ? Item::ITEM_BONUS_BOX :
|
||||
j > NITRO_BIG ? Item::ITEM_NITRO_BIG :
|
||||
j > NITRO_SMALL ? Item::ITEM_NITRO_SMALL : Item::ITEM_BANANA);
|
||||
Vec3 loc = BattleGraph::get()
|
||||
->getQuadOfNode(used_location[i]).getCenter();
|
||||
Item* item = newItem(type, loc, Vec3(0, 1, 0));
|
||||
BattleGraph::get()->insertItems(item, used_location[i]);
|
||||
|
||||
ArenaNode* an = ag->getNode(used_location[i]);
|
||||
Vec3 loc = an->getCenter();
|
||||
Vec3 quad_normal = an->getNormal();
|
||||
loc += quad_normal;
|
||||
|
||||
// Do a raycast to help place it fully on the surface
|
||||
const Material* m;
|
||||
Vec3 normal;
|
||||
Vec3 hit_point;
|
||||
const TriangleMesh& tm =
|
||||
World::getWorld()->getTrack()->getTriangleMesh();
|
||||
bool success = tm.castRay(loc, an->getCenter() + (-10000*quad_normal),
|
||||
&hit_point, &m, &normal);
|
||||
|
||||
if (success)
|
||||
{
|
||||
newItem(type, hit_point, normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("[ItemManager]","Raycast to surface failed"
|
||||
"from node %d", used_location[i]);
|
||||
newItem(type, an->getCenter(), quad_normal);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -30,15 +30,6 @@
|
||||
#include "tracks/arena_node.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
int ArenaAI::m_test_node_for_banana = Graph::UNKNOWN_SECTOR;
|
||||
|
||||
bool isNodeWithBanana(const std::pair<const Item*, int>& item_pair)
|
||||
{
|
||||
return item_pair.second == ArenaAI::m_test_node_for_banana &&
|
||||
item_pair.first->getType() == Item::ITEM_BANANA &&
|
||||
!item_pair.first->wasCollected();
|
||||
}
|
||||
|
||||
ArenaAI::ArenaAI(AbstractKart *kart)
|
||||
: AIBaseController(kart)
|
||||
{
|
||||
|
||||
@@ -128,7 +128,6 @@ private:
|
||||
virtual bool forceBraking() { return m_avoiding_item; }
|
||||
virtual bool ignorePathFinding() { return false; }
|
||||
public:
|
||||
static int m_test_node_for_banana;
|
||||
ArenaAI(AbstractKart *kart);
|
||||
virtual ~ArenaAI() {};
|
||||
virtual void update (float delta);
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
@@ -1,467 +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
|
||||
|
||||
#include "tracks/battle_graph.hpp"
|
||||
|
||||
#include <IMesh.h>
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <IMeshSceneNode.h>
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
#include "tracks/quad.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
|
||||
const int BattleGraph::UNKNOWN_POLY = -1;
|
||||
BattleGraph * BattleGraph::m_battle_graph = NULL;
|
||||
|
||||
/** Constructor, Creates a navmesh, builds a graph from the navmesh and
|
||||
* then runs shortest path algorithm to find and store paths to be used
|
||||
* by the AI. */
|
||||
BattleGraph::BattleGraph(const std::string &navmesh_file_name,
|
||||
const XMLNode *node)
|
||||
{
|
||||
m_items_on_graph.clear();
|
||||
|
||||
NavMesh::create(navmesh_file_name);
|
||||
m_navmesh_file = navmesh_file_name;
|
||||
buildGraph(NavMesh::get());
|
||||
|
||||
// Compute shortest distance from all nodes
|
||||
for(unsigned int i=0; i < NavMesh::get()->getNumberOfQuads(); i++)
|
||||
computeDijkstra(i);
|
||||
|
||||
sortNearbyQuad();
|
||||
if (node && race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
loadGoalNodes(node);
|
||||
|
||||
} // BattleGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Destructor, destroys NavMesh and the debug mesh if it exists */
|
||||
BattleGraph::~BattleGraph(void)
|
||||
{
|
||||
NavMesh::destroy();
|
||||
|
||||
if(UserConfigParams::m_track_debug)
|
||||
cleanupDebugMesh();
|
||||
GraphStructure::destroyRTT();
|
||||
} // ~BattleGraph
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Builds a graph from an existing NavMesh. The graph is stored as an
|
||||
* adjacency matrix. */
|
||||
void BattleGraph::buildGraph(NavMesh* navmesh)
|
||||
{
|
||||
const unsigned int n_quads = navmesh->getNumberOfQuads();
|
||||
|
||||
m_distance_matrix = std::vector<std::vector<float>>
|
||||
(n_quads, std::vector<float>(n_quads, 9999.9f));
|
||||
for(unsigned int i = 0; i < n_quads; i++)
|
||||
{
|
||||
const Quad& cur_quad = navmesh->getQuad(i);
|
||||
for (const int& adjacent : navmesh->getAdjacentQuads(i))
|
||||
{
|
||||
Vec3 diff = navmesh->getQuad(adjacent).getCenter()
|
||||
- cur_quad.getCenter();
|
||||
float distance = diff.length();
|
||||
m_distance_matrix[i][adjacent] = distance;
|
||||
}
|
||||
m_distance_matrix[i][i] = 0.0f;
|
||||
}
|
||||
|
||||
// Allocate and initialise the previous node data structure:
|
||||
m_parent_poly = std::vector<std::vector<int>>
|
||||
(n_quads, std::vector<int>(n_quads, BattleGraph::UNKNOWN_POLY));
|
||||
for (unsigned int i = 0; i < n_quads; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < n_quads; j++)
|
||||
{
|
||||
if(i == j || m_distance_matrix[i][j] >= 9899.9f)
|
||||
m_parent_poly[i][j] = -1;
|
||||
else
|
||||
m_parent_poly[i][j] = i;
|
||||
} // for j
|
||||
} // for i
|
||||
|
||||
} // buildGraph
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Dijkstra shortest path computation. It computes the shortest distance from
|
||||
* the specified node 'source' to all other nodes. At the end of the
|
||||
* computation, m_distance_matrix[i][j] stores the shortest path distance from
|
||||
* source to j and m_parent_poly[source][j] stores the last vertex visited on
|
||||
* the shortest path from i to j before visiting j. Suppose the shortest path
|
||||
* from i to j is i->......->k->j then m_parent_poly[i][j] = k
|
||||
*/
|
||||
void BattleGraph::computeDijkstra(int source)
|
||||
{
|
||||
// Stores the distance (float) to 'source' from a specified node (int)
|
||||
typedef std::pair<int, float> IndDistPair;
|
||||
|
||||
class Shortest
|
||||
{
|
||||
public:
|
||||
bool operator()(const IndDistPair &p1, const IndDistPair &p2)
|
||||
{
|
||||
return p1.second > p2.second;
|
||||
}
|
||||
};
|
||||
std::priority_queue<IndDistPair, std::vector<IndDistPair>, Shortest> queue;
|
||||
IndDistPair begin(source, 0.0f);
|
||||
queue.push(begin);
|
||||
const unsigned int n=getNumNodes();
|
||||
std::vector<bool> visited;
|
||||
visited.resize(n, false);
|
||||
NavMesh *navmesh = NavMesh::get();
|
||||
while(!queue.empty())
|
||||
{
|
||||
// Get element with shortest path
|
||||
IndDistPair current = queue.top();
|
||||
queue.pop();
|
||||
int cur_index = current.first;
|
||||
if(visited[cur_index]) continue;
|
||||
visited[cur_index] = true;
|
||||
|
||||
for (const int& adjacent : navmesh->getAdjacentQuads(cur_index))
|
||||
{
|
||||
// Distance already computed, can be ignored
|
||||
if(visited[adjacent]) continue;
|
||||
|
||||
float new_dist = current.second + m_distance_matrix[cur_index][adjacent];
|
||||
if(new_dist < m_distance_matrix[source][adjacent])
|
||||
{
|
||||
m_distance_matrix[source][adjacent] = new_dist;
|
||||
m_parent_poly[source][adjacent] = cur_index;
|
||||
}
|
||||
IndDistPair pair(adjacent, new_dist);
|
||||
queue.push(pair);
|
||||
}
|
||||
}
|
||||
} // computeDijkstra
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** THIS FUNCTION IS ONLY USED FOR UNIT-TESTING, to verify that the new
|
||||
* Dijkstra algorithm gives the same results.
|
||||
* computeFloydWarshall() computes the shortest distance between any two
|
||||
* nodes. At the end of the computation, m_distance_matrix[i][j] stores the
|
||||
* shortest path distance from i to j and m_parent_poly[i][j] stores the last
|
||||
* vertex visited on the shortest path from i to j before visiting j. Suppose
|
||||
* the shortest path from i to j is i->......->k->j then
|
||||
* m_parent_poly[i][j] = k
|
||||
*/
|
||||
void BattleGraph::computeFloydWarshall()
|
||||
{
|
||||
unsigned int n = getNumNodes();
|
||||
|
||||
// initialize m_parent_poly with unknown_poly so that if no path is found b/w i and j
|
||||
// then m_parent_poly[i][j] = -1 (UNKNOWN_POLY)
|
||||
// AI must check this
|
||||
m_parent_poly = std::vector< std::vector<int> > (n, std::vector<int>(n,BattleGraph::UNKNOWN_POLY));
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
for(unsigned int j=0; j<n; j++)
|
||||
{
|
||||
if(i == j || m_distance_matrix[i][j]>=9899.9f) m_parent_poly[i][j]=-1;
|
||||
else m_parent_poly[i][j] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int k=0; k<n; k++)
|
||||
{
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
for(unsigned int j=0; j<n; j++)
|
||||
{
|
||||
if( (m_distance_matrix[i][k] + m_distance_matrix[k][j]) < m_distance_matrix[i][j])
|
||||
{
|
||||
m_distance_matrix[i][j] = m_distance_matrix[i][k] + m_distance_matrix[k][j];
|
||||
m_parent_poly[i][j] = m_parent_poly[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // computeFloydWarshall
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Maps items on battle graph */
|
||||
void BattleGraph::findItemsOnGraphNodes()
|
||||
{
|
||||
const ItemManager* item_manager = ItemManager::get();
|
||||
unsigned int item_count = item_manager->getNumberOfItems();
|
||||
|
||||
for (unsigned int i = 0; i < item_count; ++i)
|
||||
{
|
||||
const Item* item = item_manager->getItem(i);
|
||||
Vec3 xyz = item->getXYZ();
|
||||
int polygon = BattleGraph::UNKNOWN_POLY;
|
||||
|
||||
for (unsigned int j = 0; j < this->getNumNodes(); ++j)
|
||||
{
|
||||
if (getQuadOfNode(j).pointInside(xyz, false))
|
||||
polygon = j;
|
||||
}
|
||||
|
||||
if (polygon != BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
m_items_on_graph.push_back(std::make_pair(item, polygon));
|
||||
Log::debug("BattleGraph","item number %d is on polygon %d", i, polygon);
|
||||
}
|
||||
else
|
||||
Log::debug("BattleGraph","Can't map item number %d with a suitable polygon", i);
|
||||
}
|
||||
} // findItemsOnGraphNodes
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
int BattleGraph::pointToNode(const int cur_node,
|
||||
const Vec3& cur_point,
|
||||
bool ignore_vertical) const
|
||||
{
|
||||
if (cur_node == BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
// Try all nodes in the battle graph
|
||||
for (unsigned int node = 0; node < this->getNumNodes(); node++)
|
||||
{
|
||||
const Quad& quad = this->getQuadOfNode(node);
|
||||
if (quad.pointInside(cur_point, ignore_vertical))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if the point is still on the same node
|
||||
const Quad& cur_quad = this->getQuadOfNode(cur_node);
|
||||
if (cur_quad.pointInside(cur_point, ignore_vertical)) return cur_node;
|
||||
|
||||
// If not then check all nearby quads (8 quads)
|
||||
// Skip the same node
|
||||
assert(cur_node == m_nearby_quads[cur_node][0]);
|
||||
for (unsigned int i = 1; i < m_nearby_quads[0].size(); i++)
|
||||
{
|
||||
const int test_node = m_nearby_quads[cur_node][i];
|
||||
const Quad& quad = this->getQuadOfNode(test_node);
|
||||
if (quad.pointInside(cur_point, ignore_vertical))
|
||||
{
|
||||
return test_node;
|
||||
}
|
||||
}
|
||||
|
||||
// Current node is still unkown:
|
||||
// Calculated distance from saved node to current position,
|
||||
// if it's close enough than use the saved node anyway, it
|
||||
// may happen when the kart stays on the edge of obstacles
|
||||
Vec3 diff = (cur_quad.getCenter() - cur_point);
|
||||
float dist = diff.length();
|
||||
|
||||
if (dist < 3.0f)
|
||||
return cur_node;
|
||||
}
|
||||
|
||||
return BattleGraph::UNKNOWN_POLY;
|
||||
} // pointToNode
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
const bool BattleGraph::differentNodeColor(int n, NodeColor* c) const
|
||||
{
|
||||
std::set<int>::iterator it;
|
||||
it = m_red_node.find(n);
|
||||
if (it != m_red_node.end())
|
||||
{
|
||||
*c = COLOR_RED;
|
||||
return true;
|
||||
}
|
||||
|
||||
it = m_blue_node.find(n);
|
||||
if (it != m_blue_node.end())
|
||||
{
|
||||
*c = COLOR_BLUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // differentNodeColor
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void BattleGraph::loadGoalNodes(const XMLNode *node)
|
||||
{
|
||||
m_red_node.clear();
|
||||
m_blue_node.clear();
|
||||
|
||||
const XMLNode *check_node = node->getNode("checks");
|
||||
for (unsigned int i = 0; i < check_node->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *goal = check_node->getNode(i);
|
||||
if (goal->getName() =="goal")
|
||||
{
|
||||
Vec3 p1, p2;
|
||||
bool first_goal = false;
|
||||
goal->get("first_goal", &first_goal);
|
||||
goal->get("p1", &p1);
|
||||
goal->get("p2", &p2);
|
||||
|
||||
int first = pointToNode(/*cur_node*/-1, p1, true);
|
||||
int last = pointToNode(/*cur_node*/-1, p2, true);
|
||||
|
||||
first_goal ? m_blue_node.insert(first) : m_red_node.insert(first);
|
||||
first_goal ? m_blue_node.insert(last) : m_red_node.insert(last);
|
||||
while (first != last)
|
||||
{
|
||||
// Find all the nodes which connect the two points of
|
||||
// goal, notice: only work if it's a straight line
|
||||
first = getNextShortestPathPoly(first, last);
|
||||
first_goal ? m_blue_node.insert(first) :
|
||||
m_red_node.insert(first);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // loadGoalNodes
|
||||
|
||||
// ============================================================================
|
||||
/** Unit testing for battle graph distance and parent node computation.
|
||||
* Instead of using hand-tuned test cases we use the tested, verified and
|
||||
* easier to understand Floyd-Warshall algorithm to compute the distances,
|
||||
* and check if the (significanty faster) Dijkstra algorithm gives the same
|
||||
* results. For now we use the cave mesh as test case.
|
||||
*/
|
||||
void BattleGraph::unitTesting()
|
||||
{
|
||||
Track *track = track_manager->getTrack("cave");
|
||||
std::string navmesh_file_name=track->getTrackFile("navmesh.xml");
|
||||
|
||||
double s = StkTime::getRealTime();
|
||||
BattleGraph *bg = new BattleGraph(navmesh_file_name);
|
||||
double e = StkTime::getRealTime();
|
||||
Log::error("Time", "Dijkstra %lf", e-s);
|
||||
|
||||
// Save the Dijkstra results
|
||||
std::vector< std::vector< float > > distance_matrix = bg->m_distance_matrix;
|
||||
std::vector< std::vector< int > > parent_poly = bg->m_parent_poly;
|
||||
bg->buildGraph(NavMesh::get());
|
||||
|
||||
// Now compute results with Floyd-Warshall
|
||||
s = StkTime::getRealTime();
|
||||
bg->computeFloydWarshall();
|
||||
e = StkTime::getRealTime();
|
||||
Log::error("Time", "Floyd-Warshall %lf", e-s);
|
||||
|
||||
int error_count = 0;
|
||||
for(unsigned int i=0; i<bg->m_distance_matrix.size(); i++)
|
||||
{
|
||||
for(unsigned int j=0; j<bg->m_distance_matrix[i].size(); j++)
|
||||
{
|
||||
if(bg->m_distance_matrix[i][j] - distance_matrix[i][j] > 0.001f)
|
||||
{
|
||||
Log::error("BattleGraph",
|
||||
"Incorrect distance %d, %d: Dijkstra: %f F.W.: %f",
|
||||
i, j, distance_matrix[i][j], bg->m_distance_matrix[i][j]);
|
||||
error_count++;
|
||||
} // if distance is too different
|
||||
|
||||
// Unortunately it happens frequently that there are different
|
||||
// shortest path with the same length. And Dijkstra might find
|
||||
// a different path then Floyd-Warshall. So the test for parent
|
||||
// polygon often results in false positives, so it is disabled,
|
||||
// but I leave the code in place in case it is useful for some
|
||||
// debugging in the feature
|
||||
#undef TEST_PARENT_POLY_EVEN_THOUGH_MANY_FALSE_POSITIVES
|
||||
#ifdef TEST_PARENT_POLY_EVEN_THOUGH_MANY_FALSE_POSITIVES
|
||||
if(bg->m_parent_poly[i][j] != parent_poly[i][j])
|
||||
{
|
||||
error_count++;
|
||||
std::vector<int> dijkstra_path = getPathFromTo(i, j, parent_poly);
|
||||
std::vector<int> floyd_path = getPathFromTo(i, j, bg->m_parent_poly);
|
||||
if(dijkstra_path.size()!=floyd_path.size())
|
||||
{
|
||||
Log::error("BattleGraph",
|
||||
"Incorrect path length %d, %d: Dijkstra: %d F.W.: %d",
|
||||
i, j, parent_poly[i][j], bg->m_parent_poly[i][j]);
|
||||
continue;
|
||||
}
|
||||
Log::error("BattleGraph", "Path problems from %d to %d:",
|
||||
i, j);
|
||||
for (unsigned k = 0; k < dijkstra_path.size(); k++)
|
||||
{
|
||||
if(dijkstra_path[k]!=floyd_path[k])
|
||||
Log::error("BattleGraph", "%d/%d dijkstra: %d floyd %d",
|
||||
k, dijkstra_path.size(), dijkstra_path[k],
|
||||
floyd_path[k]);
|
||||
} // for k<dijkstra_path.size()
|
||||
|
||||
} // if dijkstra parent_poly != floyd parent poly
|
||||
#endif
|
||||
} // for j
|
||||
} // for i
|
||||
} // unitTesting
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines the full path from 'from' to 'to' and returns it in a
|
||||
* std::vector (in reverse order). Used only for unit testing.
|
||||
*/
|
||||
std::vector<int> BattleGraph::getPathFromTo(int from, int to,
|
||||
const std::vector< std::vector< int > > parent_poly)
|
||||
{
|
||||
std::vector<int> path;
|
||||
path.push_back(to);
|
||||
while(from!=to)
|
||||
{
|
||||
to = parent_poly[from][to];
|
||||
path.push_back(to);
|
||||
}
|
||||
return path;
|
||||
} // getPathFromTo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void BattleGraph::sortNearbyQuad()
|
||||
{
|
||||
// Only try the nearby 8 quads
|
||||
const unsigned int n = 8;
|
||||
m_nearby_quads = std::vector< std::vector<int> >
|
||||
(this->getNumNodes(), std::vector<int>(n, BattleGraph::UNKNOWN_POLY));
|
||||
|
||||
for (unsigned int i = 0; i < this->getNumNodes(); i++)
|
||||
{
|
||||
// Get the distance to all nodes at i
|
||||
std::vector<float> dist = m_distance_matrix[i];
|
||||
for (unsigned int j = 0; j < n; j++)
|
||||
{
|
||||
std::vector<float>::iterator it =
|
||||
std::min_element(dist.begin(), dist.end());
|
||||
const int pos = it - dist.begin();
|
||||
m_nearby_quads[i][j] = pos;
|
||||
dist[pos] = 999999.0f;
|
||||
}
|
||||
}
|
||||
} // sortNearbyQuad
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void BattleGraph::set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
||||
const video::SColor &color) const
|
||||
{
|
||||
NavMesh::get()->getQuad(i).getVertices(v, color);
|
||||
} // set3DVerticesOfGraph
|
||||
@@ -1,166 +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_BATTLE_GRAPH_HPP
|
||||
#define HEADER_BATTLE_GRAPH_HPP
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "tracks/graph_structure.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
|
||||
class Item;
|
||||
class ItemManager;
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*
|
||||
* \brief This class stores a graph constructed from the navigatoin mesh.
|
||||
* It uses a 'simplified singleton' design pattern: it has a static create
|
||||
* function to create exactly one 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).
|
||||
\ingroup tracks
|
||||
*/
|
||||
class BattleGraph : public GraphStructure
|
||||
{
|
||||
|
||||
private:
|
||||
static BattleGraph *m_battle_graph;
|
||||
|
||||
/** The actual graph data structure, it is an adjacency matrix */
|
||||
std::vector< std::vector< float > > m_distance_matrix;
|
||||
/** The matrix that is used to store computed shortest paths */
|
||||
std::vector< std::vector< int > > m_parent_poly;
|
||||
|
||||
std::vector< std::vector< int > > m_nearby_quads;
|
||||
|
||||
/** Stores the name of the file containing the NavMesh data */
|
||||
std::string m_navmesh_file;
|
||||
|
||||
std::vector< std::pair<const Item*, int> > m_items_on_graph;
|
||||
|
||||
std::set<int> m_red_node;
|
||||
std::set<int> m_blue_node;
|
||||
|
||||
void buildGraph(NavMesh*);
|
||||
void computeFloydWarshall();
|
||||
void loadGoalNodes(const XMLNode *node);
|
||||
void sortNearbyQuad();
|
||||
|
||||
BattleGraph(const std::string &navmesh_file_name, const XMLNode *node=NULL);
|
||||
~BattleGraph(void);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
||||
const video::SColor &color) const;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const
|
||||
{ NavMesh::get()->getBoundingBox(min, max); }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool isNodeInvisible(int n) const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool hasLapLine() const
|
||||
{ return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool differentNodeColor(int n, NodeColor* c) const;
|
||||
void computeDijkstra(int n);
|
||||
static std::vector<int> getPathFromTo(int from, int to,
|
||||
const std::vector< std::vector< int > > parent_poly);
|
||||
|
||||
public:
|
||||
static const int UNKNOWN_POLY;
|
||||
|
||||
void findItemsOnGraphNodes();
|
||||
// ----------------------------------------------------------------------
|
||||
int pointToNode(const int cur_node,
|
||||
const Vec3& cur_point,
|
||||
bool ignore_vertical) const;
|
||||
// ------------------------------------------------------------------------
|
||||
static void unitTesting();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the one instance of this object. */
|
||||
static BattleGraph *get() { return m_battle_graph; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Asserts that no BattleGraph instance exists. Then
|
||||
* creates a BattleGraph instance. */
|
||||
static void create(const std::string &navmesh_file_name,
|
||||
const XMLNode *node)
|
||||
{
|
||||
assert(m_battle_graph==NULL);
|
||||
m_battle_graph = new BattleGraph(navmesh_file_name, node);
|
||||
} // create
|
||||
// ------------------------------------------------------------------------
|
||||
/** Cleans up the BattleGraph instance if it exists */
|
||||
static void destroy()
|
||||
{
|
||||
if(m_battle_graph)
|
||||
{
|
||||
delete m_battle_graph;
|
||||
m_battle_graph = NULL;
|
||||
}
|
||||
} // destroy
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of nodes in the BattleGraph (equal to the number
|
||||
* of quads in the NavMesh
|
||||
*/
|
||||
virtual const unsigned int getNumNodes() const
|
||||
{ return NavMesh::get()->getNumberOfQuads(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance between any two nodes */
|
||||
float getDistance(int from, int to) const
|
||||
{
|
||||
if (from == BattleGraph::UNKNOWN_POLY ||
|
||||
to == BattleGraph::UNKNOWN_POLY)
|
||||
return 0.0f;
|
||||
return m_distance_matrix[from][to];
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the next polygon on the shortest path from i to j.
|
||||
* Note: m_parent_poly[j][i] contains the parent of i on path from j to i,
|
||||
* which is the next node on the path from i to j (undirected graph)
|
||||
*/
|
||||
int getNextShortestPathPoly(int i, int j) const
|
||||
{
|
||||
if (i == BattleGraph::UNKNOWN_POLY || j == BattleGraph::UNKNOWN_POLY)
|
||||
return BattleGraph::UNKNOWN_POLY;
|
||||
return m_parent_poly[j][i];
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<std::pair<const Item*, int>>& getItemList()
|
||||
{ return m_items_on_graph; }
|
||||
// ------------------------------------------------------------------------
|
||||
void insertItems(Item* item, int polygon)
|
||||
{ m_items_on_graph.push_back(std::make_pair(item, polygon)); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad that belongs to a node. */
|
||||
const Quad& getQuadOfNode(unsigned int n) const
|
||||
{ return NavMesh::get()->getQuad(n); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the quad lies near the edge, which means it doesn't
|
||||
* have 4 adjacent quads.
|
||||
*/
|
||||
bool isNearEdge(unsigned int n) const
|
||||
{ return NavMesh::get()->getAdjacentQuads(n).size() != 4; }
|
||||
// ------------------------------------------------------------------------
|
||||
}; //BattleGraph
|
||||
|
||||
#endif
|
||||
@@ -1,133 +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, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "tracks/navmesh.hpp"
|
||||
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "tracks/quad.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
NavMesh *NavMesh::m_nav_mesh = NULL;
|
||||
|
||||
/** Constructor, loads the mesh information from a given set of polygons
|
||||
* from a navmesh.xml file.
|
||||
* \param filename Name of the file containing all polygons
|
||||
*/
|
||||
NavMesh::NavMesh(const std::string &filename)
|
||||
{
|
||||
|
||||
m_min = Vec3( 99999, 99999, 99999);
|
||||
m_max = Vec3(-99999, -99999, -99999);
|
||||
|
||||
XMLNode *xml = file_manager->createXMLTree(filename);
|
||||
if (xml->getName() != "navmesh")
|
||||
{
|
||||
Log::error("NavMesh", "NavMesh is invalid.");
|
||||
delete xml;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Vec3> all_vertices;
|
||||
for (unsigned int i = 0; i < xml->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node = xml->getNode(i);
|
||||
if (xml_node->getName() == "vertices")
|
||||
{
|
||||
for (unsigned int i = 0; i < xml_node->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node_node = xml_node->getNode(i);
|
||||
if (!(xml_node_node->getName() == "vertex"))
|
||||
{
|
||||
Log::error("NavMesh", "Unsupported type '%s' found"
|
||||
"in '%s' - ignored.",
|
||||
xml_node_node->getName().c_str(), filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reading vertices
|
||||
Vec3 p;
|
||||
readVertex(xml_node_node, &p);
|
||||
m_max.max(p);
|
||||
m_min.min(p);
|
||||
all_vertices.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (xml_node->getName() == "faces")
|
||||
{
|
||||
for(unsigned int i = 0; i < xml_node->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node_node = xml_node->getNode(i);
|
||||
if (xml_node_node->getName() != "face")
|
||||
{
|
||||
Log::error("NavMesh", "Unsupported type '%s' found in '%s'"
|
||||
" - ignored.",
|
||||
xml_node_node->getName().c_str(), filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reading quads
|
||||
std::vector<int> quad_index;
|
||||
std::vector<int> adjacent_quad_index;
|
||||
xml_node_node->get("indices", &quad_index);
|
||||
xml_node_node->get("adjacents", &adjacent_quad_index);
|
||||
assert(quad_index.size() == 4);
|
||||
|
||||
m_adjacent_quads.push_back(adjacent_quad_index);
|
||||
m_quads.push_back(new Quad(
|
||||
all_vertices[quad_index[0]], all_vertices[quad_index[1]],
|
||||
all_vertices[quad_index[2]], all_vertices[quad_index[3]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
delete xml;
|
||||
|
||||
} // NavMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
NavMesh::~NavMesh()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_quads.size(); i++)
|
||||
{
|
||||
delete m_quads[i];
|
||||
}
|
||||
m_quads.clear();
|
||||
} // ~NavMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Reads the vertex information from an XMLNode */
|
||||
void NavMesh::readVertex(const XMLNode *xml, Vec3* result) const
|
||||
{
|
||||
float x, y, z;
|
||||
xml->get("x", &x);
|
||||
xml->get("y", &y);
|
||||
xml->get("z", &z);
|
||||
Vec3 temp(x, y, z);
|
||||
*result = temp;
|
||||
} // readVertex
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const Vec3& NavMesh::getCenterOfQuad(unsigned int n) const
|
||||
{
|
||||
assert(m_quads.size() > 0 && n < m_quads.size());
|
||||
return m_quads[n]->getCenter();
|
||||
} // getCenterOfQuad
|
||||
@@ -1,121 +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_NAVMESH_HPP
|
||||
#define HEADER_NAVMESH_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class Quad;
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \brief This class stores a set of navigation quads. It uses a
|
||||
* 'simplified singleton' design pattern: it has a static create function
|
||||
* to create exactly one 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
|
||||
* navigation mesh at all (e.g. race mode). So get() returns NULL in this
|
||||
* case, and this is tested where necessary.
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class NavMesh
|
||||
{
|
||||
|
||||
private:
|
||||
static NavMesh *m_nav_mesh;
|
||||
|
||||
/** The 2d bounding box, used for hashing. */
|
||||
Vec3 m_min;
|
||||
Vec3 m_max;
|
||||
|
||||
/** The actual set of quads that constitute the nav mesh */
|
||||
std::vector<Quad*> m_quads;
|
||||
|
||||
std::vector<std::vector<int>> m_adjacent_quads;
|
||||
|
||||
void readVertex(const XMLNode *xml, Vec3* result) const;
|
||||
// ------------------------------------------------------------------------
|
||||
NavMesh(const std::string &filename);
|
||||
// ------------------------------------------------------------------------
|
||||
~NavMesh();
|
||||
|
||||
public:
|
||||
/** Creates a NavMesh instance. */
|
||||
static void create(const std::string &filename)
|
||||
{
|
||||
assert(m_nav_mesh == NULL);
|
||||
m_nav_mesh = new NavMesh(filename);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Cleans up the nav mesh. It is possible that this function is called
|
||||
* even if no instance exists (e.g. in race). So it is not an
|
||||
* error if there is no instance.
|
||||
*/
|
||||
static void destroy()
|
||||
{
|
||||
if (m_nav_mesh)
|
||||
{
|
||||
delete m_nav_mesh;
|
||||
m_nav_mesh = NULL;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the one instance of this object. It is possible that there
|
||||
* is no instance created (e.g. in normal race, since it doesn't have
|
||||
* a nav mesh), so we don't assert that an instance exist, and we
|
||||
* also don't create one if it doesn't exists.
|
||||
*/
|
||||
static NavMesh *get() { return m_nav_mesh; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the minimum and maximum coordinates of this navmesh. */
|
||||
void getBoundingBox(Vec3 *min, Vec3 *max) { *min=m_min; *max=m_max; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const reference to a quad */
|
||||
const Quad& getQuad(unsigned int n) const
|
||||
{
|
||||
assert(m_quads.size() > 0 && n < m_quads.size());
|
||||
return *(m_quads[n]);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const referece to a vector containing the indices
|
||||
* of quads adjacent to a given quad
|
||||
*/
|
||||
const std::vector<int>& getAdjacentQuads(unsigned int n) const
|
||||
{
|
||||
assert(m_adjacent_quads.size() > 0 && n < m_adjacent_quads.size() &&
|
||||
m_quads.size() == m_adjacent_quads.size());
|
||||
return m_adjacent_quads[n];
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the total number of quads */
|
||||
unsigned int getNumberOfQuads() const
|
||||
{
|
||||
assert(m_quads.size() > 0);
|
||||
return m_quads.size();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center of a quad */
|
||||
const Vec3& getCenterOfQuad(unsigned int n) const;
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -55,7 +55,6 @@
|
||||
#include "scriptengine/script_engine.hpp"
|
||||
#include "tracks/arena_graph.hpp"
|
||||
#include "tracks/bezier_curve.hpp"
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/model_definition_loader.hpp"
|
||||
@@ -672,9 +671,8 @@ void Track::startMusic() const
|
||||
/** Loads the quad graph for arena, i.e. the definition of all quads, and the
|
||||
* way they are connected to each other. Input file name is hardcoded for now
|
||||
*/
|
||||
void Track::loadBattleGraph(const XMLNode &node)
|
||||
void Track::loadArenaGraph(const XMLNode &node)
|
||||
{
|
||||
BattleGraph::create(m_root+"navmesh.xml", &node);
|
||||
ArenaGraph* graph = new ArenaGraph(m_root+"navmesh.xml", &node);
|
||||
Graph::setGraph(graph);
|
||||
|
||||
@@ -687,7 +685,7 @@ void Track::loadBattleGraph(const XMLNode &node)
|
||||
{
|
||||
loadMinimap();
|
||||
}
|
||||
} // loadBattleGraph
|
||||
} // loadArenaGraph
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loads the quad graph, i.e. the definition of all quads, and the way
|
||||
@@ -1663,7 +1661,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// map to.
|
||||
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
||||
else if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh)
|
||||
loadBattleGraph(*root);
|
||||
loadArenaGraph(*root);
|
||||
|
||||
ItemManager::create();
|
||||
|
||||
@@ -1879,16 +1877,6 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
|
||||
delete root;
|
||||
|
||||
if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh && !arena_random_item_created)
|
||||
BattleGraph::get()->findItemsOnGraphNodes();
|
||||
|
||||
/*if (UserConfigParams::m_track_debug &&
|
||||
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
!m_is_cutscene)
|
||||
{
|
||||
QuadGraph::get()->createDebugMesh();
|
||||
}*/
|
||||
|
||||
if (UserConfigParams::m_track_debug && Graph::get() && !m_is_cutscene)
|
||||
Graph::get()->createDebugMesh();
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ private:
|
||||
|
||||
void loadTrackInfo();
|
||||
void loadQuadGraph(unsigned int mode_id, const bool reverse);
|
||||
void loadBattleGraph(const XMLNode &node);
|
||||
void loadArenaGraph(const XMLNode &node);
|
||||
void convertTrackToBullet(scene::ISceneNode *node);
|
||||
bool loadMainTrack(const XMLNode &node);
|
||||
void loadMinimap();
|
||||
|
||||
Reference in New Issue
Block a user