Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

Track.c

Go to the documentation of this file.
00001 /****************************************************************************/
00002 /*    FILE: Track.c                                                                                                                     */
00003 /****************************************************************************/
00004 #define WIN32_LEAN_AND_MEAN
00005 #include        <windows.h>
00006 
00007 #include        <math.h>
00008 #include        <stdlib.h>
00009 #include        <assert.h>
00010 
00011 #include        "GMain.h"
00012 
00013 #include        "_bot.h"
00014 #include        "track.h"
00015 #include    "bit.h"
00016 
00017 static geBoolean Track_LinkTest(geWorld *World, TrackPt *tp, TrackPt *tp2);
00018 static geBoolean Track_LinkTrack(geWorld *World, Track* t, Track *t2);
00019 static geBoolean Track_FakeTrack(geWorld *World, geVec3d *Pos);
00020 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff);
00021 
00022 geBoolean Bot_CanSeePointToPoint(const geWorld* World, const geVec3d *Pos1, const geVec3d *Pos2);
00023 float DistWeightedY(const geVec3d *Pos1, const geVec3d *Pos2, const float Scale);
00024 
00025 #define TRACK_SEARCH_Y_RANGE 40.0f
00026 #define TOWARD_GOAL 1
00027 #define AWAY_FROM_GOAL -1
00028 
00029 int32 TrackCount=0;
00030 Track TrackList[MAX_TRACKS+2];
00031 
00032 #define MAX_NODES MAX_TRACKS+2
00033         
00034 static int32 searchnode[MAX_NODES], searchparent[MAX_NODES];
00035 static uint8 bitarr[(MAX_NODES+7)>>3]; // MAX_NODES up to the nearest 8th divisor
00036 
00037 //=====================================================================================
00038 //      Track_OnTrack
00039 //=====================================================================================
00040 geBoolean Track_OnTrack(TrackData *td)
00041 {
00042     return (td->TrackNdx >= 0);
00043 }
00044 
00045 //=====================================================================================
00046 //      Track_GetNextTrack
00047 //=====================================================================================
00048 Track* Track_GetNextTrack(Track *t)
00049 {
00050         int32 ndx;
00051 
00052         if (!t)
00053                 return(&TrackList[0]);
00054 
00055         ndx = t - &TrackList[0];
00056         assert(ndx >= 0 && ndx < TrackCount);
00057         ndx++;
00058 
00059         if (ndx >= TrackCount)
00060                 return NULL;
00061 
00062         return (&TrackList[ndx]);
00063 }
00064 
00065 //=====================================================================================
00066 //      Track_ClearTrack
00067 //=====================================================================================
00068 void Track_ClearTrack(TrackData *td)
00069 {
00070     td->TrackNdx = -1;
00071     td->PointNdx = -1;
00072 }
00073 
00074 //=====================================================================================
00075 //      Track_GetTrack
00076 //=====================================================================================
00077 Track *Track_GetTrack(TrackData *td)
00078 {
00079         return &TrackList[td->TrackNdx];
00080 }
00081 
00082 //=====================================================================================
00083 //      Track_GetDir
00084 //=====================================================================================
00085 int32 Track_GetDir(TrackData *td)
00086 {
00087         return td->TrackDir;
00088 }
00089 
00090 //=====================================================================================
00091 //      Track_PastStartPoint
00092 //=====================================================================================
00093 geBoolean Track_PastStartPoint(TrackData *td)
00094 {
00095         assert(td->TrackNdx > -1);
00096 
00097         if (td->TrackDir == 1)
00098         {
00099                 return (td->PointNdx > 0);
00100         }
00101         else
00102         if (td->TrackDir == -1)
00103         {
00104                 return (td->PointNdx < TrackList[td->PointNdx].PointCount);
00105         }
00106 
00107         assert(1==0);
00108         return GE_FALSE;
00109 }
00110 
00111 //=====================================================================================
00112 //      Track_NextPoint
00113 //=====================================================================================
00114 TrackPt *Track_NextPoint(TrackData *td)
00115 {
00116         assert(td->TrackNdx > -1);
00117 
00118     td->PointNdx += td->TrackDir;
00119 
00120     if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00121         {
00122         if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00123             {
00124             td->PointNdx = 0;
00125             return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00126             }
00127 
00128 //              td->PointNdx >= TrackList[td->TrackNdx].PointCount-1;
00129         return(NULL);
00130         }
00131 
00132     if (td->PointNdx < 0)
00133         {
00134         if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00135             {
00136             td->PointNdx = TrackList[td->TrackNdx].PointCount - 1;
00137             return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00138             }
00139 
00140                 td->PointNdx = 0;
00141         return(NULL);
00142         }
00143 
00144     assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00145 
00146     return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00147 }
00148 
00149 
00150 //=====================================================================================
00151 //      Track_PrevPoint
00152 //=====================================================================================
00153 TrackPt *Track_PrevPoint(TrackData *td)
00154     {
00155         assert(td->TrackNdx > -1);
00156 
00157     td->PointNdx -= td->TrackDir;
00158 
00159     if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00160         {
00161         if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00162             {
00163             td->PointNdx = 0;
00164             return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00165             }
00166 
00167         return(NULL);
00168         }
00169 
00170     if (td->PointNdx < 0)
00171         {
00172         if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00173             {
00174             td->PointNdx = TrackList[td->TrackNdx].PointCount - 1;
00175             return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00176             }
00177 
00178         return(NULL);
00179         }
00180 
00181     assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00182 
00183     return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00184     }
00185 
00186 
00187 //=====================================================================================
00188 //      Track_GetPoint
00189 //=====================================================================================
00190 TrackPt *Track_GetPoint(TrackData *td)
00191     {
00192         assert(td);
00193 
00194     assert(Track_OnTrack(td));
00195 
00196     if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00197         td = td;
00198 
00199     assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00200 
00201         return &TrackList[td->TrackNdx].PointList[td->PointNdx];
00202     }
00203 
00204 //=====================================================================================
00205 //      Track_Length
00206 //=====================================================================================
00207 float Track_Length(Track* t)
00208 {
00209         TrackPt *tp;
00210         float dist=0.0f;
00211 
00212     for (tp = t->PointList; tp < &t->PointList[t->PointCount-1]; tp++)
00213         {
00214                 dist += geVec3d_DistanceBetween(tp->Pos, (tp+1)->Pos);
00215         }
00216 
00217         return dist;
00218 }
00219 
00220 //=====================================================================================
00221 //      Track_GetEndPoint
00222 //=====================================================================================
00223 TrackPt* Track_GetEndPoint(TrackData *td)
00224 {
00225         Track *t = &TrackList[td->TrackNdx];
00226 
00227         assert(td);
00228     assert(Track_OnTrack(td));
00229 
00230         if (td->TrackDir == 1)
00231                 return(&t->PointList[t->PointCount-1]);
00232         else
00233                 return(&t->PointList[0]);
00234 }
00235 
00236 //=====================================================================================
00237 //      Track_GetFirstPoint
00238 //=====================================================================================
00239 TrackPt* Track_GetFirstPoint(TrackData *td)
00240 {
00241         Track *t = &TrackList[td->TrackNdx];
00242 
00243         assert(td);
00244     assert(Track_OnTrack(td));
00245 
00246         if (td->TrackDir == -1)
00247                 return(&t->PointList[t->PointCount-1]);
00248         else
00249                 return(&t->PointList[0]);
00250 }
00251 
00252 //=====================================================================================
00253 //      Track_LinkTest
00254 //=====================================================================================
00255 static geBoolean Track_LinkTest(geWorld *World, TrackPt *tp, TrackPt *tp2)
00256 {
00257 
00258         if (geVec3d_DistanceBetween(tp->Pos, tp2->Pos) > 1100)
00259                 return GE_FALSE;
00260 
00261         if (fabs(tp->Pos->Y - tp2->Pos->Y) > TRACK_SEARCH_Y_RANGE * 2)
00262                 return GE_FALSE;
00263 
00264         if (Bot_CanSeePointToPoint(World, tp->Pos, tp2->Pos))
00265                 return GE_TRUE;
00266 
00267         return GE_FALSE;
00268 }
00269 
00270 //=====================================================================================
00271 //      Track_LinkSet
00272 //=====================================================================================
00273 int32 Track_LinkSet(Track *t, Track *t2)
00274 {
00275         int32 i=0;
00276 
00277         for (i = 0; i < MAX_TRACK_VIS; i++)
00278         {
00279                 if (t->Vis[i] == t2)
00280                         break;
00281 
00282                 // make sure a spot is open 
00283                 if (!t->Vis[i])
00284                 {
00285                         t->Vis[i] = t2;
00286                         return i;
00287                 }
00288         }
00289 
00290         assert (i < MAX_TRACK_VIS);
00291 
00292         return -1;
00293 }
00294 
00295 //=====================================================================================
00296 //      Track_LinkExists
00297 //=====================================================================================
00298 geBoolean Track_LinkExists(Track *t, Track *t2)
00299 {
00300         int32 i;
00301 
00302         for (i = 0; i < MAX_TRACK_VIS; i++)
00303         {
00304                 if (t->Vis[i] == t2)
00305                         return GE_TRUE;
00306         }
00307 
00308         return(GE_FALSE);
00309 }
00310 
00311 
00312 //=====================================================================================
00313 //      Track_IsOneWay
00314 //=====================================================================================
00315 geBoolean Track_IsOneWay(Track *t)
00316 {
00317     switch (t->Type)
00318         {
00319     // for ladders only look at first track point
00320         case TRACK_TYPE_ELEVATOR_UP:
00321         case TRACK_TYPE_ELEVATOR_DOWN:
00322     case TRACK_TYPE_UP:
00323     case TRACK_TYPE_DOWN:
00324     case TRACK_TYPE_SCAN:
00325     case TRACK_TYPE_TRAVERSE_ONEWAY:
00326             {
00327                         return GE_TRUE;
00328             }
00329                 }
00330 
00331         return GE_FALSE;
00332 }
00333 
00334 //=====================================================================================
00335 //      Track_LinkTrack
00336 //      Large and somewhat nasty.  Every attempt to simplify this didn't really
00337 //      work very well.  Its mostly due to the arbitrary nature that tracks can be
00338 //      placed  Every situation needs to be accounted for.
00339 //
00340 //     E<-----S  E<---->S   Left
00341 //     S----->E  E<---->S       Right
00342 //     E<-----S  S<---->E       Left
00343 //     S----->E  S<---->E       Right
00344 //
00345 //     E<-----S  E<-----S       Left
00346 //     S----->E  E<-----S       NA
00347 //     E<-----S  S----->E       NA
00348 //     S----->E  S----->E       Right
00349 //
00350 //     E<---->S  E<-----S   Left
00351 //     E<---->S  S----->E   Right
00352 //     S<---->E  E<-----S   Left
00353 //     S<---->E  S----->E   Right
00354 //
00355 //        *      E<-----S       Left
00356 //        *      E<-----S       Left
00357 //        *      S----->E       Right
00358 //        *      S----->E       Right
00359 //
00360 //     E<---->S  E<---->S   Left OR Right
00361 //     S<---->E  E<---->S       Left OR Right
00362 //     E<---->S  S<---->E       Left OR Right
00363 //     S<---->E  S<---->E       Left OR Right
00364 //=====================================================================================
00365 
00366 static geBoolean Track_LinkTrack(geWorld *World, Track* t, Track *t2)
00367     {
00368     TrackPt *tp, *tp2;
00369         geBoolean OneWay, OneWay2;
00370         geBoolean a=GE_FALSE,b=GE_FALSE,c=GE_FALSE,d=GE_FALSE;
00371         int32 *VisFlag, *VisFlag2, i;
00372 
00373         int32 ep, ep2;
00374     geBoolean OnePoint = GE_FALSE, OnePoint2 = GE_FALSE;
00375     float e2e, s2s, e2s, s2e;
00376 
00377     if (t == t2)
00378                 return GE_FALSE;
00379 
00380         OneWay = Track_IsOneWay(t);
00381         OneWay2 = Track_IsOneWay(t2);
00382 
00383     tp = t->PointList;
00384         ep = t->PointCount - 1;
00385         tp2 = t2->PointList;
00386         ep2 = t2->PointCount - 1;
00387 
00388         VisFlag = &t->VisFlag[0];
00389         VisFlag2 = &t2->VisFlag[0];
00390 
00391     if (ep == 0) OnePoint = GE_TRUE;
00392     if (ep2 == 0) OnePoint2 = GE_TRUE;
00393 
00394     if (OnePoint && OnePoint2)
00395         {
00396         // both single points
00397                 if (!Track_LinkExists(t, t2) &&
00398             Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00399             {
00400             if ((i = Track_LinkSet(t, t2)) > -1)
00401                                 VisFlag[i] |= 1;
00402             return GE_TRUE;
00403             }
00404         }
00405     else
00406     if (OnePoint)
00407         {
00408         if (OneWay2)
00409             {
00410             // first track is single, second is oneway and not single
00411             s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00412             s2e = DistWeightedY(t->PointList[0].Pos, t2->PointList[ep2].Pos, 2.0f);
00413 
00414             if (s2s < s2e)
00415                 {
00416                             if (!Track_LinkExists(t, t2) &&
00417                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00418                     {
00419                     if ((i = Track_LinkSet(t, t2)) > -1)
00420                             VisFlag[i] |= 1;
00421                     return GE_TRUE;
00422                     }
00423                 }
00424             else
00425                     if (!Track_LinkExists(t2, t) &&
00426                 Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00427                 {
00428                 if ((i = Track_LinkSet(t2, t)) > -1)
00429                         VisFlag2[i] |= 2;
00430                 return GE_TRUE;
00431                 }
00432             }
00433         else 
00434             {
00435             // onepoint and 2way
00436                     if (!Track_LinkExists(t, t2) &&
00437                 (a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00438                 (b = Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2])))
00439                 {
00440                 if ((i = Track_LinkSet(t, t2)) > -1)
00441                                         VisFlag[i] |= 1;
00442                 if ((i = Track_LinkSet(t2, t)) > -1)
00443                                         VisFlag2[i] |= 2;
00444                                 return GE_TRUE;
00445                 }
00446             }
00447         }
00448     else
00449     if (OnePoint2)
00450         {
00451         if (OneWay)
00452             {
00453             // second track is single, first is oneway and not single
00454             s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00455             e2s = DistWeightedY(t->PointList[ep].Pos, t2->PointList[0].Pos, 2.0f);
00456 
00457             if (e2s < s2s)
00458                 {
00459                         if (!Track_LinkExists(t, t2) &&
00460                     Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00461                     {
00462                     if ((i = Track_LinkSet(t, t2)) > -1)
00463                             VisFlag[i] |= 4;
00464                     return GE_TRUE;
00465                     }
00466                 }
00467             else
00468                     if (!Track_LinkExists(t2, t) &&
00469                 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00470                 {
00471                 if ((i = Track_LinkSet(t2, t)) > -1)
00472                         VisFlag2[i] |= 1;
00473                 return GE_TRUE;
00474                 }
00475             }
00476         else
00477             {
00478             // 2way and onepoint2
00479                     if (!Track_LinkExists(t, t2) &&
00480                 (a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00481                 (b = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0])))
00482                 {
00483                 if ((i = Track_LinkSet(t, t2)) > -1)
00484                                         VisFlag[i] |= 1;
00485                 if ((i = Track_LinkSet(t2, t)) > -1)
00486                                         VisFlag2[i] |= 4;
00487                 return GE_TRUE;
00488                 }
00489             }
00490         }
00491     else
00492     if (OneWay || OneWay2)
00493         {
00494         e2e = DistWeightedY(t->PointList[ep].Pos, t2->PointList[ep2].Pos, 2.0f);
00495         s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00496         s2e = DistWeightedY(t->PointList[0].Pos, t2->PointList[ep2].Pos, 2.0f);
00497         e2s = DistWeightedY(t->PointList[ep].Pos, t2->PointList[0].Pos, 2.0f);
00498 
00499         if (e2e < s2s && e2e < s2e && e2e < e2s)
00500             {
00501             //e2e closest
00502             if (OneWay && OneWay2)
00503                 return GE_TRUE;
00504 
00505             if (OneWay)
00506                 {
00507                                 if (!Track_LinkExists(t, t2) &&
00508                     Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))
00509                     {
00510                     if ((i = Track_LinkSet(t, t2)) > -1)
00511                                                 VisFlag[i] |= 3;
00512                     return GE_TRUE;
00513                     }
00514                 }
00515 
00516             if (OneWay2)
00517                 {
00518                                 if (!Track_LinkExists(t2, t) &&
00519                     Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))
00520                     {
00521                     if ((i = Track_LinkSet(t2, t)) > -1)
00522                             VisFlag2[i] |= 3;
00523                     return GE_TRUE;
00524                     }
00525                 }
00526             }
00527 
00528 
00529         if (s2s < e2e && s2s < s2e && s2s < e2s)
00530             {
00531             //s2s closest
00532             if (OneWay && OneWay2)
00533                 return GE_TRUE;
00534 
00535             if (OneWay2)
00536                 {
00537                                 if (!Track_LinkExists(t, t2) &&
00538                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00539                     {
00540                     if ((i = Track_LinkSet(t, t2)) > -1)
00541                             VisFlag[i] |= 1;
00542                     return GE_TRUE;
00543                     }
00544                 }
00545 
00546             if (OneWay)
00547                 {
00548                                 if (!Track_LinkExists(t2, t) &&
00549                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00550                     {
00551                     if ((i = Track_LinkSet(t2, t)) > -1)
00552                             VisFlag2[i] |= 1;
00553                     return GE_TRUE;
00554                     }
00555                 }
00556             }
00557 
00558         if (s2e < e2e && s2e < s2s && s2e < e2s)
00559             {
00560             //s2e closest
00561             if (OneWay && OneWay2)
00562                 {
00563                                 if (!Track_LinkExists(t2, t) &&
00564                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00565                     {
00566                     if ((i = Track_LinkSet(t2, t)) > -1)
00567                             VisFlag2[i] |= 2;
00568                     return GE_TRUE;
00569                     }
00570                 }
00571 
00572             if (OneWay2)
00573                 {
00574                                 if (!Track_LinkExists(t2, t) &&
00575                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00576                     {
00577                     if ((i = Track_LinkSet(t2, t)) > -1)
00578                             VisFlag2[i] |= 2;
00579                     return GE_TRUE;
00580                     }
00581                 }
00582 
00583             if (OneWay)
00584                 {
00585                                 if (!Track_LinkExists(t2, t) &&
00586                     Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00587                     {
00588                     if ((i = Track_LinkSet(t2, t)) > -1)
00589                             VisFlag[i] |= 2;
00590                     return GE_TRUE;
00591                     }
00592                 }
00593             }
00594 
00595         if (e2s < e2e && e2s < s2s && e2s < s2e)
00596             {
00597             //e2s closest
00598             if (OneWay && OneWay2)
00599                 {
00600                                 if (!Track_LinkExists(t, t2) &&
00601                     Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00602                     {
00603                     if ((i = Track_LinkSet(t, t2)) > -1)
00604                             VisFlag[i] |= 4;
00605                     return GE_TRUE;
00606                     }
00607                 }
00608         
00609             if (OneWay || OneWay2)
00610                 {
00611                                 if (!Track_LinkExists(t, t2) &&
00612                     Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00613                     {
00614                     if ((i = Track_LinkSet(t, t2)) > -1)
00615                             VisFlag[i] |= 4;
00616                     return GE_TRUE;
00617                     }
00618                 }
00619             }
00620         }
00621     else
00622         if (!Track_LinkExists(t, t2) && 
00623         ((a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00624                 (b = Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2])) ||
00625                 (c = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0])) ||
00626                 (d = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))))
00627                 {
00628                 if ((i = Track_LinkSet(t, t2)) > -1)
00629                         {
00630                         if (a) VisFlag[i] |= 1;
00631                         if (b) VisFlag[i] |= 2;
00632                         if (c) VisFlag[i] |= 4;
00633                         if (d) VisFlag[i] |= 3;
00634                         }
00635         if ((i = Track_LinkSet(t2, t)) > -1)
00636                         {
00637                         if (a) VisFlag2[i] |= 1;
00638                         if (b) VisFlag2[i] |= 2;
00639                         if (c) VisFlag2[i] |= 4;
00640                         if (d) VisFlag2[i] |= 3;
00641                         }
00642 
00643         return GE_TRUE;
00644                 }
00645 
00646    return GE_FALSE;
00647    }
00648 
00649 
00650 //=====================================================================================
00651 //      Track_LinkTracks
00652 //=====================================================================================
00653 void Track_LinkTracks(geWorld *World)
00654     {
00655     Track *t, *t2;
00656         assert(World);
00657 
00658     // look at all tracks finding the closest endpoint
00659     for (t = &TrackList[0]; t < &TrackList[TrackCount]; t++)
00660         {
00661                 for (t2 = &TrackList[0]; t2 < &TrackList[TrackCount]; t2++)
00662                         {
00663             Track_LinkTrack(World, t, t2);
00664                         }
00665                 }
00666     }
00667 
00668 
00669 //=====================================================================================
00670 //      Track_FakeTrack
00671 //=====================================================================================
00672 static geBoolean Track_FakeTrack(geWorld *World, geVec3d *Pos)
00673     {
00674     Track *t, *t2;
00675     TrackPt *tp;
00676         geBoolean found = GE_FALSE;
00677 
00678         //int32 ep;
00679 
00680         assert(World);
00681 
00682         t = &TrackList[MAX_TRACKS];
00683     tp = t->PointList;
00684 
00685         // set count and position
00686         t->PointCount = 1;
00687         tp->Pos = Pos;
00688         memset(t->Vis, 0, sizeof(t->Vis));
00689 
00690     // look at all tracks finding the closest endpoint
00691         //ep = t->PointCount - 1;
00692 
00693         for (t2 = &TrackList[0]; t2 < &TrackList[TrackCount]; t2++)
00694                 {
00695         if (Track_LinkTrack(World, t, t2))
00696             found = TRUE;
00697                 }
00698 
00699         return (found);
00700     }
00701 
00702 
00703 //=====================================================================================
00704 //      Track_FindTrack
00705 //=====================================================================================
00706 Track* Track_FindTrack(GenVSI *VSI, geVec3d *StartPos, geVec3d *TgtPos, int32 player_dir, int32 *track_type, TrackData *td)
00707     {
00708     float near_dist = 999999.0f, ydiff;
00709 
00710     int32 end_point[2] = {0,0};
00711     int32 near_dir;
00712 
00713     Track *t, *near_track;
00714     TrackPt *tp, *near_tp;
00715 
00716         TrackPt *stp,*etp;
00717         float start2tgt_dist, dist0, dist1, bot2start_dist, bot2end_dist, end2tgt_dist, bot2tgt_dist, total_dist2end;
00718         int32 dir = 1;
00719         int32 *type;
00720 
00721         geBoolean OneWay = GE_FALSE;
00722         geBoolean found = GE_FALSE;
00723         static StartTrack = 0;
00724 
00725         geWorld                 *World;
00726 
00727         World = GenVSI_GetWorld(VSI);
00728         assert(World);
00729 
00730         if (td->TrackNdx <= -1)
00731         {
00732                 StartTrack = 0;
00733         }
00734         else
00735         {
00736                 StartTrack = td->TrackNdx+1;
00737         }
00738         
00739         Track_ClearTrack(td);
00740 
00741     // look at all tracks finding the closest endpoint
00742     for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
00743         {
00744         tp = t->PointList;
00745 
00746         // Skip if is not the track type we are looking for
00747                 if (track_type)
00748                 {
00749                         type = track_type;
00750         
00751                         while (*type != -1)
00752                         {
00753                                 if (t->Type == *type)
00754                                         break;
00755                                 type++;
00756                         }
00757                         
00758                         if (*type <= -1)
00759                                 continue;
00760                 }
00761 
00762                 end_point[1] = t->PointCount - 1;
00763 
00764         #if 0
00765         // Skip if already someone on this track
00766         if (TEST(t->flags, TF_TRACK_OCCUPIED))
00767             continue;
00768         #endif
00769 
00770                 OneWay = Track_IsOneWay(t);
00771 
00772         ydiff = TRACK_SEARCH_Y_RANGE;
00773 
00774                 dist0 = geVec3d_DistanceBetween(StartPos, t->PointList[end_point[0]].Pos);
00775                 dist1 = geVec3d_DistanceBetween(StartPos, t->PointList[end_point[1]].Pos);
00776 
00777                 if (t->Type == TRACK_TYPE_TRAVERSE)
00778                 {
00779                         // find the closest point to the dest on the track
00780                         TrackPt *tp;
00781                         float save_start_dist = 999999.0f, 
00782                                   save_end_dist = 999999.0f, dist;
00783 
00784                         // don't bother if Start and Tgt are already close
00785                         //if (geVec3d_DistanceBetween(TgtPos, StartPos) < 900)
00786                         //      continue;
00787 
00788                         // find closest points to Start and Tgt Positions
00789                         for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
00790                         {
00791                                 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
00792 
00793                                 if (dist < save_start_dist)
00794                                 {
00795                                         stp = tp;
00796                                         save_start_dist = dist;
00797                                 }
00798 
00799                                 dist = geVec3d_DistanceBetween(tp->Pos, TgtPos);
00800 
00801                                 if (dist < save_end_dist)
00802                                 {
00803                                         etp = tp;
00804                                         save_end_dist = dist;
00805                                 }
00806                         }
00807 
00808                         if (stp == etp)
00809                                 continue;
00810 
00811                         // compare pointer locations to see if tgt is past start point
00812                         if (etp > stp)
00813                                 dir = 1; // towards end
00814                         else
00815                                 dir = -1; // towards start
00816                 }
00817                 else
00818                 if (dist0 <= dist1)
00819                 {
00820                         stp = &t->PointList[end_point[0]];
00821                         etp = &t->PointList[end_point[1]];
00822                         dir = 1;
00823 
00824                 }
00825                 else
00826                 {
00827                         if (OneWay)
00828                                 continue;
00829 
00830                         stp = &t->PointList[end_point[1]];
00831                         etp = &t->PointList[end_point[0]];
00832                         dir = -1;
00833                 }
00834 
00835         if (player_dir == TOWARD_GOAL)
00836                         {
00837                         // early out! - tgtpos is exactly the endpoint
00838                         if (memcmp(TgtPos, etp->Pos, sizeof(*TgtPos)) == 0)
00839                                 {
00840                                 near_track = t;
00841                                 near_tp = stp;
00842                                 near_dir = dir;
00843                                 found = GE_TRUE;
00844                                 break;
00845                                 }
00846                         }
00847 
00848         bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
00849                 bot2end_dist = geVec3d_DistanceBetween(StartPos, etp->Pos);
00850 
00851         if (bot2start_dist > 1500.0f)
00852                         continue;
00853 
00854         if (bot2start_dist > near_dist)
00855                         continue;
00856 
00857         if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
00858             continue;
00859 
00860                 // approx total dist to travel - not really used yet but good to have
00861                 total_dist2end = bot2start_dist + Track_Length(t);
00862 
00863         start2tgt_dist = geVec3d_DistanceBetween(stp->Pos, TgtPos);
00864                 end2tgt_dist = geVec3d_DistanceBetween(etp->Pos, TgtPos);
00865 
00866         if (player_dir == TOWARD_GOAL)
00867                 {
00868                         // if the end point is farther than the start point - skip it
00869                         if (end2tgt_dist > start2tgt_dist)
00870                                 continue;
00871 
00872             end2tgt_dist = DistWeightedY(etp->Pos, TgtPos, 2.0f);
00873                     bot2tgt_dist = DistWeightedY(StartPos, TgtPos, 2.0f);
00874 
00875                         // if it does not get you closer - skip it
00876                         if (end2tgt_dist > bot2tgt_dist)
00877                                 continue;
00878                 }
00879                 else
00880                 if (player_dir == AWAY_FROM_GOAL)
00881                 {
00882                         // if the end point is closer than the start point - skip it
00883                         if (end2tgt_dist < start2tgt_dist)
00884                                 continue;
00885 
00886             end2tgt_dist = DistWeightedY(etp->Pos, TgtPos, 2.0f);
00887                     bot2tgt_dist = DistWeightedY(StartPos, TgtPos, 2.0f);
00888 
00889                         // if it does not get you further then skip it
00890                         if (end2tgt_dist < bot2tgt_dist)
00891                                 continue;
00892                 }
00893 
00894         if (!Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
00895                         continue;
00896                 
00897                 // end up on approx the same Y level]
00898                 // not really working for some reason
00899         //if (fabs(TgtPos->Y - etp->Pos->Y) > ydiff*2)
00900         //    continue;
00901 
00902                 found = GE_TRUE;
00903         near_dist = bot2start_dist;
00904         near_track = t;
00905         near_tp = stp;
00906                 near_dir = dir;
00907         }
00908 
00909     if (found)
00910         {
00911         // if can see the point, return the track number
00912         td->TrackNdx = near_track - &TrackList[0];
00913         td->PointNdx = near_tp - &TrackList[td->TrackNdx].PointList[0];
00914         td->TrackDir = near_dir;
00915         return (near_track);
00916         }
00917     else
00918         {
00919         Track_ClearTrack(td);
00920         return (NULL);
00921         }
00922     }
00923 
00924 //=====================================================================================
00925 //      Track_FindFarTrack
00926 //=====================================================================================
00927 Track* Track_FindFarTrack(GenVSI *VSI, geVec3d *StartPos)
00928     {
00929                 float far_dist = 0.0f;
00930                 
00931                 int32 end_point[2] = {0,0};
00932                 
00933                 Track *t, *far_track;
00934                 //TrackPt *tp;
00935                 
00936                 TrackPt *stp;
00937                 float bot2start_dist;
00938                 int32 dir = 1;
00939                 
00940                 geBoolean OneWay = GE_FALSE;
00941                 geBoolean found = GE_FALSE;
00942                 
00943                 int32 StartTrack = 0;
00944                 
00945                 geWorld                 *World;
00946                 
00947                 World = GenVSI_GetWorld(VSI);
00948                 assert(World);
00949                 
00950                 // look at all tracks finding the closest endpoint
00951                 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
00952         {
00953                         stp = t->PointList;
00954                         //end_point[1] = t->PointCount - 1;
00955                         
00956                         OneWay = Track_IsOneWay(t);
00957                         
00958                         bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
00959                         
00960                         if (bot2start_dist < far_dist)
00961                                 continue;
00962                         
00963                         if (Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
00964                 continue;
00965                         
00966                         found = GE_TRUE;
00967                         far_dist = bot2start_dist;
00968                         far_track = t;
00969                 }
00970                 
00971                 if (found)
00972             {
00973                         return (far_track);
00974             }
00975                 
00976                 return (NULL);
00977     }
00978 
00979 
00980 #if 0
00981 //=====================================================================================
00982 //      Track_FindCloseTrack
00983 //=====================================================================================
00984 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff)
00985     {
00986                 float near_dist = 999999.0f;
00987                 
00988                 Track *t, *near_track;
00989                 TrackPt *tp;
00990                 
00991                 TrackPt *stp;
00992                 float tgt2start_dist;
00993                 int32 dir = 1;
00994                 
00995                 geBoolean OneWay = GE_FALSE;
00996                 geBoolean found = GE_FALSE;
00997                 
00998                 int32 StartTrack = 0;
00999                 
01000                 geWorld                 *World;
01001 
01002                 float save_start_dist = 999999.0f, 
01003                           dist;
01004                 
01005                 World = GenVSI_GetWorld(VSI);
01006                 assert(World);
01007                 
01008                 // look at all tracks finding the closest endpoint
01009                 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
01010         {
01011                         OneWay = Track_IsOneWay(t);
01012                         
01013                         // find the closest point to the dest on the track
01014                         // find closest points to Start and Tgt Positions
01015                         for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01016                         {
01017                                 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
01018 
01019                                 if (dist < save_start_dist)
01020                                 {
01021                                         stp = tp;
01022                                         save_start_dist = dist;
01023                                 }
01024                         }
01025                         
01026                         tgt2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
01027                         
01028                         if (tgt2start_dist > 1500.0f)
01029                                 continue;
01030                         
01031                         if (tgt2start_dist > near_dist)
01032                                 continue;
01033                         
01034                         if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
01035                                 continue;
01036 
01037                         found = GE_TRUE;
01038                         near_dist = tgt2start_dist;
01039                         near_track = t;
01040                 }
01041                 
01042                 if (found)
01043         {
01044                         return (near_track);
01045         }
01046                 
01047                 return (NULL);
01048     }
01049 #else
01050 //=====================================================================================
01051 //      Track_FindCloseTrack
01052 //=====================================================================================
01053 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff)
01054     {
01055                 float near_dist = 999999.0f;
01056                 
01057                 int32 end_point[2] = {0,0};
01058                 
01059                 Track *t, *near_track;
01060                 TrackPt *tp;
01061                 
01062                 TrackPt *stp;
01063                 float bot2start_dist;
01064                 int32 dir = 1;
01065                 
01066                 geBoolean OneWay = GE_FALSE;
01067                 geBoolean found = GE_FALSE;
01068                 
01069                 int32 StartTrack = 0;
01070                 
01071                 geWorld                 *World;
01072                 
01073                 World = GenVSI_GetWorld(VSI);
01074                 assert(World);
01075                 
01076                 // look at all tracks finding the closest endpoint
01077                 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
01078         {
01079                         tp = t->PointList;
01080                         end_point[1] = t->PointCount - 1;
01081                         
01082                         OneWay = Track_IsOneWay(t);
01083                         
01084                         ydiff = TRACK_SEARCH_Y_RANGE;
01085                         
01086                         {
01087                         // find the closest point to the dest on the track
01088                         TrackPt *tp;
01089                         float save_start_dist = 999999.0f, 
01090                                   save_end_dist = 999999.0f, dist;
01091 
01092                         // find closest points to Start and Tgt Positions
01093                         for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01094                         {
01095                                 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
01096 
01097                                 if (dist < save_start_dist)
01098                                 {
01099                                         stp = tp;
01100                                         save_start_dist = dist;
01101                                 }
01102                         }
01103                         }
01104                         
01105                         bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
01106                         
01107                         if (bot2start_dist > 1500.0f)
01108                                 continue;
01109                         
01110                         if (bot2start_dist > near_dist)
01111                                 continue;
01112                         
01113                         if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
01114                                 continue;
01115 
01116                         if (!Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
01117                                 {
01118                                 TrackPt *tp;
01119                                 // see if you can see ANY points on this track
01120                                 for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01121                                 {
01122                                         if (stp == tp)
01123                                                 continue;
01124 
01125                                         if (Bot_CanSeePointToPoint(World, StartPos, tp->Pos))
01126                                                 goto found;
01127                                 }
01128 
01129                                 continue;
01130                                 }
01131                         
01132                         found:
01133 
01134                         found = GE_TRUE;
01135                         near_dist = bot2start_dist;
01136                         near_track = t;
01137                         //near_tp = stp;
01138                         //near_dir = dir;
01139                 }
01140                 
01141                 if (found)
01142         {
01143                         return (near_track);
01144         }
01145                 
01146                 return (NULL);
01147     }
01148 #endif  
01149         
01150 
01151 //=====================================================================================
01152 //      Track_FindMultiTrack
01153 //=====================================================================================
01154 geBoolean Track_FindMultiTrack(GenVSI *VSI, geVec3d *StartPos, geVec3d *EndPos, int32 dir, TrackCB *cb, Stack *nodestack)
01155         {
01156         int32 endnode, startnode;
01157         int32 s_plc, s_end, i, j, k, nodenum;
01158         Track *t, *n;
01159         geWorld *World;
01160         geBoolean found = GE_FALSE;
01161         
01162         if (!TrackCount)
01163                 return GE_FALSE;
01164         
01165         World = GenVSI_GetWorld(VSI);
01166         assert(World);
01167         
01168         //start at the end for ease of traversing
01169         if (!Track_FakeTrack(World, StartPos))
01170                 return GE_FALSE;
01171 
01172         t = &TrackList[MAX_TRACKS];
01173         assert(t);
01174         startnode = t - TrackList;
01175 
01176         // early out
01177         if (!t->Vis[0])
01178                 return GE_FALSE;
01179 
01180     if (dir == -1)
01181             t = Track_FindFarTrack(VSI, EndPos);
01182     else
01183     if (dir == 1)
01184             t = Track_FindCloseTrack(VSI, EndPos, TRACK_SEARCH_Y_RANGE*1.5f);
01185 
01186         if (!t)
01187                 return GE_FALSE;
01188 
01189         endnode = t - TrackList;
01190         
01191         //clear bitsearch array
01192         memset(bitarr, 0, sizeof(bitarr));
01193         
01194         // Create a node
01195         searchnode[0] = startnode;
01196         searchparent[0] = -1;
01197         
01198         // startnode to searched
01199         SET_BITARR(bitarr,startnode);
01200         
01201         // search place and search end
01202         for(s_plc = 0, s_end = 1; s_plc < s_end; s_plc++)
01203         {
01204                 //loop through all nodes "visible" from this node
01205                 n = &TrackList[searchnode[s_plc]];
01206                 
01207                 for (i = 0; n->Vis[i]; i++)
01208                 {
01209                         nodenum = n->Vis[i] - &TrackList[0];
01210                         
01211                         // look at ALL nextsectors !!!!!! s_plc is parent
01212                         if (nodenum < 0) 
01213                                 continue;
01214                         
01215                         // only look at sector if its not been looked at before
01216                         if (!TEST_BITARR(bitarr,nodenum))
01217                         {
01218                                 // mark sector as searched
01219                                 SET_BITARR(bitarr,nodenum);
01220 
01221                                 if (!cb->CB(VSI, cb->Data, &TrackList[nodenum]))
01222                                         continue;
01223 
01224                                 // save off this sector at the END!!!!!
01225                                 searchnode[s_end] = nodenum;
01226                                 // save off the parent sector at the END!!!!!
01227                                 searchparent[s_end] = s_plc;
01228                                 // increment s_end (search end)
01229                                 s_end++;
01230                                 
01231                                 if (nodenum == endnode)
01232                                 {
01233                                         // FOUND -A- PATH!
01234                                         found = GE_TRUE;
01235 
01236                     // clear stack
01237                     StackReset(nodestack);
01238 
01239                     for(k = s_end-1, j=0; k >= 0; k = searchparent[k])
01240                                         {
01241                                                 if (searchnode[k] >= MAX_TRACKS)
01242                                                         continue;
01243 
01244                         StackPush(nodestack, searchnode[k]);
01245                         }
01246 
01247                                         goto finish;
01248                                 }
01249                         }
01250                 }
01251         }
01252 
01253 finish:
01254 
01255         // clean links to fake track
01256         for (t = &TrackList[0]; t < &TrackList[TrackCount]; t++)
01257     {
01258                 for (i = 0; t->Vis[i]; i++)
01259                         {
01260                         if (t->Vis[i] >= &TrackList[MAX_TRACKS])
01261                                 t->Vis[i] = 0;
01262                         }
01263         }
01264 
01265         return (found);
01266 
01267         }
01268 
01269 
01270 //=====================================================================================
01271 //      Track_NextMultiTrack
01272 //=====================================================================================
01273 geBoolean Track_NextMultiTrack(GenVSI *VSI, geVec3d *StartPos, int32 TrackNdx, TrackData *td)
01274     {
01275         Track *t;
01276         TrackPt *tp, *ep;
01277         geWorld *World;
01278 
01279         geBoolean OneWay;
01280 
01281         int32 tpoint,dir;
01282         float dist2end,dist2start;
01283 
01284         assert(TrackNdx > -1);
01285 
01286         // look at all tracks finding the closest endpoint
01287         t = &TrackList[TrackNdx];
01288         tp = t->PointList;
01289         ep = &t->PointList[t->PointCount - 1];
01290         
01291         OneWay = Track_IsOneWay(t);
01292 
01293         if (OneWay)
01294                 {
01295                 td->TrackNdx = t - &TrackList[0];
01296                 td->PointNdx = 0;
01297                 td->TrackDir = 1;
01298                 return GE_TRUE;
01299                 }
01300 
01301         dist2start = geVec3d_DistanceBetween(StartPos, tp->Pos);
01302         dist2end = geVec3d_DistanceBetween(StartPos, ep->Pos);
01303 
01304         World = GenVSI_GetWorld(VSI);
01305 
01306         if (dist2start < dist2end)
01307         {
01308                 // try and see the closest point
01309                 if (Bot_CanSeePointToPoint(World, StartPos, tp->Pos))
01310                         {
01311                         dir = 1;
01312                         tpoint = 0;
01313                         }
01314                 else
01315                         {
01316                         dir = -1;
01317                         tpoint = t->PointCount - 1;
01318                         }
01319         }
01320         else
01321         {
01322                 // try and see the closest point
01323                 if (Bot_CanSeePointToPoint(World, StartPos, ep->Pos))
01324                         {
01325                         dir = -1;
01326                         tpoint = t->PointCount - 1;
01327                         }
01328                 else
01329                         {
01330                         dir = 1;
01331                         tpoint = 0;
01332                         }
01333         }
01334 
01335         td->TrackNdx = t - &TrackList[0];
01336         td->PointNdx = tpoint;
01337         td->TrackDir = dir;
01338 
01339         return GE_TRUE;
01340 }
01341 
01342 
01343 
01344 

Generated on Tue Sep 30 12:36:34 2003 for GTestAndEngine by doxygen 1.3.2