diff --git a/sources.cmake b/sources.cmake index ba4868d71..d4f28ae4d 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/karts/controller/battle_ai.cpp b/src/karts/controller/battle_ai.cpp index 72f332fe9..df83dcf32 100644 --- a/src/karts/controller/battle_ai.cpp +++ b/src/karts/controller/battle_ai.cpp @@ -2,7 +2,7 @@ // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2004-2005 Steve Baker // Copyright (C) 2006-2007 Eduardo Hernandez Munoz -// Copyright (C) 2008-2012 Joerg Henrichs +// Copyright (C) 2008-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 diff --git a/src/karts/controller/battle_ai.hpp b/src/karts/controller/battle_ai.hpp index 75fa575dc..29e157fd3 100644 --- a/src/karts/controller/battle_ai.hpp +++ b/src/karts/controller/battle_ai.hpp @@ -1,9 +1,8 @@ - // // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2004-2005 Steve Baker // Copyright (C) 2006-2007 Eduardo Hernandez Munoz -// Copyright (C) 2010 Joerg Henrichs +// Copyright (C) 2010-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 diff --git a/src/tracks/battle_graph.cpp b/src/tracks/battle_graph.cpp index e2716eddd..10d737fd7 100644 --- a/src/tracks/battle_graph.cpp +++ b/src/tracks/battle_graph.cpp @@ -23,12 +23,7 @@ #include #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" @@ -40,10 +35,6 @@ 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); @@ -60,8 +51,7 @@ BattleGraph::~BattleGraph(void) if(UserConfigParams::m_track_debug) cleanupDebugMesh(); - if (m_new_rtt != NULL) - delete m_new_rtt; + GraphStructure::destroyRTT(); } // ~BattleGraph // ----------------------------------------------------------------------------- @@ -132,266 +122,7 @@ void BattleGraph::computeFloydWarshall() } // computeFloydWarshall // ----------------------------------------------------------------------------- -/** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */ -void BattleGraph::createMesh(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_mesh = irr_driver->createQuadMesh(&m); - m_mesh_buffer = m_mesh->getMeshBuffer(0); - assert(m_mesh_buffer->getVertexType()==video::EVT_STANDARD); - const unsigned int num_nodes = getNumNodes(); - - // 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); - - if(track_color) - c = *track_color; - - // 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.setRed ((i%2) ? 255 : 0); - c.setBlue((i%2) ? 0 : 255); - } - // 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, 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. - //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")); - -} // 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 - * model. */ -void BattleGraph::createDebugMesh() -{ - if(getNumNodes()<=0) return; // no debug output if not graph - - 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"); -#endif - -} // createDebugMesh - -// ----------------------------------------------------------------------------- -/** Cleans up the debug mesh */ -void BattleGraph::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; -} - -// ----------------------------------------------------------------------------- /** Maps items on battle graph */ void BattleGraph::findItemsOnGraphNodes() { diff --git a/src/tracks/battle_graph.hpp b/src/tracks/battle_graph.hpp index 3d39aa4e2..286a08a06 100644 --- a/src/tracks/battle_graph.hpp +++ b/src/tracks/battle_graph.hpp @@ -23,21 +23,13 @@ #include #include -#include +#include "tracks/graph_structure.hpp" #include "tracks/navmesh.hpp" -namespace irr -{ - namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; } - namespace video { class ITexture; } -} -using namespace irr; - -class FrameBuffer; +class GraphStructure; class Item; class ItemManager; class Navmesh; -class RTT; /** * \ingroup tracks @@ -49,30 +41,16 @@ class RTT; * design pattern to create an instance). \ingroup tracks */ -class BattleGraph +class BattleGraph : public GraphStructure { 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 */ std::vector< std::vector< int > > m_parent_poly; - /** For debug mode only: the node of the debug mesh. */ - scene::ISceneNode *m_node; - /** For debug only: the mesh of the debug mesh. */ - scene::IMesh *m_mesh; - /** For debug only: the actual mesh buffer storing the quads. */ - scene::IMeshBuffer *m_mesh_buffer; - - /** The minimum coordinates of the quad graph. */ - Vec3 m_min_coord; - - /** Scaling for mini map. */ - float m_scaling; /** Stores the name of the file containing the NavMesh data */ std::string m_navmesh_file; @@ -81,12 +59,27 @@ private: void buildGraph(NavMesh*); void computeFloydWarshall(); - void createMesh(bool enable_transparency=false, - const video::SColor *track_color=NULL); BattleGraph(const std::string &navmesh_file_name); ~BattleGraph(void); + // ------------------------------------------------------------------------ + virtual void set3DVerticesOfGraph(int i, video::S3DVertex *v, + const video::SColor &color) const + { NavMesh::get()->setVertices(i, v, color); } + // ------------------------------------------------------------------------ + 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 isNodeInvalid(int n) const + { return (NavMesh::get()->getNavPoly(n).getVerticesIndex()).size()!=4; } + // ------------------------------------------------------------------------ + virtual const bool hasLapLine() const + { return false; } + public: static const int UNKNOWN_POLY; @@ -115,12 +108,13 @@ 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(); } + virtual const unsigned int getNumNodes() const + { return m_distance_matrix.size(); } // ---------------------------------------------------------------------- /** Returns the NavPoly corresponding to the i-th node of the BattleGraph */ const NavPoly& getPolyOfNode(int i) const - { return NavMesh::get()->getNavPoly(i); } + { return NavMesh::get()->getNavPoly(i); } // ---------------------------------------------------------------------- /** Returns the next polygon on the shortest path from i to j. @@ -129,17 +123,9 @@ public: const int & getNextShortestPathPoly(int i, int j) const; const std::vector < std::pair >& getItemList() - { return m_items_on_graph; } + { return m_items_on_graph; } - 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/graph_structure.cpp b/src/tracks/graph_structure.cpp new file mode 100644 index 000000000..388c3371d --- /dev/null +++ b/src/tracks/graph_structure.cpp @@ -0,0 +1,384 @@ +// +// 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 +#include +#include + +#include "graphics/irr_driver.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/shaders.hpp" +#include "graphics/rtts.hpp" +#include "modes/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); + + // 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; i < m_mesh_buffer->getVertexCount(); 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"); +#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_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; + else if (isNodeInvalid(count)) + { + // There should not be a node which isn't made of 4 vertices + Log::warn("Graph Structure", "There is an invalid node!"); + 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); + } + + // Transfer the 4 points of the current quad to the list of vertices + set3DVerticesOfGraph(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++; + } + + m_mesh_buffer->append(new_v, n*4, ind, n*6); + + if (hasLapLine()) + { + 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) +{ + 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 diff --git a/src/tracks/graph_structure.hpp b/src/tracks/graph_structure.hpp new file mode 100644 index 000000000..665f510d7 --- /dev/null +++ b/src/tracks/graph_structure.hpp @@ -0,0 +1,94 @@ +// +// 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 + +#include +#include +#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: + + 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 isNodeInvalid(int n) const = 0; + virtual const bool hasLapLine() 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 diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index ef78004df..4a05842c7 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -51,11 +51,7 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, const std::string &graph_file_name, const bool reverse) : m_reverse(reverse) { - m_node = NULL; - m_mesh = NULL; - m_mesh_buffer = NULL; m_lap_length = 0; - m_new_rtt = NULL; QuadSet::create(); QuadSet::get()->init(quad_file_name); m_quad_filename = quad_file_name; @@ -73,8 +69,7 @@ QuadGraph::~QuadGraph() } if(UserConfigParams::m_track_debug) cleanupDebugMesh(); - if (m_new_rtt != NULL) - delete m_new_rtt; + GraphStructure::destroyRTT(); } // ~QuadGraph // ----------------------------------------------------------------------------- @@ -394,186 +389,6 @@ void QuadGraph::setDefaultStartPositions(AlignedArray } // for im_max_karts } // setStartPositions -// ----------------------------------------------------------------------------- -/** Creates a mesh for this graph. The mesh is not added to a scene node and - * is stored in m_mesh. - * \param show_invisble If true, also create a mesh for parts of the - * driveline that are invisible. - * \param enable_transparency Enable alpha blending to make the mesh - * semi transparent. - * \param track_color Colour of the actual quads. - * \param lap_color If defined, show the lap counting line in that colour. - */ -void QuadGraph::createMesh(bool show_invisible, - bool enable_transparency, - const video::SColor *track_color, - const video::SColor *lap_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(SColor(255, 255, 255, 255))); - m.setTexture(1, getUnicolorTexture(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); - - // Count the number of quads to display (some quads might be invisible - unsigned int n = 0; - for(unsigned int i=0; igetQuad().isInvisible()) - 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; countgetQuad().isInvisible()) - 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); - } - // Transfer the 4 points of the current quad to the list of vertices - m_all_nodes[count]->getQuad().getVertices(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, n*4, ind, n*6); - - if(lap_color) - { - video::S3DVertex lap_v[4]; - irr::u16 lap_ind[6]; - video::SColor c(128, 255, 0, 0); - m_all_nodes[0]->getQuad().getVertices(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; - QuadSet::get()->getBoundingBox(&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 - -// ----------------------------------------------------------------------------- - -/** Creates the debug mesh to display the quad graph on top of the track - * model. */ -void QuadGraph::createDebugMesh() -{ - if(m_all_nodes.size()<=0) return; // no debug output if not graph - - createMesh(/*show_invisible*/true, - /*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, "quad_graph_debug"); -#ifdef DEBUG - m_node->setName("track-debug-mesh"); -#endif - -} // createDebugMesh - -// ----------------------------------------------------------------------------- -/** Removes the debug mesh from the scene. - */ -void QuadGraph::cleanupDebugMesh() -{ - 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; -} // cleanupDebugMesh - // ----------------------------------------------------------------------------- /** Returns the list of successors or a node. * \param node_number The number of the node. @@ -974,155 +789,3 @@ int QuadGraph::findOutOfRoadSector(const Vec3& xyz, } return min_sector; } // findOutOfRoadSector - -//----------------------------------------------------------------------------- -/** Takes a snapshot of the driveline quads so they can be used as minimap. - */ -void QuadGraph::makeMiniMap(const core::dimension2du &dimension, - const std::string &name, - const video::SColor &fill_color, - video::ITexture** oldRttMinimap, - FrameBuffer** newRttMinimap) -{ - const SColor oldClearColor = World::getWorld()->getClearColor(); - World::getWorld()->setClearbackBufferColor(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)); - - video::SColor red(128, 255, 0, 0); - createMesh(/*show_invisible part of the track*/ false, - /*enable_transparency*/ false, - /*track_color*/ &fill_color, - /*lap line color*/ &red ); - - 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; - QuadSet::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("Quad Graph", "[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 QuadGraph::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 diff --git a/src/tracks/quad_graph.hpp b/src/tracks/quad_graph.hpp index b40d6ff0c..e2688e4af 100644 --- a/src/tracks/quad_graph.hpp +++ b/src/tracks/quad_graph.hpp @@ -24,21 +24,12 @@ #include #include "tracks/graph_node.hpp" +#include "tracks/graph_structure.hpp" #include "tracks/quad_set.hpp" #include "utils/aligned_array.hpp" -#include "utils/no_copy.hpp" - -#include -namespace irr -{ - namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; } - namespace video { class ITexture; } -} -using namespace irr; class CheckLine; -class RTT; -class FrameBuffer; +class GraphStructure; /** * \brief This class stores a graph of quads. It uses a 'simplified singleton' @@ -50,32 +41,18 @@ class FrameBuffer; * returns NULL in this case, and this is tested where necessary. * \ingroup tracks */ -class QuadGraph : public NoCopy +class QuadGraph : public GraphStructure { private: static QuadGraph *m_quad_graph; - RTT* m_new_rtt; - /** The actual graph data structure. */ std::vector m_all_nodes; - /** For debug mode only: the node of the debug mesh. */ - scene::ISceneNode *m_node; - /** For debug only: the mesh of the debug mesh. */ - scene::IMesh *m_mesh; - /** For debug only: the actual mesh buffer storing the quads. */ - scene::IMeshBuffer *m_mesh_buffer; /** The length of the first loop. */ float m_lap_length; - /** The minimum coordinates of the quad graph. */ - Vec3 m_min_coord; - - /** Scaling for mini map. */ - float m_scaling; - /** Stores the filename - just used for error messages. */ std::string m_quad_filename; @@ -91,20 +68,32 @@ private: void addSuccessor(unsigned int from, unsigned int to); void load (const std::string &filename); void computeDistanceFromStart(unsigned int start_node, float distance); - void createMesh(bool show_invisible=true, - bool enable_transparency=false, - const video::SColor *track_color=NULL, - const video::SColor *lap_color=NULL); 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 + { m_all_nodes[i]->getQuad().getVertices(v, color); } + // ------------------------------------------------------------------------ + virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const + { QuadSet::get()->getBoundingBox(min, max); } + // ------------------------------------------------------------------------ + virtual const bool isNodeInvisible(int n) const + { return m_all_nodes[n]->getQuad().isInvisible(); } + // ------------------------------------------------------------------------ + virtual const bool isNodeInvalid(int n) const + { return false; } + // ------------------------------------------------------------------------ + virtual const bool hasLapLine() const + { return true; } + public: static const int UNKNOWN_SECTOR; - void createDebugMesh(); - void cleanupDebugMesh(); void getSuccessors(int node_number, std::vector& succ, bool for_ai=false) const; @@ -122,12 +111,6 @@ public: float forwards_distance=1.5f, float sidewards_distance=1.5f, float upwards_distance=0.0f) const; - 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; void updateDistancesForAllSuccessors(unsigned int indx, float delta, unsigned int count); @@ -164,7 +147,8 @@ public: } // destroy // ------------------------------------------------------------------------ /** Returns the number of nodes in the graph. */ - unsigned int getNumNodes() const { return (unsigned int)m_all_nodes.size();} + virtual const unsigned int getNumNodes() const + { return (unsigned int)m_all_nodes.size();} // ------------------------------------------------------------------------ /** Return the distance to the j-th successor of node n. */ float getDistanceToNext(int n, int j) const @@ -193,9 +177,7 @@ public: /** Returns the length of the main driveline. */ float getLapLength() const {return m_lap_length; } // ------------------------------------------------------------------------ - /** Returns true if the graph is to be reversed. */ bool isReverse() const {return m_reverse; } - }; // QuadGraph #endif diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index dcf7542fe..6ad97bbff 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -672,35 +672,7 @@ void Track::loadBattleGraph() } 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; - } + loadMinimap(); } } // loadBattleGraph @@ -734,35 +706,7 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse) } 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); - - QuadGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255), - &m_old_rtt_mini_map, &m_new_rtt_mini_map); - if (m_old_rtt_mini_map) - { - 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; - } + loadMinimap(); } } // loadQuadGraph @@ -1070,6 +1014,50 @@ void Track::convertTrackToBullet(scene::ISceneNode *node) } // convertTrackToBullet +// ---------------------------------------------------------------------------- + +void Track::loadMinimap() +{ + //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); + + if (m_is_arena && m_has_navmesh) + { + BattleGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255), + &m_old_rtt_mini_map, &m_new_rtt_mini_map); + } + else + { + QuadGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255), + &m_old_rtt_mini_map, &m_new_rtt_mini_map); + } + + if (m_old_rtt_mini_map) + { + 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; + } +} // loadMinimap + // ---------------------------------------------------------------------------- /** Loads the main track model (i.e. all other objects contained in the * scene might use raycast on this track model to determine the actual diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 0546ba608..b4f8f628b 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -382,6 +382,7 @@ private: void loadBattleGraph(); void convertTrackToBullet(scene::ISceneNode *node); bool loadMainTrack(const XMLNode &node); + void loadMinimap(); void createWater(const XMLNode &node); void getMusicInformation(std::vector& filenames, std::vector& m_music );