00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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;
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)
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)
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
00631
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
00678
00679
00680
00681 cam.dir = carorientation;
00682
00683
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
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
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
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