diff --git a/src/Makefile.am b/src/Makefile.am index 35b29c6de..f29a7e12f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -220,6 +220,8 @@ supertuxkart_SOURCES = \ physics/triangle_mesh.hpp \ robots/default_robot.cpp \ robots/default_robot.hpp \ + tracks/graph_node.hpp\ + tracks/graph_node.cpp\ tracks/quad.hpp \ tracks/quad.cpp \ tracks/quad_graph.hpp \ diff --git a/src/graphics/moving_texture.cpp b/src/graphics/moving_texture.cpp index c1a7b0347..9fece0c03 100644 --- a/src/graphics/moving_texture.cpp +++ b/src/graphics/moving_texture.cpp @@ -20,6 +20,11 @@ #include "graphics/moving_texture.hpp" #include "io/xml_node.hpp" +/** Constructor for an animated texture. + * \param matrix The texture matrix to modify. + * \param node An XML node containing dx and dy attributes to set the + * speed of the animation. + */ MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node) : m_matrix(matrix) { @@ -34,11 +39,33 @@ MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node) } // MovingTexture //----------------------------------------------------------------------------- +/** Constructor for an animated texture, specifying the speed of the animation + * directly. + * \param matrix The texture matrix to modify. + * \param dx Speed of the animation in X direction. + * \param dy Speed of the animation in Y direction. + */ +MovingTexture::MovingTexture(core::matrix4 *matrix, float dx, float dy) + : m_matrix(matrix) +{ + m_dx = dx; + m_dy = dy; + core::vector3df v = m_matrix->getTranslation(); + m_x = v.X; + m_y = v.Y; +} // Moving Texture + +//----------------------------------------------------------------------------- +/** Destructor for an animated texture. + */ MovingTexture::~MovingTexture() { } // ~MovingTexture //----------------------------------------------------------------------------- +/** Updates the transform of an animated texture. + * \param dt Time step size. + */ void MovingTexture::update(float dt) { m_x = m_x + dt*m_dx; diff --git a/src/graphics/moving_texture.hpp b/src/graphics/moving_texture.hpp index ffbb1974e..014755195 100644 --- a/src/graphics/moving_texture.hpp +++ b/src/graphics/moving_texture.hpp @@ -38,6 +38,7 @@ private: public: MovingTexture(core::matrix4 *matrix, const XMLNode &node); + MovingTexture(core::matrix4 *matrix, float dx, float dy); ~MovingTexture(); void update (float dt); void init () {}; diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 50730d53e..158c1b066 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -608,6 +608,10 @@ + + @@ -1206,6 +1210,10 @@ + + diff --git a/src/io/xml_node.cpp b/src/io/xml_node.cpp index edd95c493..8c559d305 100644 --- a/src/io/xml_node.cpp +++ b/src/io/xml_node.cpp @@ -194,6 +194,15 @@ int XMLNode::get(const std::string &attribute, int *value) const return 1; } // get(int) +// ---------------------------------------------------------------------------- +int XMLNode::get(const std::string &attribute, unsigned int *value) const +{ + std::string s; + if(!get(attribute, &s)) return 0; + *value = atoi(s.c_str()); + return 1; +} // get(unsigned int) + // ---------------------------------------------------------------------------- int XMLNode::get(const std::string &attribute, float *value) const { diff --git a/src/io/xml_node.hpp b/src/io/xml_node.hpp index 907ea8488..a94af7f3f 100644 --- a/src/io/xml_node.hpp +++ b/src/io/xml_node.hpp @@ -48,6 +48,7 @@ public: unsigned int getNumNodes() const {return m_nodes.size(); } int get(const std::string &attribute, std::string *value) const; int get(const std::string &attribute, int *value) const; + int get(const std::string &attribute, unsigned int *value) const; int get(const std::string &attribute, float *value) const; int get(const std::string &attribute, bool *value) const; int get(const std::string &attribute, Vec3 *value) const; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index adefb2403..eb82b486e 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -610,7 +610,7 @@ void Kart::update(float dt) { // let kart fall a bit before rescuing if(fabs( getXYZ().getZ() - -RaceManager::getTrack()->getQuadGraph().getCenterOfQuad(0).getZ() ) > 17) + -RaceManager::getTrack()->getQuadGraph().getQuad(0).getCenter().getZ() ) > 17) forceRescue(); } else if(material) diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index c5dbb5b38..c1d075c48 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -43,26 +43,27 @@ void LinearWorld::init() for(unsigned int n=0; nfindRoadSector(m_kart[n]->getXYZ(), &info.m_track_sector); + m_track->getQuadGraph().findRoadSector(m_kart[n]->getXYZ(), + &info.m_track_sector); //If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of //the road, so we have to use another function to find the sector. - info.m_on_road = info.m_track_sector != Track::UNKNOWN_SECTOR; + info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; if (!info.m_on_road) { info.m_track_sector = m_track->findOutOfRoadSector(m_kart[n]->getXYZ(), Track::RS_DONT_KNOW, - Track::UNKNOWN_SECTOR ); + QuadGraph::UNKNOWN_SECTOR ); } - m_track->spatialToTrack(info.m_curr_track_coords, - m_kart[n]->getXYZ(), - info.m_track_sector ); + m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords, + m_kart[n]->getXYZ(), + info.m_track_sector ); // Init the last track coords so that no new lap (or undoing // a lap) is counted in the first doLapCounting call. @@ -94,26 +95,26 @@ void LinearWorld::restartRace() for(unsigned int n=0; nfindRoadSector(m_kart[n]->getXYZ(), - &info.m_track_sector); + m_track->getQuadGraph().findRoadSector(m_kart[n]->getXYZ(), + &info.m_track_sector); //If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of //the road, so we have to use another function to find the sector. - info.m_on_road = info.m_track_sector != Track::UNKNOWN_SECTOR; + info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; if (!info.m_on_road) { info.m_track_sector = m_track->findOutOfRoadSector(m_kart[n]->getXYZ(), Track::RS_DONT_KNOW, - Track::UNKNOWN_SECTOR ); + QuadGraph::UNKNOWN_SECTOR ); } - m_track->spatialToTrack(info.m_curr_track_coords, - m_kart[n]->getXYZ(), - info.m_track_sector ); + m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords, + m_kart[n]->getXYZ(), + info.m_track_sector ); // This assignmet is important, otherwise (depending on previous // value of m_last_track_coors) a lap could be counted as 'undone', // decreasing the number of laps to -2. @@ -149,11 +150,12 @@ void LinearWorld::update(float delta) // update sector variables int prev_sector = kart_info.m_track_sector; - m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector); + m_track->getQuadGraph().findRoadSector(kart->getXYZ(), + &kart_info.m_track_sector); // Check if the kart is taking a shortcut (if it's not already doing one): // ----------------------------------------------------------------------- - kart_info.m_on_road = kart_info.m_track_sector != Track::UNKNOWN_SECTOR; + kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; if(!kart_info.m_on_road) { // Kart off road. Find the closest sector instead. @@ -167,9 +169,9 @@ void LinearWorld::update(float delta) // Update track coords (=progression) m_kart_info[n].m_last_track_coords = m_kart_info[n].m_curr_track_coords; - m_track->spatialToTrack(kart_info.m_curr_track_coords, - kart->getXYZ(), - kart_info.m_track_sector ); + m_track->getQuadGraph().spatialToTrack(&kart_info.m_curr_track_coords, + kart->getXYZ(), + kart_info.m_track_sector ); // Lap counting, based on the new position, but only if the kart // hasn't finished the race (otherwise it would be counted more than diff --git a/src/robots/default_robot.cpp b/src/robots/default_robot.cpp index a9c743adc..3d276febc 100644 --- a/src/robots/default_robot.cpp +++ b/src/robots/default_robot.cpp @@ -66,6 +66,7 @@ DefaultRobot::DefaultRobot(const std::string& kart_name, next.clear(); m_quad_graph->getSuccessors(i, next); int indx = rand() % next.size(); + indx = next.size()-1; m_successor_index.push_back(indx); m_next_quad_index.push_back(next[indx]); } @@ -152,7 +153,7 @@ void DefaultRobot::update(float dt) // This should not happen (anymore :) ), but it keeps the game running // in case that m_future_sector becomes undefined. - if(m_future_sector == Track::UNKNOWN_SECTOR ) + if(m_future_sector == QuadGraph::UNKNOWN_SECTOR) { #ifdef DEBUG fprintf(stderr,"DefaultRobot: m_future_sector is undefined.\n"); @@ -245,7 +246,7 @@ void DefaultRobot::handleBraking() return; } - const float MIN_SPEED = m_track->getWidth()[m_track_sector]; + const float MIN_SPEED = m_track->getQuadGraph().getNode(m_track_sector).getPathWidth(); KartInfo &kart_info = m_world->m_kart_info[ getWorldKartId() ]; //We may brake if we are about to get out of the road, but only if the //kart is on top of the road, and if we won't slow down below a certain @@ -269,7 +270,8 @@ void DefaultRobot::handleBraking() //if the curve angle is bigger than what the kart can steer, brake //even if we are in the inside, because the kart would be 'thrown' //out of the curve. - if(!(m_world->getDistanceToCenterForKart(getWorldKartId()) > m_track->getWidth()[m_track_sector] * + if(!(m_world->getDistanceToCenterForKart(getWorldKartId()) + > m_track->getQuadGraph().getNode(m_track_sector).getPathWidth() * -CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE(getMaxSteerAngle()))) { m_controls.m_brake = false; @@ -278,7 +280,8 @@ void DefaultRobot::handleBraking() } else if( m_curve_angle < -MIN_TRACK_ANGLE ) //Next curve is right { - if(!(m_world->getDistanceToCenterForKart( getWorldKartId() ) < m_track->getWidth()[m_track_sector] * + if(!(m_world->getDistanceToCenterForKart( getWorldKartId() ) + < m_track->getQuadGraph().getNode(m_track_sector).getPathWidth() * CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE(getMaxSteerAngle()))) { m_controls.m_brake = false; @@ -316,9 +319,10 @@ void DefaultRobot::handleSteering(float dt) */ //Reaction to being outside of the road if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5f > - m_track->getWidth()[m_track_sector] ) + m_track->getQuadGraph().getNode(m_track_sector).getPathWidth() ) { - steer_angle = steerToPoint(m_quad_graph->getCenterOfQuad(next), dt ); + steer_angle = steerToPoint(m_quad_graph->getQuad(next).getCenter(), + dt ); #ifdef AI_DEBUG std::cout << "- Outside of road: steer to center point." << @@ -840,7 +844,8 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos ) } /*Find if we crash with the drivelines*/ - m_track->findRoadSector(step_coord, &m_sector); + m_track->getQuadGraph().findRoadSector(step_coord, &m_sector, + /* max look ahead */ 10); #undef SHOW_FUTURE_PATH #ifdef SHOW_FUTURE_PATH @@ -861,7 +866,7 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos ) center[2] = pos[2]; sphere->setCenter( center ); sphere->setSize( m_kart_properties->getKartModel()->getLength() ); - if( m_sector == Track::UNKNOWN_SECTOR ) + if( m_sector == QuadGraph::UNKNOWN_SECTOR )) { sgVec4 colour; colour[0] = colour[3] = 255; @@ -880,7 +885,7 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos ) m_future_location = Vec3( step_coord[0], step_coord[1], 0 ); - if( m_sector == Track::UNKNOWN_SECTOR ) + if( m_sector == QuadGraph::UNKNOWN_SECTOR) { m_future_sector = m_track->findOutOfRoadSector( step_coord, Track::RS_DONT_KNOW, m_future_sector ); @@ -920,7 +925,7 @@ void DefaultRobot::findNonCrashingPoint(Vec3 *result) target_sector = m_next_quad_index[sector]; //direction is a vector from our kart to the sectors we are testing - direction = m_quad_graph->getCenterOfQuad(target_sector) - getXYZ(); + direction = m_quad_graph->getQuad(target_sector).getCenter() - getXYZ(); float len=direction.length_2d(); steps = int( len / m_kart_length ); @@ -937,16 +942,17 @@ void DefaultRobot::findNonCrashingPoint(Vec3 *result) { step_coord = getXYZ()+direction*m_kart_length * float(i); - m_track->spatialToTrack( step_track_coord, step_coord, - sector ); - + m_track->getQuadGraph().spatialToTrack(&step_track_coord, step_coord, + sector ); + distance = step_track_coord[0] > 0.0f ? step_track_coord[0] : -step_track_coord[0]; //If we are outside, the previous sector is what we are looking for - if ( distance + m_kart_width * 0.5f > m_track->getWidth()[sector] ) + if ( distance + m_kart_width * 0.5f + > m_track->getQuadGraph().getNode(sector).getPathWidth() ) { - *result = m_quad_graph->getCenterOfQuad(sector); + *result = m_quad_graph->getQuad(sector).getCenter(); #ifdef SHOW_NON_CRASHING_POINT ssgaSphere *sphere = new ssgaSphere; @@ -984,7 +990,7 @@ void DefaultRobot::reset() { m_time_since_last_shot = 0.0f; m_start_kart_crash_direction = 0; - m_sector = Track::UNKNOWN_SECTOR; + m_sector = QuadGraph::UNKNOWN_SECTOR; m_inner_curve = 0; m_curve_target_speed = getMaxSpeedOnTerrain(); m_curve_angle = 0.0; @@ -1029,7 +1035,7 @@ int DefaultRobot::calcSteps() if( fabsf(m_controls.m_steer) > 0.95 ) { const int WIDTH_STEPS = - (int)( m_track->getWidth()[m_future_sector] + (int)( m_track->getQuadGraph().getNode(m_future_sector).getPathWidth() /( m_kart_length * 2.0 ) ); steps += WIDTH_STEPS; diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp new file mode 100755 index 000000000..4ae2471a6 --- /dev/null +++ b/src/tracks/graph_node.cpp @@ -0,0 +1,104 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2009 Joerg Henrichs +// +// 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, B + +#include "tracks/quad_graph.hpp" + +#include "user_config.hpp" +#include "graphics/irr_driver.hpp" +#include "io/file_manager.hpp" +#include "io/xml_node.hpp" +#include "tracks/quad_graph.hpp" +#include "tracks/quad_set.hpp" + + +// A static variable that gives a single graph node easy access to +// all quads and avoids unnecessary parameters in many calls. +QuadSet *GraphNode::m_all_quads=NULL; + +// This static variable gives a node access to the graph, and therefore +// to the quad to which a graph node index belongs. +QuadGraph *GraphNode::m_all_nodes=NULL; + +// ---------------------------------------------------------------------------- +/** Constructor. Saves the quad index which belongs to this graph node. + * \param index Index of the quad to use for this node (in m_all_quads). + */ +GraphNode::GraphNode(unsigned int index) +{ + assert(indexgetNumberOfQuads()); + m_index = index; + m_distance_from_start = 0; + const Quad &quad = m_all_quads->getQuad(m_index); + // FIXME: those two values should probably depend on the actual + // orientation of the quad. + // The width is the average width at the beginning and at the end. + m_width = ( (quad[1]-quad[0]).length() + + (quad[3]-quad[2]).length() ) * 0.5f; + Vec3 lower = (quad[m_index][0]+quad[m_index][1]) * 0.5f; + Vec3 upper = (quad[m_index][2]+quad[m_index][3]) * 0.5f; + m_line = core::line2df(lower.getX(), lower.getY(), + upper.getX(), upper.getY() ); + // Only this 2d point is needed later + m_lower_center = core::vector2df(lower.getX(), lower.getY()); +} // GraphNode + +// ---------------------------------------------------------------------------- +/** Adds a successor to a node. This function will also pre-compute certain + * values (like distance from this node to the successor, angle (in world) + * between this node and the successor. + * \param to The index of the successor. + */ +void GraphNode::addSuccessor(unsigned int to) +{ + m_vertices.push_back(to); + // m_index is the quad index, so we use m_all_quads + const Quad &this_quad = m_all_quads->getQuad(m_index); + // to is the graph node, so we have to use m_all_nodes to get the right quad + const Quad &next_quad = m_all_nodes->getQuad(to); + + Vec3 diff = next_quad.getCenter() - this_quad.getCenter(); + m_distance_to_next.push_back(diff.length()); + + float theta = -atan2(diff.getX(), diff.getY()); + m_angle_to_next.push_back(theta); + + // The length of this quad is the average of the left and right side + float distance_to_next = ( (this_quad[2]-this_quad[1]).length() + + (this_quad[3]-this_quad[0]).length() ) *0.5f; + // The distance from start for the successor node + m_all_nodes->getNode(to).m_distance_from_start = + std::max(m_all_nodes->getNode(to).m_distance_from_start, + m_distance_from_start+distance_to_next); +} // addSuccessor +// ---------------------------------------------------------------------------- +/** Returns the distance a point has from this quad in forward and sidewards + * direction, i.e. how far forwards the point is from the beginning of the + * quad, and how far to the side from the line connecting the center points + * is it. All these computations are done in 2D only. + * \param xyz The coordinates of the point. + * \param result The X coordinate contains the sidewards distance, the + * y coordinate the forward distance. + */ +void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result) +{ + core::vector2df xyz2d(xyz.getX(), xyz.getY()); + core::vector2df closest = m_line.getClosestPoint(xyz2d); + result->setX( (closest-xyz2d).getLength()); + result->setY( (closest-m_lower_center).getLength()); +} // getDistanceFromLine diff --git a/src/tracks/graph_node.hpp b/src/tracks/graph_node.hpp new file mode 100755 index 000000000..99b94df38 --- /dev/null +++ b/src/tracks/graph_node.hpp @@ -0,0 +1,114 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2009 Joerg Henrichs +// +// 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, B + +#ifndef HEADER_GRAPH_NODE_HPP +#define HEADER_GRAPH_NODE_HPP + +#include + +#include "irrlicht.h" + +#include "tracks/quad.hpp" +#include "utils/vec3.hpp" + +class QuadSet; +class QuadGraph; + +/** This class stores a node of the graph, i.e. a list of successor + * edges. + */ +class GraphNode +{ + /** Index of this node in the set of quads. Several graph nodes can use + * the same quad, meaning it is possible to use a quad more than once, + * e.g. a figure 8 like track. */ + unsigned int m_index; + /** The list of successors. */ + std::vector m_vertices; + /** The distance to each of the successors. */ + std::vector m_distance_to_next; + /** The angle of the line from this node to each neighbour. */ + std::vector m_angle_to_next; + + /** Distance from the start to the beginning of this quad. */ + float m_distance_from_start; + + /** Width of the track, which is the average of the width at the + * beginning and at the end. FIXME: for now the width is independent + * of the orientation (e.g. a quad used more than once might once + * be used from top to bottom, one from left to right, so it should + * have a different width then). */ + float m_width; + + /** The center point of the lower two points (e.g. points 0 and 1). + * This saves some computations in getDistances later. Only the + * start point is needed, and only in 2d. + * FIXME: this should be set depending on orientation, e.g. a quad + * might be driven on from the left to the right (esp. if a quad is + * used more than once). */ + core::vector2df m_lower_center; + + /** Line between lower and upper center, saves computation in + * getDistanceFromLine() later. The line is 2d only since otherwise + * taller karts would have a larger distance from the center. It also + * saves computation, and it is only needed to determine the distance + * from the center of the drivelines anyway. */ + core::line2df m_line; +public: + /** Keep a shared pointer so that some asserts and tests can be + * done without adding additional parameters. */ + static QuadSet *m_all_quads; + /** Keep a shared pointer to the graph structure so that each node + * has access to the actual quad to which a node points. */ + static QuadGraph *m_all_nodes; + + GraphNode(unsigned int index); + void addSuccessor (unsigned int to); + void getDistances(const Vec3 &xyz, Vec3 *result); + + /** Returns the i-th successor. */ + unsigned int getSuccessor(unsigned int i) const + { return m_vertices[i]; } + // ------------------------------------------------------------------- + /** Returns the number of successors. */ + unsigned int getNumberOfSuccessors() const + { return (unsigned int)m_vertices.size(); } + // ------------------------------------------------------------------- + /** Returns the index in the quad_set of this node. */ + int getIndex() const { return m_index; } + + // ------------------------------------------------------------------- + /** Returns the distance to the j-th. successor. */ + float getDistanceToSuccessor(unsigned int j) const + { return m_distance_to_next[j]; } + + // ------------------------------------------------------------------- + /** Returns the angle from this node to the j-th. successor. */ + float getAngleToSuccessor(unsigned int j) const + { return m_angle_to_next[j]; } + // ------------------------------------------------------------------- + /** Returns the distance from start. */ + float getDistanceFromStart() const + { return m_distance_from_start; } + // ------------------------------------------------------------------- + /** Returns the width of the part for this quad. */ + float getPathWidth() const { return m_width; } +}; // GraphNode + +#endif diff --git a/src/tracks/quad.cpp b/src/tracks/quad.cpp index 0bd012123..e02ab24a1 100644 --- a/src/tracks/quad.cpp +++ b/src/tracks/quad.cpp @@ -26,6 +26,8 @@ Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3) { m_p[0]=p0; m_p[1]=p1; m_p[2]=p2; m_p[3]=p3; m_center = 0.25f*(p0+p1+p2+p3); + m_min_height = std::min ( std::min(p0.getZ(), p1.getZ()), + std::min(p0.getZ(), p1.getZ()) ); } // Quad // ---------------------------------------------------------------------------- @@ -63,5 +65,28 @@ void Quad::setVertices(video::S3DVertex *v, const video::SColor &color) const v[3].Color = color; } // setVertices +// ----------------------------------------------------------------------------- +/** Returns wether a point is to the left or to the right of a line. + * While all arguments are 3d, only the x and y coordinates are actually used. +*/ +float Quad::sideOfLine2D(const Vec3& l1, const Vec3& l2, const Vec3& p) const +{ + return (l2.getX()-l1.getX())*(p.getY()-l1.getY()) - + (l2.getY()-l1.getY())*(p.getX()-l1.getX()); +} // sideOfLine + +// ---------------------------------------------------------------------------- +bool Quad::pointInQuad(const Vec3& p) const +{ + if(sideOfLine2D(m_p[0], m_p[2], p)<0) { + return sideOfLine2D(m_p[0], m_p[1], p) > 0.0 && + sideOfLine2D(m_p[1], m_p[2], p) >= 0.0; + } else { + return sideOfLine2D(m_p[2], m_p[3], p) > 0.0 && + sideOfLine2D(m_p[3], m_p[0], p) >= 0.0; + } +} // pointInQuad + + #include "quad.hpp" diff --git a/src/tracks/quad.hpp b/src/tracks/quad.hpp index 2b2d5ce77..204f09e08 100644 --- a/src/tracks/quad.hpp +++ b/src/tracks/quad.hpp @@ -26,19 +26,34 @@ #include "utils/vec3.hpp" -class Quad { -public: +class Quad +{ +private: /** The four points of a quad. */ Vec3 m_p[4]; - /** The center, which is used by the AI. This saves some - computations at runtime. */ + + /** The center of all four points, which is used by the AI. + * This saves some computations at runtime. */ Vec3 m_center; - - Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3); - /** Returns the i-th. point of a quad. */ - const Vec3& operator[](int i) const {return m_p[i]; } - /** Returns the center of a quad. */ - const Vec3& getCenter () const {return m_center; } + + /** The minimum height of the quad, used in case that several quads + * are on top of each other when determining the sector a kart is on. */ + float m_min_height; + float sideOfLine2D(const Vec3& l1, const Vec3& l2, const Vec3& p) const; + +public: + Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3); void setVertices(video::S3DVertex *v, const video::SColor &color) const; + bool pointInQuad(const Vec3& p) const; + + // ------------------------------------------------------------------------ + /** Returns the i-th. point of a quad. */ + const Vec3& operator[](int i) const {return m_p[i]; } + // ------------------------------------------------------------------------ + /** Returns the center of a quad. */ + const Vec3& getCenter () const {return m_center; } + // ------------------------------------------------------------------------ + /** Returns the minimum height of a quad. */ + float getMinHeight() const { return m_min_height; } }; // class Quad #endif diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index 8eab81863..e24eea5e8 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -25,6 +25,8 @@ #include "io/xml_node.hpp" #include "tracks/quad_set.hpp" +const int QuadGraph::UNKNOWN_SECTOR = -1; + /** Constructor, loads the graph information for a given set of quads * from a graph file. * \param quad_file_name Name of the file of all quads @@ -36,11 +38,9 @@ QuadGraph::QuadGraph(const std::string &quad_file_name, m_node = NULL; m_mesh = NULL; m_mesh_buffer = NULL; - m_all_quads = new QuadSet(quad_file_name); - // First create all nodes - for(unsigned int i=0; igetNumberOfQuads(); i++) { - m_all_nodes.push_back(new GraphNode(i)); - } + m_all_quads = new QuadSet(quad_file_name); + GraphNode::m_all_quads = m_all_quads; + GraphNode::m_all_nodes = this; load(graph_file_name); } // QuadGraph @@ -65,24 +65,71 @@ void QuadGraph::load(const std::string &filename) if(!xml) { // No graph file exist, assume a default loop X -> X+1 + // i.e. each quad is part of the graph exactly once. + // First create an empty graph node for each quad: + for(unsigned int i=0; igetNumberOfQuads(); i++) + m_all_nodes.push_back(new GraphNode(i)); + // Then set the default loop: setDefaultSuccessors(); return; } + + // The graph file exist, so read it in. The graph file must first contain + // the node definitions, before the edges can be set. for(unsigned int i=0; igetNumNodes(); i++) { - const XMLNode *node = xml->getNode(i); - if(node->getName()!="edge") + const XMLNode *xml_node = xml->getNode(i); + // First graph node definitions: + // ----------------------------- + if(xml_node->getName()=="node-list") + { + // A list of quads is connected to a list of graph nodes: + unsigned int from, to; + xml_node->get("from-quad", &from); + xml_node->get("to-quad", &to); + for(unsigned int i=from; i<=to; i++) + { + m_all_nodes.push_back(new GraphNode(i)); + } + } + else if(xml_node->getName()=="node") + { + // A single quad is connected to a single graph node. + unsigned int id; + xml_node->get("quad", &id); + m_all_nodes.push_back(new GraphNode(id)); + } + + // Then the definition of edges between the graph nodes: + // ----------------------------------------------------- + else if(xml_node->getName()=="edge-loop") + { + // A closed loop: + unsigned int from, to; + xml_node->get("from", &from); + xml_node->get("to", &to); + for(unsigned int i=from; i<=to; i++) + { + assert(i!=to ? i+1 : from addSuccessor(i!=to ? i+1 : from); + } + } + else if(xml_node->getName()=="edge") + { + // Adds a single edge to the graph: + unsigned int from, to; + xml_node->get("from", &from); + xml_node->get("to", &to); + assert(toaddSuccessor(to); + } // edge + else { fprintf(stderr, "Incorrect specification in '%s': '%s' ignored\n", - filename.c_str(), node->getName().c_str()); + filename.c_str(), xml_node->getName().c_str()); continue; - } - int from, to; - node->get("from", &from); - node->get("to", &to); - assert(from>=0 && from <(int)m_all_nodes.size()); - m_all_nodes[from]->addSuccessor(to, *m_all_quads); - } // from + } // incorrect specification + } delete xml; setDefaultSuccessors(); @@ -96,8 +143,7 @@ void QuadGraph::setDefaultSuccessors() { for(unsigned int i=0; igetNumberOfSuccessors()==0) { - m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1, - *m_all_quads); + m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1); } // if size==0 } // for i& succ) const { const GraphNode *v=m_all_nodes[node_number]; for(unsigned int i=0; igetNumberOfSuccessors(); i++) { - succ.push_back((*v)[i]); + succ.push_back(v->getSuccessor(i)); } } // getSuccessors -// ============================================================================ -/** Adds a successor to a node. This function will also pre-compute certain - * values (like distance from this node to the successor, angle (in world) - * between this node and the successor. - * \param to The index of the successor. +//----------------------------------------------------------------------------- +/** This function takes absolute coordinates (coordinates in OpenGL + * space) and transforms them into coordinates based on the track. It is + * for 2D coordinates, thought it can be used on 3D vectors. The y-axis + * of the returned vector is how much of the track the point has gone + * through, the x-axis is on which side of the road it is. The Z axis + * is not changed. + * \param dst Returns the results in the X and Y coordinates. + * \param xyz The position of the kart. + * \param sector The graph node the position is on. */ -void QuadGraph::GraphNode::addSuccessor(int to, const QuadSet &quad_set) +void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz, + const int sector) const { - m_vertices.push_back(to); - Vec3 this_xyz = quad_set.getCenterOfQuad(m_index); - Vec3 next_xyz = quad_set.getCenterOfQuad(to); - Vec3 diff = next_xyz - this_xyz; - m_distance_to_next.push_back(diff.length()); + if(sector == UNKNOWN_SECTOR ) + { + std::cerr << "WARNING: UNKNOWN_SECTOR in spatialToTrack().\n"; + return; + } + + getNode(sector).getDistances(xyz, dst); + +} // spatialToTrack + +//----------------------------------------------------------------------------- +/** findRoadSector returns in which sector on the road the position + * xyz is. If xyz is not on top of the road, it returns + * UNKNOWN_SECTOR. + * + * The 'sector' could be defined as the number of the closest track + * segment to XYZ. + * \param XYZ Position for which the segment should be determined. + * \param sector Contains the previous sector (as a shortcut, since usually + * the sector is the same as the last one), and on return the result + * \param max_lookahead Maximum number of graph nodes that are to be searched + * from the current sector number. This is used by the AI to make sure + * the AI does not skip any parts of the track (e.g. if the graph has + * a loop, the AI code skip the whole loop otherwise and continue + * on the normal path). Only used ith sector is not UNKNOWN_SECTOR. + * Defaults to -1, which indicates to use all graph nodes. The actual + * value might depend on the track, the size of the drivelines etc. + */ +void QuadGraph::findRoadSector(const Vec3& xyz, int *sector, + int max_lookahead) const +{ + if(*sector!=UNKNOWN_SECTOR) + { + // Most likely the kart will still be on the sector it was before, + // so this simple case is tested first. + if(getQuad(*sector).pointInQuad(xyz) ) + return; + + // Then check all immediate neighbours. If it's any of them, + // immediately return without any further tests. + const GraphNode &node = *m_all_nodes[*sector]; + for(unsigned int i=0; i0) + ? max_lookahead + : m_all_nodes.size(); + *sector = UNKNOWN_SECTOR; + for(unsigned int i=0; i-1.0f) + { + min_dist = dist; + *sector = indx; + } + } // for i #include +#include "tracks/graph_node.hpp" #include "tracks/quad_set.hpp" /** This class stores a graph of quads. */ class QuadGraph { - /** This class stores a node of the graph, i.e. a list of successor - * edges. */ - class GraphNode - { - /** Index of this node in m_all_quads. */ - int m_index; - /** The list of successors. */ - std::vector m_vertices; - /** The distance to each of the successors. */ - std::vector m_distance_to_next; - /** The angle of the line from this node to each neighbour. */ - std::vector m_angle_to_next; - public: - /** Constructor, stores the index. - * \param index Index of this node in m_all_quads. */ - GraphNode(int index) { m_index = index; } - void addSuccessor (int to, const QuadSet &quad_set); - /** Returns the i-th successor. */ - unsigned int operator[] (int i) const {return m_vertices[i]; } - /** Returns the number of successors. */ - unsigned int getNumberOfSuccessors() const - { return (unsigned int)m_vertices.size(); } - /** Returns the index in the quad_set of this node. */ - int getIndex() const { return m_index; } - /** Returns the distance to the j-th. successor. */ - float getDistanceToSuccessor(int j) const - { return m_distance_to_next[j]; } - /** Returns the angle from this node to the j-th. successor. */ - float getAngleToSuccessor(int j) const - { return m_angle_to_next[j]; } - }; // GraphNode - - // ======================================================================== -protected: + +private: /** The actual graph data structure. */ std::vector m_all_nodes; /** The set of all quads. */ @@ -75,31 +44,45 @@ protected: void setDefaultSuccessors(); void load (const std::string &filename); public: + static const int UNKNOWN_SECTOR; + QuadGraph (const std::string &quad_file_name, const std::string graph_file_name); ~QuadGraph (); void createDebugMesh(); void getSuccessors(int quadNumber, std::vector& succ) const; + void spatialToTrack(Vec3 *dst, const Vec3& xyz, + const int sector) const; + void findRoadSector(const Vec3& XYZ, int *sector, + int max_lookahead=-1) const; /** Returns the number of nodes in the graph. */ unsigned int getNumNodes() const { return m_all_nodes.size(); } - /** Returns the quad set for this graph. */ - const QuadSet* getQuads() const { return m_all_quads; } - /** Returns the center of a quad. - * \param n Index of the quad. */ - const Vec3& getCenterOfQuad(int n) const - { return m_all_quads->getCenterOfQuad(n); } + // ---------------------------------------------------------------------- /** Return the distance to the j-th successor of node n. */ 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 { return m_all_nodes[n]->getAngleToSuccessor(j); } + // ---------------------------------------------------------------------- /** Returns the number of successors of a node n. */ 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 + { 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]; } + // ---------------------------------------------------------------------- + /** Returns the distance from the start to the beginning of a quad. */ + float getDistanceFromStart(int j) const + { return m_all_nodes[j]->getDistanceFromStart(); } }; // QuadGraph #endif diff --git a/src/tracks/quad_set.cpp b/src/tracks/quad_set.cpp index 2a9743067..b5b3d7812 100644 --- a/src/tracks/quad_set.cpp +++ b/src/tracks/quad_set.cpp @@ -71,6 +71,8 @@ void QuadSet::load(const std::string &filename) { } for(unsigned int i=0; igetNumNodes(); i++) { + if(i==293) + printf("XX"); const XMLNode *xml_node = xml->getNode(i); if(xml_node->getName()!="quad") { diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 389a6e794..8814b5414 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -53,7 +53,6 @@ const float Track::NOHIT = -99999.9f; const int Track::QUAD_TRI_NONE = -1; const int Track::QUAD_TRI_FIRST = 1; const int Track::QUAD_TRI_SECOND = 2; -const int Track::UNKNOWN_SECTOR = -1; // ---------------------------------------------------------------------------- Track::Track( std::string filename_, float w, float h, bool stretch ) @@ -156,118 +155,6 @@ int Track::pointInQuad return QUAD_TRI_NONE; } // pointInQuad -//----------------------------------------------------------------------------- -/** findRoadSector returns in which sector on the road the position - * xyz is. If xyz is not on top of the road, it returns - * UNKNOWN_SECTOR. - * - * The 'sector' could be defined as the number of the closest track - * segment to XYZ. - * \param XYZ Position for which the segment should be determined. - * \param sector Contains the previous sector (as a shortcut, since usually - * the sector is the same as the last one), and on return the result - */ -void Track::findRoadSector(const Vec3& XYZ, int *sector)const -{ - if(*sector!=UNKNOWN_SECTOR) - { - int next = (unsigned)(*sector) + 1 < m_left_driveline.size() ? *sector + 1 : 0; - if(pointInQuad(m_left_driveline[*sector], - m_right_driveline[*sector], - m_right_driveline[next], - m_left_driveline[next], XYZ ) != QUAD_TRI_NONE) - // Still in the same sector, no changes - return; - } - /* To find in which 'sector' of the track the kart is, we use a - 'point in triangle' algorithm for each triangle in the quad - that forms each track segment. - */ - std::vector possible_segment_tris; - const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size(); - int triangle; - int next; - - for( size_t i = 0; i < DRIVELINE_SIZE ; ++i ) - { - next = (unsigned int)i + 1 < DRIVELINE_SIZE ? (int)i + 1 : 0; - triangle = pointInQuad(m_left_driveline[i], m_right_driveline[i], - m_right_driveline[next], m_left_driveline[next], - XYZ ); - - if (triangle != QUAD_TRI_NONE && ((XYZ.getZ()-m_left_driveline[i].getZ()) < 1.0f)) - { - possible_segment_tris.push_back(SegmentTriangle((int)i, triangle)); - } - } - - /* Since xyz can be on more than one 2D track segment, we have to - find on top of which one of the possible track segments it is. - */ - const int POS_SEG_SIZE = (int)possible_segment_tris.size(); - if( POS_SEG_SIZE == 0 ) - { - //xyz is not on the road - *sector = UNKNOWN_SECTOR; - return; - } - - //POS_SEG_SIZE > 1 - /* To find on top of which track segment the variable xyz is, - we get which of the possible triangles that are under xyz - has the lower distance on the height(Y or Z) axis. - */ - float dist; - float near_dist = 99999; - int nearest = QUAD_TRI_NONE; - size_t segment; - sgVec4 plane; - - for( int i = 0; i < POS_SEG_SIZE; ++i ) - { - segment = possible_segment_tris[i].segment; - next = segment + 1 < DRIVELINE_SIZE ? (int)segment + 1 : 0; - - // Note: we can make the plane with the normal driveliens - // (not the one with tolerance), since the driveliens with - // tolerance lie in the same plane. - if( possible_segment_tris[i].triangle == QUAD_TRI_FIRST ) - { - sgMakePlane( plane, m_left_driveline[segment].toFloat(), - m_right_driveline[segment].toFloat(), - m_right_driveline[next].toFloat() ); - } - else //possible_segment_tris[i].triangle == QUAD_TRI_SECOND - { - sgMakePlane( plane, m_right_driveline[next].toFloat(), - m_left_driveline[next].toFloat(), - m_left_driveline[segment].toFloat() ); - } - - dist = sgHeightAbovePlaneVec3( plane, XYZ.toFloat() ); - - /* sgHeightAbovePlaneVec3 gives a negative dist if the plane - is on top, so we have to rule it out. - - However, for some reason there are cases where we get - negative values for the track segment we should be on. - */ - if( dist > -2.0 && dist < near_dist) - { - near_dist = dist; - nearest = i; - } - } - - if( nearest != QUAD_TRI_NONE ) - { - *sector=possible_segment_tris[nearest].segment; - return; - } - *sector = UNKNOWN_SECTOR; - return; // This only happens if the position is - // under all the possible sectors -} // findRoadSector //----------------------------------------------------------------------------- /** findOutOfRoadSector finds the sector where XYZ is, but as it name implies, it is more accurate for the outside of the track than the @@ -303,7 +190,7 @@ int Track::findOutOfRoadSector const int CURR_SECTOR ) const { - int sector = UNKNOWN_SECTOR; + int sector = QuadGraph::UNKNOWN_SECTOR; float dist; //FIXME: it can happen that dist is bigger than nearest_dist for all the //the points we check (currently a limit of +/- 10), and if so, the @@ -318,7 +205,7 @@ int Track::findOutOfRoadSector int begin_sector = 0; int count = DRIVELINE_SIZE; - if(CURR_SECTOR != UNKNOWN_SECTOR ) + if(CURR_SECTOR != QuadGraph::UNKNOWN_SECTOR ) { const int LIMIT = 10; //The limit prevents shortcuts if( CURR_SECTOR - LIMIT < 0 ) @@ -361,76 +248,13 @@ int Track::findOutOfRoadSector begin_sector = next_sector; } // for j - if(sector==UNKNOWN_SECTOR || sector >=DRIVELINE_SIZE) + if(sector==QuadGraph::UNKNOWN_SECTOR || sector >=DRIVELINE_SIZE) { printf("unknown sector found.\n"); } return sector; } // findOutOfRoadSector -//----------------------------------------------------------------------------- -/** spatialToTrack() takes absolute coordinates (coordinates in OpenGL - * space) and transforms them into coordinates based on the track. It is - * for 2D coordinates, thought it can be used on 3D vectors. The y-axis - * of the returned vector is how much of the track the point has gone - * through, the x-axis is on which side of the road it is, and the z-axis - * contains half the width of the track at this point. The return value - * is p1, i.e. the first of the two driveline points between which the - * kart is currently located. - */ -int Track::spatialToTrack -( - Vec3& dst, /* out */ - const Vec3& POS, - const int SECTOR -) const -{ - if( SECTOR == UNKNOWN_SECTOR ) - { - std::cerr << "WARNING: UNKNOWN_SECTOR in spatialToTrack().\n"; - return -1; - } - - const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size(); - const size_t PREV = SECTOR == 0 ? DRIVELINE_SIZE - 1 : SECTOR - 1; - const size_t NEXT = (size_t)SECTOR+1 >= DRIVELINE_SIZE ? 0 : SECTOR + 1; - - const float DIST_PREV = (m_driveline[PREV]-POS).length2_2d(); - const float DIST_NEXT = (m_driveline[NEXT]-POS).length2_2d(); - - size_t p1, p2; - if ( DIST_NEXT < DIST_PREV ) - { - p1 = SECTOR; p2 = NEXT; - } - else - { - p1 = PREV; p2 = SECTOR; - } - - sgVec3 line_eqn; - sgVec2 tmp; - - sgMake2DLine ( line_eqn, m_driveline[p1].toFloat(), m_driveline[p2].toFloat() ); - - dst.setX(sgDistToLineVec2 ( line_eqn, POS.toFloat() ) ); - - sgAddScaledVec2 ( tmp, POS.toFloat(), line_eqn, -dst.getX() ); - - float dist_from_driveline_p1 = sgDistanceVec2 ( tmp, m_driveline[p1].toFloat() ); - dst.setY(dist_from_driveline_p1 + m_distance_from_start[p1]); - // Set z-axis to half the width (linear interpolation between the - // width at p1 and p2) - m_path_width is actually already half the width - // of the track. This is used to determine if a kart is too far - // away from the road and is therefore considered taking a shortcut. - - float fraction = dist_from_driveline_p1 - / (m_distance_from_start[p2]-m_distance_from_start[p1]); - dst.setZ(m_path_width[p1]*(1-fraction)+fraction*m_path_width[p2]); - - return (int)p1; -} // spatialToTrack - //----------------------------------------------------------------------------- const Vec3& Track::trackToSpatial(const int SECTOR ) const { @@ -477,73 +301,6 @@ btTransform Track::getStartTransform(unsigned int pos) const return start; } // getStartTransform -//----------------------------------------------------------------------------- -void Track::addDebugToScene(int type) const -{ - if(type & 1) - { - /* - ssgaSphere *sphere; - sgVec3 center; - sgVec4 colour; - for(unsigned int i = 0; i < m_driveline.size(); ++i) - { - sphere = new ssgaSphere; - sgCopyVec3(center, m_driveline[i].toFloat()); - sphere->setCenter(center); - sphere->setSize(getWidth()[i] / 4.0f); - - if(i == 0) - { - colour[0] = colour[2] = colour[3] = 255; - colour[1] = 0; - } - else - { - colour[0] = colour[1] = colour[3] = 255; - colour[2] = 0; - } - sphere->setColour(colour); - stk_scene->add(sphere); - } // for i - */ - } /// type ==1 - // 2: drivelines - if(type & 2) - { - /* - ssgVertexArray* v_array = new ssgVertexArray(); - ssgColourArray* c_array = new ssgColourArray(); - const std::vector &left = m_left_driveline; - const std::vector &right = m_right_driveline; - for(unsigned int i = 0; i < m_driveline.size(); i++) - { - int ip1 = i==m_driveline.size()-1 ? 0 : i+1; - // The segment display must be slightly higher than the - // track, otherwise it's not clearly visible. - sgVec3 v; - sgCopyVec3(v,left [i ].toFloat()); v[2]+=0.1f; v_array->add(v); - sgCopyVec3(v,right[i ].toFloat()); v[2]+=0.1f; v_array->add(v); - sgCopyVec3(v,right[ip1].toFloat()); v[2]+=0.1f; v_array->add(v); - sgCopyVec3(v,left [ip1].toFloat()); v[2]+=0.1f; v_array->add(v); - sgVec4 vc; - vc[0] = i%2==0 ? 1.0f : 0.0f; - vc[1] = 1.0f-v[0]; - vc[2] = 0.0f; - vc[3] = 0.1f; - c_array->add(vc);c_array->add(vc);c_array->add(vc);c_array->add(vc); - } // for i - // if GL_QUAD_STRIP is used, the colours are smoothed, so the changes - // from one segment to the next are not visible. - ssgVtxTable* l = new ssgVtxTable(GL_QUADS, v_array, - (ssgNormalArray*)NULL, - (ssgTexCoordArray*)NULL, - c_array); - stk_scene->add(l); - */ - } -} // addDebugToScene - //----------------------------------------------------------------------------- /** It's not the nicest solution to have two very similar version of a function, * i.e. drawScaled2D and draw2Dview - but to keep both versions const, the @@ -870,8 +627,8 @@ void Track::loadTrack(const std::string &filename) m_camera_final_hpr.degreeToRad(); m_sky_type = SKY_NONE; - const XMLNode *node = root->getNode("sky-dome"); - if(node) + const XMLNode *xml_node = root->getNode("sky-dome"); + if(xml_node) { m_sky_type = SKY_DOME; m_sky_vert_segments = 16; @@ -879,19 +636,19 @@ void Track::loadTrack(const std::string &filename) m_sky_sphere_percent = 1.0f; m_sky_texture_percent = 1.0f; std::string s; - node->get("texture", &s ); + xml_node->get("texture", &s ); m_sky_textures.push_back(s); - node->get("vertical", &m_sky_vert_segments ); - node->get("horizontal", &m_sky_hori_segments ); - node->get("sphere-percent", &m_sky_sphere_percent ); - node->get("texture-percent", &m_sky_texture_percent); + xml_node->get("vertical", &m_sky_vert_segments ); + xml_node->get("horizontal", &m_sky_hori_segments ); + xml_node->get("sphere-percent", &m_sky_sphere_percent ); + xml_node->get("texture-percent", &m_sky_texture_percent); } // if sky-dome - node = root->getNode("sky-box"); - if(node) + xml_node = root->getNode("sky-box"); + if(xml_node) { std::string s; - node->get("texture", &s); + xml_node->get("texture", &s); m_sky_textures = StringUtils::split(s, ' '); if(m_sky_textures.size()!=6) { @@ -970,14 +727,10 @@ void Track::loadDriveline() << " vertex long. Track is " << m_name << " ." << std::endl; m_driveline.reserve(DRIVELINE_SIZE); - m_path_width.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); - - float width = ( m_right_driveline[i] - center_point ).length(); - m_path_width.push_back(width); } for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i) @@ -1032,7 +785,7 @@ Track::readDrivelineFromFile(std::vector& line, const std::string& file_ex throw std::runtime_error(msg.str()); } - int prev_sector = UNKNOWN_SECTOR; + int prev_sector = QuadGraph::UNKNOWN_SECTOR; SGfloat prev_distance = 1.51f; while(!feof(fd)) { @@ -1057,7 +810,7 @@ Track::readDrivelineFromFile(std::vector& line, const std::string& file_ex Vec3 point(x,y,z); - if(prev_sector != UNKNOWN_SECTOR) + if(prev_sector != QuadGraph::UNKNOWN_SECTOR) prev_distance = (point-line[prev_sector]).length2_2d(); //1.5f was choosen because it's more or less the length of the tuxkart @@ -1151,17 +904,17 @@ void Track::convertTrackToBullet(const scene::IMesh *mesh) * scene might use raycast on this track model to determine the actual * height of the terrain. */ -bool Track::loadMainTrack(const XMLNode &node) +bool Track::loadMainTrack(const XMLNode &xml_node) { std::string model_name; - node.get("model", &model_name); + xml_node.get("model", &model_name); std::string full_path = file_manager->getTrackFile(model_name, getIdent()); scene::IMesh *mesh = irr_driver->getAnimatedMesh(full_path); if(!mesh) { fprintf(stderr, "Warning: Main track model '%s' in '%s' not found, aborting.\n", - node.getName().c_str(), model_name.c_str()); + xml_node.getName().c_str(), model_name.c_str()); exit(-1); } @@ -1177,12 +930,12 @@ bool Track::loadMainTrack(const XMLNode &node) scene::ISceneNode *scene_node = irr_driver->addOctTree(mesh); core::vector3df xyz(0,0,0); - node.getXYZ(&xyz); + xml_node.getXYZ(&xyz); core::vector3df hpr(0,0,0); - node.getHPR(&hpr); + xml_node.getHPR(&hpr); scene_node->setPosition(xyz); scene_node->setRotation(hpr); - handleAnimatedTextures(scene_node, node); + handleAnimatedTextures(scene_node, xml_node); m_all_nodes.push_back(scene_node); scene_node->setMaterialFlag(video::EMF_LIGHTING, false); @@ -1621,8 +1374,6 @@ void Track::loadTrackModel() trans -> addKid(lod ); m_model-> addKid(trans ); lod -> setRanges(r, 2); - if(user_config->m_track_debug) - addDebugToScene(user_config->m_track_debug); } else @@ -1637,6 +1388,23 @@ void Track::loadTrackModel() if(m_sky_type==SKY_DOME) { + scene::ISceneNode *node = irr_driver->addSkyDome(m_sky_textures[0], + m_sky_hori_segments, + m_sky_vert_segments, + m_sky_texture_percent, + m_sky_sphere_percent); + for(unsigned int i=0; igetMaterialCount(); i++) + { + video::SMaterial &irrMaterial=node->getMaterial(i); + for(unsigned int j=0; jaddSkyDome(m_sky_textures[0], m_sky_hori_segments, m_sky_vert_segments, diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 79a4b40aa..3437c4f74 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -106,8 +106,6 @@ public: static const int QUAD_TRI_FIRST; static const int QUAD_TRI_SECOND; - static const int UNKNOWN_SECTOR; - struct SegmentTriangle { int segment; @@ -166,20 +164,15 @@ public: ~Track (); bool isArena () const { return m_is_arena; } void cleanup (); - void addDebugToScene (int type ) const; void draw2Dview (float x_offset, float y_offset ) const; void drawScaled2D (float x, float y, float w, float h ) const; - void findRoadSector (const Vec3& XYZ, int *sector) const; int findOutOfRoadSector(const Vec3& XYZ, const RoadSide SIDE, const int CURR_SECTOR ) const; - int spatialToTrack (Vec3& dst, - const Vec3& POS, - const int SECTOR ) const; const Vec3& trackToSpatial (const int SECTOR) const; void loadTrackModel (); void addMusic (MusicInformation* mi) @@ -207,8 +200,7 @@ public: const std::string& getDescription () const {return m_description; } const std::string& getDesigner () const {return m_designer; } const std::string& getScreenshotFile () const {return m_screenshot; } - const std::vector& getWidth () const {return m_path_width; } - const std::string& getItemStyle () const {return m_item_style; } + const std::string& getItemStyle () const {return m_item_style; } bool hasFinalCamera () const {return m_has_final_camera; } const Vec3& getCameraPosition () const {return m_camera_final_position;} const Vec3& getCameraHPR () const {return m_camera_final_hpr; }