From 12e4c76a6f9e27304283d2424a4c8c9afe628054 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 15 Dec 2015 02:32:01 +0800 Subject: [PATCH] Add minimap for battle mode when it has a navigation mesh TODO: update battle island arena to use only 4 vertices per poly --- src/karts/controller/battle_ai.cpp | 2 +- src/states_screens/race_gui.cpp | 6 +- src/tracks/battle_graph.cpp | 301 +++++++++++++++++++++-------- src/tracks/battle_graph.hpp | 43 +++-- src/tracks/navmesh.cpp | 42 ++++ src/tracks/navmesh.hpp | 34 +++- src/tracks/track.cpp | 63 +++++- src/tracks/track.hpp | 1 + 8 files changed, 383 insertions(+), 109 deletions(-) diff --git a/src/karts/controller/battle_ai.cpp b/src/karts/controller/battle_ai.cpp index 2c4cd746c..72f332fe9 100644 --- a/src/karts/controller/battle_ai.cpp +++ b/src/karts/controller/battle_ai.cpp @@ -832,7 +832,7 @@ void BattleAI::handleItems(const float dt) void BattleAI::handleItemCollection(Vec3* aim_point, int* target_node) { float distance = 99999.9f; - const std::vector< std::pair >& item_list = + const std::vector< std::pair >& item_list = BattleGraph::get()->getItemList(); const unsigned int items_count = item_list.size(); unsigned int closest_item_num = 0; diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index 476d97d92..b920f69f6 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -342,8 +342,10 @@ void RaceGUI::drawGlobalTimer() void RaceGUI::drawGlobalMiniMap() { World *world = World::getWorld(); - // arenas currently don't have a map. - if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return; + // draw a map when arena has a navigation mesh. + if ((world->getTrack()->isArena() && !(world->getTrack()->hasNavMesh())) || + world->getTrack()->isSoccer()) + return; const video::ITexture *old_rtt_mini_map = world->getTrack()->getOldRttMiniMap(); const FrameBuffer* new_rtt_mini_map = world->getTrack()->getNewRttMiniMap(); diff --git a/src/tracks/battle_graph.cpp b/src/tracks/battle_graph.cpp index 93ff15750..e2716eddd 100644 --- a/src/tracks/battle_graph.cpp +++ b/src/tracks/battle_graph.cpp @@ -24,10 +24,13 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/shaders.hpp" +#include "graphics/rtts.hpp" #include "items/item_manager.hpp" +#include "modes/world.hpp" #include "tracks/navmesh.hpp" #include "utils/log.hpp" -#include "utils/vec3.hpp" const int BattleGraph::UNKNOWN_POLY = -1; BattleGraph * BattleGraph::m_battle_graph = NULL; @@ -37,14 +40,30 @@ BattleGraph * BattleGraph::m_battle_graph = NULL; * by the AI. */ BattleGraph::BattleGraph(const std::string &navmesh_file_name) { + m_node = NULL; + m_mesh = NULL; + m_mesh_buffer = NULL; + m_new_rtt = NULL; + m_items_on_graph.clear(); + NavMesh::create(navmesh_file_name); m_navmesh_file = navmesh_file_name; buildGraph(NavMesh::get()); computeFloydWarshall(); - findItemsOnGraphNodes(ItemManager::get()); - } // BattleGraph +// ----------------------------------------------------------------------------- +/** Destructor, destroys NavMesh and the debug mesh if it exists */ +BattleGraph::~BattleGraph(void) +{ + NavMesh::destroy(); + + if(UserConfigParams::m_track_debug) + cleanupDebugMesh(); + if (m_new_rtt != NULL) + delete m_new_rtt; +} // ~BattleGraph + // ----------------------------------------------------------------------------- /** Builds a graph from an existing NavMesh. The graph is stored as an adjacency * matrix. */ @@ -113,17 +132,7 @@ void BattleGraph::computeFloydWarshall() } // computeFloydWarshall // ----------------------------------------------------------------------------- -/** Destructor, destroys NavMesh and the debug mesh if it exists */ -BattleGraph::~BattleGraph(void) -{ - NavMesh::destroy(); - - if(UserConfigParams::m_track_debug) - cleanupDebugMesh(); -} // ~BattleGraph - -// ----------------------------------------------------------------------------- -/** Creates the actual mesh that is used by createDebugMesh() */ +/** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */ void BattleGraph::createMesh(bool enable_transparency, const video::SColor *track_color) { @@ -133,78 +142,56 @@ void BattleGraph::createMesh(bool enable_transparency, 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_mesh = irr_driver->createQuadMesh(&m); m_mesh_buffer = m_mesh->getMeshBuffer(0); assert(m_mesh_buffer->getVertexType()==video::EVT_STANDARD); - // Eps is used to raise the track debug quads a little bit higher than - // the ground, so that they are actually visible. - core::vector3df eps(0, 0.4f, 0); - video::SColor c = video::SColor(255, 255, 0, 0); + const unsigned int num_nodes = getNumNodes(); - // Declare vector to hold new converted vertices, vertices are copied over - // for each polygon, although it results in redundant vertex copies in the - // final vector, this is the only way I know to make each poly have different color. - std::vector new_v; + // Four vertices for each of the n-1 remaining quads + video::S3DVertex *new_v = new video::S3DVertex[4*num_nodes]; + // 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*num_nodes]; + video::SColor c(255, 255, 0, 0); - // Declare vector to hold indices - std::vector ind; + if(track_color) + c = *track_color; - // Now add all polygons + // Now add all quads int i=0; - for(unsigned int count=0; countgetNavPoly(count).getVerticesIndex()).size() !=4) + { + Log::warn("Battle Graph", "There is an invalid poly!"); + continue; + } + // Swap the colours from red to blue and back if(!track_color) { - c.setAlpha(178); - //c.setRed ((i%2) ? 255 : 0); - //c.setBlue((i%3) ? 0 : 255); - c.setRed(7*i%256); - c.setBlue((2*i)%256); - c.setGreen((3*i)%256); + c.setRed ((i%2) ? 255 : 0); + c.setBlue((i%2) ? 0 : 255); } - - NavPoly poly = NavMesh::get()->getNavPoly(count); - - //std::vector vInd = poly.getVerticesIndex(); - const std::vector& v = poly.getVertices(); - - // Number of triangles in the triangle fan - unsigned int numberOfTriangles = v.size() -2 ; + // Transfer the 4 points of the current quad to the list of vertices + NavMesh::get()->setVertices(count, new_v+4*i, 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++; + } // for i=1; iappend(new_v.data(), new_v.size(), ind.data(), ind.size()); + m_mesh_buffer->append(new_v, num_nodes*4, ind, num_nodes*6); // Instead of setting the bounding boxes, we could just disable culling, // since the debug track should always be drawn. @@ -212,7 +199,157 @@ void BattleGraph::createMesh(bool enable_transparency, m_mesh_buffer->recalculateBoundingBox(); m_mesh->setBoundingBox(m_mesh_buffer->getBoundingBox()); + m_mesh_buffer->getMaterial().setTexture(0, irr_driver->getTexture("unlit.png")); + } // createMesh +// ----------------------------------------------------------------------------- +/** Takes a snapshot of the navmesh so they can be used as minimap. + */ +void BattleGraph::makeMiniMap(const core::dimension2du &dimension, + const std::string &name, + const video::SColor &fill_color, + video::ITexture** oldRttMinimap, + FrameBuffer** newRttMinimap) +{ + 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(/*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; + NavMesh::get()->getBoundingBox(&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("BattleGraph", "[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 BattleGraph::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 // ----------------------------------------------------------------------------- /** Creates the debug mesh to display the quad graph on top of the track @@ -221,10 +358,21 @@ void BattleGraph::createDebugMesh() { if(getNumNodes()<=0) return; // no debug output if not graph - createMesh(/*enable_transparency*/false); + createMesh(/*enable_transparency*/true); + + // Now colour the quads red/blue/red ... + video::SColor c( 128, 255, 0, 0); + video::S3DVertex *v = (video::S3DVertex*)m_mesh_buffer->getVertices(); + for(unsigned int i=0; igetVertexCount(); i++) + { + // Swap the colours from red to blue and back + c.setRed ((i%2) ? 255 : 0); + c.setBlue((i%2) ? 0 : 255); + v[i].Color = c; + } m_node = irr_driver->addMesh(m_mesh, "track-debug-mesh"); #ifdef DEBUG -// m_node->setName("track-debug-mesh"); + m_node->setName("track-debug-mesh"); #endif } // createDebugMesh @@ -244,14 +392,15 @@ void BattleGraph::cleanupDebugMesh() } // ----------------------------------------------------------------------------- - -void BattleGraph::findItemsOnGraphNodes(ItemManager * item_manager) +/** 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) { - Item* item = item_manager->getItem(i); + const Item* item = item_manager->getItem(i); Vec3 xyz = item->getXYZ(); int polygon = BattleGraph::UNKNOWN_POLY; diff --git a/src/tracks/battle_graph.hpp b/src/tracks/battle_graph.hpp index aea60c41c..3d39aa4e2 100644 --- a/src/tracks/battle_graph.hpp +++ b/src/tracks/battle_graph.hpp @@ -23,12 +23,9 @@ #include #include +#include #include "tracks/navmesh.hpp" -class Navmesh; -class Item; -class ItemManager; - namespace irr { namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; } @@ -36,6 +33,12 @@ namespace irr } using namespace irr; +class FrameBuffer; +class Item; +class ItemManager; +class Navmesh; +class RTT; + /** * \ingroup tracks * @@ -52,6 +55,8 @@ class BattleGraph private: static BattleGraph *m_battle_graph; + RTT* m_new_rtt; + /** 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 */ @@ -63,16 +68,21 @@ private: /** For debug only: the actual mesh buffer storing the quads. */ scene::IMeshBuffer *m_mesh_buffer; - /** Stores the name of the file containing the NavMesh data */ - std::string m_navmesh_file; + /** The minimum coordinates of the quad graph. */ + Vec3 m_min_coord; - std::vector< std::pair > m_items_on_graph; + /** Scaling for mini map. */ + float m_scaling; + + /** Stores the name of the file containing the NavMesh data */ + std::string m_navmesh_file; + + std::vector< std::pair > m_items_on_graph; void buildGraph(NavMesh*); void computeFloydWarshall(); void createMesh(bool enable_transparency=false, const video::SColor *track_color=NULL); - void findItemsOnGraphNodes(ItemManager*); BattleGraph(const std::string &navmesh_file_name); ~BattleGraph(void); @@ -105,7 +115,7 @@ public: // ---------------------------------------------------------------------- /** Returns the number of nodes in the BattleGraph (equal to the number of * polygons in the NavMesh */ - unsigned int getNumNodes() const { return m_distance_matrix.size(); } + unsigned int getNumNodes() const { return m_distance_matrix.size(); } // ---------------------------------------------------------------------- /** Returns the NavPoly corresponding to the i-th node of the BattleGraph */ @@ -116,13 +126,20 @@ public: /** 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) */ - const int & getNextShortestPathPoly(int i, int j) const; + const int & getNextShortestPathPoly(int i, int j) const; - const std::vector< std::pair >& getItemList() + const std::vector < std::pair >& getItemList() { return m_items_on_graph; } - void createDebugMesh(); - void cleanupDebugMesh(); + void createDebugMesh(); + void cleanupDebugMesh(); + void findItemsOnGraphNodes(); + 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; }; //BattleGraph #endif diff --git a/src/tracks/navmesh.cpp b/src/tracks/navmesh.cpp index bf849c762..a43f1fe7c 100644 --- a/src/tracks/navmesh.cpp +++ b/src/tracks/navmesh.cpp @@ -37,6 +37,8 @@ NavMesh *NavMesh::m_nav_mesh = NULL; NavMesh::NavMesh(const std::string &filename) { + m_min = Vec3( 99999, 99999, 99999); + m_max = Vec3(-99999, -99999, -99999); m_n_verts=0; m_n_polys=0; @@ -68,6 +70,8 @@ NavMesh::NavMesh(const std::string &filename) //Reading vertices Vec3 p; readVertex(xml_node_node, &p); + m_max.max(p); + m_min.min(p); m_n_verts++; m_verts.push_back(p); } @@ -116,6 +120,44 @@ NavMesh::~NavMesh() { } // ~NavMesh +// ---------------------------------------------------------------------------- +/** Sets the vertices in a irrlicht vertex array to the 4 points of this quad. + */ +void NavMesh::setVertices(int n, video::S3DVertex *v, const video::SColor &color) const +{ + NavPoly poly = NavMesh::get()->getNavPoly(n); + const std::vector& p = poly.getVertices(); + + if (p.size() !=4) return; + + // Eps is used to raise the track debug quads a little bit higher than + // the ground, so that they are actually visible. + core::vector3df eps(0, 0.1f, 0); + v[0].Pos = p[0].toIrrVector()+eps; + v[1].Pos = p[1].toIrrVector()+eps; + v[2].Pos = p[2].toIrrVector()+eps; + v[3].Pos = p[3].toIrrVector()+eps; + + core::triangle3df tri(p[0].toIrrVector(), p[1].toIrrVector(), + p[2].toIrrVector()); + core::vector3df normal = tri.getNormal(); + normal.normalize(); + v[0].Normal = normal; + v[1].Normal = normal; + v[2].Normal = normal; + + core::triangle3df tri1(p[0].toIrrVector(), p[2].toIrrVector(), + p[3].toIrrVector()); + core::vector3df normal1 = tri1.getNormal(); + normal1.normalize(); + v[3].Normal = normal1; + + v[0].Color = color; + v[1].Color = color; + v[2].Color = color; + v[3].Color = color; +} // setVertices + // ---------------------------------------------------------------------------- /** Reads the vertex information from an XMLNode */ diff --git a/src/tracks/navmesh.hpp b/src/tracks/navmesh.hpp index 0a4890c86..5ef79f1ad 100644 --- a/src/tracks/navmesh.hpp +++ b/src/tracks/navmesh.hpp @@ -55,6 +55,10 @@ 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 nav polys that constitute the nav mesh */ std::vector m_polys; @@ -102,39 +106,53 @@ public: * 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 NavPoly */ const NavPoly& getNavPoly(int n) const { return m_polys[n]; } - + // ------------------------------------------------------------------------ /** Returns a const reference to a vertex(Vec3) */ const Vec3& getVertex(int n) const { return m_verts[n]; } - + // ------------------------------------------------------------------------ + /** Sets the vertices in a irrlicht vertex array to + * the 4 points of a navpoly. + * \param n The number of a navpoly. + * \param v The vertex array in which to set the vertices. + * \param color The color to use for this quad. + */ + void setVertices(int n, video::S3DVertex *v, + const video::SColor &color) const; + // ------------------------------------------------------------------------ /** Returns a const reference to a vector containing all vertices */ const std::vector& getAllVertices() const { return m_verts; } - + // ------------------------------------------------------------------------ /** Returns the total number of polys */ unsigned int getNumberOfPolys() const { return m_n_polys; } - + // ------------------------------------------------------------------------ /** Returns the total number of vertices */ unsigned int getNumberOfVerts() const { return m_n_verts; } - + // ------------------------------------------------------------------------ /** Returns maximum vertices per polygon */ unsigned int getMaxVertsPerPoly() const { return m_nvp; } - + // ------------------------------------------------------------------------ /** Returns the center of a polygon */ const Vec3& getCenterOfPoly(int n) const {return m_polys[n].getCenter();} - + // ------------------------------------------------------------------------ /** Returns a const referece to a vector containing the indices * of polygons adjacent to a given polygon */ const std::vector& getAdjacentPolys(int n) const {return m_polys[n].getAdjacents();} - + // ------------------------------------------------------------------------ /** Returns a const reference to a vector containing the vertices * of a given polygon. */ const std::vector getVertsOfPoly(int n) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index c9b42b84f..dcf7542fe 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -657,6 +657,53 @@ void Track::startMusic() const music_manager->clearCurrentMusic(); } // startMusic +//----------------------------------------------------------------------------- +/** Loads the polygon graph for battle, i.e. the definition of all polys, and the way + * they are connected to each other. Input file name is hardcoded for now + */ +void Track::loadBattleGraph() +{ + BattleGraph::create(m_root+"navmesh.xml"); + + if(BattleGraph::get()->getNumNodes()==0) + { + Log::warn("track", "No graph nodes defined for track '%s'\n", + m_filename.c_str()); + } + else + { + //Check whether the hardware can do nonsquare or + // non power-of-two textures + video::IVideoDriver* const video_driver = irr_driver->getVideoDriver(); + bool nonpower = false; //video_driver->queryFeature(video::EVDF_TEXTURE_NPOT); + bool nonsquare = + video_driver->queryFeature(video::EVDF_TEXTURE_NSQUARE); + + //Create the minimap resizing it as necessary. + m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize(); + core::dimension2du size = m_mini_map_size + .getOptimalSize(!nonpower,!nonsquare); + + BattleGraph::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) + { + m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_old_rtt_mini_map->getSize().Width); + m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_old_rtt_mini_map->getSize().Height); + } + else if (m_new_rtt_mini_map) + { + m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_new_rtt_mini_map->getWidth()); + m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_new_rtt_mini_map->getHeight()); + } + else + { + m_minimap_x_scale = 0; + m_minimap_y_scale = 0; + } + } +} // loadBattleGraph + //----------------------------------------------------------------------------- /** Loads the quad graph, i.e. the definition of all quads, and the way * they are connected to each other. @@ -723,7 +770,10 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse) void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const { - QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at); + if (m_is_arena && m_has_navmesh) + BattleGraph::get()->mapPoint2MiniMap(xyz, draw_at); + else + QuadGraph::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); } @@ -1605,6 +1655,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) // 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); + else if (m_is_arena && !m_is_soccer && !m_is_cutscene && m_has_navmesh) + loadBattleGraph(); ItemManager::create(); @@ -1829,15 +1881,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) delete root; - // ItemManager assumes the existence of a QuadGraph, that is why the - // quad graph is loaded before ItemManager::create(). This is undesirable - // but requires signifcant code overhaul to fix. The new battle graph - // performs its own computatoins separate from ItemManager. But - // Battle Graph needs ItemManager to be created, and all items to be - // added to ItemManager. Loading battle graph here is therefore a workaround - // to the main problem. if (m_is_arena && !m_is_soccer && !m_is_cutscene && m_has_navmesh) - BattleGraph::create(m_root + "navmesh.xml"); + BattleGraph::get()->findItemsOnGraphNodes(); if (UserConfigParams::m_track_debug && race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES && diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index cc98d3ea8..0546ba608 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -379,6 +379,7 @@ private: void loadTrackInfo(); void loadQuadGraph(unsigned int mode_id, const bool reverse); + void loadBattleGraph(); void convertTrackToBullet(scene::ISceneNode *node); bool loadMainTrack(const XMLNode &node); void createWater(const XMLNode &node);