src/vamos/track/Strip_Track.cc

Go to the documentation of this file.
00001 //  Strip_Track.cc - a track.
00002 //
00003 //      Vamos Automotive Simulator
00004 //  Copyright (C) 2001--2004 Sam Varner
00005 //
00006 //  This program is free software; you can redistribute it and/or modify
00007 //  it under the terms of the GNU General Public License as published by
00008 //  the Free Software Foundation; either version 2 of the License, or
00009 //  (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 #include <vamos/track/Strip_Track.h>
00021 #include <vamos/geometry/Spline.h>
00022 #include <vamos/geometry/Gl_Texture_Image.h>
00023 
00024 #include <GL/glu.h>
00025 
00026 #include <cmath>
00027 #include <sstream>
00028 #include <cassert>
00029 
00030 using namespace Vamos_Geometry;
00031 
00032 //* Class Strip_Track
00033 
00034 Vamos_Track::
00035 Strip_Track::Strip_Track () :
00036   m_min_x (0.0),
00037   m_max_x (0.0),
00038   m_min_y (0.0),
00039   m_max_y (0.0),
00040   //mp_elevation (new Spline (0.0, 0.0)),
00041   m_length (0.0),
00042   m_sky_list_id (0)
00043 {
00044   m_timing_lines.clear ();
00045 }
00046 
00047 extern bool verbose_output;
00048 
00049 Vamos_Track::
00050 Strip_Track::~Strip_Track ()
00051 {
00052         if (verbose_output)
00053                 std::cout << "track deinit" << std::endl;
00054   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00055            it != m_segments.end ();
00056            it++)
00057         {
00058           delete (*it);
00059         }
00060   //delete mp_elevation;
00061         
00062         if (verbose_output)
00063                 std::cout << "track deinit done" << std::endl;
00064 }
00065 
00066 // Read the track definition file.
00067 void Vamos_Track::
00068 Strip_Track::read (std::string data_dir, std::string track_file)
00069 {
00070   // Remember the file name for re-reading.
00071   if ((data_dir != "") && (track_file != ""))
00072         {
00073           m_data_dir = data_dir;
00074           m_track_file = track_file;
00075         }
00076 
00077   m_min_x = 0.0;
00078   m_max_x = 0.0;
00079   m_min_y = 0.0;
00080   m_max_y = 0.0;
00081 
00082   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00083            it != m_segments.end ();
00084            it++)
00085         {
00086           delete (*it);
00087         }
00088   m_segments.clear ();
00089   m_timing_lines.clear ();
00090 
00091   Strip_Track_Reader reader (m_data_dir, m_track_file, this);
00092 }
00093 
00094 void Vamos_Track::
00095 Strip_Track::build_sky_box (std::string sides_image, 
00096                                                         std::string top_image,
00097                                                         std::string bottom_image,
00098                                                         bool smooth)
00099 {
00100   if (m_sky_list_id != 0)
00101         {
00102           glDeleteLists (m_sky_list_id, 1);
00103         }
00104 
00105   double height = 400.0;
00106   double length = 400.0;
00107   double width = 400.0;
00108 
00109   double x = -length / 2.0;
00110   double y = -width / 2.0;
00111   double z = -height / 2.0;
00112 
00113   Gl_Texture_Image sky_sides (sides_image, smooth);
00114   Gl_Texture_Image sky_top (top_image, smooth);
00115   Gl_Texture_Image sky_bottom (bottom_image, smooth);
00116 
00117   // Clamp the textures to aviod showing seams.
00118   sky_sides.clamp_to_edge ();
00119   sky_top.clamp_to_edge ();
00120   sky_bottom.clamp_to_edge ();
00121 
00122   m_sky_list_id = glGenLists (1);
00123   glNewList (m_sky_list_id, GL_COMPILE);
00124 
00125   glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00126 
00127   sky_sides.activate ();
00128 
00129   // front
00130   glBegin (GL_QUAD_STRIP);
00131   glTexCoord2d (0.0, 0.0); 
00132   glVertex3d (x + length, y + width, z + height);
00133   glTexCoord2d (0.0, 1.0); 
00134   glVertex3d (x + length, y + width, z);
00135   glTexCoord2d (0.25, 0.0); 
00136   glVertex3d (x + length, y, z + height); 
00137   glTexCoord2d (0.25, 1.0); 
00138   glVertex3d (x + length, y, z);
00139 
00140   // right
00141   glTexCoord2d (0.25, 0.0); 
00142   glVertex3d (x + length, y, z + height);
00143   glTexCoord2d (0.25, 1.0); 
00144   glVertex3d (x + length, y, z);
00145   glTexCoord2d (0.5, 0.0); 
00146   glVertex3d (x, y, z + height); 
00147   glTexCoord2d (0.5, 1.0); 
00148   glVertex3d (x, y, z);
00149 
00150   // back
00151   glTexCoord2d (0.5, 0.0); 
00152   glVertex3d (x, y, z + height);
00153   glTexCoord2d (0.5, 1.0); 
00154   glVertex3d (x, y, z);
00155   glTexCoord2d (0.75, 0.0); 
00156   glVertex3d (x, y + width, z + height); 
00157   glTexCoord2d (0.75, 1.0); 
00158   glVertex3d (x, y + width, z);
00159 
00160   // left
00161   glTexCoord2d (0.75, 0.0); 
00162   glVertex3d (x, y + width, z + height);
00163   glTexCoord2d (0.75, 1.0); 
00164   glVertex3d (x, y + width, z);
00165   glTexCoord2d (1.0, 0.0); 
00166   glVertex3d (x + length, y + width, z + height); 
00167   glTexCoord2d (1.0, 1.0); 
00168   glVertex3d (x + length, y + width, z);
00169   glEnd();
00170 
00171   // top
00172   sky_top.activate ();
00173 
00174   glBegin (GL_QUADS);           
00175   glTexCoord2d (0.0, 0.0); 
00176   glVertex3d (x, y + width, z + height);
00177   glTexCoord2d (0.0, 1.0); 
00178   glVertex3d (x + length, y + width, z + height); 
00179   glTexCoord2d (1.0, 1.0); 
00180   glVertex3d (x + length, y, z + height);
00181   glTexCoord2d (1.0, 0.0); 
00182   glVertex3d (x, y, z + height);
00183   glEnd();
00184 
00185   // bottom
00186   sky_bottom.activate ();
00187 
00188   glBegin (GL_QUADS);           
00189   glTexCoord2d (0.0, 0.0); 
00190   glVertex3d (x, y + width, z);
00191   glTexCoord2d (0.0, 1.0); 
00192   glVertex3d (x, y + width, z);
00193   glTexCoord2d (1.0, 1.0); 
00194   glVertex3d (x + length, y, z); 
00195   glTexCoord2d (1.0, 0.0); 
00196   glVertex3d (x + length, y, z);
00197   glEnd();
00198 
00199   glFlush ();
00200   glEndList ();
00201 }
00202 
00203 // Add a straight or curved segment of road to the track.
00204 void Vamos_Track::
00205 Strip_Track::add_segment (Road_Segment* seg)
00206 {
00207   m_segments.push_back (seg);
00208 }
00209 
00210 // Make the track.
00211 void Vamos_Track::
00212 Strip_Track::build (bool is_closed, double track_length)
00213 {
00214   set_skews ();
00215   if (is_closed)
00216     {
00217       build_circuit ();
00218     }
00219   if (track_length != 0.0)
00220     {
00221       set_length (track_length);
00222     }
00223 
00224   m_length = 0.0;
00225   
00226   //mp_elevation->clear ();
00227   //mp_elevation->load (Two_Point (0.0, 0.0));
00228 
00229   Three_Vector start_coords (0.0, 0.0, 0.0);
00230   double start_angle = 0.0;
00231   double start_bank = 0.0;
00232 
00233   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00234            it != m_segments.end ();
00235            it++)
00236         {
00237           //(*it)->build_elevation (mp_elevation, m_length);
00238           m_length += (*it)->length ();
00239         }
00240 
00241   size_t strips = (*(m_segments.begin ()))->materials ().size ();
00242   std::vector <double> texture_offsets (strips);
00243 
00244         //enable detail texture
00245         utility.SelectTU(1);
00246         glEnable(GL_TEXTURE_2D);
00247         detailtex = textures.Load("track/track2.png", true);
00248         glBindTexture(GL_TEXTURE_2D, detailtex);
00249         utility.SelectTU(0);
00250         
00251   m_length = 0.0;
00252   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00253            it != m_segments.end ();
00254            it++)
00255         {
00256           (*it)->build (m_length, start_coords, start_angle, start_bank,
00257                                         texture_offsets, detailtex);
00258           texture_offsets = (*it)->texture_offsets ();
00259 
00260           // Update the bounding dimensions.
00261           if ((*it)->min_x () < m_min_x)
00262                 m_min_x = (*it)->min_x ();
00263           if ((*it)->max_x () > m_max_x)
00264                 m_max_x = (*it)->max_x ();
00265           if ((*it)->min_y () < m_min_y)
00266                 m_min_y = (*it)->min_y ();
00267           if ((*it)->max_y () > m_max_y)
00268                 m_max_y = (*it)->max_y ();
00269 
00270           m_length += (*it)->length ();
00271           start_coords = (*it)->end_coords ();
00272           start_angle = (*it)->end_angle ();
00273           start_bank = (*it)->end_bank ();
00274         }
00275 }
00276 
00277 void Vamos_Track::
00278 Strip_Track::set_skews ()
00279 {
00280   for (std::vector <Road_Segment*>::iterator it = m_segments.begin () + 1;
00281            it != m_segments.end ();
00282            it++)
00283         {
00284       double skew = (*it)->skew ();
00285       if ((skew != 0.0) && ((*it)->arc () != 0.0))
00286         {
00287           if ((*(it - 1))->arc () == 0.0)
00288             (*(it - 1))->set_end_skew (skew);
00289           if ((*(it + 1))->arc () == 0.0)
00290             (*(it + 1))->set_start_skew (-skew);
00291         }
00292     }
00293 }
00294 
00295 void Vamos_Track::
00296 Strip_Track::build_circuit ()
00297 {
00298   Road_Segment* last_straight = *(m_segments.end () - 1);
00299   Road_Segment* last_curve = *(m_segments.end () - 2);
00300   Road_Segment* other_straight = *(m_segments.end () - 3);
00301 
00302   if ((last_straight->radius () != 0.0) 
00303           || (last_curve->radius () == 0.0) 
00304           || (other_straight->radius () != 0.0))
00305         {
00306           throw Can_Not_Close ();
00307         }
00308 
00309   double end_x = 0.0;
00310   double end_y = 0.0;
00311   double end_angle = 0.0;
00312   double straight_angle = 0.0;
00313   double center_x = 0.0;
00314   double center_y = 0.0;
00315   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00316            it != m_segments.end () - 1;
00317            it++)
00318         {
00319       if ((*it)->radius () == 0.0)
00320         {
00321           end_x += (*it)->length () * cos (end_angle);
00322           end_y += (*it)->length () * sin (end_angle);
00323           straight_angle = end_angle;
00324         }
00325       else
00326         {
00327           center_x = end_x - (*it)->radius () * sin (end_angle);
00328           center_y = end_y + (*it)->radius () * cos (end_angle);
00329           end_angle += (*it)->arc ();
00330           end_x = center_x + (*it)->radius () * sin (end_angle);
00331           end_y = center_y - (*it)->radius () * cos (end_angle);
00332         }
00333     }
00334 
00335   // Change the length, but not the radius of the last curve to make the last
00336   // straight and parallel with the beginning of the first segment.
00337   end_angle -= last_curve->arc ();
00338   if (end_angle > pi)
00339     {
00340       end_angle = 2.0 * pi - end_angle;
00341     }
00342   else if (end_angle < -pi)
00343     {
00344       end_angle = -2.0 * pi - end_angle;
00345     }
00346   else
00347     {
00348       end_angle = -end_angle;
00349     }
00350 
00351   last_curve->set_arc (end_angle);
00352 
00353   double delta_length = 
00354     -(center_y - last_curve->radius ()) / sin (straight_angle);
00355   other_straight->set_length (other_straight->length () + delta_length);
00356 
00357   last_straight->set_length (-center_x 
00358                              - delta_length * cos (straight_angle)
00359                              + 0.5);
00360 
00361   // Force the segment to end at 0, 0.
00362   last_straight->last_segment (true);
00363 }
00364 
00365 void Vamos_Track::
00366 Strip_Track::draw_sky (const Vamos_Geometry::Three_Vector& view) const
00367 {
00368   glLoadIdentity ();
00369   glTranslatef (view [0], view [1], view [2]);
00370 
00371   // Draw the sky and then clear the depth buffer to keep it behind
00372   // everything else.
00373   glCallList (m_sky_list_id);
00374   glClear (GL_DEPTH_BUFFER_BIT);
00375 }
00376 
00377 void Vamos_Track::
00378 Strip_Track::draw () const
00379 {
00380   //glLoadIdentity ();
00381   for (std::vector <Road_Segment*>::const_iterator it = m_segments.begin ();
00382            it != m_segments.end ();
00383            it++)
00384         {
00385           (*it)->draw ();
00386         }
00387 }
00388 
00389 void Vamos_Track::Strip_Track::
00390 speed_trap (double start, double end)
00391 {
00392   m_speed_trap_start = start;
00393   m_speed_trap_end = end;
00394 }
00395 
00396 // Scale the track to a particular length.
00397 void Vamos_Track::
00398 Strip_Track::set_length (double length)
00399 {
00400   assert (m_segments.size () != 0);
00401 
00402   // Find the current length.
00403   double old_length = 0.0;
00404   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00405            it != m_segments.end ();
00406            it++)
00407         {
00408           old_length += (*it)->length ();
00409         }
00410 
00411   assert (old_length != 0.0);
00412   double factor = length / old_length;
00413 
00414   // Adjust the segments.
00415   for (std::vector <Road_Segment*>::iterator it = m_segments.begin ();
00416            it != m_segments.end ();
00417            it++)
00418         {
00419           (*it)->scale (factor);
00420         }
00421 }
00422 
00424 
00425 // Return the new position for a vehicle at POS when a reset is
00426 // performed.
00427 Three_Vector Vamos_Track::
00428 Strip_Track::reset_position (const Three_Vector& pos,
00429                                                          size_t& segment_index)
00430 {
00431   const Three_Vector& track_pos = track_coordinates (pos, segment_index);
00432 
00433   const Road_Segment* segment = m_segments [segment_index];
00434   const double along = track_pos [0] - segment->start_distance ();
00435   Three_Vector direction = segment->barrier_normal (along, -1.0);
00436   direction [2] = -sin (segment->bank (along));
00437 
00438   const double across = track_pos [1];
00439   return pos - across * direction;
00440 }
00441 
00442 // Return the new orientation for a vehicle at POS when a reset is
00443 // performed.
00444 Three_Matrix Vamos_Track::
00445 Strip_Track::reset_orientation (const Three_Vector& pos,
00446                                                                 size_t& segment_index)
00447 {
00448   Three_Matrix orientation;
00449   orientation.identity ();
00450 
00451   // Align the car's up direction with the normal.
00452   const Three_Vector& track_pos = track_coordinates (pos, segment_index);
00453 
00454   const Road_Segment* segment = m_segments [segment_index];
00455   const double along = track_pos [0] - segment->start_distance ();
00456   const double across = track_pos [1];
00457   Three_Vector normal = segment->normal (along, across); 
00458   orientation.rotate (Three_Vector (-asin (normal [1]), 
00459                                                                         asin (normal [0]),
00460                                                                         segment->angle (along)));
00461   return orientation;
00462 }
00463 
00464 // Return the elevation of the track at the x and y components of POS.
00465 double Vamos_Track::
00466 Strip_Track::elevation (const Three_Vector& pos, 
00467                                                 double bump_parameter,
00468                                                 size_t& segment_index)
00469 {
00470   //return track_coordinates (pos, segment_index)[2] 
00471         //+ m_material->bump (bump_parameter);
00472 
00473         track_coordinates(pos, segment_index);
00474         
00475         return m_segments[segment_index]->elevationxy(pos[0], pos[1])
00476         + m_material->bump (bump_parameter);
00477 }
00478 
00479 bool Vamos_Track::Strip_Track::ontrack(const Vamos_Geometry::Three_Vector& world_pos)
00480 {
00481         size_t segment_index = 0;
00482         int i = 0;
00483         
00484         for (i = 0; i < (int) m_segments.size(); i++)
00485         {
00486                 bool found = false;
00487                 segment_index = i;
00488                 Three_Vector track_pos = segment_coordinates (world_pos, segment_index, found);
00489                 //double w = 20.0;
00490                 //if ((track_pos[1] >= 0 && track_pos[1] < w) || (track_pos[1] < 0 && track_pos[1] > -w))
00491                 if (found)
00492                 {
00493                         if ((track_pos[1] >= 0 && track_pos[1] < m_segments[segment_index]->left_width(track_pos[0])) || (track_pos[1] < 0 && track_pos[1] > -m_segments[segment_index]->right_width(track_pos[0])))
00494                         {
00495                                 //cout << track_pos[1] << " ";
00496                                 //cout << i << "/" << m_segments.size() << " ";
00497                                 return true;
00498                         }
00499                 }
00500         }
00501 
00502         return false;
00503 }
00504 
00505 size_t Vamos_Track::Strip_Track::getsegment(const Vamos_Geometry::Three_Vector& pos)
00506 {
00507         /*size_t insegment = 0;
00508         
00509         track_coordinates(pos, insegment);
00510         
00511         return insegment;*/
00512         
00513         size_t segment_index = 0;
00514         int i = 0;
00515         
00516         size_t insegment = 0;
00517         
00518         for (i = 0; i < (int) m_segments.size(); i++)
00519         {
00520                 segment_index = i;
00521                 //Three_Vector track_pos = track_coordinates (pos, segment_index);
00522                 Three_Vector track_pos;
00523                 double innit = m_segments[segment_index]->coordinates (pos, track_pos);
00524                 
00525                 //double w = 20.0;
00526                 //if ((track_pos[1] >= 0 && track_pos[1] < w) || (track_pos[1] < 0 && track_pos[1] > -w))
00527                 if (innit == 0.0f && ((track_pos[1] >= 0 && track_pos[1] < m_segments[segment_index]->left_width(track_pos[0])) || (track_pos[1] < 0 && track_pos[1] > -m_segments[segment_index]->right_width(track_pos[0]))))
00528                 {
00529                         //cout << track_pos[1] << " ";
00530                         //cout << i << "/" << m_segments.size() << " ";
00531                         //return true;
00532                         insegment = i;                  
00533                 }
00534         }
00535 
00536         return insegment;
00537 }
00538 
00539 /*bool Vamos_Track::Strip_Track::ontrack(const Vamos_Geometry::Three_Vector& world_pos)
00540 {
00541         Three_Vector track_pos;
00542         unsigned int segment_index = 0;
00543         assert (segment_index < m_segments.size ());
00544         Road_Segment* segment = m_segments [segment_index];
00545 
00546         double off = 0;
00547         
00548         size_t i = 0;
00549         while (i < m_segments.size ())
00550         {
00551           off = segment->coordinates (world_pos, track_pos); 
00552           if (off == 0.0)
00553                 {
00554                   break;
00555                 }
00556 
00557           if (off > 0.0)
00558                 {
00559                   segment_index++;
00560                   if (segment_index == m_segments.size ())
00561                         {
00562                           segment_index = 0;
00563                         }
00564                 }
00565           else
00566                 {
00567                   if (segment_index == 0)
00568                         {
00569                           segment_index = m_segments.size ();
00570                         }
00571                   segment_index--;
00572                 }
00573           segment = m_segments [segment_index];
00574           i++;
00575         }
00576 
00577         // Throw an exception if a segment could not be found.
00578         if (i >= m_segments.size ())
00579         {
00580                 //return true;
00581                 return false;
00582         }
00583         else
00584         {
00585                 //cout << track_pos[0] << "," << track_pos[1] << "," << track_pos[2] << ":" << segment->start_distance() << ":" << segment->left_road_width(track_pos[0]) << endl;
00586                 *//*if (track_pos[1] >= 0)
00587                 {
00588                         double w = segment->left_width(track_pos[0]);
00589                         if (track_pos[1] < w)
00590                                 return true;
00591                 }
00592                 else
00593                 {
00594                         double w = segment->right_width(track_pos[0]+segment->start_distance());
00595                         if (track_pos[1] > w)
00596                                 return true;
00597                 }*/
00598                 /*
00599                 //double w = segment->left_road_width(track_pos[0]);
00600                 //if (track_pos[1] > w)
00601                 double w = 20.0;
00602                 if ((track_pos[1] >= 0 && track_pos[1] < w) || (track_pos[1] < 0 && track_pos[1] > -w))
00603                 {
00604                         //cout << track_pos[1] << " ";
00605                         //cout << i << "/" << m_segments.size() << " ";
00606                         return true;
00607                 }
00608                 
00609                 return false;
00610         }
00611 }*/
00612 
00613 // Return WORLD_POS transformed to the track's coordinate system.
00614 // SEGMENT_INDEX will be modified if the position on another
00615 // segment.
00616 Three_Vector Vamos_Track::
00617 Strip_Track::track_coordinates (const Three_Vector& world_pos,
00618                                                                 size_t& segment_index)
00619 {
00620   // Find the distance along the track, distance from center, and elevation
00621   // for the world coordinates `world_pos [0]' and `world_pos [1]'.
00622 
00623   Three_Vector track_pos;
00624   assert (segment_index < m_segments.size ());
00625   Road_Segment* segment = m_segments [segment_index];
00626 
00627         /*if (segment_index == 0)
00628                 cout << "bingo" << endl;*/
00629         
00630         double off = -1337;
00631         
00632   size_t i = 0;
00633         //cout << "begin" << endl;
00634   while (i < m_segments.size ())
00635         {
00636                 //cout << i << "!!!" << endl;
00637           off = segment->coordinates (world_pos, track_pos); 
00638                 //cout << off << endl;
00639           if (off == 0.0)
00640                 {
00641                         //cout << "fuk" << endl;
00642                   break;
00643                 }
00644 
00645           if (off > 0.0)
00646                 {
00647                   segment_index++;
00648                   if (segment_index == m_segments.size ())
00649                         {
00650                           segment_index = 0;
00651                         }
00652                 }
00653           else
00654                 {
00655                   if (segment_index == 0)
00656                         {
00657                           segment_index = m_segments.size ();
00658                         }
00659                   segment_index--;
00660                 }
00661           segment = m_segments [segment_index];
00662           i++;
00663         }
00664 
00665   // Throw an exception if a segment could not be found.
00666   if (i == m_segments.size ())
00667         {
00668           std::cout << "road segment not found" << std::endl;
00669                 //cout << off << endl;
00670           throw Segment_Not_Found (world_pos);
00671         }
00672         
00673   assert (segment_index < m_segments.size ());
00674   m_material = segment->material_at (track_pos [0], track_pos [1]);
00675   track_pos[0] += segment->start_distance ();
00676   return track_pos;
00677 }
00678 
00679 Three_Vector Vamos_Track::
00680 Strip_Track::segment_coordinates (const Three_Vector& world_pos,
00681                                                                 size_t& segment_index, bool &found)
00682 {
00683   // Find the distance along the track, distance from center, and elevation
00684   // for the world coordinates `world_pos [0]' and `world_pos [1]'.
00685 
00686   Three_Vector track_pos;
00687   assert (segment_index < m_segments.size ());
00688   Road_Segment* segment = m_segments [segment_index];
00689 
00690         /*if (segment_index == 0)
00691                 cout << "bingo" << endl;*/
00692         
00693         double off = -1337;
00694         
00695   size_t i = 0;
00696         //cout << "begin" << endl;
00697   while (i < m_segments.size ())
00698         {
00699                 //cout << i << "!!!" << endl;
00700           off = segment->coordinates (world_pos, track_pos); 
00701                 //cout << off << endl;
00702           if (off == 0.0)
00703                 {
00704                   break;
00705                 }
00706 
00707           if (off > 0.0)
00708                 {
00709                   segment_index++;
00710                   if (segment_index == m_segments.size ())
00711                         {
00712                           segment_index = 0;
00713                         }
00714                 }
00715           else
00716                 {
00717                   if (segment_index == 0)
00718                         {
00719                           segment_index = m_segments.size ();
00720                         }
00721                   segment_index--;
00722                 }
00723           segment = m_segments [segment_index];
00724           i++;
00725         }
00726 
00727   // Throw an exception if a segment could not be found.
00728   if (i == m_segments.size ())
00729         {
00730           //std::cout << "road segment not found" << std::endl;
00731                 //cout << off << endl;
00732           found = false;
00733                 return track_pos;
00734         }
00735 
00736         //cout << off << endl;
00737         //cout << i << endl;
00738 
00739         found = true;
00740   assert (segment_index < m_segments.size ());
00741   m_material = segment->material_at (track_pos [0], track_pos [1]);
00742   track_pos [0] += segment->start_distance ();
00743   return track_pos;
00744 }
00745 
00746 Vamos_Track::Track_Contact_Info Vamos_Track::
00747 Strip_Track::test_for_contact (const Three_Vector& pos, 
00748                                                            double bump_parameter,
00749                                                            size_t& segment_index)
00750 {
00751   Three_Vector track_pos = track_coordinates (pos, segment_index);
00752   const Road_Segment* segment = m_segments [segment_index];
00753   track_pos [0] -= segment->start_distance ();
00754 
00755   bool contact = false;
00756   Three_Vector normal;
00757 
00758   // Test for contact with the road.
00759   double diff = elevation (pos, bump_parameter, segment_index) - pos [2];
00760   if (diff >= 0.0)
00761         {
00762           contact = true;
00763           normal = segment->normal (track_pos [0], track_pos [1]);
00764         }
00765 
00766   // Test for contact with the walls.
00767   // Left
00768   if (!contact)
00769         {
00770           const Material_Handle material = segment->left_material ();
00771           double bump = material->bump (bump_parameter);
00772           diff = track_pos [1] - (segment->left_width (track_pos [0]) + bump); 
00773           if (diff >= 0.0)
00774                 {
00775                   contact = true;
00776                   normal = segment->barrier_normal (track_pos [0], track_pos [1]);
00777                 }
00778         }
00779 
00780   // Right
00781   if (!contact)
00782         {
00783           const Material_Handle material = segment->right_material ();
00784           double bump = material->bump (bump_parameter);
00785           diff = -track_pos [1] - (segment->right_width (track_pos [0]) + bump); 
00786           if (diff >= 0.0)
00787                 {
00788                   contact = true;
00789                   normal = segment->barrier_normal (track_pos [0], track_pos [1]);
00790                 }
00791         }
00792 
00793   return Track_Contact_Info (contact, diff, normal, m_material);
00794 }
00795 
00796 // Return the distance along the track for the given position.
00797 double Vamos_Track::
00798 Strip_Track::distance (const Three_Vector& pos, size_t& segment_index)
00799 {       
00800   return track_coordinates (pos, segment_index)[0];
00801 }
00802 
00803 Three_Vector Vamos_Track::
00804 Strip_Track::position (double along, double from_center) const
00805 {
00806   assert ((along >= 0.0) && (along <= m_length));
00807   double distance = 0.0;
00808   for (std::vector <Road_Segment*>::const_iterator it = m_segments.begin ();
00809            it != m_segments.end ();
00810            it++)
00811         {
00812       if (distance + (*it)->length () >= along)
00813         {
00814           return (*it)->position (along - distance, from_center);
00815         }
00816       distance += (*it)->length ();
00817         }
00818   assert (false);
00819   return Three_Vector (0.0, 0.0, 0.0);
00820 }
00821 
00822 // Return the timing sector at the given distance.
00823 int Vamos_Track::
00824 Strip_Track::sector (double distance)
00825 {
00826   for (size_t i = 0; i < m_timing_lines.size (); i++)
00827         {
00828           if (m_timing_lines [i] > distance)
00829                 return i - 1;
00830         }
00831   return m_timing_lines.size () - 1;
00832 }
00833 
00834 //* Class Track_Reader
00835 
00836 //** Constructor
00837 Vamos_Track::
00838 Strip_Track_Reader::Strip_Track_Reader (std::string data_dir, 
00839                                                                                 std::string track_file, 
00840                                                                                 Strip_Track* road) 
00841   : m_first_road (true),
00842         m_data_dir (data_dir),
00843         mp_road (road),
00844     m_circuit (false),
00845     m_length (0.0)
00846 {
00847   read (data_dir + track_file);
00848 }
00849 
00850 void Vamos_Track::
00851 Strip_Track_Reader::on_start_tag (const Vamos_Geometry::XML_Tag& tag)
00852 {
00853   //  std::cout << "start " << tag.get_label () << std::endl;
00854   m_tag = tag.get_label ();
00855   m_path = m_path + '/' + m_tag;
00856 
00857   const Vamos_Geometry::XML_Tag::Attribute_List& 
00858         attribs = tag.get_attributes ();
00859 
00860   if (m_tag == "sky")
00861         {
00862           m_strings.clear ();
00863           m_strings.resize (3);
00864           m_bools.clear ();
00865           m_bools.resize (1);
00866         }
00867   else if (m_tag == "material")
00868         {
00869           m_name = attribs [0].value;
00870           std::string type = attribs [1].value;
00871           if (type == "rubber")
00872                 m_material_type = Material::RUBBER;
00873           else if (type == "metal")
00874                 m_material_type = Material::METAL;
00875           else if (type == "asphalt")
00876                 m_material_type = Material::ASPHALT;
00877           else if (type == "concrete")
00878                 m_material_type = Material::CONCRETE;
00879           else if (type == "grass")
00880                 m_material_type = Material::GRASS;
00881           else if (type == "gravel")
00882                 m_material_type = Material::GRAVEL;
00883           else if (type == "dirt")
00884                 m_material_type = Material::DIRT;
00885           else
00886                 {
00887                   std::cerr << "Strip_Track_Reader: Warning: Unknown material \"" 
00888                                         << attribs [1].value << '\"' << std::endl;
00889                   m_material_type = Material::UNKNOWN;
00890                 }
00891                         
00892           m_bools.clear ();
00893           m_bools.resize (2);
00894           m_doubles.clear ();
00895           m_doubles.resize (8);
00896           m_strings.clear ();
00897         }
00898   else if (m_tag == "segment")
00899         {
00900           m_name = attribs [0].value;
00901           m_strings.resize (7);
00902         }
00903   else if (m_tag == "road")
00904         {
00905           if (m_first_road)
00906                 {
00907                   // Clear the vector so that it gets filled with 0.0 when
00908                   // it's resized.
00909                   m_doubles.clear ();
00910                   m_doubles.resize (21);
00911                   m_bools.clear ();
00912                   m_bools.resize (6);
00913                   m_points.clear ();
00914                   m_points.resize (2);
00915                   m_left_profile.clear ();
00916                   m_right_profile.clear ();
00917 
00918                   m_first_road = false;
00919                 }
00920 
00921           m_doubles [3] = 0.0; // left kerb start
00922           m_doubles [6] = 0.0; // left kerb end
00923           m_doubles [9] = 0.0; // right kerb start
00924           m_doubles [12] = 0.0; // right kerb end
00925       m_doubles [20] = 0.0; // skew
00926           m_strings.clear ();
00927           m_strings.resize (2);
00928           m_strings [0] = attribs [0].value;
00929           m_bools [0] = false;
00930           m_bools [1] = false;
00931           m_bools [2] = false;
00932           m_bools [3] = false;
00933           m_bools [4] = false;
00934           m_elev_points.clear ();
00935 
00936           for (size_t i = 0; i < 4; i++)
00937                 {
00938                   if (m_point_vectors [i].size () > 0)
00939                         {
00940                           Two_Point last_point = *(m_point_vectors [i].end () - 1);
00941                           last_point.x = 0.0;
00942                           m_point_vectors [i].clear ();
00943                           m_point_vectors [i].push_back (last_point);
00944                         }
00945                 }
00946 
00947           m_braking_markers.clear ();
00948           m_model_info.clear ();
00949         }
00950   else if (m_tag == "left-kerb")
00951         {
00952           m_doubles [6] = -1.0; // end
00953         }
00954   else if (m_tag == "right-kerb")
00955         {
00956           m_doubles [12] = -1.0; // end
00957         }
00958   else if (m_tag == "circuit")
00959         {
00960           m_circuit = true;
00961         }
00962   else if (m_tag == "timing-line")
00963         {
00964           m_doubles.clear ();
00965         }
00966   else if (m_tag == "track-length")
00967         {
00968           m_doubles.clear ();
00969         }
00970 
00971   if (m_path == "/track/road/left-kerb/start/transition")
00972         {
00973           m_bools [1] = true;
00974         }
00975   else if (m_path == "/track/road/left-kerb/end/transition")
00976         {
00977           m_bools [2] = true;
00978         }
00979   else if (m_path == "/track/road/right-kerb/start/transition")
00980         {
00981           m_bools [3] = true;
00982         }
00983   else if (m_path == "/track/road/right-kerb/end/transition")
00984         {
00985           m_bools [4] = true;
00986         }
00987 }
00988 
00989 void Vamos_Track::
00990 Strip_Track_Reader::on_end_tag (const Vamos_Geometry::XML_Tag& tag)
00991 {
00992   //  std::cout << "end " << tag.get_label () << std::endl;
00993   m_tag = tag.get_label ();
00994   m_path = m_path.substr (0, m_path.find_last_of ("/"));
00995 
00996   if (m_tag == "sky")
00997         {
00998           mp_road->build_sky_box (m_data_dir + m_strings [0], 
00999                                                           m_data_dir + m_strings [1],
01000                                                           m_data_dir + m_strings [2],
01001                                                           m_bools [0]);
01002         }
01003   else if (m_tag == "material")
01004         {
01005           m_materials [m_name] = 
01006                 Material_Handle (new Material 
01007                                                  (m_material_type,
01008                                                   m_doubles [0], m_doubles [1],
01009                                                   m_doubles [2], m_doubles [3],
01010                                                   m_doubles [4], m_doubles [5], 
01011                                                   new Gl_Texture_Image (m_data_dir + m_strings [0],
01012                                                                                                 m_bools [0],
01013                                                                                                 m_bools [1],
01014                                                                                                 m_doubles [6],
01015                                                                                                 m_doubles [7])));
01016         }
01017   else if (m_tag == "smooth")
01018         {
01019           m_bools [0] = true;
01020         }
01021   else if (m_tag == "mipmap")
01022         {
01023           m_bools [1] = true;
01024         }
01025   else if (m_tag == "segment")
01026         {
01027           std::vector <Material_Handle> mat;
01028           mat.resize (7);
01029           mat [0] = m_materials [m_strings [0]];
01030           mat [1] = m_materials [m_strings [1]];
01031           mat [2] = m_materials [m_strings [2]];
01032           mat [3] = m_materials [m_strings [3]];
01033           mat [4] = m_materials [m_strings [4]];
01034           mat [5] = m_materials [m_strings [5]];
01035           mat [6] = m_materials [m_strings [6]];
01036           m_segments [m_name] = mat;
01037         }
01038   else if (m_tag == "braking-marker")
01039         {
01040           Side side = m_bools [5] ? RIGHT : LEFT;
01041           m_braking_markers.
01042                 push_back (new Braking_Marker (m_doubles [19],
01043                                                                            m_points [0],
01044                                                                            m_points [1],
01045                                                                            side,
01046                                                                            m_data_dir + m_strings [1]));
01047         }
01048   else if (m_tag == "model")
01049          {
01050           m_model_info.push_back (m_current_model_info);
01051         }
01052   else if (m_tag == "road")
01053         {
01054           double left_start_trans = m_bools [1] ? m_doubles [4] : 0.0;
01055           double left_end_trans = m_bools [2] ? m_doubles [7] : 0.0;
01056           double right_start_trans = m_bools [3] ? m_doubles [10] : 0.0;
01057           double right_end_trans = m_bools [4] ? m_doubles [13] : 0.0;
01058 
01059           std::vector <Two_Point> vec;
01060 
01061           if (!m_bools [0])
01062                 {
01063                   m_doubles [2] = 0.0;
01064                 }
01065           Road_Segment* segment = new Road_Segment (m_doubles [0], 
01066                                                                                                 m_doubles [1], 
01067                                                                                                 m_doubles [2],
01068                                                 m_doubles [20],
01069                                                                                                 m_point_vectors [0], 
01070                                                                                                 m_point_vectors [1],
01071                                                                                                 m_point_vectors [2], 
01072                                                                                                 m_point_vectors [3],
01073                                                                                                 new Kerb (m_left_profile, 
01074                                                                                                                   m_doubles [3],
01075                                                                                                                   left_start_trans, 
01076                                                                                                                   m_doubles [5],
01077                                                                                                                   m_doubles [6],
01078                                                                                                                   left_end_trans,
01079                                                                                                                   m_doubles [8]),
01080                                                                                                 new Kerb (m_right_profile,
01081                                                                                                                   m_doubles [9],
01082                                                                                                                   right_start_trans,
01083                                                                                                                   m_doubles [11],
01084                                                                                                                   m_doubles [12],
01085                                                                                                                   right_end_trans,
01086                                                                                                                   m_doubles [14]),
01087                                                                                                 m_doubles [15], 
01088                                                                                                 m_doubles [16],
01089                                                                                                 //m_elev_points, 
01090                                                                                                 vec,
01091                                                                                                 m_doubles [17], 
01092                                                                                                 m_doubles [18],
01093                                                                                                 m_segments [m_strings [0]],
01094                                                                                                 m_braking_markers);
01095           mp_road->add_segment (segment);
01096           for (std::vector <Road_Segment::Model_Info>::iterator
01097                          it = m_model_info.begin ();
01098                    it !=  m_model_info.end ();
01099                    it++)
01100                 {
01101                   segment->add_model_info (*it);
01102                 }
01103         }
01104   else if (m_tag == "timing-line")
01105         {
01106           mp_road->timing_line (m_doubles [0]);
01107         }
01108   else if (m_tag == "track")
01109     {
01110       mp_road->build (m_circuit, m_length);
01111     }
01112 }
01113 
01114 void Vamos_Track::
01115 Strip_Track_Reader::on_data (std::string data_string)
01116 {
01117   std::string data = remove_leading_space (data_string);
01118   if (data.size () == 0)
01119         {
01120           return;
01121         }
01122   std::istringstream is (data.c_str ());
01123 
01124   char delim;
01125 
01126   if (m_path == "/track/sky/sides")
01127         {
01128           m_strings [0] = data;
01129         }
01130   else if (m_path == "/track/sky/top")
01131         {
01132           m_strings [1] = data;
01133         }
01134   else if (m_path == "/track/sky/bottom")
01135         {
01136           m_strings [2] = data;
01137         }
01138   else if (m_path == "/track/material/friction")
01139         {
01140           is >> m_doubles [0];
01141         }
01142   else if (m_path == "/track/material/restitution")
01143         {
01144           is >> m_doubles [1];
01145         }
01146   else if (m_path == "/track/material/rolling")
01147         {
01148           is >> m_doubles [2];
01149         }
01150   else if (m_path == "/track/material/drag")
01151         {
01152           is >> m_doubles [3];
01153         }
01154   else if (m_path == "/track/material/bump-amplitude")
01155         {
01156           is >> m_doubles [4];
01157         }
01158   else if (m_path == "/track/material/bump-wavelength")
01159         {
01160           is >> m_doubles [5];
01161         }
01162   else if (m_path == "/track/material/texture/width")
01163         {
01164           is >> m_doubles [6];
01165         }
01166   else if (m_path == "/track/material/texture/length")
01167         {
01168           is >> m_doubles [7];
01169         }
01170   else if (m_path == "/track/material/texture/file")
01171         {
01172           m_strings.push_back (data);
01173         }
01174   else if (m_path == "/track/segment")
01175         {
01176           is >> delim >> m_strings [0] 
01177                  >> m_strings [1] 
01178                  >> m_strings [2] 
01179                  >> m_strings [3] 
01180                  >> m_strings [4]
01181                  >> m_strings [5]
01182                  >> m_strings [6];
01183         }
01184   else if (m_path == "/track/road/resolution")
01185         {
01186           is >> m_doubles [0];
01187         }
01188   else if (m_path == "/track/road/length")
01189         {
01190           is >> m_doubles [1];
01191         }
01192   else if (m_path == "/track/road/radius")
01193         {
01194           m_bools [0] = true;
01195           is >> m_doubles [2];
01196         }
01197   else if (m_path == "/track/road/skew")
01198         {
01199           is >> m_doubles [20];
01200         }
01201   else if (m_path == "/track/road/left-width")
01202         {
01203           Two_Point point;
01204           is >> point;
01205           m_point_vectors [0].push_back (point);
01206         }
01207   else if (m_path == "/track/road/right-width")
01208         {
01209           Two_Point point;
01210           is >> point;
01211           m_point_vectors [1].push_back (point);
01212         }
01213   else if (m_path == "/track/road/left-road-width")
01214         {
01215           Two_Point point;
01216           is >> point;
01217           m_point_vectors [2].push_back (point);
01218         }
01219   else if (m_path == "/track/road/right-road-width")
01220         {
01221           Two_Point point;
01222           is >> point;
01223           m_point_vectors [3].push_back (point);
01224         }
01225   // Left Kerb
01226   else if (m_path == "/track/road/left-kerb/start/distance")
01227         {
01228           is >> m_doubles [3];
01229         }
01230   else if (m_path == "/track/road/left-kerb/start/transition/length")
01231         {
01232           is >> m_doubles [4];
01233         }
01234   else if (m_path == "/track/road/left-kerb/start/transition/width")
01235         {
01236           is >> m_doubles [5];
01237         }
01238   else if (m_path == "/track/road/left-kerb/end/distance")
01239         {
01240           is >> m_doubles [6];
01241         }
01242   else if (m_path == "/track/road/left-kerb/end/transition/length")
01243         {
01244           is >> m_doubles [7];
01245         }
01246   else if (m_path == "/track/road/left-kerb/end/transition/width")
01247         {
01248           is >> m_doubles [8];
01249         }
01250   else if (m_path == "/track/road/left-kerb/profile")
01251         {
01252           Two_Point point;
01253           m_left_profile.clear ();
01254           m_left_profile.push_back (point);
01255           while (is >> point)
01256                 {
01257                   m_left_profile.push_back (point);
01258                 }
01259         }
01260   // Right Kerb
01261   else if (m_path == "/track/road/right-kerb/start/distance")
01262         {
01263           is >> m_doubles [9];
01264         }
01265   else if (m_path == "/track/road/right-kerb/start/transition/length")
01266         {
01267           is >> m_doubles [10];
01268         }
01269   else if (m_path == "/track/road/right-kerb/start/transition/width")
01270         {
01271           is >> m_doubles [11];
01272         }
01273   else if (m_path == "/track/road/right-kerb/end/distance")
01274         {
01275           is >> m_doubles [12];
01276         }
01277   else if (m_path == "/track/road/right-kerb/end/transition/length")
01278         {
01279           is >> m_doubles [13];
01280         }
01281   else if (m_path == "/track/road/right-kerb/end/transition/width")
01282         {
01283           is >> m_doubles [14];
01284         }
01285   else if (m_path == "/track/road/right-kerb/profile")
01286         {
01287           Two_Point point;
01288           m_right_profile.clear ();
01289           m_right_profile.push_back (point);
01290           while (is >> point)
01291                 {
01292                   m_right_profile.push_back (point);
01293                 }
01294         }
01295 
01296   else if (m_path == "/track/road/left-wall-height")
01297         {
01298           is >> m_doubles [15];
01299         }
01300   else if (m_path == "/track/road/right-wall-height")
01301         {
01302           is >> m_doubles [16];
01303         }
01304   else if (m_path == "/track/road/elevation")
01305         {
01306           char delim;
01307           double dist;
01308           double elev;
01309           is >> delim >> dist >> delim >> elev;
01310           //m_elev_points.push_back (Two_Point (dist, elev));
01311         }
01312   else if (m_path == "/track/road/bank")
01313         {
01314           is >> m_doubles [17];
01315         }
01316   else if (m_path == "/track/road/bank-pivot")
01317         {
01318           is >> m_doubles [18];
01319         }
01320   else if (m_path == "/track/road/braking-marker/file")
01321         {
01322           m_strings [1] = data;
01323         }
01324   else if (m_path == "/track/road/braking-marker/distance")
01325         {
01326           is >> m_doubles [19];
01327         }
01328   else if (m_path == "/track/road/braking-marker/size")
01329         {
01330           is >> m_points [0];
01331         }
01332   else if (m_path == "/track/road/braking-marker/offset")
01333         {
01334           is >> m_points [1];
01335         }
01336   else if (m_path == "/track/road/braking-marker/side")
01337         {
01338           m_bools [5] = (data == "right");
01339         }
01340   else if (m_path == "/track/road/model/file")
01341         {
01342           std::string file;
01343           is >> file;
01344           m_current_model_info.file = m_data_dir + "tracks/" + file;
01345         }
01346   else if (m_path == "/track/road/model/scale")
01347         {
01348           is >> m_current_model_info.scale;
01349         }
01350   else if (m_path == "/track/road/model/translate")
01351         {
01352           is >> m_current_model_info.translation;
01353         }
01354   else if (m_path == "/track/road/model/rotate")
01355         {
01356           is >> m_current_model_info.rotation;
01357         }
01358   else if (m_path == "/track/track-length")
01359     {
01360       is >> m_length;
01361     }
01362   else
01363         {
01364           double arg;
01365           is >> arg;
01366           m_doubles.push_back (arg);
01367         }
01368 }

Generated on Thu Oct 19 04:05:56 2006 by  doxygen 1.4.6