Add minimap for battle mode when it has a navigation mesh
TODO: update battle island arena to use only 4 vertices per poly
This commit is contained in:
parent
e6068923b4
commit
12e4c76a6f
@ -832,7 +832,7 @@ void BattleAI::handleItems(const float dt)
|
||||
void BattleAI::handleItemCollection(Vec3* aim_point, int* target_node)
|
||||
{
|
||||
float distance = 99999.9f;
|
||||
const std::vector< std::pair<Item*, int> >& item_list =
|
||||
const std::vector< std::pair<const Item*, int> >& item_list =
|
||||
BattleGraph::get()->getItemList();
|
||||
const unsigned int items_count = item_list.size();
|
||||
unsigned int closest_item_num = 0;
|
||||
|
@ -342,8 +342,10 @@ void RaceGUI::drawGlobalTimer()
|
||||
void RaceGUI::drawGlobalMiniMap()
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
// arenas currently don't have a map.
|
||||
if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
|
||||
// draw a map when arena has a navigation mesh.
|
||||
if ((world->getTrack()->isArena() && !(world->getTrack()->hasNavMesh())) ||
|
||||
world->getTrack()->isSoccer())
|
||||
return;
|
||||
|
||||
const video::ITexture *old_rtt_mini_map = world->getTrack()->getOldRttMiniMap();
|
||||
const FrameBuffer* new_rtt_mini_map = world->getTrack()->getNewRttMiniMap();
|
||||
|
@ -24,10 +24,13 @@
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
#include "graphics/rtts.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
const int BattleGraph::UNKNOWN_POLY = -1;
|
||||
BattleGraph * BattleGraph::m_battle_graph = NULL;
|
||||
@ -37,14 +40,30 @@ BattleGraph * BattleGraph::m_battle_graph = NULL;
|
||||
* by the AI. */
|
||||
BattleGraph::BattleGraph(const std::string &navmesh_file_name)
|
||||
{
|
||||
m_node = NULL;
|
||||
m_mesh = NULL;
|
||||
m_mesh_buffer = NULL;
|
||||
m_new_rtt = NULL;
|
||||
m_items_on_graph.clear();
|
||||
|
||||
NavMesh::create(navmesh_file_name);
|
||||
m_navmesh_file = navmesh_file_name;
|
||||
buildGraph(NavMesh::get());
|
||||
computeFloydWarshall();
|
||||
findItemsOnGraphNodes(ItemManager::get());
|
||||
|
||||
} // BattleGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Destructor, destroys NavMesh and the debug mesh if it exists */
|
||||
BattleGraph::~BattleGraph(void)
|
||||
{
|
||||
NavMesh::destroy();
|
||||
|
||||
if(UserConfigParams::m_track_debug)
|
||||
cleanupDebugMesh();
|
||||
if (m_new_rtt != NULL)
|
||||
delete m_new_rtt;
|
||||
} // ~BattleGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Builds a graph from an existing NavMesh. The graph is stored as an adjacency
|
||||
* matrix. */
|
||||
@ -113,17 +132,7 @@ void BattleGraph::computeFloydWarshall()
|
||||
} // computeFloydWarshall
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Destructor, destroys NavMesh and the debug mesh if it exists */
|
||||
BattleGraph::~BattleGraph(void)
|
||||
{
|
||||
NavMesh::destroy();
|
||||
|
||||
if(UserConfigParams::m_track_debug)
|
||||
cleanupDebugMesh();
|
||||
} // ~BattleGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Creates the actual mesh that is used by createDebugMesh() */
|
||||
/** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */
|
||||
void BattleGraph::createMesh(bool enable_transparency,
|
||||
const video::SColor *track_color)
|
||||
{
|
||||
@ -133,78 +142,56 @@ void BattleGraph::createMesh(bool enable_transparency,
|
||||
m.Lighting = false;
|
||||
if(enable_transparency)
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
m.setTexture(0, getUnicolorTexture(video::SColor(255, 255, 255, 255)));
|
||||
m.setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||
m_mesh = irr_driver->createQuadMesh(&m);
|
||||
m_mesh_buffer = m_mesh->getMeshBuffer(0);
|
||||
assert(m_mesh_buffer->getVertexType()==video::EVT_STANDARD);
|
||||
|
||||
// Eps is used to raise the track debug quads a little bit higher than
|
||||
// the ground, so that they are actually visible.
|
||||
core::vector3df eps(0, 0.4f, 0);
|
||||
video::SColor c = video::SColor(255, 255, 0, 0);
|
||||
const unsigned int num_nodes = getNumNodes();
|
||||
|
||||
// Declare vector to hold new converted vertices, vertices are copied over
|
||||
// for each polygon, although it results in redundant vertex copies in the
|
||||
// final vector, this is the only way I know to make each poly have different color.
|
||||
std::vector<video::S3DVertex> new_v;
|
||||
// Four vertices for each of the n-1 remaining quads
|
||||
video::S3DVertex *new_v = new video::S3DVertex[4*num_nodes];
|
||||
// Each quad consists of 2 triangles with 3 elements, so
|
||||
// we need 2*3 indices for each quad.
|
||||
irr::u16 *ind = new irr::u16[6*num_nodes];
|
||||
video::SColor c(255, 255, 0, 0);
|
||||
|
||||
// Declare vector to hold indices
|
||||
std::vector<irr::u16> ind;
|
||||
if(track_color)
|
||||
c = *track_color;
|
||||
|
||||
// Now add all polygons
|
||||
// Now add all quads
|
||||
int i=0;
|
||||
for(unsigned int count=0; count<getNumNodes(); count++)
|
||||
for(unsigned int count=0; count<num_nodes; count++)
|
||||
{
|
||||
///compute colors
|
||||
// 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.setAlpha(178);
|
||||
//c.setRed ((i%2) ? 255 : 0);
|
||||
//c.setBlue((i%3) ? 0 : 255);
|
||||
c.setRed(7*i%256);
|
||||
c.setBlue((2*i)%256);
|
||||
c.setGreen((3*i)%256);
|
||||
c.setRed ((i%2) ? 255 : 0);
|
||||
c.setBlue((i%2) ? 0 : 255);
|
||||
}
|
||||
|
||||
NavPoly poly = NavMesh::get()->getNavPoly(count);
|
||||
|
||||
//std::vector<int> vInd = poly.getVerticesIndex();
|
||||
const std::vector<Vec3>& v = poly.getVertices();
|
||||
|
||||
// Number of triangles in the triangle fan
|
||||
unsigned int numberOfTriangles = v.size() -2 ;
|
||||
// Transfer the 4 points of the current quad to the list of vertices
|
||||
NavMesh::get()->setVertices(count, new_v+4*i, c);
|
||||
|
||||
// Set up the indices for the triangles
|
||||
// (note, afaik with opengl we could use quads directly, but the code
|
||||
// would not be portable to directx anymore).
|
||||
ind[6*i ] = 4*i+2; // First triangle: vertex 0, 1, 2
|
||||
ind[6*i+1] = 4*i+1;
|
||||
ind[6*i+2] = 4*i;
|
||||
ind[6*i+3] = 4*i+3; // second triangle: vertex 0, 1, 3
|
||||
ind[6*i+4] = 4*i+2;
|
||||
ind[6*i+5] = 4*i;
|
||||
i++;
|
||||
} // for i=1; i<QuadSet::get()
|
||||
|
||||
for( unsigned int count = 1; count<=numberOfTriangles; count++)
|
||||
{
|
||||
video::S3DVertex v1,v2,v3;
|
||||
v1.Pos=v[0].toIrrVector() + eps;
|
||||
v2.Pos=v[count].toIrrVector() + eps;
|
||||
v3.Pos=v[count+1].toIrrVector() + eps;
|
||||
|
||||
v1.Color = c;
|
||||
v2.Color = c;
|
||||
v3.Color = c;
|
||||
|
||||
core::triangle3df tri(v1.Pos, v2.Pos, v3.Pos);
|
||||
core::vector3df normal = tri.getNormal();
|
||||
normal.normalize();
|
||||
v1.Normal = normal;
|
||||
v2.Normal = normal;
|
||||
v3.Normal = normal;
|
||||
|
||||
new_v.push_back(v1);
|
||||
new_v.push_back(v2);
|
||||
new_v.push_back(v3);
|
||||
|
||||
ind.push_back(i++);
|
||||
ind.push_back(i++);
|
||||
ind.push_back(i++);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_mesh_buffer->append(new_v.data(), new_v.size(), ind.data(), ind.size());
|
||||
m_mesh_buffer->append(new_v, num_nodes*4, ind, num_nodes*6);
|
||||
|
||||
// Instead of setting the bounding boxes, we could just disable culling,
|
||||
// since the debug track should always be drawn.
|
||||
@ -212,7 +199,157 @@ void BattleGraph::createMesh(bool enable_transparency,
|
||||
m_mesh_buffer->recalculateBoundingBox();
|
||||
m_mesh->setBoundingBox(m_mesh_buffer->getBoundingBox());
|
||||
|
||||
m_mesh_buffer->getMaterial().setTexture(0, irr_driver->getTexture("unlit.png"));
|
||||
|
||||
} // createMesh
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Takes a snapshot of the navmesh so they can be used as minimap.
|
||||
*/
|
||||
void BattleGraph::makeMiniMap(const core::dimension2du &dimension,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color,
|
||||
video::ITexture** oldRttMinimap,
|
||||
FrameBuffer** newRttMinimap)
|
||||
{
|
||||
const video::SColor oldClearColor = World::getWorld()->getClearColor();
|
||||
World::getWorld()->setClearbackBufferColor(video::SColor(0, 255, 255, 255));
|
||||
World::getWorld()->forceFogDisabled(true);
|
||||
*oldRttMinimap = NULL;
|
||||
*newRttMinimap = NULL;
|
||||
|
||||
RTT* newRttProvider = NULL;
|
||||
IrrDriver::RTTProvider* oldRttProvider = NULL;
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
m_new_rtt = newRttProvider = new RTT(dimension.Width, dimension.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldRttProvider = new IrrDriver::RTTProvider(dimension, name, true);
|
||||
}
|
||||
|
||||
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 255, 255, 255));
|
||||
|
||||
createMesh(/*enable_transparency*/ false,
|
||||
/*track_color*/ &fill_color);
|
||||
|
||||
m_node = irr_driver->addMesh(m_mesh, "mini_map");
|
||||
#ifdef DEBUG
|
||||
m_node->setName("minimap-mesh");
|
||||
#endif
|
||||
|
||||
m_node->setAutomaticCulling(0);
|
||||
m_node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
|
||||
// Add the camera:
|
||||
// ---------------
|
||||
scene::ICameraSceneNode *camera = irr_driver->addCameraSceneNode();
|
||||
Vec3 bb_min, bb_max;
|
||||
NavMesh::get()->getBoundingBox(&bb_min, &bb_max);
|
||||
Vec3 center = (bb_max+bb_min)*0.5f;
|
||||
|
||||
float dx = bb_max.getX()-bb_min.getX();
|
||||
float dz = bb_max.getZ()-bb_min.getZ();
|
||||
|
||||
// Set the scaling correctly. Also the center point (which is used
|
||||
// as the camera position) needs to be adjusted: the track must
|
||||
// be aligned to the left/top of the texture which is used (otherwise
|
||||
// mapPoint2MiniMap doesn't work), so adjust the camera position
|
||||
// that the track is properly aligned (view from the side):
|
||||
// c camera
|
||||
// / \ .
|
||||
// / \ <--- camera angle
|
||||
// / \ .
|
||||
// { [-] } <--- track flat (viewed from the side)
|
||||
// If [-] is the shorter side of the track, then the camera will
|
||||
// actually render the area in { } - which is the length of the
|
||||
// longer side of the track.
|
||||
// To align the [-] side to the left, the camera must be moved
|
||||
// the distance betwwen '{' and '[' to the right. This distance
|
||||
// is exacly (longer_side - shorter_side) / 2.
|
||||
// So, adjust the center point by this amount:
|
||||
if(dz > dx)
|
||||
{
|
||||
center.setX(center.getX() + (dz-dx)*0.5f);
|
||||
m_scaling = dimension.Width / dz;
|
||||
}
|
||||
else
|
||||
{
|
||||
center.setZ(center.getZ() + (dx-dz)*0.5f);
|
||||
m_scaling = dimension.Width / dx;
|
||||
}
|
||||
|
||||
float range = (dx>dz) ? dx : dz;
|
||||
|
||||
core::matrix4 projection;
|
||||
projection.buildProjectionMatrixOrthoLH(range /* width */,
|
||||
range /* height */,
|
||||
-1, bb_max.getY()-bb_min.getY()+1);
|
||||
camera->setProjectionMatrix(projection, true);
|
||||
|
||||
irr_driver->suppressSkyBox();
|
||||
irr_driver->clearLights();
|
||||
|
||||
// Adjust Y position by +1 for max, -1 for min - this helps in case that
|
||||
// the maximum Y coordinate is negative (otherwise the minimap is mirrored)
|
||||
// and avoids problems for tracks which have a flat (max Y = min Y) minimap.
|
||||
camera->setPosition(core::vector3df(center.getX(), bb_min.getY() + 1.0f, center.getZ()));
|
||||
//camera->setPosition(core::vector3df(center.getX() - 5.0f, bb_min.getY() - 1 - 5.0f, center.getZ() - 15.0f));
|
||||
camera->setUpVector(core::vector3df(0, 0, 1));
|
||||
camera->setTarget(core::vector3df(center.getX(),bb_min.getY()-1,center.getZ()));
|
||||
//camera->setAspectRatio(1.0f);
|
||||
camera->updateAbsolutePosition();
|
||||
|
||||
video::ITexture* texture = NULL;
|
||||
FrameBuffer* frame_buffer = NULL;
|
||||
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
frame_buffer = newRttProvider->render(camera, GUIEngine::getLatestDt());
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = oldRttProvider->renderToTexture();
|
||||
delete oldRttProvider;
|
||||
}
|
||||
|
||||
cleanupDebugMesh();
|
||||
irr_driver->removeCameraSceneNode(camera);
|
||||
m_min_coord = bb_min;
|
||||
|
||||
|
||||
if (texture == NULL && frame_buffer == NULL)
|
||||
{
|
||||
Log::error("BattleGraph", "[makeMiniMap] WARNING: RTT does not appear to work,"
|
||||
"mini-map will not be available.");
|
||||
}
|
||||
|
||||
*oldRttMinimap = texture;
|
||||
*newRttMinimap = frame_buffer;
|
||||
World::getWorld()->setClearbackBufferColor(oldClearColor);
|
||||
World::getWorld()->forceFogDisabled(false);
|
||||
|
||||
irr_driver->getSceneManager()->clear();
|
||||
VAOManager::kill();
|
||||
irr_driver->clearGlowingNodes();
|
||||
irr_driver->clearLights();
|
||||
irr_driver->clearForcedBloom();
|
||||
irr_driver->clearBackgroundNodes();
|
||||
} // makeMiniMap
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns the 2d coordinates of a point when drawn on the mini map
|
||||
* texture.
|
||||
* \param xyz Coordinates of the point to map.
|
||||
* \param draw_at The coordinates in pixel on the mini map of the point,
|
||||
* only the first two coordinates will be used.
|
||||
*/
|
||||
void BattleGraph::mapPoint2MiniMap(const Vec3 &xyz,Vec3 *draw_at) const
|
||||
{
|
||||
draw_at->setX((xyz.getX()-m_min_coord.getX())*m_scaling);
|
||||
draw_at->setY((xyz.getZ()-m_min_coord.getZ())*m_scaling);
|
||||
|
||||
} // mapPoint
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Creates the debug mesh to display the quad graph on top of the track
|
||||
@ -221,10 +358,21 @@ void BattleGraph::createDebugMesh()
|
||||
{
|
||||
if(getNumNodes()<=0) return; // no debug output if not graph
|
||||
|
||||
createMesh(/*enable_transparency*/false);
|
||||
createMesh(/*enable_transparency*/true);
|
||||
|
||||
// Now colour the quads red/blue/red ...
|
||||
video::SColor c( 128, 255, 0, 0);
|
||||
video::S3DVertex *v = (video::S3DVertex*)m_mesh_buffer->getVertices();
|
||||
for(unsigned int i=0; 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");
|
||||
m_node->setName("track-debug-mesh");
|
||||
#endif
|
||||
|
||||
} // createDebugMesh
|
||||
@ -244,14 +392,15 @@ void BattleGraph::cleanupDebugMesh()
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void BattleGraph::findItemsOnGraphNodes(ItemManager * item_manager)
|
||||
/** Maps items on battle graph */
|
||||
void BattleGraph::findItemsOnGraphNodes()
|
||||
{
|
||||
const ItemManager* item_manager = ItemManager::get();
|
||||
unsigned int item_count = item_manager->getNumberOfItems();
|
||||
|
||||
for (unsigned int i = 0; i < item_count; ++i)
|
||||
{
|
||||
Item* item = item_manager->getItem(i);
|
||||
const Item* item = item_manager->getItem(i);
|
||||
Vec3 xyz = item->getXYZ();
|
||||
int polygon = BattleGraph::UNKNOWN_POLY;
|
||||
|
||||
|
@ -23,12 +23,9 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include <dimension2d.h>
|
||||
#include "tracks/navmesh.hpp"
|
||||
|
||||
class Navmesh;
|
||||
class Item;
|
||||
class ItemManager;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class ISceneNode; class IMesh; class IMeshBuffer; }
|
||||
@ -36,6 +33,12 @@ namespace irr
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
class FrameBuffer;
|
||||
class Item;
|
||||
class ItemManager;
|
||||
class Navmesh;
|
||||
class RTT;
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*
|
||||
@ -52,6 +55,8 @@ class BattleGraph
|
||||
private:
|
||||
static BattleGraph *m_battle_graph;
|
||||
|
||||
RTT* m_new_rtt;
|
||||
|
||||
/** The actual graph data structure, it is an adjacency matrix */
|
||||
std::vector< std::vector< float > > m_distance_matrix;
|
||||
/** The matrix that is used to store computed shortest paths */
|
||||
@ -63,16 +68,21 @@ private:
|
||||
/** For debug only: the actual mesh buffer storing the quads. */
|
||||
scene::IMeshBuffer *m_mesh_buffer;
|
||||
|
||||
/** Stores the name of the file containing the NavMesh data */
|
||||
std::string m_navmesh_file;
|
||||
/** The minimum coordinates of the quad graph. */
|
||||
Vec3 m_min_coord;
|
||||
|
||||
std::vector< std::pair<Item*, int> > m_items_on_graph;
|
||||
/** Scaling for mini map. */
|
||||
float m_scaling;
|
||||
|
||||
/** Stores the name of the file containing the NavMesh data */
|
||||
std::string m_navmesh_file;
|
||||
|
||||
std::vector< std::pair<const Item*, int> > m_items_on_graph;
|
||||
|
||||
void buildGraph(NavMesh*);
|
||||
void computeFloydWarshall();
|
||||
void createMesh(bool enable_transparency=false,
|
||||
const video::SColor *track_color=NULL);
|
||||
void findItemsOnGraphNodes(ItemManager*);
|
||||
|
||||
BattleGraph(const std::string &navmesh_file_name);
|
||||
~BattleGraph(void);
|
||||
@ -105,7 +115,7 @@ public:
|
||||
// ----------------------------------------------------------------------
|
||||
/** Returns the number of nodes in the BattleGraph (equal to the number of
|
||||
* polygons in the NavMesh */
|
||||
unsigned int getNumNodes() const { return m_distance_matrix.size(); }
|
||||
unsigned int getNumNodes() const { return m_distance_matrix.size(); }
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/** Returns the NavPoly corresponding to the i-th node of the BattleGraph */
|
||||
@ -116,13 +126,20 @@ public:
|
||||
/** Returns the next polygon on the shortest path from i to j.
|
||||
* Note: m_parent_poly[j][i] contains the parent of i on path from j to i,
|
||||
* which is the next node on the path from i to j (undirected graph) */
|
||||
const int & getNextShortestPathPoly(int i, int j) const;
|
||||
const int & getNextShortestPathPoly(int i, int j) const;
|
||||
|
||||
const std::vector< std::pair<Item*, int> >& getItemList()
|
||||
const std::vector < std::pair<const Item*, int> >& getItemList()
|
||||
{ return m_items_on_graph; }
|
||||
|
||||
void createDebugMesh();
|
||||
void cleanupDebugMesh();
|
||||
void createDebugMesh();
|
||||
void cleanupDebugMesh();
|
||||
void findItemsOnGraphNodes();
|
||||
void makeMiniMap(const core::dimension2du &where,
|
||||
const std::string &name,
|
||||
const video::SColor &fill_color,
|
||||
video::ITexture** oldRttMinimap,
|
||||
FrameBuffer** newRttMinimap);
|
||||
void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const;
|
||||
}; //BattleGraph
|
||||
|
||||
#endif
|
||||
|
@ -37,6 +37,8 @@ NavMesh *NavMesh::m_nav_mesh = NULL;
|
||||
NavMesh::NavMesh(const std::string &filename)
|
||||
{
|
||||
|
||||
m_min = Vec3( 99999, 99999, 99999);
|
||||
m_max = Vec3(-99999, -99999, -99999);
|
||||
m_n_verts=0;
|
||||
m_n_polys=0;
|
||||
|
||||
@ -68,6 +70,8 @@ NavMesh::NavMesh(const std::string &filename)
|
||||
//Reading vertices
|
||||
Vec3 p;
|
||||
readVertex(xml_node_node, &p);
|
||||
m_max.max(p);
|
||||
m_min.min(p);
|
||||
m_n_verts++;
|
||||
m_verts.push_back(p);
|
||||
}
|
||||
@ -116,6 +120,44 @@ NavMesh::~NavMesh()
|
||||
{
|
||||
} // ~NavMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the vertices in a irrlicht vertex array to the 4 points of this quad.
|
||||
*/
|
||||
void NavMesh::setVertices(int n, video::S3DVertex *v, const video::SColor &color) const
|
||||
{
|
||||
NavPoly poly = NavMesh::get()->getNavPoly(n);
|
||||
const std::vector<Vec3>& p = poly.getVertices();
|
||||
|
||||
if (p.size() !=4) return;
|
||||
|
||||
// Eps is used to raise the track debug quads a little bit higher than
|
||||
// the ground, so that they are actually visible.
|
||||
core::vector3df eps(0, 0.1f, 0);
|
||||
v[0].Pos = p[0].toIrrVector()+eps;
|
||||
v[1].Pos = p[1].toIrrVector()+eps;
|
||||
v[2].Pos = p[2].toIrrVector()+eps;
|
||||
v[3].Pos = p[3].toIrrVector()+eps;
|
||||
|
||||
core::triangle3df tri(p[0].toIrrVector(), p[1].toIrrVector(),
|
||||
p[2].toIrrVector());
|
||||
core::vector3df normal = tri.getNormal();
|
||||
normal.normalize();
|
||||
v[0].Normal = normal;
|
||||
v[1].Normal = normal;
|
||||
v[2].Normal = normal;
|
||||
|
||||
core::triangle3df tri1(p[0].toIrrVector(), p[2].toIrrVector(),
|
||||
p[3].toIrrVector());
|
||||
core::vector3df normal1 = tri1.getNormal();
|
||||
normal1.normalize();
|
||||
v[3].Normal = normal1;
|
||||
|
||||
v[0].Color = color;
|
||||
v[1].Color = color;
|
||||
v[2].Color = color;
|
||||
v[3].Color = color;
|
||||
} // setVertices
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** Reads the vertex information from an XMLNode */
|
||||
|
@ -55,6 +55,10 @@ class NavMesh
|
||||
private:
|
||||
static NavMesh *m_nav_mesh;
|
||||
|
||||
/** The 2d bounding box, used for hashing. */
|
||||
Vec3 m_min;
|
||||
Vec3 m_max;
|
||||
|
||||
/** The actual set of nav polys that constitute the nav mesh */
|
||||
std::vector<NavPoly> m_polys;
|
||||
|
||||
@ -102,39 +106,53 @@ public:
|
||||
* also don't create one if it doesn't exists. */
|
||||
static NavMesh *get() { return m_nav_mesh; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the minimum and maximum coordinates of this navmesh. */
|
||||
void getBoundingBox(Vec3 *min, Vec3 *max)
|
||||
{ *min=m_min; *max=m_max; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const reference to a NavPoly */
|
||||
const NavPoly& getNavPoly(int n) const
|
||||
{ return m_polys[n]; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const reference to a vertex(Vec3) */
|
||||
const Vec3& getVertex(int n) const
|
||||
{ return m_verts[n]; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the vertices in a irrlicht vertex array to
|
||||
* the 4 points of a navpoly.
|
||||
* \param n The number of a navpoly.
|
||||
* \param v The vertex array in which to set the vertices.
|
||||
* \param color The color to use for this quad.
|
||||
*/
|
||||
void setVertices(int n, video::S3DVertex *v,
|
||||
const video::SColor &color) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const reference to a vector containing all vertices */
|
||||
const std::vector<Vec3>& getAllVertices() const
|
||||
{ return m_verts; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the total number of polys */
|
||||
unsigned int getNumberOfPolys() const
|
||||
{ return m_n_polys; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the total number of vertices */
|
||||
unsigned int getNumberOfVerts() const
|
||||
{ return m_n_verts; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns maximum vertices per polygon */
|
||||
unsigned int getMaxVertsPerPoly() const
|
||||
{ return m_nvp; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center of a polygon */
|
||||
const Vec3& getCenterOfPoly(int n) const
|
||||
{return m_polys[n].getCenter();}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const referece to a vector containing the indices
|
||||
* of polygons adjacent to a given polygon */
|
||||
const std::vector<int>& getAdjacentPolys(int n) const
|
||||
{return m_polys[n].getAdjacents();}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a const reference to a vector containing the vertices
|
||||
* of a given polygon. */
|
||||
const std::vector<Vec3> getVertsOfPoly(int n)
|
||||
|
@ -657,6 +657,53 @@ void Track::startMusic() const
|
||||
music_manager->clearCurrentMusic();
|
||||
} // startMusic
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loads the polygon graph for battle, i.e. the definition of all polys, and the way
|
||||
* they are connected to each other. Input file name is hardcoded for now
|
||||
*/
|
||||
void Track::loadBattleGraph()
|
||||
{
|
||||
BattleGraph::create(m_root+"navmesh.xml");
|
||||
|
||||
if(BattleGraph::get()->getNumNodes()==0)
|
||||
{
|
||||
Log::warn("track", "No graph nodes defined for track '%s'\n",
|
||||
m_filename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Check whether the hardware can do nonsquare or
|
||||
// non power-of-two textures
|
||||
video::IVideoDriver* const video_driver = irr_driver->getVideoDriver();
|
||||
bool nonpower = false; //video_driver->queryFeature(video::EVDF_TEXTURE_NPOT);
|
||||
bool nonsquare =
|
||||
video_driver->queryFeature(video::EVDF_TEXTURE_NSQUARE);
|
||||
|
||||
//Create the minimap resizing it as necessary.
|
||||
m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize();
|
||||
core::dimension2du size = m_mini_map_size
|
||||
.getOptimalSize(!nonpower,!nonsquare);
|
||||
|
||||
BattleGraph::get()->makeMiniMap(size, "minimap::" + m_ident, video::SColor(127, 255, 255, 255),
|
||||
&m_old_rtt_mini_map, &m_new_rtt_mini_map);
|
||||
if (m_old_rtt_mini_map)
|
||||
{
|
||||
m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_old_rtt_mini_map->getSize().Width);
|
||||
m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_old_rtt_mini_map->getSize().Height);
|
||||
}
|
||||
else if (m_new_rtt_mini_map)
|
||||
{
|
||||
m_minimap_x_scale = float(m_mini_map_size.Width) / float(m_new_rtt_mini_map->getWidth());
|
||||
m_minimap_y_scale = float(m_mini_map_size.Height) / float(m_new_rtt_mini_map->getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_minimap_x_scale = 0;
|
||||
m_minimap_y_scale = 0;
|
||||
}
|
||||
}
|
||||
} // loadBattleGraph
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loads the quad graph, i.e. the definition of all quads, and the way
|
||||
* they are connected to each other.
|
||||
@ -723,7 +770,10 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
||||
|
||||
void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const
|
||||
{
|
||||
QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
if (m_is_arena && m_has_navmesh)
|
||||
BattleGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
else
|
||||
QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
draw_at->setX(draw_at->getX() * m_minimap_x_scale);
|
||||
draw_at->setY(draw_at->getY() * m_minimap_y_scale);
|
||||
}
|
||||
@ -1605,6 +1655,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// the information about the size of the texture to render the mini
|
||||
// map to.
|
||||
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
||||
else if (m_is_arena && !m_is_soccer && !m_is_cutscene && m_has_navmesh)
|
||||
loadBattleGraph();
|
||||
|
||||
ItemManager::create();
|
||||
|
||||
@ -1829,15 +1881,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
|
||||
delete root;
|
||||
|
||||
// ItemManager assumes the existence of a QuadGraph, that is why the
|
||||
// quad graph is loaded before ItemManager::create(). This is undesirable
|
||||
// but requires signifcant code overhaul to fix. The new battle graph
|
||||
// performs its own computatoins separate from ItemManager. But
|
||||
// Battle Graph needs ItemManager to be created, and all items to be
|
||||
// added to ItemManager. Loading battle graph here is therefore a workaround
|
||||
// to the main problem.
|
||||
if (m_is_arena && !m_is_soccer && !m_is_cutscene && m_has_navmesh)
|
||||
BattleGraph::create(m_root + "navmesh.xml");
|
||||
BattleGraph::get()->findItemsOnGraphNodes();
|
||||
|
||||
if (UserConfigParams::m_track_debug &&
|
||||
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
|
@ -379,6 +379,7 @@ private:
|
||||
|
||||
void loadTrackInfo();
|
||||
void loadQuadGraph(unsigned int mode_id, const bool reverse);
|
||||
void loadBattleGraph();
|
||||
void convertTrackToBullet(scene::ISceneNode *node);
|
||||
bool loadMainTrack(const XMLNode &node);
|
||||
void createWater(const XMLNode &node);
|
||||
|
Loading…
Reference in New Issue
Block a user