diff --git a/src/challenges/challenge.cpp b/src/challenges/challenge.cpp index 83c72ec61..47988e496 100644 --- a/src/challenges/challenge.cpp +++ b/src/challenges/challenge.cpp @@ -104,7 +104,7 @@ const std::string Challenge::getUnlockedMessage() const Track* track = track_manager->getTrack( m_feature[n].name ); message = StringUtils::insert_values( _("New track '%s'\nnow available"), - _(track->getName()) ); + _(track->getName().c_str()) ); break; } case UNLOCK_MODE: diff --git a/src/graphics/scene.cpp b/src/graphics/scene.cpp index 2a13c4219..8def2b6b0 100644 --- a/src/graphics/scene.cpp +++ b/src/graphics/scene.cpp @@ -69,22 +69,11 @@ void Scene::reset() //----------------------------------------------------------------------------- void Scene::draw(float dt) { - glEnable ( GL_DEPTH_TEST ) ; - const Track* TRACK = RaceManager::getTrack(); - - glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; - for (Cameras::iterator i = m_cameras.begin(); i != m_cameras.end(); ++i) { (*i)->update(dt); (*i)->apply (); } // for cameras - if (TRACK->useFog()) - { - glDisable ( GL_FOG ) ; - } - - glViewport ( 0, 0, UserConfigParams::m_width, UserConfigParams::m_height ) ; } diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 684941ac2..ddebc06dc 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -74,8 +74,9 @@ void World::init() TimedRace::setClockMode( CHRONO ); m_use_highscores = true; - // Create the race gui before anything else is attached to the scene node. - // This allows the race gui to do any rendering on texture. + // Create the race gui before anything else is attached to the scene node + // (which happens when the track is loaded). This allows the race gui to + // do any rendering on texture. m_race_gui = new RaceGUI(); // Grab the track file @@ -161,7 +162,6 @@ void World::init() // objects need to allocate data structures depending on the number // of karts. m_track->reset(); - m_track->startMusic(); if(!history->replayHistory()) history->initRecording(); diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index 0c0dbae65..d1c6b8d24 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -42,26 +42,15 @@ using namespace irr; */ RaceGUI::RaceGUI() { - // FIXME: translation problem - m_pos_string[0] = "?!?"; - m_pos_string[1] = "1st"; - m_pos_string[2] = "2nd"; - m_pos_string[3] = "3rd"; - m_pos_string[4] = "4th"; - m_pos_string[5] = "5th"; - m_pos_string[6] = "6th"; - m_pos_string[7] = "7th"; - m_pos_string[8] = "8th"; - m_pos_string[9] = "9th"; - m_pos_string[10] = "10th"; - - int icon_width=40; - int icon_player_width=50; - if(UserConfigParams::m_height<600) - { - icon_width = 27; - icon_player_width = 35; - } + m_marker_rendered_size = 32; + m_marker_ai_size = 14; + m_marker_player_size = 16; + m_map_rendered_width = 128; + m_map_rendered_height = 128; + m_map_width = 100; + m_map_height = 100; + m_map_left = 10; + m_map_bottom = 10; m_speed_meter_icon = material_manager->getMaterial("speedback.png"); m_speed_bar_icon = material_manager->getMaterial("speedfore.png"); @@ -87,16 +76,16 @@ void RaceGUI::createMarkerTexture() // Textures must be power of 2, so while(npower2>1)-1; - irr_driver->beginRenderToTexture(core::dimension2di(marker_size * npower2, marker_size), + int radius = (m_marker_rendered_size>>1)-1; + irr_driver->beginRenderToTexture(core::dimension2di(m_marker_rendered_size * npower2, + m_marker_rendered_size), "RaceGUI::markers"); for(unsigned int i=0; igetNumKarts(); i++) { const std::string& kart_name = race_manager->getKartName(i); const KartProperties *kp = kart_properties_manager->getKart(kart_name); - core::vector2df center((float)((marker_size>>1)+i*marker_size), - (float)(marker_size>>1)); + core::vector2df center((float)((m_marker_rendered_size>>1)+i*m_marker_rendered_size), + (float)(m_marker_rendered_size>>1) ); int count = kp->getShape(); core::array vertices; createRegularPolygon(count, (float)radius, center,&vertices); @@ -109,7 +98,6 @@ void RaceGUI::createMarkerTexture() #endif } m_marker = irr_driver->endRenderToTexture(); - core::dimension2di X = m_marker->getOriginalSize(); } // createMarkerTexture //----------------------------------------------------------------------------- @@ -171,64 +159,40 @@ void RaceGUI::drawTimer () } // drawTimer //----------------------------------------------------------------------------- -#define TRACKVIEW_SIZE 100 - -void RaceGUI::drawMap() +/** Draws the mini map and the position of all karts on it. + */ +void RaceGUI::drawMiniMap() { // arenas currently don't have a map. if(RaceManager::getTrack()->isArena()) return; + const video::ITexture *mini_map=RaceManager::getTrack()->getMiniMap(); - core::rect dest(10, UserConfigParams::m_height-60, - 60, UserConfigParams::m_height-10); + int upper_y = UserConfigParams::m_height-m_map_bottom-m_map_height; + int lower_y = UserConfigParams::m_height-m_map_bottom; + core::rect dest(m_map_left, upper_y, + m_map_left + m_map_width, lower_y); core::rect source(core::position2di(0, 0), mini_map->getOriginalSize()); - //FIXME irr_driver->getVideoDriver()->draw2DImage(mini_map, dest, source, 0, 0, true); - - core::rect dest1( 10, UserConfigParams::m_height-10, - 100, UserConfigParams::m_height-110); - core::rect source1(core::position2di(0, 0), m_marker->getOriginalSize()); - irr_driver->getVideoDriver()->draw2DImage(m_marker, dest, source1, 0, 0, true); + irr_driver->getVideoDriver()->draw2DImage(mini_map, dest, source, 0, 0, true); - return; - - glDisable ( GL_TEXTURE_2D ) ; - assert(RaceManager::getWorld() != NULL); - int xLeft = 10; - int yTop = 10; - - RaceManager::getTrack() -> draw2Dview ( (float)xLeft, (float)yTop ); - - glBegin ( GL_QUADS ) ; - - for ( unsigned int i = 0 ; i < race_manager->getNumKarts() ; i++ ) + for(unsigned int i=0; igetNumKarts(); i++) { - Kart* kart = RaceManager::getKart(i); + const Kart *kart = RaceManager::getKart(i); if(kart->isEliminated()) continue; // don't draw eliminated kart - //glColor3fv ( kart->getColor().toFloat()); - const Vec3& xyz = kart->getXYZ(); - - /* If it's a player, draw a bigger sign */ - // TODO - /* - if (kart -> isPlayerKart ()) - { - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft+3, (float)yTop+3); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft-2, (float)yTop+3); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft-2, (float)yTop-2); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft+3, (float)yTop-2); - } - else - { - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft+2, (float)yTop+2); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft-1, (float)yTop+2); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft-1, (float)yTop-1); - RaceManager::getTrack() -> glVtx ( xyz.toFloat(), (float)xLeft+2, (float)yTop-1); - } - */ - } - - glEnd () ; - glEnable ( GL_TEXTURE_2D ) ; + const Vec3& xyz = kart->getXYZ(); + Vec3 draw_at; + RaceManager::getTrack()->mapPoint2MiniMap(xyz, &draw_at); + int marker_height = m_marker->getOriginalSize().Height; + core::rect source(i *m_marker_rendered_size, 0, + (i+1)*m_marker_rendered_size, m_marker_rendered_size); + int marker_half_size = (kart->isPlayerKart() ? m_marker_player_size + : m_marker_ai_size )>>1; + core::rect position(m_map_left+(int)(draw_at.getX()-marker_half_size), + lower_y -(int)(draw_at.getY()+marker_half_size), + m_map_left+(int)(draw_at.getX()+marker_half_size), + lower_y -(int)(draw_at.getY()-marker_half_size)); + irr_driver->getVideoDriver()->draw2DImage(m_marker, position, source, NULL, NULL, true); + } // for i AllMessageType; AllMessageType m_messages; + /** A texture with all mini dots to be displayed in the minimap for all karts. */ video::ITexture *m_marker; + /** The mini map of the track. */ + video::ITexture *m_mini_map; + /** The size of a single marker in pixels, must be a power of 2. */ + int m_marker_rendered_size; + + /** The size of a single marker on the screen for AI karts, + * need not be a power of 2. */ + int m_marker_ai_size; + + /** The size of a single marker on the screen or player karts, + * need not be a power of 2. */ + int m_marker_player_size; + + /** The width of the rendered mini map in pixels, must be a power of 2. */ + int m_map_rendered_width; + + /** The height of the rendered mini map in pixels, must be a power of 2. */ + int m_map_rendered_height; + + /** Width of the map in pixels on the screen, need not be a power of 2. */ + int m_map_width; + + /** Height of the map in pixels on the screen, need not be a power of 2. */ + int m_map_height; + + /** Distance of map from left side of screen. */ + int m_map_left; + + /** Distance of map from bottom of screen. */ + int m_map_bottom; + + + void createMarkerTexture(); void createRegularPolygon(unsigned int n, float radius, const core::vector2df ¢er, @@ -110,7 +143,7 @@ private: float ratio_x, float ratio_y ); void drawPlayerIcons (const KartIconDisplayInfo* info); void oldDrawPlayerIcons (); - void drawMap (); + void drawMiniMap (); void drawTimer (); void drawMusicDescription (); void cleanupMessages (const float dt); @@ -127,6 +160,10 @@ public: void addMessage(const std::string &m, const Kart *kart, float time, int fonst_size, const video::SColor &color=video::SColor(255, 255, 0, 255)); + + /** Returns the size of the texture on which to render the minimap to. */ + const core::dimension2di getMiniMapSize() const + { return core::dimension2di(m_map_width, m_map_height); } }; #endif diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index d38d0b036..4eda6d854 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -38,6 +38,7 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, m_node = NULL; m_mesh = NULL; m_mesh_buffer = NULL; + m_lap_length = 0; m_all_quads = new QuadSet(quad_file_name); GraphNode::m_all_quads = m_all_quads; GraphNode::m_all_nodes = this; @@ -132,6 +133,15 @@ void QuadGraph::load(const std::string &filename) } delete xml; + for(unsigned int i=0; igetSuccessor(0)==0) + { + m_lap_length = m_all_nodes[i]->getDistanceFromStart() + + m_all_nodes[i]->getDistanceToSuccessor(0); + break; + } + } setDefaultSuccessors(); } // load @@ -406,11 +416,6 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2di &dimension, const video::SColor &fill_color) { irr_driver->beginRenderToTexture(dimension, name); - for(unsigned int i=0; igetNumberOfQuads(); i++) - { -// core::array vertices; -// vertices.push_back(core::vertices - } createMesh(); video::S3DVertex *v = (video::S3DVertex*)m_mesh_buffer->getVertices(); for(unsigned int i=0; igetVertexCount(); i++) @@ -420,16 +425,38 @@ video::ITexture *QuadGraph::makeMiniMap(const core::dimension2di &dimension, m_node = irr_driver->addMesh(m_mesh); // add Debug Mesh m_node->setMaterialFlag(video::EMF_LIGHTING, false); + // Add the camera: + // --------------- + scene::ICameraSceneNode *camera = irr_driver->addCamera(); Vec3 bb_min, bb_max; m_all_quads->getBoundingBox(&bb_min, &bb_max); Vec3 center = (bb_max+bb_min)*0.5f; - scene::ICameraSceneNode *camera = irr_driver->addCamera(); - camera->setPosition(core::vector3df(center.getX(), 120, center.getY())); + core::matrix4 projection; + projection.buildProjectionMatrixOrthoLH(bb_max.getX()-bb_min.getX(), + bb_max.getY()-bb_min.getY(), + -1, bb_max.getZ()-bb_min.getZ()+1); + camera->setProjectionMatrix(projection, true); + camera->setPosition(core::vector3df(center.getX(), bb_max.getZ(), center.getY())); camera->setUpVector(core::vector3df(0,0,1)); camera->setTarget(core::vector3df(center.getX(),0,center.getY())); video::ITexture *texture=irr_driver->endRenderToTexture(); cleanupDebugMesh(); + m_min_coord = bb_min; + m_scaling = dimension.Width/(bb_max.getX()-bb_min.getX()); return texture; } // drawMiniMap +//----------------------------------------------------------------------------- + /** 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.getX()); + draw_at->setY((xyz.getY()-m_min_coord.getY())*m_scaling.getY()); + +} // mapPoint \ No newline at end of file diff --git a/src/tracks/quad_graph.hpp b/src/tracks/quad_graph.hpp index 11fc1e3b5..4270cd4a5 100644 --- a/src/tracks/quad_graph.hpp +++ b/src/tracks/quad_graph.hpp @@ -41,6 +41,15 @@ private: /** 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, only x and y components are used. */ + Vec3 m_scaling; + void setDefaultSuccessors(); void load (const std::string &filename); void createMesh(); @@ -66,33 +75,37 @@ public: const std::string &name, const video::SColor &fill_color =video::SColor(127, 255, 255, 255) ); + void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const; /** Returns the number of nodes in the graph. */ - unsigned int getNumNodes() const { return m_all_nodes.size(); } + unsigned int getNumNodes() const { return m_all_nodes.size(); } // ---------------------------------------------------------------------- /** Return the distance to the j-th successor of node n. */ - float getDistanceToNext(int n, int j) const + float getDistanceToNext(int n, int j) const { return m_all_nodes[n]->getDistanceToSuccessor(j);} // ---------------------------------------------------------------------- /** Returns the angle of the line between node n and its j-th. * successor. */ - float getAngleToNext(int n, int j) const + float getAngleToNext(int n, int j) const { return m_all_nodes[n]->getAngleToSuccessor(j); } // ---------------------------------------------------------------------- /** Returns the number of successors of a node n. */ - int getNumberOfSuccessors(int n) const + int getNumberOfSuccessors(int n) const { return m_all_nodes[n]->getNumberOfSuccessors(); } // ---------------------------------------------------------------------- /** Returns the quad that belongs to a graph node. */ - const Quad& getQuad(unsigned int j) const + const Quad& getQuad(unsigned int j) const { return m_all_quads->getQuad(m_all_nodes[j]->getIndex()); } // ---------------------------------------------------------------------- /** Returns the quad that belongs to a graph node. */ - GraphNode& getNode(unsigned int j) const{ return *m_all_nodes[j]; } + GraphNode& getNode(unsigned int j) const{ return *m_all_nodes[j]; } // ---------------------------------------------------------------------- /** Returns the distance from the start to the beginning of a quad. */ - float getDistanceFromStart(int j) const + float getDistanceFromStart(int j) const { return m_all_nodes[j]->getDistanceFromStart(); } + // ---------------------------------------------------------------------- + /** Returns the length of the main driveline. */ + float getLapLength() const {return m_lap_length; } }; // QuadGraph #endif diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 05ba85d11..dcd5c462f 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -45,6 +45,7 @@ using namespace irr; #include "physics/physical_object.hpp" #include "physics/triangle_mesh.hpp" #include "race/race_manager.hpp" +#include "states_screens/race_gui.hpp" #include "tracks/bezier_curve.hpp" #include "tracks/check_manager.hpp" #include "tracks/quad_graph.hpp" @@ -54,28 +55,24 @@ using namespace irr; const float Track::NOHIT = -99999.9f; // ---------------------------------------------------------------------------- -Track::Track( std::string filename_, float w, float h, bool stretch ) +Track::Track( std::string filename) { - m_filename = filename_; - m_item_style = ""; - m_track_2d_width = w; - m_track_2d_height = h; - m_do_stretch = stretch; - m_description = ""; - m_designer = ""; - m_screenshot = ""; - m_version = 0; - m_track_mesh = new TriangleMesh(); - m_non_collision_mesh = new TriangleMesh(); + m_filename = filename; + m_item_style = ""; + m_description = ""; + m_designer = ""; + m_screenshot = ""; + m_version = 0; + m_track_mesh = new TriangleMesh(); + m_non_collision_mesh = new TriangleMesh(); m_all_nodes.clear(); m_all_meshes.clear(); - m_has_final_camera = false; - m_is_arena = false; - m_quad_graph = NULL; - m_animation_manager = NULL; - m_check_manager = NULL; + m_has_final_camera = false; + m_is_arena = false; + m_quad_graph = NULL; + m_animation_manager = NULL; + m_check_manager = NULL; loadTrack(m_filename); - loadQuadGraph(); } // Track //----------------------------------------------------------------------------- @@ -85,6 +82,7 @@ Track::~Track() if(m_quad_graph) delete m_quad_graph; if(m_animation_manager) delete m_animation_manager; if(m_check_manager) delete m_check_manager; + if(m_mini_map) irr_driver->removeTexture(m_mini_map); } // ~Track //----------------------------------------------------------------------------- @@ -153,18 +151,9 @@ btTransform Track::getStartTransform(unsigned int pos) const orig.setZ( m_start_positions[pos][2] ); } else - { - // sometimes the first kart would be too close - // to the first driveline point and not to the last one --> - // This kart would not get any lap counting done in the first - // lap! Therefore an offset is substracted from its Y location, - // and this offset is calculated based on the drivelines - float offset = 1.5f; - if(m_left_driveline[0].getY() > 0 || m_right_driveline[0].getY() > 0) - offset += std::max(m_left_driveline[0].getY(), m_left_driveline[0].getY()); - + { orig.setX( pos sy ) - { - sx = sy; - x += w/2 - width*sx/2; - } - else - { - sy = sx; - } - - const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size(); - - glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT ); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable (GL_TEXTURE_2D); - - glColor4f ( 1, 1, 1, 0.5) ; - - glBegin ( GL_QUAD_STRIP ) ; - - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * sy) ; - - glVertex2f ( x + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - } - glVertex2f ( x + ( m_left_driveline[0].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[0].getY() - m_driveline_min.getY() ) * sy) ; - glVertex2f ( x + ( m_right_driveline[0].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[0].getY() - m_driveline_min.getY() ) * sy ) ; - - glEnd () ; - - glEnable( GL_LINE_SMOOTH ); - glEnable( GL_POINT_SMOOTH ); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - - glLineWidth(1); - glPointSize(1); - - glColor4f ( 0, 0, 0, 1 ) ; - - glBegin ( GL_LINES ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE - 1 ; ++i ) - { - /*Draw left driveline of the map*/ - glVertex2f ( x + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - - glVertex2f ( x + ( m_left_driveline[i+1].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[i+1].getY() - m_driveline_min.getY() ) * sy ) ; - - - /*Draw left driveline of the map*/ - glVertex2f ( x + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - - glVertex2f ( x + ( m_right_driveline[i+1].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[i+1].getY() - m_driveline_min.getY() ) * sy ) ; - } - - //Close the left driveline - glVertex2f ( x + ( m_left_driveline[DRIVELINE_SIZE - 1].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[DRIVELINE_SIZE - 1].getY() - m_driveline_min.getY() ) * sy ) ; - - glVertex2f ( x + ( m_left_driveline[0].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[0].getY() - m_driveline_min.getY() ) * sy ) ; - - - //Close the right driveline - glVertex2f ( x + ( m_right_driveline[DRIVELINE_SIZE - 1].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[DRIVELINE_SIZE - 1].getY() - m_driveline_min.getY() ) * sy ) ; - - glVertex2f ( x + ( m_right_driveline[0].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[0].getY() - m_driveline_min.getY() ) * sy ) ; - glEnd () ; - -#if 0 - //FIXME: We are not sure if it's a videocard problem, but on Linux with a - //Nvidia Geforce4 mx 440, we get problems with GL_LINE_LOOP; - //If this issue is solved, using GL_LINE_LOOP is a better solution than - //GL_LINES - glBegin ( GL_LINE_LOOP ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - } - glEnd () ; - - glBegin ( GL_LINE_LOOP ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - } - glEnd () ; -#endif - - - glBegin ( GL_POINTS ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - - glVertex2f ( x + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * sx, - y + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * sy ) ; - } - glEnd () ; - - glPopAttrib(); - -} // drawScaled2D - -//----------------------------------------------------------------------------- -void Track::draw2Dview (float x_offset, float y_offset) const -{ - - const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size(); - - glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT ); - - glEnable ( GL_BLEND ); - glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable (GL_TEXTURE_2D); - - //TODO: maybe colors should be configurable, or at least the alpha value - glColor4f ( 1.0f, 1.0f, 1.0f, 0.4f) ; - - -/*FIXME: Too much calculations here, we should be generating scaled driveline arrays - * in Track::loadQuadGraph so all we'd be doing is pumping out predefined - * vertexes in-game. - */ - /*Draw white filling of the map*/ - glBegin ( GL_QUAD_STRIP ) ; - - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) { - glVertex2f ( x_offset + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y) ; - glVertex2f ( x_offset + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - } - glVertex2f ( x_offset + ( m_left_driveline[0].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[0].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - glVertex2f ( x_offset + ( m_right_driveline[0].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[0].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glEnd () ; - - - glEnable( GL_LINE_SMOOTH ); - glEnable( GL_POINT_SMOOTH ); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - - glLineWidth(2); - glPointSize(2); - - glColor4f ( 0,0,0,1) ; - - - glBegin ( GL_LINES ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE - 1 ; ++i ) - { - /*Draw left driveline of the map*/ - glVertex2f ( x_offset + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glVertex2f ( x_offset + ( m_left_driveline[i+1].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[i+1].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - - /*Draw left driveline of the map*/ - glVertex2f ( x_offset + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glVertex2f ( x_offset + ( m_right_driveline[i+1].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[i+1].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - } - - //Close the left driveline - glVertex2f ( x_offset + ( m_left_driveline[DRIVELINE_SIZE - 1].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[DRIVELINE_SIZE - 1].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glVertex2f ( x_offset + ( m_left_driveline[0].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[0].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - - //Close the right driveline - glVertex2f ( x_offset + ( m_right_driveline[DRIVELINE_SIZE - 1].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[DRIVELINE_SIZE - 1].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glVertex2f ( x_offset + ( m_right_driveline[0].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[0].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - glEnd () ; - -#if 0 - //FIXME: We are not sure if it's a videocard problem, but on Linux with a - //Nvidia Geforce4 mx 440, we get problems with GL_LINE_LOOP; - //If this issue is solved, using GL_LINE_LOOP is a better solution than - //GL_LINES - glBegin ( GL_LINE_LOOP ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x_offset + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - } - glEnd () ; - - glBegin ( GL_LINE_LOOP ) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x_offset + ( m_right_driveline[i].get() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - } - glEnd () ; -#endif - - /*Because of the way OpenGL draws lines of widths higher than 1, - *we have to draw the joints too, in order to fill small spaces - *between lines - */ - glBegin ( GL_POINTS) ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - glVertex2f ( x_offset + ( m_left_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_left_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - - glVertex2f ( x_offset + ( m_right_driveline[i].getX() - m_driveline_min.getX() ) * m_scale_x, - y_offset + ( m_right_driveline[i].getY() - m_driveline_min.getY() ) * m_scale_y ) ; - } - glEnd () ; - - glPopAttrib(); - -} // draw2Dview - //----------------------------------------------------------------------------- void Track::loadTrack(const std::string &filename) { @@ -453,7 +181,7 @@ void Track::loadTrack(const std::string &filename) m_gravity = 9.80665f; m_sun_position = core::vector3df(0.4f, 0.4f, 0.4f); m_sky_color = video::SColorf(0.3f, 0.7f, 0.9f, 1.0f); - m_fog_color = video::SColorf(0.3f, 0.7f, 0.9f, 1.0f); + m_fog_color = video::SColorf(0.3f, 0.7f, 0.9f, 1.0f).toSColor(); m_ambient_color = video::SColorf(0.5f, 0.5f, 0.5f, 1.0f); m_specular_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); m_diffuse_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); @@ -600,136 +328,16 @@ void Track::loadQuadGraph() { m_quad_graph = new QuadGraph(file_manager->getTrackFile(m_ident+".quads"), file_manager->getTrackFile(m_ident+".graph")); - m_mini_map = m_quad_graph->makeMiniMap(core::dimension2di(128,128), m_ident); + m_mini_map = m_quad_graph->makeMiniMap(RaceManager::getWorld()->getRaceGUI()->getMiniMapSize(), + "minimap::"+m_ident); if(m_quad_graph->getNumNodes()==0) { fprintf(stderr, "No graph nodes defined for track '%s'\n", m_filename.c_str()); exit(-1); } - readDrivelineFromFile(m_left_driveline, ".drvl"); - - const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size(); - m_right_driveline.reserve(DRIVELINE_SIZE); - readDrivelineFromFile(m_right_driveline, ".drvr"); - - if(m_right_driveline.size() != m_left_driveline.size()) - std::cout << "Error: driveline's sizes do not match, right " << - "driveline is " << m_right_driveline.size() << " vertex long " << - "and the left driveline is " << m_left_driveline.size() - << " vertex long. Track is " << m_name << " ." << std::endl; - - m_driveline.reserve(DRIVELINE_SIZE); - for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i) - { - Vec3 center_point = (m_left_driveline[i]+m_right_driveline[i])*0.5; - m_driveline.push_back(center_point); - } - - for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i) - { - unsigned int next = i + 1 >= DRIVELINE_SIZE ? 0 : i + 1; - float dx = m_driveline[next].getX() - m_driveline[i].getX(); - float dy = m_driveline[next].getY() - m_driveline[i].getY(); - - float theta = -atan2(dx, dy); - } - - m_driveline_min = Vec3( 9999999.9f); - m_driveline_max = Vec3(-9999999.9f); - - float d = 0.0f ; - for ( size_t i = 0 ; i < DRIVELINE_SIZE ; ++i ) - { - //Both drivelines must be checked to get the true size of - //the drivelines, and using the center driveline is not - //good enough. - m_driveline_min.min(m_right_driveline[i]); - m_driveline_min.min(m_left_driveline[i] ); - m_driveline_max.max(m_right_driveline[i]); - m_driveline_max.max(m_left_driveline[i] ); - - d += (m_driveline[i]-m_driveline[ i==DRIVELINE_SIZE-1 ? 0 : i+1 ]).length(); - } - m_total_distance = d; - Vec3 sc = m_driveline_max - m_driveline_min; - - m_scale_x = m_track_2d_width / sc.getX(); - m_scale_y = m_track_2d_height / sc.getY(); - - if(!m_do_stretch) m_scale_x = m_scale_y = std::min(m_scale_x, m_scale_y); - } // loadQuadGraph -//----------------------------------------------------------------------------- -void -Track::readDrivelineFromFile(std::vector& line, const std::string& file_ext) -{ - std::string path = file_manager->getTrackFile(m_ident+file_ext); - FILE *fd = fopen ( path.c_str(), "r" ) ; - - if ( fd == NULL ) - { - std::ostringstream msg; - msg<<"Can't open '"< 15.0f) - { - fprintf(stderr,"In file %s point %d is too far(>15.0) from next point at %d.\n", - path, prev_sector, prev_distance); - } -#endif - - line.push_back(point); - ++prev_sector; - prev_distance -= 1.5f; - } - - fclose ( fd ) ; -} // readDrivelineFromFile - // ----------------------------------------------------------------------------- //* Convert the ssg track tree into its physics equivalents. void Track::createPhysicsModel() @@ -965,6 +573,11 @@ void Track::createWater(const XMLNode &node) */ void Track::loadTrackModel() { + // Load the graph only now: this function is called from world, after + // the race gui was created. The race gui is needed since it stores + // the information about the size of the texture to render the mini + // map to. + loadQuadGraph(); // Add the track directory to the texture search path file_manager->pushTextureSearchPath(file_manager->getTrackFile("",getIdent())); file_manager->pushModelSearchPath (file_manager->getTrackFile("",getIdent())); @@ -1106,11 +719,10 @@ void Track::loadTrackModel() file_manager->popTextureSearchPath(); file_manager->popModelSearchPath (); - const core::vector3df &sun_pos = getSunPos(); - irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 120, 120, 120)); - m_light = irr_driver->getSceneManager()->addLightSceneNode(NULL, sun_pos, video::SColorf(1.0f,1.0f,1.0f)); + m_light = irr_driver->getSceneManager()->addLightSceneNode(NULL, m_sun_position, + video::SColorf(1.0f,1.0f,1.0f)); m_light->setLightType(video::ELT_DIRECTIONAL); m_light->setRotation( core::vector3df(180, 45, 45) ); @@ -1118,13 +730,17 @@ void Track::loadTrackModel() m_light->getLightData().SpecularColor = irr::video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); /* - m_light = irr_driver->getSceneManager()->addLightSceneNode(0, sun_pos); + m_light = irr_driver->getSceneManager()->addLightSceneNode(0, m_sun_position); video::SLight light; // HACK & TEST: checking how ambient looks for some things, must be properly done once we reach an agreement light.AmbientColor = irr::video::SColorf(0.666666f, 0.666666f, 0.666666f, 0.0f); m_light->setLightData(light); */ - + + if(m_use_fog) + { + irr_driver->getVideoDriver()->setFog(m_fog_color, true, m_fog_start, m_fog_end, m_fog_density); + } // Note: the physics world for irrlicht is created in loadMainTrack createPhysicsModel(); diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 39d6844a5..c5bbdf504 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -72,13 +72,14 @@ private: Vec3 m_camera_final_hpr; bool m_is_arena; int m_version; - bool loadMainTrack(const XMLNode &node); - void createWater(const XMLNode &node); + /** The graph used to connect the quads. */ QuadGraph *m_quad_graph; + /** The type of sky to be used for the track. */ enum {SKY_NONE, SKY_BOX, SKY_DOME} m_sky_type; + /** A list of the textures for the sky to use. It contains one texture * in case of a dome, and 6 textures for a box. */ std::vector m_sky_textures; @@ -100,6 +101,18 @@ private: /** If a sky dome is used, percentage of the texture to be used. */ float m_sky_texture_percent; + std::string m_name; + bool m_use_fog; + float m_fog_density; + float m_fog_start; + float m_fog_end; + core::vector3df m_sun_position; + video::SColorf m_ambient_color; + video::SColorf m_specular_color; + video::SColorf m_diffuse_color; + video::SColorf m_sky_color; + video::SColor m_fog_color; + /** The texture for the mini map, which is displayed in the race gui. */ video::ITexture *m_mini_map; @@ -112,86 +125,60 @@ private: /** Checkline manager. */ CheckManager *m_check_manager; + void loadTrack(const std::string &filename); + void itemCommand(const Vec3 &xyz, Item::ItemType item_type, + int bNeedHeight); + void loadQuadGraph(); + void convertTrackToBullet(const scene::IMesh *mesh); + bool loadMainTrack(const XMLNode &node); + void createWater(const XMLNode &node); + void getMusicInformation(std::vector& filenames, + std::vector& m_music ); void loadCurves(const XMLNode &node); void handleAnimatedTextures(scene::ISceneNode *node, const XMLNode &xml); -public: - - std::string m_name; - bool m_use_fog; - float m_fog_density; - float m_fog_start; - float m_fog_end; - core::vector3df m_sun_position; - video::SColorf m_ambient_color; - video::SColorf m_specular_color; - video::SColorf m_diffuse_color; - video::SColorf m_sky_color; - video::SColorf m_fog_color; - - //FIXME: Maybe the next 4 vectors should be inside an struct and be used - //from a vector of structs? - //FIXME: should the driveline be set as a sgVec2? -private: - std::vector m_driveline; - //Left and Right drivelines for overhead map rendering. - std::vector m_left_driveline; - std::vector m_right_driveline; public: /** Start positions for arenas (unused in linear races) */ std::vector m_start_positions; - - Vec3 m_driveline_min; - Vec3 m_driveline_max; - - - float m_total_distance; static const float NOHIT; - float m_track_2d_width, // Width and heigth of the 2d display of the track - m_track_2d_height; - float m_scale_x, // Scaling to fit track into the size determined by - m_scale_y; // track2dWidth/Heightheigth - bool m_do_stretch; // 2d track display might be stretched to fit better - - Track (std::string filename,float w=100, - float h=100, bool stretch=1); + Track (std::string filename); ~Track (); bool isArena () const { return m_is_arena; } void cleanup (); /** Returns the texture with the mini map for this track. */ const video::ITexture*getMiniMap () const { return m_mini_map; } - void draw2Dview (float x_offset, - float y_offset ) const; - void drawScaled2D (float x, float y, float w, - float h ) const; - const Vec3& trackToSpatial (const int SECTOR) const; void loadTrackModel (); void addMusic (MusicInformation* mi) {m_music.push_back(mi); } float getGravity () const {return m_gravity; } + /** Returns the version of the .track file. */ int getVersion () const {return m_version; } - float getTrackLength () const {return m_total_distance; } + + /** Returns the length of the main driveline. */ + float getTrackLength () const {return m_quad_graph->getLapLength(); } + + /** Returns a unique identifier for this track (the directory name). */ const std::string& getIdent () const {return m_ident; } - const char* getName () const {return m_name.c_str(); } + + /** Returns the name of the track, which is e.g. displayed on the screen. */ + + const std::string& getName () const {return m_name; } + + /** Returns all groups this track belongs to. */ const std::vector getGroups () const {return m_groups; } + + /** Starts the music for this track. */ void startMusic () const; + + /** Returns the filename of this track. */ const std::string& getFilename () const {return m_filename; } - const core::vector3df& getSunPos () const {return m_sun_position; } - const video::SColorf& getAmbientCol () const {return m_ambient_color; } - const video::SColorf& getDiffuseCol () const {return m_diffuse_color; } - const video::SColorf& getSpecularCol () const {return m_specular_color; } - const video::SColorf& getFogColor () const {return m_fog_color; } - const video::SColorf& getSkyColor () const {return m_sky_color; } - const bool& useFog () const {return m_use_fog; } - const float& getFogDensity () const {return m_fog_density; } - const float& getFogStart () const {return m_fog_start; } - const float& getFogEnd () const {return m_fog_end; } + const std::string& getDescription () const {return m_description; } const std::string& getDesigner () const {return m_designer; } const std::string& getScreenshotFile () const {return m_screenshot; } @@ -218,26 +205,15 @@ public: * \param n Number of the quad for which the angle is asked. */ float getAngle(int n) const - { return m_quad_graph->getAngleToNext(n, 0); } - /* - void glVtx (sgVec2 v, float x_offset, float y_offset) const - { - glVertex2f( - x_offset+(v[0]-m_driveline_min[0])*m_scale_x, - y_offset+(v[1]-m_driveline_min[1])*m_scale_y); - }*/ - -private: - void loadTrack(const std::string &filename); - void itemCommand(const Vec3 &xyz, Item::ItemType item_type, - int bNeedHeight); - void loadQuadGraph(); - void readDrivelineFromFile(std::vector& line, - const std::string& file_ext); - void convertTrackToBullet(const scene::IMesh *mesh); - void getMusicInformation(std::vector& filenames, - std::vector& m_music ); -} -; // class Track + { return m_quad_graph->getAngleToNext(n, 0); } + /** 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 mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const + { m_quad_graph->mapPoint2MiniMap(xyz, draw_at); } +}; // class Track #endif