src/vamosworld.cc

Go to the documentation of this file.
00001 /* vim: set noexpandtab shiftwidth=8 cino=:
00002  ***************************************************************************
00003  *                      vamosworld.cc
00004  *
00005  *  Sat Mar 26 14:06:16 2005
00006  *  Copyright  2005  Joe Venzon
00007  *  joe@venzon.net
00008  ****************************************************************************/
00009 
00010 /*
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 
00027 #include "vamosworld.h"
00028 
00029 extern void LoadingScreen(string loadtext);
00030 
00031 extern void snap_screenshot();
00032 
00033 VAMOSWORLD::VAMOSWORLD()
00034  : world(0), steerpos(0), cammode(CMChaseRigid), joyinfo(false), oldseg(0),initdone(false), shift_time(0)
00035 {
00036         error_log.open("logs/vamosworld.log");
00037 }
00038 
00039 void VAMOSWORLD::DeInit()
00040 {
00041         if (initdone)
00042         {
00043                 delete world;
00044                 initdone = false;
00045                 track_p->ClearRoads();
00046                 UnloadHUD();
00047         }
00048 }
00049 
00050 void VAMOSWORLD::Init (TRACK * track)
00051 {       
00052         UpdateSettings();
00053 
00054         lastcamchange = 0.0f;
00055 
00056         world = new Vamos_World::World (track);
00057 
00058         UnloadHUD();
00059         LoadHUD();
00060 
00061         track_p = track;
00062 
00063         ifstream cf;
00064         int modenum = 0;
00065         settings.Get( "game.camera_mode", modenum );
00066         switch (modenum)
00067         {
00068                 case 0:
00069                         SetCameraMode(CMChaseRigid);
00070                         break;
00071                 case 1:
00072                         SetCameraMode(CMChase);
00073                         break;
00074                 case 2:
00075                         SetCameraMode(CMOrbit);
00076                         break;
00077                 case 3:
00078                         SetCameraMode(CMHood);
00079                         break;
00080                 case 4:
00081                         SetCameraMode(CMFree);
00082                         break;
00083                 case 5:
00084                         SetCameraMode(CMInCar);
00085                         break;
00086                 case 6:
00087                         SetCameraMode(CMExternal);
00088                         break;
00089                 case 7:
00090                         SetCameraMode(CMExtFollow);
00091                         break;
00092         }
00093 
00094         VERTEX initcam = track_p->GetStart().ScaleR(-1);
00095         initcam.y -= 6;
00096         cam.position = initcam;
00097 
00098         initdone = true;
00099 }
00100 
00101 extern bool verbose_output;
00102 VAMOSWORLD::~VAMOSWORLD()
00103 {
00104         if (verbose_output)
00105                 cout << "vamosworld deinit" << endl;
00106 
00107         error_log.close();
00108 
00109         DeInit();
00110 }
00111 
00112 extern GLfloat LightPosition[4];
00113 
00114 void VAMOSWORLD::DrawShadows()
00115 {
00116         glPushMatrix();
00117 
00118         if (MP_DBGDEEP)
00119                 cout << "car shadow start" << endl;
00120         draw_shadows();
00121         if (MP_DBGDEEP)
00122                 cout << "car shadow done" << endl;
00123 
00124         glPopMatrix();
00125 }
00126 
00127 void VAMOSWORLD::Draw()
00128 {
00129         glPushMatrix();
00130 
00131         QUATERNION goofyfoot;
00132         goofyfoot.Rotate(-3.141593/2.0, 1,0,0);
00133         double tempmat[16];
00134         goofyfoot.GetMat(tempmat);
00135         glMultMatrixd(tempmat);
00136 
00137         float lp[4];
00138         lp[0] = LightPosition[0];
00139         lp[1] = LightPosition[1];
00140         lp[2] = LightPosition[2];
00141         lp[3] = 0;
00142         VERTEX lpv;
00143         lpv.Set(lp);
00144         lpv = goofyfoot.ReturnConjugate().RotateVec(lpv);
00145         lp[0] = lpv.x;
00146         lp[1] = lpv.y;
00147         lp[2] = lpv.z;
00148         glLightfv( GL_LIGHT1, GL_POSITION,  lp);
00149 
00150         glPushMatrix();
00151         glEnable(GL_STENCIL_TEST);
00152         glMatrixMode (GL_MODELVIEW);
00153         glPopMatrix();
00154 
00155         glPopMatrix();
00156 
00157         lp[0] = LightPosition[0];
00158         lp[1] = LightPosition[1];
00159         lp[2] = LightPosition[2];
00160         lp[3] = 0;
00161 }
00162 
00163 void VAMOSWORLD::draw_cars(bool draw_interior, bool draw_focused_car)
00164 {
00165         glMatrixMode (GL_MODELVIEW);
00166 
00167         for (std::vector <Vamos_World::Car_Information>::iterator it = world->m_cars.begin ();
00168            it != world->m_cars.end ();
00169            it++)
00170         {
00171                 assert (it->car != 0);
00172 
00173                 glPushAttrib(GL_ALL_ATTRIB_BITS);
00174                 glEnable(GL_DEPTH_TEST);
00175                 glDepthMask(1);
00176                 glDisable(GL_CULL_FACE);
00177                 glEnable(GL_BLEND);
00178                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00179 
00180                 it->car->SetReflectionTexture(&sphere_reflection);
00181 
00182                 utility.SelectTU(0);
00183                         glPushMatrix();
00184 
00185                         it->car->draw (true);
00186                         if (draw_interior)
00187                         {
00188                                 it->car->draw_interior ();
00189                         }
00190                         glPopMatrix();
00191 
00192                 utility.SelectTU(0);
00193                 glPopAttrib();
00194         }
00195 }
00196 
00197 void VAMOSWORLD::draw_shadows()
00198 {
00199         glPushAttrib(GL_ALL_ATTRIB_BITS);
00200         glMatrixMode (GL_MODELVIEW);
00201 
00202         glDisable(GL_DEPTH_TEST);
00203         glDepthMask(0);
00204         glCullFace(GL_FRONT);
00205         glEnable(GL_CULL_FACE);
00206 
00207         int count = 0;
00208 
00209         std::vector <Vamos_World::Car_Information>::iterator it;
00210         //draw shadows, make tire sounds, create smoke
00211         for( it = world->m_cars.begin (); it != world->m_cars.end (); it++ )
00212         {
00213                 if (MP_DBGDEEP)
00214                         cout << "wheel pos start" << endl;
00215 
00216                 assert (it->car != 0);
00217 
00218                 if (it->car->chassis().IsValid())
00219                 {               
00220                         glPushMatrix();
00221                         VERTEX pos;
00222                         Vamos_Geometry::Three_Vector cp = it->car->chassis().position() + it->car->chassis().center_of_mass();
00223                         pos.Set(cp[0], cp[1], cp[2]);
00224 
00225                         VERTEX posyup;
00226                         posyup.Set(cp[0], cp[2], -cp[1]);
00227 
00228                         float x1, x2, y1, y2;
00229                         x1 = 3;
00230                         x2 = -3;
00231                         y1 = 3;
00232                         y2 = -3;
00233 
00234                         VERTEX wheelpos[4];
00235 
00236                         int i = 0;
00237 
00238                         double slide[4];
00239                         double wheelspeed[4];
00240                         double carspeed = GetCar(CONT_PLAYERLOCAL)->car->chassis().cm_velocity().magnitude();
00241                         for (i = 0; i < 4; i++)
00242                         {
00243                                 Vamos_Geometry::Three_Vector tv = it->car->wheel(i)->contact_position();
00244                                 wheelpos[i].Set(tv[0],tv[1],tv[2]);
00245                                 slide[i] = it->car->wheel(i)->slide();
00246                                 wheelspeed[i] = it->car->wheel(i)->rotational_speed();
00247                         }
00248 
00249                         VERTEX coord[4];
00250                         coord[0].Set(x1,y1,0);
00251                         coord[1].Set(x1,y2,0);
00252                         coord[2].Set(x2,y2,0);
00253                         coord[3].Set(x2,y1,0);
00254 
00255                         VERTEX shadowpos[4];
00256 
00257                         for (i = 0; i < 4; i++)
00258                                 shadowpos[i] = coord[i];
00259 
00260                         if (MP_DBGDEEP)
00261                                 cout << "wheel pos done" << endl;
00262 
00263                         size_t segidx;
00264                         QUATERNION rot;
00265                         double angle;
00266                         Vamos_Geometry::Three_Vector aa = it->car->chassis().axis_angle(&angle);
00267                         rot.SetAxisAngle(angle*(3.141593/180.0),aa[0],aa[1],aa[2]);
00268 
00269                         QUATERNION carorientation;
00270                         carorientation.SetAxisAngle(angle*(3.141593/180), -aa[0], -aa[2], aa[1]);
00271                         carorientation.Rotate(3.141593/2.0,0,1,0);
00272 
00273                         for (i = 0; i < 4; i++)
00274                         {
00275                                 segidx = 0;
00276                                 coord[i] = rot.RotateVec(coord[i]);
00277                         }
00278 
00279                         Vamos_Geometry::Three_Vector cm = it->car->chassis().center_of_mass();
00280                         VERTEX cmv;
00281 
00282                         if (MP_DBGDEEP)
00283                                 cout << "coord adjust start" << endl;
00284 
00285                         cmv.Set(cm[0],cm[1],cm[2]);
00286                         for (i = 0; i < 4; i++)
00287                         {
00288                                 coord[i].x = coord[i].x - rot.RotateVec(cmv).x;
00289                                 coord[i].y = coord[i].y - rot.RotateVec(cmv).y;
00290 
00291                                 VERTEX origin;
00292                                 origin = coord[i]+pos;
00293                                 origin.z = -origin.y;
00294                                 origin.y = 0;
00295                                 coord[i].z = world->p_track->Elevation(origin);
00296                                 VERTEX c;
00297                                 c.Set(coord[i].x+pos.x, coord[i].y+pos.y, coord[i].z);
00298                         }
00299 
00300                         VERTEX tirecoord[4], tc2[4];
00301                         for (i = 0; i < 4; i++)
00302                         {
00303                                 tirecoord[i] = rot.RotateVec(wheelpos[i]);
00304                                 shadowpos[i] = rot.RotateVec(shadowpos[i]);
00305                                 tirecoord[i] = tirecoord[i] - rot.RotateVec(cmv);
00306                                 tirecoord[i] = pos + tirecoord[i];
00307                                 shadowpos[i] = pos + shadowpos[i];
00308 
00309                                 float temp = tirecoord[i].z;
00310                                 tirecoord[i].z = -tirecoord[i].y;
00311                                 tirecoord[i].y = temp;
00312                                 tc2[i] = tirecoord[i];
00313 
00314                                 temp = shadowpos[i].z;
00315                                 shadowpos[i].z = -shadowpos[i].y;
00316                                 shadowpos[i].y = temp;
00317                         }
00318 
00319                         VERTEX tctemp = tc2[2];
00320                         tc2[2] = tc2[3];
00321                         tc2[3] = tctemp;
00322 
00323                         if (MP_DBGDEEP)
00324                                 cout << "coord adjust stop" << endl;
00325 
00326                         if (count == 0 || multiplay.TickCar(count))
00327                         {
00328 
00329                                 for (i = 0; i < 4; i++)
00330                                 {
00331                                         float slidemultiple = 1.0; //for venzon tire code
00332 
00333                                         float speed_offset = -5.0;
00334                                         float speed_gain = 0.25;
00335                                         float attenuate = (wheelspeed[i] + speed_offset)*speed_gain;
00336                                         if (attenuate < 0)
00337                                                 attenuate = 0;
00338                                         if (attenuate > 1)
00339                                                 attenuate = 1;
00340 
00341                                         float carfactor = (carspeed-10)*0.25;
00342                                         if (carfactor < 0)
00343                                                 carfactor = 0;
00344                                         if (carfactor > 1)
00345                                                 carfactor = 1;
00346                                         carfactor = 1.0 - carfactor;
00347 
00348                                         slidemultiple *= (attenuate*carfactor+1.0-carfactor);
00349 
00350                                         float prob = 0;
00351                                         float probmultiple = 100;
00352                                         float maxprob = 0.1;
00353                                         if (slide[i] > 0)
00354                                         {
00355                                                 float squeal = slide[i]*slidemultiple;
00356                                                 if (squeal < 0)
00357                                                         squeal = -squeal;
00358                                                 float offset = 0.2;
00359                                                 float gain = 1.0;
00360                                                 squeal -= offset;
00361                                                 squeal *= gain;
00362                                                 if (squeal < 0)
00363                                                         squeal = 0;
00364                                                 if (squeal > 1)
00365                                                         squeal = 1;
00366                                                 prob = (l_timefactor / l_fps) * probmultiple;
00367                                                 prob = prob * squeal;
00368                                                 if (prob < 0) //not sure this is necessary
00369                                                         prob = -prob;
00370                                                 VERTEX dir;
00371                                                 dir.y = 1;
00372                                                 particle.SetParams(1.0*slide[i], 2.0*slide[i], 5.0, 14.0,
00373                                                         0.3, 1.0, dir, 0.5, 1.0);
00374                                                 if (prob > maxprob)
00375                                                         prob = maxprob;
00376                                                 particle.ProbAddParticle(tirecoord[i], prob);
00377                                         }
00378 
00379                                         float squeal = slide[i]*slidemultiple;
00380                                         if (squeal < 0) //not sure this is necessary
00381                                                 squeal = -squeal;
00382                                         float offset = 0.05;
00383                                         float gain = 0.5;
00384                                         squeal -= offset;
00385                                         squeal *= gain;
00386                                         if (squeal < 0)
00387                                                 squeal = 0;
00388                                         if (squeal > 1)
00389                                                 squeal = 1;
00390 
00391                                         bool snddebug = false;
00392                                         float maxgain = 0.3;
00393                                         gain = squeal;
00394                                         if (gain > maxgain)
00395                                                 gain = maxgain;
00396                                         if (l_timefactor != 0.0f)
00397                                                 if (!snddebug) sound.SetGain(it->car->GetTireSoundSource(i), gain);
00398                                         float pitch = 1.0-squeal;
00399                                         float pitchvariation = 0.4;
00400                                         pitch *= pitchvariation;
00401                                         pitch = pitch + (1.0-pitchvariation);
00402                                         if (!snddebug) sound.SetPitch(it->car->GetTireSoundSource(i), pitch);
00403 
00404                                         VERTEX tvel;
00405                                         if (!tirecoord[i].nan() && !tvel.nan())
00406                                                 if (!snddebug) sound.SetPosVel(it->car->GetTireSoundSource(i), tirecoord[i], tvel);
00407 
00408                                         oldtirepos[i] = tirecoord[i];
00409                                 }
00410                         }
00411 
00412                         if (car_shadows_enabled)
00413                         {
00414                                 AABB shadowbox;
00415                                 VERTEX minbox, maxbox;
00416                                 bool hasmin[3];
00417                                 bool hasmax[3];
00418 
00419                                 VERTEX shadowquad[4];
00420                                 for (i = 0; i < 4; i++)
00421                                 {
00422                                         shadowquad[i] = shadowpos[i];
00423                                 }
00424 
00425                                 for (i = 0; i < 3; i++) hasmin[i] = false;
00426                                 for (i = 0; i < 3; i++) hasmax[i] = false;
00427 
00428                                 for (i = 0; i < 4; i++)
00429                                 {
00430                                         if (shadowquad[i].x < minbox.x || !hasmin[0])
00431                                         {
00432                                                 minbox.x = shadowquad[i].x;
00433                                                 hasmin[0] = true;
00434                                         }
00435                                         if (shadowquad[i].y < minbox.y || !hasmin[1])
00436                                         {
00437                                                 minbox.y = shadowquad[i].y;
00438                                                 hasmin[1] = true;
00439                                         }
00440                                         if (-shadowquad[i].z < minbox.z || !hasmin[2])
00441                                         {
00442                                                 minbox.z = -shadowquad[i].z;
00443                                                 hasmin[2] = true;
00444                                         }
00445 
00446                                         if (shadowquad[i].x > maxbox.x || !hasmax[0])
00447                                         {
00448                                                 maxbox.x = shadowquad[i].x;
00449                                                 hasmax[0] = true;
00450                                         }
00451                                         if (shadowquad[i].y > maxbox.y || !hasmax[1])
00452                                         {
00453                                                 maxbox.y = shadowquad[i].y;
00454                                                 hasmax[1] = true;
00455                                         }
00456                                         if (-shadowquad[i].z > maxbox.z || !hasmax[2])
00457                                         {
00458                                                 maxbox.z = -shadowquad[i].z;
00459                                                 hasmax[2] = true;
00460                                         }
00461                                 }
00462                                 maxbox.y += 5;
00463                                 minbox.y -= 5;
00464                                 shadowbox.SetFromCorners(minbox,maxbox);
00465                                 list <OBJECTTRI> trilist;
00466                                 objects.GetTrisInBBox(shadowbox, trilist);
00467 
00468                                 utility.SelectTU(0);
00469                                 glEnable(GL_TEXTURE_2D);
00470                                 glEnable(GL_BLEND);
00471                                 glDisable(GL_LIGHTING);
00472                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00473                                 it->car->shadow_texture()->Activate();
00474 
00475                                 glEnable(GL_DEPTH_TEST);
00476                                 glDepthFunc( GL_LEQUAL );
00477                                 glColor4f(1,1,1,1);
00478                                 glDisable(GL_CULL_FACE);
00479                                 glCullFace(GL_FRONT);
00480 
00481                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00482                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00483 
00484                                 VERTEX shadowdim;
00485                                 shadowdim.x = 6;
00486                                 shadowdim.z = 6;
00487 
00488                                 float roadheight = world->p_track->Elevation(posyup);
00489 
00490                                 glBegin(GL_TRIANGLES);
00491                                         for (list <OBJECTTRI>::iterator i = trilist.begin(); i != trilist.end(); i++)
00492                                         {
00493                                                 i->v1.z = -i->v1.z;
00494                                                 i->v2.z = -i->v2.z;
00495                                                 i->v3.z = -i->v3.z;
00496 
00497                                                 ShadowTexCoord(posyup, carorientation, shadowdim, i->v1, roadheight);
00498                                                 glVertex3fv(i->v1.v3());
00499                                                 ShadowTexCoord(posyup, carorientation, shadowdim, i->v2, roadheight);
00500                                                 glVertex3fv(i->v2.v3());
00501                                                 ShadowTexCoord(posyup, carorientation, shadowdim, i->v3, roadheight);
00502                                                 glVertex3fv(i->v3.v3());
00503                                         }
00504                                 glEnd();
00505                         }
00506 
00507                         glDisable(GL_CULL_FACE);
00508                         glDisable(GL_BLEND);
00509                         glEnable(GL_LIGHTING);
00510                         glEnable(GL_TEXTURE_2D);
00511                         glPopMatrix();
00512                 }
00513         }
00514 
00515         glEnable(GL_DEPTH_TEST);
00516         glDepthMask(1);
00517         glDisable(GL_CULL_FACE);
00518 
00519         utility.SelectTU(0);
00520 
00521         utility.SelectTU(1);
00522         glDisable(GL_TEXTURE_GEN_S);
00523         glDisable(GL_TEXTURE_GEN_T);
00524         glDisable(GL_TEXTURE_2D);
00525         utility.SelectTU(0);
00526         glDepthMask(1);
00527 
00528         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00529         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00530 
00531         glPopAttrib();
00532 }
00533 
00534 void VAMOSWORLD::ShadowTexCoord(VERTEX &carpos, QUATERNION &carorientation, VERTEX & shadowdim, VERTEX &vert, float roadheight)
00535 {
00536         VERTEX vertdiff;
00537         vertdiff = vert-carpos;
00538         vertdiff = carorientation.RotateVec(vertdiff);
00539 
00540         float trans = 1.0;
00541         float transmin = -3;
00542         float transbotline = -2.0;
00543         float transtopline = 1.5;
00544         float transmax = 2;
00545         float vertheight = vert.y - roadheight;
00546         if (vertheight < transmin || vertheight > transmax)
00547                 trans = 1.0;
00548         else if (vertheight > transbotline && vertheight < transtopline)
00549                 trans = 0.0;
00550         else if (vertheight < transbotline)
00551                 trans = 1.0-((vertheight - transmin)*(1/(transbotline - transmin)));
00552         else if (vertheight > transtopline)
00553                 trans = 1.0-((transmax - vertheight)*(1/(transmax - transtopline)));
00554 
00555         float opacity = 1.0f-(trans);
00556 
00557         glColor4f(1,1,1,opacity);
00558 
00559         vertdiff.x *= (1.0/shadowdim.x);
00560         vertdiff.z *= (1.0/shadowdim.z);
00561 
00562         vertdiff.x += 0.5;
00563         vertdiff.z += 0.5;
00564 
00565         float u = vertdiff.x;
00566         float v = vertdiff.z;
00567 
00568         glTexCoord2d(u,v);
00569 }
00570 
00571 void VAMOSWORLD::Update(float timefactor, float fps, SDL_Joystick ** js)
00572 {       
00573         l_timefactor = timefactor;
00574         l_fps = fps;
00575 
00576         if (l_timefactor <= 0 || fps < 5)
00577         {
00578                 sound.MuteAll();
00579                 return;
00580         }
00581 
00582         for (std::vector <Vamos_World::Car_Information>::iterator it = world->m_cars.begin ();
00583         it != world->m_cars.end ();
00584         it++)
00585         {
00586                 bool advance = false;
00587                 int nextsector = 0;
00588                 if (track_p->NumSectors() > 0)
00589                 {
00590                         nextsector = (it->car->GetSector() + 1) % track_p->NumSectors();
00591                         for (int p = 0; p < 4; p++)
00592                         {
00593                                 if (it->car->GetColPatch(p) == track_p->GetLapSequence(nextsector))
00594                                 {
00595                                         advance = true;
00596                                 }
00597                         }
00598                 }
00599 
00600                 if (advance)
00601                 {
00602                         if (nextsector == 0)
00603                         {
00604                                 timer.Lap((it->car->GetSector() >= 0));
00605                         }
00606 
00607                         it->car->SetSector(nextsector);
00608                 }
00609         }
00610 
00611         bool camswitch = false;
00612 
00613         ProcessControls(js, timefactor, fps);
00614 
00615         const int repeat = 1;
00616         double dt = (timefactor/fps)/(float)repeat;
00617         for (int loop = 0; loop < repeat; loop++)
00618         {
00619                 PhysUpdate(dt);
00620         }
00621         dt = (timefactor/fps);
00622 
00623         if (GetCar(CONT_PLAYERLOCAL) != 0)
00624         {
00625 
00626                 Vamos_Geometry::Three_Vector cm = GetCar(CONT_PLAYERLOCAL)->car->chassis().position();
00627                 if (cammode != CMFree && cammode != CMChase && cammode != CMExternal && cammode != CMExtFollow)
00628                 {
00629                         cam.position.Set(-cm[0], -cm[2], cm[1]);
00630                         //cam.position.Set(cm[1], -cm[2], cm[0]);
00631                         //cam.position.DebugPrint();
00632                 }
00633 
00634                 double angle;
00635                 Vamos_Geometry::Three_Vector axis = GetCar(CONT_PLAYERLOCAL)->car->chassis().axis_angle (&angle);
00636                 Vamos_Geometry::Three_Vector vvel = GetCar(CONT_PLAYERLOCAL)->car->chassis().cm_velocity();
00637                 VERTEX vel;
00638                 vel.Set(vvel[0],vvel[1],vvel[2]);
00639 
00640                 if (cammode == CMChase || cammode == CMChaseRigid || cammode == CMHood || cammode == CMInCar)
00641                 {
00642                         QUATERNION carorientation;
00643                         carorientation.SetAxisAngle(angle*(3.141593/180), -axis[0], -axis[2], axis[1]);
00644                         carorientation.Rotate(3.141593/2.0,0,1,0);                      
00645                         if (cammode == CMChase)
00646                         {
00647                                 VERTEX idealpos;
00648                                 idealpos.Set(-cm[0], -cm[2], cm[1]);
00649                                 VERTEX temp;
00650                                 temp.Set(0,-2,0);
00651                                 idealpos = idealpos + carorientation.RelativeMove(temp);
00652                                 temp.Set(0,0,-7.5);
00653                                 idealpos = idealpos + carorientation.RelativeMove(temp);
00654 
00655                                 float dirblend = 1.0;
00656                                 float posblend = 10.0*(timefactor/fps);
00657                                 if (dirblend < 0)
00658                                         dirblend = 0;
00659                                 else if (dirblend > 1)
00660                                         dirblend = 1;
00661                                 if (posblend < 0)
00662                                         posblend = 0;
00663                                 else if (posblend > 1)
00664                                         posblend = 1;
00665                                 cam.position = cam.position.interpolatewith(idealpos, posblend);
00666                                 cam.dir.LookAt(-cam.position.x, -cam.position.y, -cam.position.z, cm[0], cm[2]+2, -cm[1], 0,1,0);
00667                                 cam.dir = cam.dir.ReturnConjugate();
00668 
00669                         }
00670                         else if (cammode == CMHood)
00671                         {
00672                                 cam.dir = carorientation;
00673 
00674                                 Vamos_Geometry::Three_Vector vp = GetCar(CONT_PLAYERLOCAL)->car->view_position();
00675                                 vp = vp - GetCar(CONT_PLAYERLOCAL)->car->chassis().center_of_mass();
00676 
00677                                 //VERTEX cmass;
00678                                 //cmass.Set(GetCar(CONT_PLAYERLOCAL)->car->chassis().center_of_mass()[0],GetCar(CONT_PLAYERLOCAL)->car->chassis().center_of_mass()[1],GetCar(CONT_PLAYERLOCAL)->car->chassis().center_of_mass()[2]);
00679                                 //cmass.DebugPrint();
00680                                 
00681                                 cam.dir = carorientation;
00682                                 
00683                                 //cam.MoveRelative(vp[1],-vp[2],vp[0]+1.0);
00684                                 cam.MoveRelative(0.0, -vp[2], vp[1]+1.0);
00685                         }
00686                         else if (cammode == CMInCar)
00687                         {
00688                                 Vamos_Geometry::Three_Vector vp = GetCar(CONT_PLAYERLOCAL)->car->view_position();
00689                                 vp = vp - GetCar(CONT_PLAYERLOCAL)->car->chassis().center_of_mass();
00690                                 cam.dir = carorientation;
00691 
00692                                 VERTEX idealpos, viewpos;
00693                                 viewpos.Set(-vp[0], -vp[2], vp[1]);
00694                                 //viewpos.Set(vp[1], -vp[2], vp[0]);
00695                                 idealpos.Set(-cm[0], -cm[2], cm[1]);
00696                                 idealpos = idealpos + carorientation.RelativeMove(viewpos);
00697 
00698                                 if (camneedupdate)
00699                                 {
00700                                         cam.position = idealpos;
00701                                         cam_lastpos = cam.position;
00702                                         cam_lastpos2 = cam.position;
00703                                         camneedupdate = false;
00704                                         cam_lastvel.zero();
00705                                         cam_lastaccel.zero();
00706                                         cam_jerk.zero();
00707                                 }
00708 
00709                                 VERTEX accel;
00710                                 VERTEX vel;
00711                                 vel = cam.position - cam_lastpos2;
00712                                 vel.Scale(1.0/dt);
00713                                 accel = cam_lastvel - vel;
00714                                 cam_lastvel = vel;
00715                                 assert (timefactor != 0);
00716                                 accel.Scale(1.0/dt);
00717                                 accel = cam_lastaccel + (accel-cam_lastaccel).ScaleR(0.002);
00718                                 cam_lastpos2 = cam.position;
00719 
00720                                 VERTEX jerk;
00721                                 jerk = accel - cam_lastaccel;
00722                                 jerk.Scale(1.0/dt);
00723                                 cam_jerk = cam_jerk + (jerk-cam_jerk).ScaleR(0.002);
00724                                 cam_lastaccel = accel;
00725 
00726                                 jerk = accel;
00727                                 jerk = cam_jerk;
00728 
00729                                 float jerkscale = 0.015;
00730                                 float jerkmax = 0.1;
00731 
00732                                 jerk.Scale(jerkscale);
00733                                 if (jerk.x >= 0)
00734                                 {
00735                                         if (jerk.x > jerkmax)
00736                                                 jerk.x = jerkmax;
00737                                 }
00738                                 else
00739                                 {
00740                                         if (jerk.x < -jerkmax)
00741                                                 jerk.x = -jerkmax;
00742                                 }
00743                                 if (jerk.y >= 0)
00744                                 {
00745                                         if (jerk.y > jerkmax)
00746                                                 jerk.y = jerkmax;
00747                                 }
00748                                 else
00749                                 {
00750                                         if (jerk.y < -jerkmax)
00751                                                 jerk.y = -jerkmax;
00752                                 }
00753                                 if (jerk.z >= 0)
00754                                 {
00755                                         if (jerk.z > jerkmax)
00756                                                 jerk.z = jerkmax;
00757                                 }
00758                                 else
00759                                 {
00760                                         if (jerk.z < -jerkmax)
00761                                                 jerk.z = -jerkmax;
00762                                 }
00763 
00764                                 idealpos = idealpos + jerk;
00765 
00766                                 cam.position.Set(idealpos.x, idealpos.y, idealpos.z);
00767 
00768                         }
00769                         else //CMChaseRigid
00770                         {
00771                                 cam.dir = carorientation;
00772                                 cam.MoveRelative(0,-2.0,0);
00773                                 cam.MoveRelative(0,0,-7.75);
00774                         }
00775                 }
00776                 else if (cammode == CMOrbit)
00777                 {
00778                         float mindist = 7;
00779                         float maxdist = 20;
00780 
00781                         cam.MoveRelative(0,-1.0,0);
00782                         cam.MoveRelative(0,0,-(mindist*(mouse.GetZoom())+maxdist*(1.0f-mouse.GetZoom())));
00783 
00784                         VERTEX cpos = cam.position.ScaleR(-1.0);
00785                         float elev = track_p->Elevation(cpos)+0.5;
00786                         if (cpos.y < elev)
00787                                 cam.position.y = -elev;
00788 
00789                         cam.dir = mouse.GetDir();
00790                 }
00791                 else if (cammode == CMFree)
00792                 {
00793                         cam.dir = mouse.GetDir();
00794                 }
00795 
00796                 if (cammode != CMFree && cammode != CMOrbit)
00797                 {
00798                         mouse.InitDir(cam.dir);
00799                 }
00800 
00801         }
00802 
00803         int count = 0;
00804 
00805         std::vector <Vamos_World::Car_Information>::iterator it;
00806         for( it = world->m_cars.begin (); it != world->m_cars.end (); it++ )
00807         {
00808                 Vamos_Geometry::Three_Vector cm = it->car->chassis().position();
00809 
00810                 int sid = it->car->GetSoundSource();
00811                 float rpm = Vamos_Geometry::rad_s_to_rpm (it->car->engine ()->rotational_speed ());
00812                 sound.SetPitch(sid, rpm / 7000.0f);
00813                 count++;
00814                 float egain = it->car->engine()->throttle();
00815                 egain = egain*0.5+0.5;
00816                 if (rpm < 500.0)
00817                 {
00818                         egain *= (rpm / 7000.0f);
00819                 }
00820                 sound.SetGain(sid, egain);
00821                 VERTEX carpos;
00822                 carpos.x = cm[0];
00823                 carpos.y = cm[2];
00824                 carpos.z = -cm[1];
00825                 VERTEX campos = cam.position;
00826                 campos.Scale(-1);
00827                 QUATERNION q = cam.dir;
00828                 VERTEX at, up;
00829                 up.y = 1.0;
00830                 at.z = -1;
00831 
00832                 VERTEX camvel = cam.position - cam_lastpos;
00833                 camvel.Scale(1.0/dt);
00834                 if (camswitch)
00835                         camvel.zero();
00836                 sound.SetListener(campos, camvel, q.ReturnConjugate().RotateVec(at), q.ReturnConjugate().RotateVec(up));
00837 
00838                 VERTEX carvel;
00839                 carvel.x = carpos.x - it->car->car_lastpos[0];
00840                 carvel.y = carpos.y - it->car->car_lastpos[1];
00841                 carvel.z = carpos.z - it->car->car_lastpos[2];
00842                 carvel.Scale(1.0/dt);
00843                 if (!carpos.nan() && !carvel.nan())
00844                         sound.SetPosVel(sid, carpos, carvel);
00845 
00846                 cam_lastpos = cam.position;
00847                 it->car->car_lastpos[0] = cm[0];
00848                 it->car->car_lastpos[1] = cm[2];
00849                 it->car->car_lastpos[2] = -cm[1];
00850         }
00851 
00852         GetCar(CONT_PLAYERLOCAL)->car->GetState(replay.curstate.chassispos, 
00853                 replay.curstate.chassisorientation,
00854                 replay.curstate.chassisvel,
00855                 replay.curstate.chassisangvel,
00856                 replay.curstate.suspdisp,
00857                 replay.curstate.suspcompvel,
00858                 replay.curstate.whlangvel,
00859                 replay.curstate.gear,
00860                 replay.curstate.enginespeed,
00861                 replay.curstate.clutchspeed,
00862                 replay.curstate.enginedrag,
00863                 replay.curstate.tirespeed
00864                 );
00865 
00866         replay.curstate.segment = GetCar(CONT_PLAYERLOCAL)->segment_index;
00867         replay.curstate.time = replay.GetTime();
00868         multiplay.GetCurState(0)->CopyFrom(replay.curstate);
00869         multiplay.GetCurState(0)->time = multiplay.GetTime(0);
00870         replay.IncrementFrame();
00871         multiplay.Update(timefactor/fps);
00872         if (replay.Playing() != -1)
00873         {
00874                 CARSTATE * cst = replay.LoadState();
00875                 if (cst != NULL)
00876                 {
00877                         Vamos_World::Car_Information * rcar = NULL;
00878                         if (replay.GhostCar())
00879                                 rcar = GetCar(CONT_REPLAY);
00880                         else
00881                                 rcar = GetCar(CONT_PLAYERLOCAL);
00882                         rcar->segment_index = cst->segment;
00883                         rcar->car->SetState(cst->chassispos, 
00884                                 cst->chassisorientation,
00885                                 cst->chassisvel,
00886                                 cst->chassisangvel,
00887                                 cst->suspdisp,
00888                                 cst->suspcompvel,
00889                                 cst->whlangvel,
00890                                 cst->gear,
00891                                 cst->enginespeed,
00892                                 cst->clutchspeed,
00893                                 cst->enginedrag,
00894                                 cst->tirespeed
00895                                 );
00896                 }
00897         }
00898 
00899         if (multiplay.NumConnected() > 0)
00900         {
00901                 int p;
00902                 for (p = 0; p < multiplay.NumConnected(); p++)
00903                 {
00904                         if (multiplay.StateToLoad(p+1))
00905                         {
00906                                 CARSTATE * cst = multiplay.GetLoadState(p+1);
00907                                 if (cst != NULL)
00908                                 {
00909                                         GetCar(CONT_PLAYERREMOTE)->segment_index = cst->segment;
00910                                         GetCar(CONT_PLAYERREMOTE)->car->SetState(cst->chassispos,
00911                                         cst->chassisorientation,
00912                                         cst->chassisvel,
00913                                         cst->chassisangvel,
00914                                         cst->suspdisp,
00915                                         cst->suspcompvel,
00916                                         cst->whlangvel,
00917                                         cst->gear,
00918                                         cst->enginespeed,
00919                                         cst->clutchspeed,
00920                                         cst->enginedrag,
00921                                         cst->tirespeed
00922                                         );
00923                                 }
00924 
00925                                 multiplay.ClearStateToLoad(p+1);
00926                         }
00927                 }
00928         }
00929 
00930         world->m_contact_info.clear ();
00931 }
00932 
00933 extern void MainPause();
00934 extern void MainUnpause();
00935 
00936 double dabs(double val)
00937 {
00938         if (val < 0)
00939                 return -val;
00940         else
00941                 return val;
00942 }
00943 
00944 void VAMOSWORLD::ProcessControls(SDL_Joystick ** js, float timefactor, float fps)
00945 {
00946         string dofunction = "";
00947         double dovalue = 0.0;
00948         double dotime = 0.0;
00949         bool held = false;
00950 
00951         if (GetCar(CONT_PLAYERLOCAL) != 0)
00952         {
00953 
00954                 int i;
00955 
00956                 joyinfo_js = js[0];
00957                 joyinfo_jsarray = js;
00958 
00959                 if (replay.Playing() != -1)
00960                 {
00961                         for (i = 0; i < replay.GetNumFuncs(); i++)
00962                         {
00963                                 FUNCTION_MEMORY curfunc = replay.GetFunc(i);
00964                                 if (curfunc.active)
00965                                 {
00966                                         if (replay.GhostCar())
00967                                                 DoOp(GetCar(CONT_REPLAY), curfunc.func_name, curfunc.newval, 0.0, false, timefactor, fps); 
00968                                         else
00969                                                 DoOp(GetCar(CONT_PLAYERLOCAL), curfunc.func_name, curfunc.newval, 0.0, false, timefactor, fps); 
00970                                 }
00971                         }
00972                 }
00973 
00974                 if (MP_DBGDEEP)
00975                         cout << "multiplay tick start" << endl;
00976                 if (multiplay.NumConnected() > 0)
00977                 {
00978                         if (multiplay.TickCar(1) && !multiplay.NOOPTick(1))
00979                         {
00980                                 for (i = 0; i < multiplay.NumFuncs(1); i++)
00981                                 {
00982                                         FUNCTION_MEMORY curfunc = multiplay.GetFuncMem(1)[i];
00983                                         dofunction = curfunc.func_name;
00984                                         if (curfunc.active && !(dofunction.find("view_") == 0 || dofunction == "screen_shot" || dofunction == "track_shot" || dofunction == "pause" || dofunction == "reset"))
00985                                         {
00986                                                 DoOp(GetCar(CONT_PLAYERREMOTE), curfunc.func_name, curfunc.newval, 0.0, false, timefactor, fps); 
00987                                         }
00988                                         dofunction = "";
00989                                 }
00990                         }
00991                 }
00992                 if (MP_DBGDEEP)
00993                         cout << "multiplay tick done" << endl;
00994 
00995                 for (gamecontrols.ControlIteratorReset(); gamecontrols.ControlIteratorGetControl() != NULL; gamecontrols.ControlIteratorIncrement())
00996                 {
00997                         CONTROL & curctrl = *(gamecontrols.ControlIteratorGetControl());
00998                         dofunction = "";
00999                         dovalue = 0.0;
01000                         dotime = 0.0;
01001                         held = false;
01002 
01003                         //joystick input
01004                         if (curctrl.GetType() == Joy)
01005                         {
01006                                 SDL_Joystick * joytouse;
01007 
01008                                 int joynum = curctrl.GetJoyNum();
01009 
01010                                 if (joynum >= 0 && joynum < SDL_NumJoysticks())
01011                                 {
01012                                         joytouse = js[joynum];
01013 
01014                                         if (curctrl.GetJoyType() == Button)
01015                                         {
01016                                                 if (curctrl.GetOneTime())
01017                                                 {
01018                                                         if (curctrl.GetJoyPushDown())
01019                                                         {
01020                                                                 if (!curctrl.GetJoyButtonLastState() && SDL_JoystickGetButton(joytouse, curctrl.GetJoyButton()))
01021                                                                 {
01022                                                                         dofunction = curctrl.GetName();
01023                                                                         dovalue = 1.0;
01024                                                                 }
01025                                                         }
01026                                                         else if (!curctrl.GetJoyPushDown())
01027                                                         {
01028                                                                 if (!curctrl.GetJoyButtonLastState() && SDL_JoystickGetButton(joytouse, curctrl.GetJoyButton()))
01029                                                                 {
01030                                                                         dofunction = curctrl.GetName();
01031                                                                         dovalue = 0.0;
01032                                                                 }
01033                                                         }
01034                                                 }
01035                                                 else