Remove duplicated code, plus some more cleanup
This commit is contained in:
parent
12e4c76a6f
commit
74c547cb1d
@ -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/*")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
416
src/tracks/graph_structure.cpp
Normal file
416
src/tracks/graph_structure.cpp
Normal 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
|
99
src/tracks/graph_structure.hpp
Normal file
99
src/tracks/graph_structure.hpp
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user