Added improved default start positions. Start positions now follow the drivelines,

and the scene.xml file can specify how many karts to set in one row, and the
distance between karts in X and Z direction.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6256 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-10-11 21:49:35 +00:00
parent 12cb80f9d0
commit 19b225a7ce
10 changed files with 208 additions and 145 deletions

View File

@ -276,24 +276,22 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart)
{ {
// no need for the overhead to compute exact distance with sqrt(), so using the // no need for the overhead to compute exact distance with sqrt(), so using the
// 'manhattan' heuristic which will do fine enough. // 'manhattan' heuristic which will do fine enough.
const Vec3 &v=world->getTrack()->getStartPosition(n); btTransform &s = world->getTrack()->getStartTransform(n+1);
const Vec3 &v=s.getOrigin();
const float dist_n= fabs(kart_x - v.getX()) + const float dist_n= fabs(kart_x - v.getX()) +
fabs(kart_z - v.getZ()); fabs(kart_z - v.getZ());
if(dist_n < smallest_distance_found || closest_id_found == -1) if(dist_n < smallest_distance_found || closest_id_found == -1)
{ {
closest_id_found = n; closest_id_found = n+1;
smallest_distance_found = dist_n; smallest_distance_found = dist_n;
} }
} }
assert(closest_id_found != -1); assert(closest_id_found != -1);
const Vec3 &v=world->getTrack()->getStartPosition(closest_id_found); const btTransform &s = world->getTrack()->getStartTransform(closest_id_found);
kart->setXYZ( Vec3(v) ); const Vec3 &xyz = s.getOrigin();
kart->setXYZ(xyz);
// FIXME - implement correct heading kart->setRotation(s.getRotation());
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
world->getTrack()->getStartHeading(closest_id_found));
kart->setRotation(heading);
//position kart from same height as in World::resetAllKarts //position kart from same height as in World::resetAllKarts
btTransform pos; btTransform pos;

View File

@ -132,14 +132,13 @@ void World::init()
for(unsigned int i=0; i<num_karts; i++) for(unsigned int i=0; i<num_karts; i++)
{ {
btTransform init_pos=m_track->getStartTransform(i);
const std::string& kart_ident = const std::string& kart_ident =
history->replayHistory() ? history->getKartIdent(i) history->replayHistory() ? history->getKartIdent(i)
: race_manager->getKartIdent(i); : race_manager->getKartIdent(i);
int local_player_id = race_manager->getKartLocalPlayerId(i); int local_player_id = race_manager->getKartLocalPlayerId(i);
int global_player_id = race_manager->getKartGlobalPlayerId(i); int global_player_id = race_manager->getKartGlobalPlayerId(i);
Kart* newkart = createKart(kart_ident, i, local_player_id, Kart* newkart = createKart(kart_ident, i, local_player_id,
global_player_id, init_pos); global_player_id);
m_karts.push_back(newkart); m_karts.push_back(newkart);
newkart->setWorldKartId(m_karts.size()-1); newkart->setWorldKartId(m_karts.size()-1);
m_track->adjustForFog(newkart->getNode()); m_track->adjustForFog(newkart->getNode());
@ -169,13 +168,12 @@ void World::init()
* this player on the local machine. * this player on the local machine.
* \param global_player_id If the kart is a player kart this is the index of * \param global_player_id If the kart is a player kart this is the index of
* this player globally (i.e. including network players). * this player globally (i.e. including network players).
* \param init_pos The start transform (xyz and hpr).
*/ */
Kart *World::createKart(const std::string &kart_ident, int index, Kart *World::createKart(const std::string &kart_ident, int index,
int local_player_id, int global_player_id, int local_player_id, int global_player_id)
const btTransform &init_pos)
{ {
int position = index+1; int position = index+1;
btTransform init_pos = m_track->getStartTransform(index);
Kart *new_kart = new Kart(kart_ident, position, init_pos); Kart *new_kart = new Kart(kart_ident, position, init_pos);
Controller *controller = NULL; Controller *controller = NULL;
switch(race_manager->getKartType(index)) switch(race_manager->getKartType(index))

View File

@ -115,8 +115,7 @@ protected:
loadAIController (Kart *kart); loadAIController (Kart *kart);
virtual Kart *createKart(const std::string &kart_ident, int index, virtual Kart *createKart(const std::string &kart_ident, int index,
int local_player_id, int global_player_id, int local_player_id, int global_player_id);
const btTransform &init_pos);
/** Pointer to the track. The track is managed by world. */ /** Pointer to the track. The track is managed by world. */
Track* m_track; Track* m_track;

View File

@ -30,7 +30,6 @@
CheckManager::CheckManager(const XMLNode &node, Track *track) CheckManager::CheckManager(const XMLNode &node, Track *track)
{ {
bool lap_line_found = false;
for(unsigned int i=0; i<node.getNumNodes(); i++) for(unsigned int i=0; i<node.getNumNodes(); i++)
{ {
const XMLNode *check_node = node.getNode(i); const XMLNode *check_node = node.getNode(i);
@ -39,14 +38,6 @@ CheckManager::CheckManager(const XMLNode &node, Track *track)
{ {
CheckLine *cl = new CheckLine(this, *check_node, i); CheckLine *cl = new CheckLine(this, *check_node, i);
m_all_checks.push_back(cl); m_all_checks.push_back(cl);
// Only record the first lap line to be used to compute
// start coordinates with. The track exporter always exports
// the one based on the quads first.
if(cl->getType()==CheckStructure::CT_NEW_LAP && !lap_line_found)
{
track->setStartCoordinates(cl->getLine2D());
lap_line_found = true;
}
} // checkline } // checkline
else if(type=="check-lap") else if(type=="check-lap")
{ {

View File

@ -45,17 +45,19 @@ GraphNode::GraphNode(unsigned int index)
m_index = index; m_index = index;
m_distance_from_start = 0; m_distance_from_start = 0;
const Quad &quad = m_all_quads->getQuad(m_index); const Quad &quad = m_all_quads->getQuad(m_index);
// FIXME: those two values should probably depend on the actual // FIXME: the following values should depend on the actual orientation
// orientation of the quad. // of the quad. ATM we always assume that indices 0,1 are the lower end,
// and 2,3 are the upper end.
// The width is the average width at the beginning and at the end. // The width is the average width at the beginning and at the end.
m_width = ( (quad[1]-quad[0]).length() m_width = ( (quad[1]-quad[0]).length()
+ (quad[3]-quad[2]).length() ) * 0.5f; + (quad[3]-quad[2]).length() ) * 0.5f;
Vec3 lower = (quad[0]+quad[1]) * 0.5f; m_lower_center = (quad[0]+quad[1]) * 0.5f;
Vec3 upper = (quad[2]+quad[3]) * 0.5f; m_upper_center = (quad[2]+quad[3]) * 0.5f;
m_line = core::line2df(lower.getX(), lower.getZ(), m_line = core::line2df(m_lower_center.getX(), m_lower_center.getZ(),
upper.getX(), upper.getZ() ); m_upper_center.getX(), m_upper_center.getZ() );
// Only this 2d point is needed later // Only this 2d point is needed later
m_lower_center = core::vector2df(lower.getX(), lower.getZ()); m_lower_center_2d = core::vector2df(m_lower_center.getX(),
m_lower_center.getZ() );
} // GraphNode } // GraphNode
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -71,7 +73,8 @@ void GraphNode::addSuccessor(unsigned int to)
const Quad &this_quad = m_all_quads->getQuad(m_index); 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 // 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); const Quad &next_quad = m_all_nodes->getQuad(to);
core::vector2df d2=m_lower_center-m_all_nodes->getNode(to).getLowerCenter(); core::vector2df d2 = m_lower_center_2d
- m_all_nodes->getNode(to).m_lower_center_2d;
Vec3 diff = next_quad.getCenter() - this_quad.getCenter(); Vec3 diff = next_quad.getCenter() - this_quad.getCenter();
m_distance_to_next.push_back(d2.getLength()); m_distance_to_next.push_back(d2.getLength());
@ -113,7 +116,7 @@ void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result)
result->setX( (closest-xyz2d).getLength()); // to the right result->setX( (closest-xyz2d).getLength()); // to the right
else else
result->setX(-(closest-xyz2d).getLength()); // to the left result->setX(-(closest-xyz2d).getLength()); // to the left
result->setZ( m_distance_from_start + (closest-m_lower_center).getLength()); result->setZ( m_distance_from_start + (closest-m_lower_center_2d).getLength());
} // getDistances } // getDistances
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -25,9 +25,9 @@
#include "irrlicht.h" #include "irrlicht.h"
#include "tracks/quad.hpp" #include "tracks/quad.hpp"
#include "tracks/quad_set.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
class QuadSet;
class QuadGraph; class QuadGraph;
/** /**
@ -59,11 +59,14 @@ class GraphNode
/** The center point of the lower two points (e.g. points 0 and 1). /** The center point of the lower two points (e.g. points 0 and 1).
* This saves some computations in getDistances later. Only the * This saves some computations in getDistances later. Only the
* start point is needed, and only in 2d. * start point is needed, and only in 2d. */
* FIXME: this should be set depending on orientation, e.g. a quad core::vector2df m_lower_center_2d;
* might be driven on from the left to the right (esp. if a quad is
* used more than once). */ /** Lower center point of the graph node. */
core::vector2df m_lower_center; Vec3 m_lower_center;
/** Upper center point of the graph node. */
Vec3 m_upper_center;
/** Line between lower and upper center, saves computation in /** Line between lower and upper center, saves computation in
* getDistanceFromLine() later. The line is 2d only since otherwise * getDistanceFromLine() later. The line is 2d only since otherwise
@ -87,33 +90,43 @@ public:
/** Returns the i-th successor. */ /** Returns the i-th successor. */
unsigned int getSuccessor(unsigned int i) const unsigned int getSuccessor(unsigned int i) const
{ return m_vertices[i]; } { return m_vertices[i]; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the number of successors. */ /** Returns the number of successors. */
unsigned int getNumberOfSuccessors() const unsigned int getNumberOfSuccessors() const
{ return (unsigned int)m_vertices.size(); } { return (unsigned int)m_vertices.size(); }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the index in the quad_set of this node. */ /** Returns the index in the quad_set of this node. */
int getIndex() const { return m_index; } int getIndex() const { return m_index; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the i-th. point of a quad. ATM this just returns the vertices
* from the quads, but if necessary this method will also consider
* rotated quads. So index 0 will always be lower left point, then
* counterclockwise. */
const Vec3& operator[](int i) const
{return m_all_quads->getQuad(m_index)[i];}
// ------------------------------------------------------------------------
/** Returns the distance to the j-th. successor. */ /** Returns the distance to the j-th. successor. */
float getDistanceToSuccessor(unsigned int j) const float getDistanceToSuccessor(unsigned int j) const
{ return m_distance_to_next[j]; } { return m_distance_to_next[j]; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the angle from this node to the j-th. successor. */ /** Returns the angle from this node to the j-th. successor. */
float getAngleToSuccessor(unsigned int j) const float getAngleToSuccessor(unsigned int j) const
{ return m_angle_to_next[j]; } { return m_angle_to_next[j]; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the distance from start. */ /** Returns the distance from start. */
float getDistanceFromStart() const float getDistanceFromStart() const
{ return m_distance_from_start; } { return m_distance_from_start; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the width of the part for this quad. */ /** Returns the width of the part for this quad. */
float getPathWidth() const { return m_width; } float getPathWidth() const { return m_width; }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------
/** Returns the center point of the lower edge of this graph node. */ /** Returns the center point of the lower edge of this graph node. */
const core::vector2df& getLowerCenter() const {return m_lower_center;} const Vec3& getLowerCenter() const {return m_lower_center;}
// ------------------------------------------------------------------------
/** Returns the center point of the upper edge of this graph node. */
const Vec3& getUpperCenter() const {return m_upper_center;}
}; // GraphNode }; // GraphNode
#endif #endif

View File

@ -19,6 +19,8 @@
#include "tracks/quad_graph.hpp" #include "tracks/quad_graph.hpp"
#include "LinearMath/btTransform.h"
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
@ -175,6 +177,78 @@ void QuadGraph::setDefaultSuccessors()
} // for i<m_allNodes.size() } // for i<m_allNodes.size()
} // setDefaultSuccessors } // setDefaultSuccessors
// -----------------------------------------------------------------------------
/** Sets all start positions depending on the quad graph. The number of
* entries needed is defined by the size of the start_transform (though all
* entries will be overwritten).
* E.g. the karts will be placed as:
* 1 \
* 2 +-- row with three karts, each kart is 'sidewards_distance'
* 3 / to the right of the previous kart, and
* 4 'forwards_distance' behind the previous kart.
* 5 The next row starts again with the kart being
* 6 'forwards_distance' behind the end of the previous row.
* etc.
* \param start_transforms A vector sized to the needed number of start
* positions. The values will all be overwritten with the
* default start positions.
* \param karts_per_row How many karts to place in each row.
* \param forwards_distance Distance in forward (Z) direction between
* each kart.
* \param sidewards_distance Distance in sidewards (X) direction between
* karts.
*/
void QuadGraph::setDefaultStartPositions(std::vector<btTransform>
*start_transforms,
unsigned int karts_per_row,
float forwards_distance,
float sidewards_distance,
float upwards_distance) const
{
// Node 0 is always the node on which the start line is.
int current_node = getPredecessor(0);
int placed_karts_in_row = 0;
float distance_from_start = 0.0f;
// Maximum distance to left (or right) of centre line
const float max_x_dist = (karts_per_row-1)*0.5f*sidewards_distance;
// X position relative to the centre line
float x_pos = -max_x_dist;
for(unsigned int i=0; i<start_transforms->size(); i++)
{
// First find on which segment we have to start
while(distance_from_start > getNode(current_node).getDistanceToSuccessor(0))
{
distance_from_start -= getNode(current_node).getDistanceToSuccessor(0);
current_node = getPredecessor(current_node);
}
const GraphNode &gn = getNode(current_node);
const Quad &quad = m_all_quads->getQuad(gn.getIndex());
Vec3 center_line = gn.getLowerCenter() - gn.getUpperCenter();
center_line.normalize();
Vec3 horizontal_line = gn[3] - gn[2];
horizontal_line.normalize();
Vec3 start = gn.getUpperCenter()
+ center_line * distance_from_start
+ horizontal_line * x_pos;
// Add a certain epsilon to the height in case that the
// drivelines are beneath the track.
(*start_transforms)[i].setOrigin(start+Vec3(0,upwards_distance,0));
(*start_transforms)[i].setRotation(
btQuaternion(btVector3(0, 1, 0),
gn.getAngleToSuccessor(0)));
if(fabsf(x_pos - max_x_dist)<0.1f)
x_pos = -max_x_dist;
else
x_pos += sidewards_distance;
distance_from_start += forwards_distance;
} // for i<stk_config->m_max_karts
} // setStartPositions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** Creates a mesh for this graph. The mesh is not added to a scene node and /** Creates a mesh for this graph. The mesh is not added to a scene node and
* is stored in m_mesh. * is stored in m_mesh.
@ -282,13 +356,37 @@ void QuadGraph::cleanupDebugMesh()
* \param node_number The number of the node. * \param node_number The number of the node.
* \param succ A vector of ints to which the successors are added. * \param succ A vector of ints to which the successors are added.
*/ */
void QuadGraph::getSuccessors(int node_number, std::vector<unsigned int>& succ) const { void QuadGraph::getSuccessors(int node_number,
const GraphNode *v=m_all_nodes[node_number]; std::vector<unsigned int>& succ) const
for(unsigned int i=0; i<v->getNumberOfSuccessors(); i++) { {
succ.push_back(v->getSuccessor(i)); const GraphNode *gn=m_all_nodes[node_number];
for(unsigned int i=0; i<gn->getNumberOfSuccessors(); i++) {
succ.push_back(gn->getSuccessor(i));
} }
} // getSuccessors } // getSuccessors
//-----------------------------------------------------------------------------
/** Returns the first predecessor or a node (i.e. the one usually on the main
* driveline).
* \param node_number The number of the node.
* \return The node number of the first predecessor node, or -1 if no
* predecessor was found (and a warning is printed in this case).
*/
int QuadGraph::getPredecessor(unsigned int target_node) const
{
for(unsigned int node_id=0; node_id<m_all_nodes.size(); node_id++)
{
const GraphNode *gn=m_all_nodes[node_id];
for(unsigned int i=0; i <gn ->getNumberOfSuccessors(); i++)
{
if(gn->getSuccessor(i)==target_node)
return node_id;
} // for i<gn->getNumberOfSuccessors()
} // node_id<m_all_nodes.size()
printf("Warning: no predecessor for node '%d' found.\n", target_node);
return -1;
} // getPredecessor
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This function takes absolute coordinates (coordinates in OpenGL /** This function takes absolute coordinates (coordinates in OpenGL
* space) and transforms them into coordinates based on the track. The y-axis * space) and transforms them into coordinates based on the track. The y-axis

View File

@ -62,6 +62,7 @@ private:
void setDefaultSuccessors(); void setDefaultSuccessors();
void load (const std::string &filename); void load (const std::string &filename);
void createMesh(bool show_invisible=true); void createMesh(bool show_invisible=true);
int getPredecessor(unsigned int target_node) const;
public: public:
static const int UNKNOWN_SECTOR; static const int UNKNOWN_SECTOR;
@ -70,7 +71,7 @@ public:
~QuadGraph (); ~QuadGraph ();
void createDebugMesh(); void createDebugMesh();
void cleanupDebugMesh(); void cleanupDebugMesh();
void getSuccessors(int quadNumber, void getSuccessors(int node_number,
std::vector<unsigned int>& succ) const; std::vector<unsigned int>& succ) const;
void spatialToTrack(Vec3 *dst, const Vec3& xyz, void spatialToTrack(Vec3 *dst, const Vec3& xyz,
const int sector) const; const int sector) const;
@ -80,6 +81,12 @@ public:
const int curr_sector=UNKNOWN_SECTOR, const int curr_sector=UNKNOWN_SECTOR,
std::vector<int> *all_sectors=NULL std::vector<int> *all_sectors=NULL
) const; ) const;
void setDefaultStartPositions(std::vector<btTransform>
*start_transforms,
unsigned int karts_per_row,
float forwards_distance=1.5f,
float sidewards_distance=1.5f,
float upwards_distance=0.0f) const;
video::ITexture *makeMiniMap(const core::dimension2du &where, video::ITexture *makeMiniMap(const core::dimension2du &where,
const std::string &name, const std::string &name,
const video::SColor &fill_color const video::SColor &fill_color

View File

@ -76,11 +76,9 @@ Track::Track(std::string filename)
m_animation_manager = NULL; m_animation_manager = NULL;
m_check_manager = NULL; m_check_manager = NULL;
m_mini_map = NULL; m_mini_map = NULL;
m_start_angle = 0;
m_sky_dx = 0.05f; m_sky_dx = 0.05f;
m_sky_dy = 0.0f; m_sky_dy = 0.0f;
m_max_kart_count = 8; m_max_kart_count = 8;
m_start_transform.setIdentity();
loadTrackInfo(); loadTrackInfo();
} // Track } // Track
@ -171,63 +169,6 @@ const Vec3& Track::trackToSpatial(const int sector) const
return m_quad_graph->getQuad(sector).getCenter(); return m_quad_graph->getQuad(sector).getCenter();
} // trackToSpatial } // trackToSpatial
//-----------------------------------------------------------------------------
/** This function determines the linear transform and rotation for the start
* coordinates in order to line up propery behind the specified start line.
* The transform and rotation is saved in a matrix and applied to all
* start coordinates later on, see getStartTransform().
* \param line The start line.
*/
void Track::setStartCoordinates(const core::line2df& line)
{
core::vector2df start = line.start;
core::vector2df end = line.end;
m_start_angle = -atan2(end.Y - start.Y,
end.X - start.X);
core::vector2df mid = (start+end)*0.5f;
btQuaternion q(Vec3(0, 1, 0), m_start_angle);
m_start_transform.setRotation(q);
m_start_transform.setOrigin(Vec3(mid.X, 0, mid.Y));
} // setStartCoordinates
//-----------------------------------------------------------------------------
/** Returns the start coordinates for a kart on a given position pos
(with pos ranging from 0 to kart_num-1).
*/
btTransform Track::getStartTransform(unsigned int pos) const
{
Vec3 orig;
float angle;
if(pos<m_start_positions.size())
{
orig = m_start_positions[pos];
angle = 0;
}
else
{
// Distance from middle of start line in X direction.
// +-X_DIST is used to place the karts left/right
const float X_DIST = 1.5f;
// Distance from start line in Z direction.
const float Z_DIST_FROM_START = 1.5f;
const float Z_DIST = 1.5f;
orig = Vec3( X_DIST * (pos%2==0) ? 1.0f : -1.0f,
1.0f,
-Z_DIST*pos-Z_DIST_FROM_START);
orig = m_start_transform(orig);
angle = m_start_angle;
}
btTransform start;
start.setOrigin(orig);
start.setRotation(btQuaternion(btVector3(0, 1, 0),
pos<m_start_heading.size()
? DEGREE_TO_RAD*m_start_heading[pos]
: angle ));
return start;
} // getStartTransform
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Track::loadTrackInfo() void Track::loadTrackInfo()
{ {
@ -516,7 +457,6 @@ bool Track::loadMainTrack(const XMLNode &root)
std::string model_name; std::string model_name;
track_node->get("model", &model_name); track_node->get("model", &model_name);
std::string full_path = m_root+"/"+model_name; std::string full_path = m_root+"/"+model_name;
// scene::IMesh *mesh = irr_driver->getAnimatedMesh(full_path);
scene::IMesh *mesh = irr_driver->getMesh(full_path); scene::IMesh *mesh = irr_driver->getMesh(full_path);
if(!mesh) if(!mesh)
{ {
@ -750,11 +690,6 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
m_sky_type = SKY_NONE; m_sky_type = SKY_NONE;
m_track_object_manager = new TrackObjectManager(); m_track_object_manager = new TrackObjectManager();
// 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.
if (!m_is_arena) loadQuadGraph(mode_id);
// Add the track directory to the texture search path // Add the track directory to the texture search path
file_manager->pushTextureSearchPath(m_root); file_manager->pushTextureSearchPath(m_root);
file_manager->pushModelSearchPath (m_root); file_manager->pushModelSearchPath (m_root);
@ -783,6 +718,35 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
<<"', aborting."; <<"', aborting.";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
// 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.
if (!m_is_arena) loadQuadGraph(mode_id);
// Set the default start positions. Node that later the default
// positions can still be overwritten.
float forwards_distance = 1.5f;
float sidewards_distance = 3.0f;
float upwards_distance = 0.1f;
int karts_per_row = 2;
const XMLNode *default_start=root->getNode("default-start");
if(default_start)
{
default_start->get("forwards-distance", &forwards_distance );
default_start->get("sidewards-distance", &sidewards_distance);
default_start->get("upwards-distance", &upwards_distance );
default_start->get("karts-per-row", &karts_per_row );
}
m_start_transforms.resize(race_manager->getNumberOfKarts());
m_quad_graph->setDefaultStartPositions(&m_start_transforms,
karts_per_row,
forwards_distance,
sidewards_distance,
upwards_distance);
loadMainTrack(*root); loadMainTrack(*root);
unsigned int main_track_count = m_all_nodes.size(); unsigned int main_track_count = m_all_nodes.size();
@ -821,12 +785,15 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
} }
else if (name=="start") else if (name=="start")
{ {
unsigned int position=0;
node->get("position", &position);
Vec3 xyz(0,0,0); Vec3 xyz(0,0,0);
node->getXYZ(&xyz); node->getXYZ(&xyz);
m_start_positions.push_back(xyz);
float h=0; float h=0;
node->get("h", &h); node->get("h", &h);
m_start_heading.push_back(h); m_start_transforms[position].setOrigin(xyz);
m_start_transforms[position].setRotation(
btQuaternion(btVector3(0,1,0),h ) );
} }
else if(name=="camera") else if(name=="camera")
{ {

View File

@ -53,22 +53,10 @@ private:
std::string m_ident; std::string m_ident;
std::string m_screenshot; std::string m_screenshot;
std::vector<MusicInformation*> m_music; std::vector<MusicInformation*> m_music;
/** Start heading of karts (if specified in the scene file). */
std::vector<float> m_start_heading;
/** Start positions of karts (if specified in the scene file). */ /** Start transforms of karts (either the default, or the ones taken
std::vector<Vec3> m_start_positions; * from the scene file). */
std::vector<btTransform> m_start_transforms;
/** A transform which is applied to the default start coordinates
* (i.e. only if no start coordinates are defined for the track).
* This is used to position the karts in case that the lap counting
* line is not centered around (0,0,0), or rotated. */
btTransform m_start_transform;
/** The explicit angle of the lap counting line. This angle can
* not be easily deduced from m_start_transform (problem with the
* sign), so it is saved additionally so that karts can be rotated
* properly if no explicit start positions are given. */
float m_start_angle;
std::string m_item_style; std::string m_item_style;
std::string m_description; std::string m_description;
@ -121,11 +109,14 @@ private:
/** If a sky dome is used, the number of horizontal segments /** If a sky dome is used, the number of horizontal segments
* the sphere should be divided in. */ * the sphere should be divided in. */
int m_sky_hori_segments; int m_sky_hori_segments;
/** If a sky dome is used, the number of vertical segments /** If a sky dome is used, the number of vertical segments
* the sphere should be divided in. */ * the sphere should be divided in. */
int m_sky_vert_segments; int m_sky_vert_segments;
/** If a sky dome is used, percentage of the sphere to be used. */ /** If a sky dome is used, percentage of the sphere to be used. */
float m_sky_sphere_percent; float m_sky_sphere_percent;
/** If a sky dome is used, percentage of the texture to be used. */ /** If a sky dome is used, percentage of the texture to be used. */
float m_sky_texture_percent; float m_sky_texture_percent;
@ -213,7 +204,7 @@ public:
const std::string& getIdent () const {return m_ident; } const std::string& getIdent () const {return m_ident; }
/** Returns the name of the track, which is e.g. displayed on the screen. */ /** Returns the name of the track, which is e.g. displayed on the screen. */
const irr::core::stringw& getName () const {return m_name; } const irr::core::stringw& getName () const {return m_name; }
/** Returns all groups this track belongs to. */ /** Returns all groups this track belongs to. */
const std::vector<std::string> const std::vector<std::string>
@ -225,13 +216,16 @@ public:
/** Returns the filename of this track. */ /** Returns the filename of this track. */
const std::string& getFilename () const {return m_filename; } const std::string& getFilename () const {return m_filename; }
//const std::string& getDescription () const {return m_description; }
const std::string& getDesigner () const {return m_designer; } const std::string& getDesigner () const {return m_designer; }
/** Returns an absolute path to the screenshot file of this track */ /** Returns an absolute path to the screenshot file of this track */
const std::string& getScreenshotFile () const {return m_screenshot; } const std::string& getScreenshotFile () const {return m_screenshot; }
btTransform getStartTransform (unsigned int pos) const; /** Returns the start coordinates for a kart with a given index.
* \param index Index of kart ranging from 0 to kart_num-1. */
btTransform getStartTransform (unsigned int index) const
{return m_start_transforms[index];}
void getTerrainInfo(const Vec3 &pos, float *hot, Vec3* normal, void getTerrainInfo(const Vec3 &pos, float *hot, Vec3* normal,
const Material **material) const; const Material **material) const;
float getTerrainHeight(const Vec3 &pos) const; float getTerrainHeight(const Vec3 &pos) const;
@ -239,7 +233,6 @@ public:
void update(float dt); void update(float dt);
void reset(); void reset();
void adjustForFog(scene::ISceneNode *node); void adjustForFog(scene::ISceneNode *node);
void setStartCoordinates(const core::line2df& line);
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const; void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const;
/** Sets pointer to the aabb of this track. */ /** Sets pointer to the aabb of this track. */
void getAABB(const Vec3 **min, const Vec3 **max) const void getAABB(const Vec3 **min, const Vec3 **max) const
@ -282,11 +275,7 @@ public:
/** Get the number of start positions defined in the scene file. */ /** Get the number of start positions defined in the scene file. */
unsigned int getNumberOfStartPositions() const unsigned int getNumberOfStartPositions() const
{ return m_start_positions.size(); } { return m_start_transforms.size(); }
/** Returns the i-th. start position. */
const Vec3 &getStartPosition(unsigned int i) {return m_start_positions[i];}
/** Returns the heading of the i-th. start position. */
const float getStartHeading(unsigned int i) {return m_start_heading[i]; }
/** \return the maximum number of karts that this track can sustain without them starting off-track */ /** \return the maximum number of karts that this track can sustain without them starting off-track */
int getMaxKartCount() const { return m_max_kart_count; } int getMaxKartCount() const { return m_max_kart_count; }