Remove duplicated code, plus some more cleanup

This commit is contained in:
Benau 2015-12-19 02:09:37 +08:00
parent 12e4c76a6f
commit 74c547cb1d
11 changed files with 591 additions and 747 deletions

View File

@ -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/*")

View File

@ -2,7 +2,7 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
// 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

View File

@ -1,9 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
// 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

View File

@ -23,12 +23,7 @@
#include <IMeshSceneNode.h>
#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,15 +35,12 @@ 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());
setType();
computeFloydWarshall();
} // BattleGraph
@ -60,8 +52,7 @@ BattleGraph::~BattleGraph(void)
if(UserConfigParams::m_track_debug)
cleanupDebugMesh();
if (m_new_rtt != NULL)
delete m_new_rtt;
GraphStructure::destroyRTT();
} // ~BattleGraph
// -----------------------------------------------------------------------------
@ -132,266 +123,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; count<num_nodes; count++)
{
// There should not be a poly which isn't made of 4 vertices
if((NavMesh::get()->getNavPoly(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; i<QuadSet::get()
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.
//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; 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
// -----------------------------------------------------------------------------
/** 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()
{

View File

@ -23,21 +23,13 @@
#include <string>
#include <set>
#include <dimension2d.h>
#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,8 +59,6 @@ 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);
@ -115,7 +91,8 @@ 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 */
@ -131,15 +108,13 @@ public:
const std::vector < std::pair<const Item*, int> >& getItemList()
{ 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;
// ------------------------------------------------------------------------
/** Sets the type of this graph. */
virtual void setType() { m_graph_type = GraphType::GT_BATTLE; }
// ------------------------------------------------------------------------
virtual const std::vector<GraphNode*> getAllNodes() const
{return std::vector<GraphNode*>();}
}; //BattleGraph
#endif

View File

@ -0,0 +1,416 @@
//
// 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 <IMesh.h>
#include <ICameraSceneNode.h>
#include <IMeshSceneNode.h>
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/shaders.hpp"
#include "graphics/rtts.hpp"
#include "modes/world.hpp"
#include "tracks/quad_set.hpp"
#include "tracks/navmesh.hpp"
#include "utils/log.hpp"
// -----------------------------------------------------------------------------
GraphStructure::GraphStructure()
{
m_graph_type = GT_RACE;
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,
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(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 std::vector<GraphNode*> all_nodes = getAllNodes();
unsigned int n;
if (m_graph_type == GT_RACE)
{
// Count the number of quads to display (some quads might be invisible
n = 0;
for (unsigned int i = 0; i < getNumNodes(); i++)
{
if (show_invisible || !all_nodes[i]->getQuad().isInvisible())
n++;
}
}
else
n = getNumNodes();
// 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 < getNumNodes(); count++)
{
// Ignore invisible quads
if (m_graph_type == GT_RACE)
{
if (!show_invisible && all_nodes[count]->getQuad().isInvisible())
continue;
}
else if ((NavMesh::get()->getNavPoly(count).getVerticesIndex()).size() !=4 &&
m_graph_type == GT_BATTLE)
{
// There should not be a poly which isn't made of 4 vertices
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
if (m_graph_type == GT_RACE)
all_nodes[count]->getQuad().getVertices(new_v+4*i, c);
else
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++;
}
m_mesh_buffer->append(new_v, n*4, ind, n*6);
if (lap_color && m_graph_type == GT_RACE)
{
video::S3DVertex lap_v[4];
irr::u16 lap_ind[6];
video::SColor c(128, 255, 0, 0);
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
// -----------------------------------------------------------------------------
/** 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));
if (m_graph_type == GT_RACE)
{
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);
}
else
{
createMesh(/*show_invisible part of the track*/ false,
/*enable_transparency*/ false,
/*track_color*/ &fill_color,
/*lap line color*/ NULL);
}
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;
if (m_graph_type == GT_RACE)
QuadSet::get()->getBoundingBox(&bb_min, &bb_max);
else
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 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

View File

@ -0,0 +1,99 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2015 SuperTuxKart Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_GRAPH_STRUCTURE_HPP
#define HEADER_GRAPH_STRUCTURE_HPP
#include <string>
#include <dimension2d.h>
#include <SColor.h>
#include "tracks/graph_node.hpp"
#include "utils/vec3.hpp"
#include "utils/no_copy.hpp"
namespace irr
{
namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; }
namespace video { class ITexture; }
}
using namespace irr;
class FrameBuffer;
class RTT;
/**
* \brief Virtual base class for a graph structure.
*
* A graph structure has a certain type:
* GT_RACE : Graph used by a lap race.
* GT_BATTLE: Graph used by a battle arena.
*
* \ingroup tracks
*/
class GraphStructure : public NoCopy
{
public:
enum GraphType {GT_RACE, GT_BATTLE};
protected:
/** The type of this graph. */
GraphType m_graph_type;
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,
const video::SColor *lap_color=NULL);
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;
virtual const std::vector<GraphNode*> getAllNodes() const = 0;
virtual void setType() = 0;
}; // GraphStructure
#endif

View File

@ -51,16 +51,13 @@ 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;
m_quad_graph = this;
load(graph_file_name);
setType();
} // QuadGraph
// -----------------------------------------------------------------------------
@ -73,8 +70,7 @@ QuadGraph::~QuadGraph()
}
if(UserConfigParams::m_track_debug)
cleanupDebugMesh();
if (m_new_rtt != NULL)
delete m_new_rtt;
GraphStructure::destroyRTT();
} // ~QuadGraph
// -----------------------------------------------------------------------------
@ -394,186 +390,6 @@ void QuadGraph::setDefaultStartPositions(AlignedArray<btTransform>
} // for i<stk_config->m_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; i<m_all_nodes.size(); i++)
{
if(show_invisible || !m_all_nodes[i]->getQuad().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; count<m_all_nodes.size(); count++)
{
// Ignore invisible quads
if(!show_invisible && m_all_nodes[count]->getQuad().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; i<QuadSet::get()
m_mesh_buffer->append(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; 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, "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 +790,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

View File

@ -24,21 +24,12 @@
#include <set>
#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 <dimension2d.h>
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<GraphNode*> 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,10 +68,6 @@ 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,
@ -103,8 +76,6 @@ private:
public:
static const int UNKNOWN_SECTOR;
void createDebugMesh();
void cleanupDebugMesh();
void getSuccessors(int node_number,
std::vector<unsigned int>& succ,
bool for_ai=false) const;
@ -122,12 +93,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 +129,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 +159,13 @@ 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; }
// ------------------------------------------------------------------------
/** Sets the type of this graph. */
virtual void setType() { m_graph_type = GraphType::GT_RACE; }
// ------------------------------------------------------------------------
virtual const std::vector<GraphNode*> getAllNodes() const
{ return m_all_nodes; }
}; // QuadGraph
#endif

View File

@ -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

View File

@ -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<std::string>& filenames,
std::vector<MusicInformation*>& m_music );