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 #include "track.h"
00026
00027 ROADSTRIP::ROADSTRIP()
00028 {
00029 patchnodes = NULL;
00030 }
00031
00032 void ROADSTRIP::ClearPatches()
00033 {
00034 coltree.DeleteChildren();
00035 coltree.leaves.clear();
00036
00037 while (patchnodes != NULL)
00038 {
00039 BEZIERNODE * oldfirst = patchnodes;
00040 patchnodes = patchnodes->next;
00041 delete oldfirst;
00042 }
00043 }
00044
00045 BEZIER * ROADSTRIP::Add(BEZIER newpatch)
00046 {
00047 BEZIERNODE * lastnode = NULL;
00048 BEZIERNODE * curnode = patchnodes;
00049
00050 while (curnode != NULL)
00051 {
00052 lastnode = curnode;
00053 curnode = curnode->next;
00054 }
00055
00056
00057 if (lastnode != NULL && lastnode->next == NULL)
00058 {
00059 lastnode->next = new BEZIERNODE;
00060 lastnode->next->patch.CopyFrom(newpatch);
00061
00062
00063 lastnode->patch.Attach(lastnode->next->patch);
00064 return &(lastnode->next->patch);
00065 }
00066
00067 if (patchnodes == NULL)
00068 {
00069 patchnodes = new BEZIERNODE;
00070 patchnodes->patch.CopyFrom(newpatch);
00071 return &(patchnodes->patch);
00072 }
00073
00074 return NULL;
00075 }
00076
00077 BEZIER * ROADSTRIP::AddNew()
00078 {
00079 BEZIER newpatch;
00080 return Add(newpatch);
00081 }
00082
00083 bool ROADSTRIP::ReadFrom(ifstream &openfile)
00084 {
00085
00086 ClearPatches();
00087
00088 lastcolpatch = NULL;
00089
00090 if (!openfile)
00091 return false;
00092
00093 BEZIER * newpatch = NULL;
00094 BEZIER temppatch;
00095
00096 int num;
00097
00098
00099 openfile >> num;
00100
00101 int i;
00102
00103 for (i = 0; i < num; i++)
00104 {
00105
00106 if (!temppatch.ReadFrom(openfile))
00107 return false;
00108 newpatch = Add(temppatch);
00109 }
00110
00111 if (num > 2 && newpatch != NULL)
00112 {
00113
00114 if (newpatch->points[0][0].equals(patchnodes->patch.points[3][0]) && newpatch->points[0][3].equals(patchnodes->patch.points[3][3]))
00115 {
00116 newpatch->Attach(patchnodes->patch);
00117 }
00118 }
00119
00120 GenerateCollisionTree();
00121
00122 return true;
00123 }
00124
00125 bool ROADSTRIP::WriteTo(ofstream &openfile)
00126 {
00127 BEZIERNODE * curnode = patchnodes;
00128
00129 openfile << NumPatches() << endl << endl;
00130
00131 while (curnode != NULL)
00132 {
00133 curnode->patch.WriteTo(openfile);
00134 openfile << endl;
00135
00136 curnode = curnode->next;
00137 }
00138
00139 return true;
00140 }
00141
00142 int ROADSTRIP::NumPatches()
00143 {
00144 BEZIERNODE * curnode = patchnodes;
00145
00146 int num = 0;
00147
00148 while (curnode != NULL)
00149 {
00150 num++;
00151
00152 curnode = curnode->next;
00153 }
00154
00155 return num;
00156 }
00157
00158 bool ROADSTRIP::DeleteLastPatch()
00159 {
00160 BEZIERNODE * lastnode = NULL;
00161 BEZIERNODE * prevlastnode = NULL;
00162 BEZIERNODE * curnode = patchnodes;
00163
00164 while (curnode != NULL)
00165 {
00166 prevlastnode = lastnode;
00167 lastnode = curnode;
00168 curnode = curnode->next;
00169 }
00170
00171
00172 if (lastnode != NULL && lastnode->next == NULL)
00173 {
00174 if (prevlastnode != NULL)
00175 {
00176 delete prevlastnode->next;
00177 prevlastnode->next = NULL;
00178 return true;
00179 }
00180 else
00181 {
00182 delete patchnodes;
00183 patchnodes = NULL;
00184 return true;
00185 }
00186 }
00187
00188 return false;
00189 }
00190
00191 BEZIER * ROADSTRIP::GetLastPatch()
00192 {
00193 BEZIERNODE * lastnode = NULL;
00194 BEZIERNODE * prevlastnode = NULL;
00195 BEZIERNODE * curnode = patchnodes;
00196
00197 while (curnode != NULL)
00198 {
00199 prevlastnode = lastnode;
00200 lastnode = curnode;
00201 curnode = curnode->next;
00202 }
00203
00204
00205 if (lastnode != NULL && lastnode->next == NULL)
00206 {
00207 if (prevlastnode != NULL)
00208 {
00209 return &(prevlastnode->next->patch);
00210 }
00211 else
00212 {
00213 return &(patchnodes->patch);
00214 }
00215 }
00216
00217 return NULL;
00218 }
00219
00220 void ROADSTRIP::Visualize (bool wireframe, bool fill, VERTEX color)
00221 {
00222
00223
00224 BEZIERNODE * curnode = patchnodes;
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 int count = 0;
00236 int drawn = 0;
00237
00238 while (curnode != NULL)
00239 {
00240
00241 bool drawme = true;
00242
00243 VERTEX & pos = curnode->patch.center;
00244 for (int i=0;i<6;i++)
00245 {
00246 float rd=cam.frustum[i][0]*pos.x+
00247 cam.frustum[i][1]*pos.y+
00248 cam.frustum[i][2]*pos.z+
00249 cam.frustum[i][3];
00250 if (rd<=-curnode->patch.radius)
00251 {
00252 drawme = false;
00253 }
00254 }
00255
00256 if (drawme)
00257 {
00258 curnode->patch.Visualize(wireframe, fill, color);
00259 drawn++;
00260 }
00261
00262 curnode = curnode->next;
00263 count++;
00264 }
00265
00266
00267 }
00268
00269 bool ROADSTRIP::Collide(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest)
00270 {
00271 BEZIER * cp;
00272 VERTEX normal;
00273 return Collide(origin, direction, outtri, closest, cp, normal);
00274 }
00275
00276 bool ROADSTRIP::CollideBruteForce(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, BEZIER * & colpatch)
00277 {
00278 BEZIERNODE * curnode = patchnodes;
00279 BEZIERNODE * lastnode = patchnodes;
00280
00281 bool collide;
00282 bool hadcollision = false;
00283 VERTEX tvert;
00284 VERTEX tnorm;
00285
00286 int count = 0;
00287
00288 while (curnode != NULL)
00289 {
00290
00291
00292
00293 collide = curnode->patch.BEZIER_COLLIDE_FUNCTION(origin, direction, tvert, tnorm);
00294 if (collide && !closest)
00295 {
00296 outtri = tvert;
00297 colpatch = &(curnode->patch);
00298
00299
00300
00301
00302 lastnode->next = curnode->next;
00303 if (lastnode != curnode)
00304 curnode->next = patchnodes;
00305 patchnodes = curnode;
00306
00307 return true;
00308 }
00309 else if (collide && closest)
00310 {
00311 if ((hadcollision && (origin - tvert).len() < (origin - outtri).len()) || !hadcollision)
00312 {
00313 outtri = tvert;
00314 colpatch = &(curnode->patch);
00315 }
00316
00317 hadcollision = true;
00318 }
00319
00320 count++;
00321
00322 lastnode = curnode;
00323 curnode = curnode->next;
00324 }
00325
00326 if (closest && hadcollision)
00327 {
00328 return true;
00329 }
00330
00331 return false;
00332 }
00333
00334 bool ROADSTRIP::Collide(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, BEZIER * & colpatch, VERTEX & normal)
00335 {
00336 bool col = false;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 col = CollideBranch(origin, direction, outtri, closest, colpatch, &coltree, normal);
00350
00351 if (col)
00352 lastcolpatch = colpatch;
00353
00354 return col;
00355 }
00356
00357 bool ROADSTRIP::CollideBranch(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, BEZIER * & colpatch, BEZIERCOLBRANCH * branch, VERTEX & normal)
00358 {
00359 if (branch == NULL)
00360 return false;
00361
00362 bool verbose = false;
00363
00364 if (verbose)
00365 {
00366 if (branch->left != NULL && branch->right != NULL)
00367 {
00368 cout << "Parent" << endl;
00369 }
00370 else
00371 cout << "Leaf" << endl;
00372 }
00373
00374
00375 if (branch->left == NULL && branch->right == NULL)
00376 {
00377 bool collide;
00378 bool hadcollision = false;
00379 VERTEX tvert;
00380 VERTEX tnorm;
00381
00382 int count = 0;
00383
00384 list <BEZIERNODE *>::iterator i1 = branch->leaves.begin();
00385
00386 for (i1 = branch->leaves.begin(); i1 != branch->leaves.end(); i1++)
00387 {
00388
00389
00390
00391 collide = (*i1)->patch.BEZIER_COLLIDE_FUNCTION(origin, direction, tvert, tnorm);
00392 if (collide && !closest)
00393 {
00394 normal = tnorm;
00395 outtri = tvert;
00396 colpatch = &((*i1)->patch);
00397
00398
00399
00400
00401
00402
00403
00404 return true;
00405 }
00406 else if (collide && closest)
00407 {
00408 if ((hadcollision && (origin - tvert).len() < (origin - outtri).len()) || !hadcollision)
00409 {
00410 normal = tnorm;
00411 outtri = tvert;
00412 colpatch = &((*i1)->patch);
00413 }
00414
00415 hadcollision = true;
00416 }
00417
00418 count++;
00419 }
00420
00421 if (closest && hadcollision)
00422 {
00423 return true;
00424 }
00425
00426 return false;
00427 }
00428
00429 if (verbose)
00430 {
00431 origin.DebugPrint();
00432 branch->bbox.DebugPrint();
00433 }
00434
00435
00436 if (!branch->bbox.IntersectRay(origin, direction))
00437 return false;
00438
00439 if (verbose)
00440 cout << "BBOX collision" << endl;
00441
00442 bool rcol = false;
00443 bool lcol = false;
00444
00445 BEZIER * r_colpatch, * l_colpatch;
00446 VERTEX r_outtri, l_outtri;
00447
00448 if (right != NULL)
00449 rcol = CollideBranch(origin, direction, r_outtri, closest, r_colpatch, branch->right, normal);
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 if (left != NULL)
00460 lcol = CollideBranch(origin, direction, l_outtri, closest, l_colpatch, branch->left, normal);
00461
00462
00463 if (lcol && !rcol)
00464 {
00465 outtri = l_outtri;
00466 colpatch = l_colpatch;
00467 return lcol;
00468 }
00469
00470
00471 if (rcol && !lcol)
00472 {
00473 outtri = r_outtri;
00474 colpatch = r_colpatch;
00475 return rcol;
00476 }
00477
00478
00479 if (lcol && rcol)
00480 {
00481 if ((origin - r_outtri).len() < (origin - l_outtri).len())
00482 {
00483 outtri = r_outtri;
00484 colpatch = r_colpatch;
00485 return rcol;
00486 }
00487 else
00488 {
00489 outtri = l_outtri;
00490 colpatch = l_colpatch;
00491 return lcol;
00492 }
00493 }
00494
00495 return false;
00496 }
00497
00498 void ROADSTRIP::GenerateCollisionTree()
00499 {
00500 bool verbose = false;
00501
00502 BEZIERNODE * curnode = patchnodes;
00503
00504 if (verbose)
00505 cout << "Generating collision tree..." << endl;
00506
00507 coltree.DeleteChildren();
00508
00509 coltree.left = NULL;
00510 coltree.right = NULL;
00511
00512 coltree.leaves.clear();
00513
00514 while (curnode != NULL)
00515 {
00516 coltree.leaves.push_back(curnode);
00517
00518 curnode = curnode->next;
00519 }
00520
00521 GenerateBranches(&coltree);
00522
00523 if (verbose)
00524 cout << "done" << endl;
00525 }
00526
00527 void ROADSTRIP::GenerateBranches(BEZIERCOLBRANCH * branch)
00528 {
00529 bool verbose = false;
00530
00531 list <BEZIERNODE *>::iterator i1 = branch->leaves.begin();
00532
00533
00534 VERTEX avgcenter;
00535 float maxv[3];
00536 float minv[3];
00537 bool havevals[6];
00538 int n = 0;
00539 for (n = 0; n < 3; n++)
00540 {
00541 minv[n] = 0;
00542 maxv[n] = 0;
00543 }
00544 for (n = 0; n < 6; n++)
00545 havevals[n] = false;
00546
00547
00548
00549 int numleaves = 0;
00550
00551 for (i1 = branch->leaves.begin(); i1 != branch->leaves.end(); i1++)
00552 numleaves++;
00553
00554 i1 = branch->leaves.begin();
00555 while (i1 != branch->leaves.end())
00556 {
00557 VERTEX p[4];
00558 p[0] = (*i1)->patch.points[0][0];
00559 p[1] = (*i1)->patch.points[0][3];
00560 p[2] = (*i1)->patch.points[3][3];
00561 p[3] = (*i1)->patch.points[3][0];
00562
00563 int i, c;
00564 for (c = 0; c < 4; c++)
00565 {
00566 float * v = p[c].v3();
00567 for (i = 0; i < 3; i++)
00568 {
00569 if (v[i] > maxv[i] || !havevals[i])
00570 {
00571 maxv[i] = v[i];
00572 havevals[i] = true;
00573 }
00574 if (v[i] < minv[i] || !havevals[i+3])
00575 {
00576 minv[i] = v[i];
00577 havevals[i+3] = true;
00578 }
00579 }
00580 }
00581
00582 VERTEX pcenter = p[0] + p[1] + p[2] + p[3];
00583 pcenter.Scale(0.25);
00584 avgcenter = avgcenter + pcenter.ScaleR(1.0/numleaves);
00585
00586 i1++;
00587 }
00588
00589 VERTEX minvals, maxvals;
00590 minvals.Set(minv);
00591 maxvals.Set(maxv);
00592 branch->bbox.SetFromCorners(minvals, maxvals);
00593 if (verbose)
00594 {
00595 cout << "Bounding box:" << endl;
00596 branch->bbox.GetPos().DebugPrint();
00597 branch->bbox.GetSize().DebugPrint();
00598 branch->bbox.GetCenter().DebugPrint();
00599 }
00600
00601
00602 VERTEX axismask;
00603 axismask.Set(1,0,0);
00604 if (maxvals.x - minvals.x > maxvals.y - minvals.y && maxvals.x - minvals.x > maxvals.z - minvals.z)
00605 {
00606 axismask.Set(1,0,0);
00607 }
00608 else if (maxvals.y - minvals.y > maxvals.x - minvals.x && maxvals.y - minvals.y > maxvals.z - minvals.z)
00609 {
00610 axismask.Set(0,1,0);
00611 }
00612 else if (maxvals.z - minvals.z > maxvals.y - minvals.y && maxvals.z - minvals.z > maxvals.x - minvals.x)
00613 {
00614 axismask.Set(0,0,1);
00615 }
00616
00617 int ll = 0;
00618 int lr = 0;
00619
00620
00621 if (numleaves > LEAVES_PER_BBOX)
00622 {
00623
00624 branch->left = new BEZIERCOLBRANCH;
00625 branch->right = new BEZIERCOLBRANCH;
00626
00627 int distributor = 0;
00628
00629
00630 for (i1 = branch->leaves.begin(); i1 != branch->leaves.end(); i1++)
00631 {
00632 VERTEX p[4];
00633 p[0] = (*i1)->patch.points[0][0];
00634 p[1] = (*i1)->patch.points[0][3];
00635 p[2] = (*i1)->patch.points[3][3];
00636 p[3] = (*i1)->patch.points[3][0];
00637
00638 VERTEX pcenter = p[0] + p[1] + p[2] + p[3];
00639 pcenter.Scale(0.25);
00640
00641 if (pcenter.dot(axismask) - avgcenter.dot(axismask) > 0.0)
00642 branch->right->leaves.push_back(*i1);
00643 else if (pcenter.dot(axismask) - avgcenter.dot(axismask) < 0.0)
00644 branch->left->leaves.push_back(*i1);
00645 else
00646 {
00647
00648 if (distributor % 2 == 0)
00649 branch->right->leaves.push_back(*i1);
00650 else
00651 branch->left->leaves.push_back(*i1);
00652
00653 distributor++;
00654 }
00655 }
00656
00657
00658 branch->leaves.clear();
00659
00660
00661 for (i1 = branch->left->leaves.begin(); i1 != branch->left->leaves.end(); i1++)
00662 ll++;
00663 for (i1 = branch->right->leaves.begin(); i1 != branch->right->leaves.end(); i1++)
00664 lr++;
00665
00666 if (verbose) cout << "Parent Leaves: " << numleaves << " L: " << ll << " R: " << lr << endl;
00667
00668 if (ll == 0 || lr == 0)
00669 {
00670 if (lr != 0)
00671 {
00672 for (i1 = branch->right->leaves.begin(); i1 != branch->right->leaves.end(); i1++)
00673 branch->leaves.push_back(*i1);
00674 branch->right->leaves.clear();
00675 }
00676
00677 if (ll != 0)
00678 {
00679 for (i1 = branch->left->leaves.begin(); i1 != branch->left->leaves.end(); i1++)
00680 branch->leaves.push_back(*i1);
00681 branch->left->leaves.clear();
00682 }
00683
00684 delete branch->left;
00685 branch->left = NULL;
00686
00687 delete branch->right;
00688 branch->right = NULL;
00689 }
00690 else
00691 {
00692 GenerateBranches(branch->left);
00693 GenerateBranches(branch->right);
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 }
00710 else
00711 {
00712 branch->right = NULL;
00713 branch->left = NULL;
00714
00715 if (verbose) cout << "(Leaf)" << endl;
00716 }
00717 }
00718
00719
00720
00721
00722
00723 TRACK::TRACK()
00724 {
00725 roads = NULL;
00726 lastelev = -100;
00727 }
00728
00729 TRACK::~TRACK()
00730 {
00731 ClearRoads();
00732 }
00733
00734 void TRACK::ClearRoads()
00735 {
00736 while (roads != NULL)
00737 {
00738 ROADSTRIPNODE * oldfirst = roads;
00739 roads = roads->next;
00740 delete oldfirst;
00741 }
00742 }
00743
00744 ROADSTRIP * TRACK::AddNewRoad()
00745 {
00746
00747
00748
00749
00750
00751
00752 ROADSTRIPNODE * lastnode = NULL;
00753 ROADSTRIPNODE * curnode = roads;
00754
00755 while (curnode != NULL)
00756 {
00757 lastnode = curnode;
00758 curnode = curnode->next;
00759 }
00760
00761
00762 if (lastnode != NULL && lastnode->next == NULL)
00763 {
00764 lastnode->next = new ROADSTRIPNODE;
00765
00766
00767
00768
00769 return &(lastnode->next->road);
00770 }
00771
00772 if (roads == NULL)
00773 {
00774 roads = new ROADSTRIPNODE;
00775 return &(roads->road);
00776 }
00777
00778 return NULL;
00779 }
00780
00781 void TRACK::VisualizeRoads(bool wireframe, bool fill, ROADSTRIP * selectedroad)
00782 {
00783 ROADSTRIPNODE * curnode = roads;
00784
00785 VERTEX color;
00786 color.zero();
00787 color.z = 1;
00788
00789
00790
00791 while (curnode != NULL)
00792 {
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815 color.zero();
00816 if (&(curnode->road) == selectedroad)
00817 color.y = 1;
00818 else
00819 {
00820 color.y = 0.5;
00821 color.z = 0.5;
00822 }
00823
00824 curnode->road.Visualize(wireframe, fill, color);
00825 curnode = curnode->next;
00826 }
00827 }
00828
00829 void TRACK::Write(string trackname)
00830 {
00831 ofstream trackfile;
00832 trackfile.open((settings.GetDataDir() + "/tracks/" + trackname + "/roads.trk").c_str());
00833
00834 VERTEX sl = GetStart();
00835 trackfile << sl.x << " " << sl.y << " " << sl.z << endl << endl;
00836
00837 trackfile << NumRoads() << endl << endl;
00838
00839 ROADSTRIPNODE * curnode = roads;
00840
00841 while (curnode != NULL && trackfile)
00842 {
00843 curnode->road.WriteTo(trackfile);
00844 curnode = curnode->next;
00845 }
00846 }
00847
00848 int TRACK::NumRoads()
00849 {
00850 ROADSTRIPNODE * curnode = roads;
00851
00852 int num = 0;
00853
00854 while (curnode != NULL)
00855 {
00856 num++;
00857 curnode = curnode->next;
00858 }
00859
00860 return num;
00861 }
00862
00863 void TRACK::Load(string trackname)
00864 {
00865 ifstream trackfile;
00866 trackfile.open((settings.GetDataDir() + "/tracks/" + trackname + "/roads.trk").c_str());
00867
00868 CONFIGFILE trackconfig;
00869 trackconfig.Load((settings.GetDataDir() + "/tracks/" + trackname + "/track.txt").c_str());
00870 float tvert[3];
00871 VERTEX sl;
00872 trackconfig.GetParam("start position", tvert);
00873 string strcullfaces;
00874 trackconfig.GetParam("cull faces", strcullfaces);
00875 sl.Set(tvert);
00876
00877 if (strcullfaces == "no")
00878 cullfaces = false;
00879 else
00880 cullfaces = true;
00881
00882 int numroads, i;
00883
00884
00885
00886
00887
00888 SetStart(sl);
00889
00890 VERTEX sov;
00891 trackconfig.GetParam("start orientation-xyz", tvert);
00892 sov.Set(tvert);
00893 QUATERNION so;
00894 so.x = sov.x;
00895 so.y = sov.y;
00896 so.z = sov.z;
00897 trackconfig.GetParam("start orientation-w", so.w);
00898 SetStartOrientation(so);
00899
00900 if (trackfile)
00901 {
00902 trackfile >> numroads;
00903 }
00904 else
00905 {
00906 cout << "No track named " << trackname << ", creating a new one." << endl;
00907 return;
00908 }
00909
00910 ClearRoads();
00911
00912 ROADSTRIP * newroad;
00913
00914 for (i = 0; i < numroads && trackfile; i++)
00915 {
00916 newroad = AddNewRoad();
00917 newroad->ReadFrom(trackfile);
00918 }
00919
00920 lapsequence.clear();
00921 int lapmarkers;
00922 if (trackconfig.GetParam("lap sequences", lapmarkers))
00923 {
00924 for (int l = 0; l < lapmarkers; l++)
00925 {
00926 float lapraw[3];
00927 stringstream lapname;
00928 lapname << "lap sequence " << l;
00929 trackconfig.GetParam(lapname.str(), lapraw);
00930 lapsequence.push_back(GetBezier((int) lapraw[0], (int) lapraw[1]));
00931 }
00932 }
00933
00934 float f;
00935 trackconfig.GetParam("non-treaded friction coefficient", f);
00936 friction1 = f;
00937 trackconfig.GetParam("treaded friction coefficient", f);
00938 friction2 = f;
00939 }
00940
00941 void TRACK::Delete(ROADSTRIP * striptodel)
00942 {
00943 bool deleted = false;
00944
00945 ROADSTRIPNODE * lastnode = NULL;
00946 ROADSTRIPNODE * curnode = roads;
00947
00948 while (curnode != NULL)
00949 {
00950
00951
00952
00953
00954
00955 if (striptodel == &(curnode->road))
00956 {
00957 curnode = curnode->next;
00958
00959 if (lastnode == NULL)
00960 {
00961 roads = curnode;
00962 }
00963 else
00964 {
00965 lastnode->next = curnode;
00966 }
00967
00968 delete striptodel;
00969
00970 deleted = true;
00971 }
00972 else
00973 {
00974 lastnode = curnode;
00975 curnode = curnode->next;
00976 }
00977 }
00978
00979
00980 if (!deleted)
00981 delete striptodel;
00982
00983 striptodel = NULL;
00984 }
00985
00986 bool TRACK::CollideRoads(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, ROADSTRIP * &collideroad, BEZIER * & collidepatch, VERTEX & normal)
00987 {
00988 ROADSTRIPNODE * curnode = roads;
00989
00990 bool collide;
00991 bool hadcollision = false;
00992 VERTEX tvert;
00993 VERTEX tnorm;
00994
00995 while (curnode != NULL)
00996 {
00997
00998 collide = curnode->road.Collide(origin, direction, tvert, closest, collidepatch, tnorm);
00999 if (collide && !closest)
01000 {
01001 outtri = tvert;
01002 collideroad = &(curnode->road);
01003 normal = tnorm;
01004 return true;
01005 }
01006 else if (collide && closest)
01007 {
01008 if ((hadcollision && (origin - tvert).len() < (origin - outtri).len()) || !hadcollision)
01009 {
01010 normal = tnorm;
01011 outtri = tvert;
01012 collideroad = &(curnode->road);
01013 }
01014
01015 hadcollision = true;
01016 }
01017
01018 curnode = curnode->next;
01019 }
01020
01021 if (closest && hadcollision)
01022 {
01023 return true;
01024 }
01025
01026 outtri = origin;
01027 return false;
01028 }
01029
01030 bool TRACK::Collide(VERTEX origin, VERTEX direction, float seglen, VERTEX &outtri, bool closest, VERTEX & normal, float & dist)
01031 {
01032 bool verbose = false;
01033
01034 bool col = false;
01035
01036 dist = 0;
01037
01038 VERTEX zero;
01039
01040 if (direction.equals(zero))
01041 return false;
01042
01043 direction = direction.normalize();
01044
01045
01046
01047
01048 normal.Set(0,1,0);
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 OBJECTNODE * tnode;
01061 col = objects.Collide(origin, direction, outtri, closest, normal, seglen, tnode);
01062
01063
01064 if (col)
01065 {
01066 dist = (outtri - origin).len();
01067 if (dist > seglen)
01068 return false;
01069 if (verbose)
01070 {
01071 cout << "model collision: " << dist << endl;
01072
01073 outtri.DebugPrint();
01074 cout << endl;
01075 }
01076 }
01077
01078
01079
01080
01081
01082
01083 if (normal.nan())
01084 {
01085 cout << "Detected NaN in normal vector" << endl;
01086 normal.Set(0,1,0);
01087 }
01088
01089 if (outtri.nan())
01090 {
01091 cout << "Detected NaN in collision point" << endl;
01092 outtri = origin;
01093 }
01094
01095 if (!(dist <= 0 || dist > 0))
01096 {
01097 cout << "Detected NaN in collision distance" << endl;
01098 dist = 0;
01099 }
01100
01101 return col;
01102 }
01103
01104 bool TRACK::CollideD(VERTEXD origin, VERTEXD direction, double seglen, VERTEXD &outtri, bool closest, VERTEXD & normal, double & dist)
01105 {
01106 bool verbose = false;
01107
01108 bool col = false;
01109
01110 dist = 0;
01111
01112 if (direction.x == 0 && direction.y == 0 && direction.z == 0)
01113 return false;
01114
01115 direction = direction.normalize();
01116
01117
01118
01119
01120 normal.Set(0,1,0);
01121
01122
01123
01124 col = objects.CollideD(origin, direction, outtri, closest, normal, seglen);
01125
01126
01127 if (col)
01128 {
01129 dist = (outtri - origin).len();
01130
01131
01132
01133
01134
01135
01136 if (verbose)
01137 {
01138 cout << "model collision: " << dist << endl;
01139
01140 outtri.DebugPrint();
01141 cout << endl;
01142 }
01143 }
01144
01145
01146
01147
01148
01149 if (normal.nan())
01150 {
01151 cout << "Detected NaN in normal vector" << endl;
01152 normal.Set(0,1,0);
01153 }
01154
01155 if (outtri.nan())
01156 {
01157 cout << "Detected NaN in collision point" << endl;
01158 outtri = origin;
01159 }
01160
01161 if (!(dist <= 0 || dist > 0))
01162 {
01163 cout << "Detected NaN in collision distance" << endl;
01164 dist = 0;
01165 }
01166
01167 return col;
01168 }
01169
01170 double TRACK::Elevation(VERTEX origin)
01171 {
01172 VERTEX normal;
01173 return Elevation(origin, normal);
01174 }
01175
01176 double TRACK::Elevation(VERTEX origin, VERTEX & normal)
01177 {
01178 origin.y += 1000;
01179 return ElevationSeg(origin, normal, 10000.0f);
01180 }
01181
01182 double TRACK::ElevationSeg(VERTEX origin, VERTEX & normal, float seglen)
01183 {
01184 BEZIER * colpatch;
01185 OBJECTNODE * colnode;
01186 return ElevationSeg(origin, normal, seglen, colpatch, colnode);
01187 }
01188
01189 double TRACK::ElevationSeg(VERTEX origin, VERTEX & normal, float seglen, BEZIER * &colpatch, OBJECTNODE * &colnode)
01190 {
01191 if (origin.nan())
01192 {
01193 cout << "Detected NaN in origin vector" << endl;
01194 }
01195
01196 if (!(seglen < 0 || seglen >= 0))
01197 {
01198 cout << "Detected NaN in seglen" << endl;
01199 }
01200
01201 bool verbose = false;
01202
01203
01204 VERTEX dir;
01205 dir.y = -1;
01206 double elev = -100000;
01207 VERTEX colpt;
01208 bool col = false;
01209 bool bezcol = false;
01210 bool modelcol = false;
01211
01212 ROADSTRIP * colstrip;
01213
01214
01215 normal.Set(0,1,0);
01216
01217
01218 bool closest = true;
01219
01220 colnode = NULL;
01221 colpatch = NULL;
01222
01223 col = CollideRoads(origin, dir, colpt, closest, colstrip, colpatch, normal);
01224
01225
01226
01227 if (col)
01228 {
01229 bezcol = true;
01230 elev = colpt.y;
01231 if (verbose)
01232 cout << "track collision" << endl;
01233
01234
01235
01236
01237 }
01238 else
01239 {
01240 if (objects.GetCollideAndDriveTogether())
01241 {
01242 colpatch = NULL;
01243
01244 closest = true;
01245 col = objects.Collide(origin, dir, colpt, closest, normal, seglen, colnode);
01246 if (col)
01247 {
01248 elev = colpt.y;
01249 modelcol = true;
01250 }
01251 else
01252 elev = origin.y - seglen;
01253 }
01254 else
01255 {
01256
01257 closest = false;
01258 col = objects.CollideDriveable(origin, dir, colpt, closest, normal);
01259
01260
01261 if (col)
01262 {
01263 elev = colpt.y;
01264 if (verbose)
01265 cout << "model collision" << endl;
01266 }
01267 }
01268 }
01269
01270 if (!col && verbose)
01271 cout << "no collision" << endl;
01272
01273
01274
01275 if (col)
01276 {
01277 if (normal.nan())
01278 {
01279 cout << "Detected NaN in normal vector " << bezcol << " " << modelcol << endl;
01280 normal.Set(0,1,0);
01281 }
01282
01283 if (!(elev < 0 || elev >= 0))
01284 {
01285 cout << "Detected NaN in elevation " << bezcol << " " << modelcol << endl;
01286
01287
01288
01289
01290 return -100000;
01291 }
01292 }
01293
01294 return elev;
0129