00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <vamos/world/World.h>
00019
00020 #include <cassert>
00021
00022 using Vamos_Geometry::Three_Vector;
00023 using Vamos_Geometry::Three_Matrix;
00024
00025
00026 Vamos_World::
00027 Times::Times () :
00028 m_current (0.0),
00029 m_previous (0.0),
00030 m_best (0.0),
00031 m_difference (0.0)
00032 {
00033 }
00034
00035 void Vamos_World::
00036 Times::update (double time_step)
00037 {
00038 m_current += time_step;
00039 }
00040
00041 void Vamos_World::
00042 Times::finalize ()
00043 {
00044 if (m_best != 0.0)
00045 {
00046 m_difference = m_current - m_best;
00047 }
00048
00049 if ((m_current < m_best) || (m_best == 0.0))
00050 {
00051 m_best = m_current;
00052 }
00053
00054 m_previous = m_current;
00055 m_current = 0.0;
00056 }
00057
00058 void Vamos_World::
00059 Times::reset ()
00060 {
00061 m_current = 0.0;
00062 }
00063
00064
00065 Vamos_World::
00066 Timing_Info::Timing_Info () :
00067 m_sector (-1),
00068 m_previous_sector (-1),
00069 m_distance (0.0)
00070 {
00071 }
00072
00073 void Vamos_World::
00074 Timing_Info::update_sector_info (int sector)
00075 {
00076 if (sector == int (ma_sector_times.size ()))
00077 {
00078 ma_sector_times.push_back (Times ());
00079 }
00080
00081 if ((sector != m_sector) && (sector != -1))
00082 {
00083 if (m_sector != -1)
00084 {
00085 ma_sector_times [m_sector].finalize ();
00086
00087 if (sector == 0)
00088 {
00089 m_lap_times.finalize ();
00090 }
00091 }
00092 m_previous_sector = m_sector;
00093 m_sector = sector;
00094 }
00095 }
00096
00097 void Vamos_World::
00098 Timing_Info::update_times (int sector, double time_step)
00099 {
00100 m_lap_times.update (time_step);
00101 if (sector != -1)
00102 {
00103 ma_sector_times [sector].update (time_step);
00104 }
00105 }
00106
00107 void Vamos_World::
00108 Timing_Info::update (double time_step, double distance, int sector)
00109 {
00110 update_sector_info (sector);
00111 update_times (sector, time_step);
00112 m_distance = distance;
00113 }
00114
00115 void Vamos_World::
00116 Timing_Info::reset ()
00117 {
00118 m_lap_times.reset ();
00119 ma_sector_times [m_sector].reset ();
00120
00121 m_sector = -1;
00122 m_previous_sector = -1;
00123 m_distance = 0.0;
00124 }
00125
00126
00127 void Vamos_World::
00128 Car_Information::reset ()
00129 {
00130 timing.reset ();
00131 segment_index = 0;
00132 car->reset ();
00133 }
00134
00135
00136 Vamos_World::
00137 World::World (TRACK * track)
00138 : m_focused_car_index (0),
00139 p_track (track),
00140 m_gravity (-9.8)
00141 {
00142 }
00143
00144 extern bool verbose_output;
00145
00146 Vamos_World::
00147 World::~World ()
00148 {
00149 if (verbose_output)
00150 std::cout << "world deinit" << std::endl;
00151 for (std::vector <Car_Information>::iterator it = m_cars.begin ();
00152 it != m_cars.end ();
00153 it++)
00154 {
00155 delete it->car;
00156 }
00157
00158
00159
00160 if (verbose_output)
00161 std::cout << "world deinit done" << std::endl;
00162 }
00163
00164 extern float FrameTime();
00165
00166 void Vamos_World::
00167 World::interact (Vamos_Body::Car* car, size_t segment_index)
00168 {
00169 bool verbose = false;
00170
00171 Vamos_Geometry::Material * tmatroad = new Vamos_Geometry::Material(
00172 Vamos_Geometry::Material::ASPHALT, 1.0, 1.0,
00173 1.0, 0.0,
00174 0.0, 0.0,
00175 0);
00176 Vamos_Geometry::Material * tmatwall = new Vamos_Geometry::Material(
00177 Vamos_Geometry::Material::CONCRETE, 1.0, -0.8,
00178 1.0, 0.0,
00179 0.0, 0.0,
00180 0);
00181 Vamos_Geometry::Material_Handle material = tmatroad;
00182 Vamos_Geometry::Material_Handle materialwall = tmatwall;
00183
00184 size_t i;
00185
00186
00187 int loopcount = 0;
00188 bool col = true;
00189 const int maxloops = 4;
00190 while (col && loopcount < maxloops)
00191 {
00192 loopcount++;
00193 col = false;
00194
00195 QUATERNION rot;
00196 double angle;
00197 Three_Vector aa = car->chassis().axis_angle(&angle);
00198
00199
00200
00201 rot.SetAxisAngle(angle*(3.141593/180), aa[0], aa[2], -aa[1]);
00202
00203
00204 Three_Vector chassispos = car->chassis().position();
00205 VERTEX cp;
00206 cp.Set(chassispos[0],chassispos[2],-chassispos[1]);
00207
00208 VERTEX cmv;
00209 Vamos_Geometry::Three_Vector cm = car->chassis().center_of_mass();
00210 cmv.Set(cm[0], cm[2], -cm[1]);
00211
00212
00213 JOEMODEL * mod = car->GetCollisionModel();
00214 if (mod != NULL)
00215 {
00216 unsigned int nfaces = mod->GetFaces();
00217
00218
00219 float maxv[3];
00220 float minv[3];
00221 bool havevals[6];
00222 int n = 0;
00223 for (n = 0; n < 6; n++)
00224 havevals[n] = false;
00225
00226 unsigned int f;
00227 unsigned int v;
00228 VERTEX modelfaces[nfaces*3];
00229 for (f = 0; f < nfaces; f++)
00230 {
00231 for (v = 0; v < 3; v++)
00232 {
00233
00234 modelfaces[f*3+v].Set(mod->GetVert(mod->GetFace(f)[v]));
00235
00236 modelfaces[f*3+v] = cp + rot.RotateVec(cmv.ScaleR(-1.0)) +
00237 rot.RotateVec(modelfaces[f*3+v]);
00238
00239
00240 modelfaces[f*3+v].z = -modelfaces[f*3+v].z;
00241
00242
00243 for (n = 0; n < 3; n++)
00244 {
00245 if (modelfaces[f*3+v].v3()[n] > maxv[n] || !havevals[n])
00246 {
00247 maxv[n] = modelfaces[f*3+v].v3()[n];
00248 havevals[n] = true;
00249 }
00250 if (modelfaces[f*3+v].v3()[n] < minv[n] || !havevals[n+3])
00251 {
00252 minv[n] = modelfaces[f*3+v].v3()[n];
00253 havevals[n+3] = true;
00254 }
00255 }
00256 }
00257 }
00258
00259
00260 AABB modelbbox;
00261 VERTEX minvals, maxvals;
00262 minvals.Set(minv);
00263 maxvals.Set(maxv);
00264 modelbbox.SetFromCorners(minvals, maxvals);
00265
00266 VERTEX normal, colpt;
00267 float depth;
00268
00269 col = p_track->CollideModel(modelfaces, nfaces, modelbbox, colpt, false, normal, depth);
00270
00271 if (verbose && col)
00272 {
00273 float miny = 10000;
00274 for (f = 0; f < nfaces; f++)
00275 {
00276 for (v = 0; v < 3; v++)
00277 {
00278 if (modelfaces[f*3+v].y < miny)
00279 miny = modelfaces[f*3+v].y;
00280 }
00281 }
00282
00283 cout << "Loop " << loopcount << endl;
00284 colpt.DebugPrint();
00285 cout << miny << endl;
00286 normal.DebugPrint();
00287 cout << "depth: " << depth << endl << endl;
00288 }
00289
00290 if (col && !colpt.nan() && !normal.nan() && (depth >= 0 || depth < 0))
00291 {
00292 Three_Vector colpos;
00293 Three_Vector norm;
00294
00295
00296
00297
00298 norm.m_vec[0] = normal.x;
00299 norm.m_vec[1] = -normal.z;
00300 norm.m_vec[2] = normal.y;
00301
00302 colpos.m_vec[0] = colpt.x;
00303 colpos.m_vec[1] = -colpt.z;
00304 colpos.m_vec[2] = colpt.y;
00305
00306 car->chassis().single_point_contact(colpos, depth+0.001, norm, materialwall, FrameTime());
00307 }
00308 }
00309 }
00310
00311
00312 i = 0;
00313 int wheelcount = 0;
00314 for (i = 0; i < 4; i++)
00315 car->SetColPatch(i, NULL);
00316 for (std::vector <Vamos_Body::Particle*>::iterator
00317 it = car->chassis ().particles ().begin ();
00318 it != car->chassis ().particles ().end ();
00319 it++, i++)
00320 {
00321 if (!(*it)->single_contact ())
00322 {
00323 const Three_Vector& pos = car->chassis ().contact_position (*it);
00324
00325
00326
00327 VERTEX particlepos;
00328 particlepos.Set(pos.m_vec[0],pos.m_vec[2],-pos.m_vec[1]);
00329
00330 bool con = false;
00331 Three_Vector norm;
00332 double depth = 0;
00333 VERTEX normal;
00334 VERTEX origin = particlepos;
00335 origin.y += 0.5;
00336 BEZIER * tcolpatch = NULL;
00337 OBJECTNODE * tcolnode = NULL;
00338 depth = p_track->ElevationSeg(origin, normal, 10.0, tcolpatch, tcolnode) - particlepos.y;
00339
00340 car->SetColPatch(wheelcount, tcolpatch);
00341
00342
00343 float f1 = 1.0;
00344 float f2 = 1.0;
00345 float rr = 1.0;
00346 float rd = 0.0;
00347 if (tcolpatch != NULL)
00348 {
00349 p_track->GetFrictionParams(f1, f2);
00350 }
00351 else if (tcolnode != NULL)
00352 {
00353 f1 = tcolnode->friction1;
00354 f2 = tcolnode->friction2;
00355
00356
00357
00358 float posx = origin.x;
00359 float posz = origin.z;
00360 float phase = 2*3.141593*(posx+posz) / tcolnode->bumplength;
00361 float shift = 2.0*sin(phase*1.414214);
00362 float amplitude = 0.25*tcolnode->bumpmag;
00363 float bumpoffset = amplitude * (sin (phase + shift) + sin (1.414214*phase) - 2.0);
00364 depth += bumpoffset;
00365
00366 rr = tcolnode->rolling_resistance_factor;
00367 rd = tcolnode->rolling_drag;
00368 }
00369 car->SetColParams(wheelcount, f1, f2, rr, rd);
00370
00371 wheelcount++;
00372
00373
00374
00375 if (depth < 0 || depth >= 0)
00376 {
00377
00378
00379 if (depth > 0)
00380 con = true;
00381 norm.m_vec[0] = normal.x;
00382 norm.m_vec[1] = -normal.z;
00383 norm.m_vec[2] = normal.y;
00384 if (con)
00385 {
00386 if (depth > 1.0)
00387 {
00388 cout << "Large suspension displacement detected: " << depth << endl;
00389 }
00390
00391
00392
00393
00394
00395 car->chassis ().contact (*it, depth,
00396 norm, material);
00397
00398 }
00399 }
00400 else
00401 cout << "Not contacting with NaN surface" << endl;
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 i = 0;
00525 for (std::vector <Vamos_Body::Particle*>::iterator
00526 it = car->chassis ().particles ().begin ();
00527 it != car->chassis ().particles ().end ();
00528 it++, i++)
00529 {
00530 car->chassis ().wind (*it, Three_Vector(0,0,0)
00531 - car->chassis ().velocity (*it),
00532 1.2);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 }
00633
00634 void Vamos_World::
00635 World::collide (Vamos_Body::Car* car1, Vamos_Body::Car* car2)
00636 {
00637
00638
00639 for (std::vector <Vamos_Body::Particle*>::iterator
00640 it = car1->chassis ().particles ().begin ();
00641 it != car1->chassis ().particles ().end ();
00642 it++)
00643 {
00644 if (car2->collision (car1->chassis ().transform_out ((*it)->position ())))
00645 {
00646 std::cout << "boom" << std::endl;
00647 }
00648 }
00649 }
00650 void Vamos_World::
00651 World::reset ()
00652 {
00653 reset(false);
00654 }
00655
00656
00657 void Vamos_World::
00658 World::reset (bool all)
00659 {
00660
00661 {
00662 for (std::vector <Vamos_World::Car_Information>::iterator carit = m_cars.begin ();
00663 carit != m_cars.end ();
00664 carit++)
00665 reset(&(*carit));
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 }
00778
00779 void Vamos_World::
00780 World::reset (Car_Information * cartoreset)
00781 {
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 VERTEX vpos = p_track->GetStart();
00792 Three_Vector position(vpos.x, -vpos.z, vpos.y);
00793
00794 QUATERNION qstart;
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 double o3x3[3][3];
00807 float orient[16];
00808
00809 qstart = p_track->GetStartOrientation();
00810 QUATERNION qtemp = qstart;
00811 qstart.x = qtemp.x;
00812 qstart.y = qtemp.z;
00813 qstart.z = -qtemp.y;
00814
00815 qstart.Rotate(-3.141593/2.0, 0,0,1);
00816
00817 qstart.GetMat(orient);
00818 bool flip = false;
00819 for (int i = 0; i < 3; i++)
00820 {
00821 if (flip)
00822 o3x3[i][0] = orient[i+0];
00823 else
00824 o3x3[0][i] = orient[i+0];
00825 }
00826 for (int i = 0; i < 3; i++)
00827 {
00828 if (flip)
00829 o3x3[i][1] = orient[i+4];
00830 else
00831 o3x3[1][i] = orient[i+4];
00832 }
00833 for (int i = 0; i < 3; i++)
00834 {
00835 if (flip)
00836 o3x3[i][2] = orient[i+8];
00837 else
00838 o3x3[2][i] = orient[i+8];
00839 }
00840
00841
00842 Three_Matrix orientation(o3x3);
00843
00844 cartoreset->car->reset (position, orientation);
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 VERTEX cp;
00858
00859 double elevation;
00860
00861
00862
00863 bool have_max = false;
00864 double max_diff = 0.0;
00865
00866
00867
00868 for (std::vector <Vamos_Body::Particle*>::iterator it =
00869 cartoreset->car->chassis ().particles ().begin ();
00870 it != cartoreset->car->chassis ().particles ().end ();
00871 it++)
00872 {
00873 Three_Vector pos =
00874 cartoreset->car->chassis ().contact_position (*it);
00875
00876
00877
00878
00879 cp.Set(pos.m_vec[0], pos.m_vec[2], -pos.m_vec[1]);
00880 elevation = p_track->Elevation (cp);
00881
00882 double diff = elevation - pos [2];
00883
00884 if (diff > max_diff || !have_max)
00885 {
00886 max_diff = diff;
00887 have_max = true;
00888 }
00889
00890
00891 }
00892
00893
00894 cartoreset->car->reset (position + Three_Vector (0.0, 0.0, max_diff+0.0), orientation);
00895
00896
00897 }
00898
00899
00900 void Vamos_World::
00901 World::restart ()
00902 {
00903 focused_car ()->reset ();
00904 }
00905
00906
00907
00908 void Vamos_World::
00909 World::gravity (double g)
00910 {
00911 m_gravity = -std::abs (g);
00912 if (focused_car () != 0)
00913 {
00914 focused_car ()->car->chassis ().
00915 gravity (Three_Vector (0.0, 0.0, m_gravity));
00916 }
00917 }
00918
00919 void Vamos_World::
00920 World::add_car (Vamos_Body::Car* car)
00921 {
00922 car->chassis ().gravity (Three_Vector (0.0, 0.0, m_gravity));
00923 m_cars.push_back (Car_Information (car));
00924 }
00925
00926 void Vamos_World::
00927 World::set_focused_car (size_t index)
00928 {
00929 assert (index < m_cars.size ());
00930 m_focused_car_index = index;
00931 }
00932
00933 void Vamos_World::
00934 World::focus_other_car (int delta)
00935 {
00936 set_focused_car ((m_focused_car_index + delta) % m_cars.size ());
00937 }
00938
00939 Vamos_World::Car_Information* Vamos_World::
00940 World::focused_car ()
00941 {
00942 if (m_focused_car_index >= m_cars.size ()) return 0;
00943 return &m_cars [m_focused_car_index];
00944 }