00001
00002 #include "ReVolt.h"
00003 #include "Geom.h"
00004 #include "NewColl.h"
00005 #include "Particle.h"
00006 #include "Body.h"
00007 #include "Aerial.h"
00008 #include "Wheel.h"
00009 #ifndef _PSX
00010 #include "Model.h"
00011 #endif
00012 #include "Car.h"
00013 #ifndef _PSX
00014 #include "Main.h"
00015 #include "Level.h"
00016 #endif
00017
00018 #ifdef _PC
00019 #include "Instance.h"
00020 #endif
00021
00022 #include "ctrlread.h"
00023 #include "Object.h"
00024 #include "Field.h"
00025 #include "control.h"
00026 #include "player.h"
00027 #include "spark.h"
00028 #ifdef _PC
00029 #include "ai.h"
00030 #endif
00031
00032
00034
00035
00036
00037
00038 #if defined(_PSX)
00039 COLLSKIN *LoadCollSkin();
00040 #endif
00041
00042 void COL_BodyCollHandler(OBJECT *obj);
00043 void COL_CarCollHandler(OBJECT *obj);
00044
00045 static void COL_AllObjectColls(void);
00046 static void COL_DummyColl(OBJECT *obj);
00047 static bool COL_Dummy2Coll(OBJECT *obj1, OBJECT *obj2);
00048 static void COL_BodyWorldColl(OBJECT *obj);
00049 static void COL_CarWorldColl(OBJECT *obj);
00050 static bool COL_BodyBodyColl(OBJECT *obj1, OBJECT *obj2);
00051 static bool COL_CarBodyColl(OBJECT *obj1, OBJECT *obj2);
00052 static bool COL_BodyCarColl(OBJECT *obj1, OBJECT *obj2);
00053 static bool COL_CarCarColl(OBJECT *obj1, OBJECT *obj2);
00054 static REAL CorrugationAmp(CORRUGATION *cor, REAL dx, REAL dy);
00055
00056 void AdjustBodyColl(COLLINFO_BODY *collInfo, MATERIAL *material);
00057 CONVEX *CreateConvex(INDEX nConvex);
00058 void FreeCollSkin(COLLSKIN *collSkin);
00059 bool SetupConvex(CONVEX *skin, INDEX nPts, INDEX extraPts, INDEX nEdges, INDEX nFaces);
00060 void DestroyConvex(CONVEX *skin, int nSkins);
00061 void DestroySpheres(SPHERE *spheres);
00062 bool CreateCopyCollSkin(COLLSKIN *collSkin);
00063 void BuildWorldSkin(COLLSKIN *bodySkin, VEC *pos, MAT *mat);
00064 #ifdef _PC
00065 CONVEX *LoadConvex(FILE *fp, INDEX *nSkins, int extraPtsPerEdge);
00066 SPHERE *LoadSpheres(FILE *fp, INDEX *nSpheres);
00067 #elif defined(_N64)
00068 CONVEX *LoadConvex(FIL *fp, INDEX *nSkins, int extraPtsPerEdge);
00069 SPHERE *LoadSpheres(FIL *fp, INDEX *nSpheres);
00070 #endif
00071 bool PointInConvex(VEC *pos, CONVEX *skin, PLANE *plane, REAL *minDepth);
00072 PLANE *LineToConvexColl(VEC *sPos, VEC *ePos, CONVEX *skin, REAL *penDepth, REAL *time);
00073 void ModifyShift(VEC *shift, REAL shiftMag, VEC *normal);
00074 bool PointInCollPolyBounds(VEC *pt, NEWCOLLPOLY *poly);
00075 bool SphereInCollPolyBounds(VEC *pt, REAL radius, NEWCOLLPOLY *poly);
00076 bool SphereConvex(VEC *spherePos, REAL sphereRad, CONVEX *skin,VEC *collPos, PLANE *collPlane, REAL *collDepth);
00077 void MakeAxisAlignedBBox(COLLSKIN *collSkin, BBOX *totBBox);
00078 void RotTransBBox(BBOX *bBoxIn, MAT *rotMat, VEC *dR, BBOX *bBoxOut);
00079 void TransBBox(BBOX *bBox, VEC *sPos);
00080 REAL CorrugationAmp(CORRUGATION *cor, REAL dx, REAL dy);
00081 int GetCollPolyVertices(NEWCOLLPOLY *poly, VEC *v0, VEC *v1, VEC *v2, VEC *v3);
00082 void AddPointToBBox(BBOX *bBox, VEC *pos);
00083 void AddPosRadToBBox(BBOX *bBox, VEC *pos, REAL radius);
00084 void RotTransBBox(BBOX *srcBox, MAT *mat, VEC *vec, BBOX *destBox);
00085
00086 bool LineOfSight(VEC *src, VEC *dest);
00087 bool LineOfSightDist(VEC *src, VEC *dest, REAL *minT, PLANE **plane);
00088 #ifdef _PC
00089 bool LineOfSightObj(VEC *src, VEC *dest, REAL *minT);
00090 bool LineOfSightBody(NEWBODY *body, VEC *src, VEC *dest, REAL *minDist);
00091 bool LineOfSightSphere(VEC *sphPos, REAL rad, VEC *src, VEC *dest, REAL *minDist);
00092 bool LineOfSightConvex(NEWBODY *body, VEC *src, VEC *dest, REAL *minDist);
00093 #endif
00094
00095 void RotTransCollPolys(NEWCOLLPOLY *collPoly, int nPolys, MAT *rMat, VEC *dPos);
00096 void TransCollPolys(NEWCOLLPOLY *collPoly, int nPolys, VEC *dPos);
00097 COLLINFO_BODY *NextBodyCollInfo();
00098
00099
00100 int NonPlanarCount = 0;
00101 int QuadCollCount = 0;
00102 int TriCollCount = 0;
00103
00105
00106
00107
00108
00109 NEWCOLLPOLY *COL_WorldCollPoly = NULL;
00110 INDEX COL_NWorldCollPolys = 0;
00111 NEWCOLLPOLY *COL_InstanceCollPoly = NULL;
00112 INDEX COL_NInstanceCollPolys = 0;
00113 COLLGRID_DATA COL_CollGridData;
00114 COLLGRID *COL_CollGrid;
00115 long COL_NCollGrids;
00116
00117
00118 COLLINFO_BODY COL_BodyCollInfo[MAX_COLLS_BODY];
00119 COLLINFO_WHEEL COL_WheelCollInfo[MAX_COLLS_WHEEL];
00120 int COL_NBodyColls = 0;
00121 int COL_NBodyDone = 0;
00122 int COL_NWheelColls = 0;
00123 int COL_NWheelDone = 0;
00124
00125
00126 COLLINFO_BODY *COL_ThisBodyColl[MAX_COLLS_PER_BODY];
00127 int COL_NThisBodyColls = 0;
00128 int COL_NCollsTested = 0;
00129
00130
00131
00132 PLANE DummyPlane;
00133 REAL DummyReal;
00134
00135
00137
00138
00139
00140
00141 static bool (*COL_ObjObjColl[MAX_COLL_TYPES][MAX_COLL_TYPES])(OBJECT *obj1, OBJECT *obj2) = {
00142
00143 {COL_Dummy2Coll, COL_Dummy2Coll, COL_Dummy2Coll, },
00144 {COL_Dummy2Coll, COL_BodyBodyColl, COL_BodyCarColl, },
00145 {COL_Dummy2Coll, COL_CarBodyColl, COL_CarCarColl, }
00146 };
00147
00148 static void (*COL_ObjWorldColl[MAX_COLL_TYPES])(OBJECT *obj) = {
00149 COL_DummyColl,
00150 COL_BodyWorldColl,
00151 COL_CarWorldColl,
00152 };
00153
00155
00156
00157
00158 MATERIAL COL_MaterialInfo[MATERIAL_NTYPES] = {
00159 {
00160 MATERIAL_SKID | MATERIAL_SPARK,
00161 Real(1.0),
00162 Real(1.0),
00163 Real(0.0),
00164 0x707070L,
00165 CORRUG_NONE,
00166 DUST_NONE,
00167 {ZERO, ZERO, ZERO}
00168 },
00169 {
00170 MATERIAL_SKID | MATERIAL_SPARK,
00171 Real(0.8),
00172 Real(0.9),
00173 Real(0.2),
00174 0x707070,
00175 CORRUG_NONE,
00176 DUST_NONE,
00177 {ZERO, ZERO, ZERO}
00178 },
00179 {
00180 MATERIAL_SKID | MATERIAL_SPARK,
00181 Real(0.9),
00182 Real(0.9),
00183 Real(0.2),
00184 0x909090,
00185 CORRUG_NONE,
00186 DUST_NONE,
00187 {ZERO, ZERO, ZERO}
00188 },
00189 {
00190 MATERIAL_SKID,
00191 Real(1.0),
00192 Real(1.0),
00193 Real(0.0),
00194 0x404040,
00195 CORRUG_NONE,
00196 DUST_NONE,
00197 {ZERO, ZERO, ZERO}
00198 },
00199 {
00200 MATERIAL_SKID | MATERIAL_DUSTY,
00201 Real(0.5),
00202 Real(0.6),
00203 Real(0.0),
00204 0x402040,
00205 CORRUG_NONE,
00206 DUST_SAND,
00207 {ZERO, ZERO, ZERO}
00208 },
00209 {
00210 MATERIAL_SKID,
00211 Real(0.7),
00212 Real(0.9),
00213 Real(0.1),
00214 0x404040,
00215 CORRUG_NONE,
00216 DUST_NONE,
00217 {ZERO, ZERO, ZERO}
00218 },
00219 {
00220 MATERIAL_SKID,
00221 Real(1.0),
00222 Real(0.7),
00223 Real(0.0),
00224 0x202020,
00225 CORRUG_NONE,
00226 DUST_NONE,
00227 {ZERO, ZERO, ZERO}
00228 },
00229 {
00230 MATERIAL_SKID,
00231 Real(1.0),
00232 Real(0.5),
00233 Real(0.0),
00234 0x202020,
00235 CORRUG_NONE,
00236 DUST_NONE,
00237 {ZERO, ZERO, ZERO}
00238 },
00239 {
00240 MATERIAL_OUTOFBOUNDS,
00241 Real(1.0),
00242 Real(1.0),
00243 Real(0.0),
00244 0x0,
00245 CORRUG_NONE,
00246 DUST_NONE,
00247 {ZERO, ZERO, ZERO}
00248 },
00249 {
00250 MATERIAL_SKID | MATERIAL_SPARK,
00251 Real(0.7),
00252 Real(0.8),
00253 Real(0.2),
00254 0x303030,
00255 CORRUG_NONE,
00256 DUST_NONE,
00257 {ZERO, ZERO, ZERO}
00258 },
00259 {
00260 MATERIAL_SKID | MATERIAL_SPARK,
00261 Real(0.3),
00262 Real(0.3),
00263 Real(0.2),
00264 0x303030,
00265 CORRUG_NONE,
00266 DUST_NONE,
00267 {ZERO, ZERO, ZERO}
00268 },
00269 {
00270 MATERIAL_SKID | MATERIAL_SPARK,
00271 Real(0.8),
00272 Real(0.8),
00273 Real(0.4),
00274 0x505050,
00275 CORRUG_NONE,
00276 DUST_NONE,
00277 {ZERO, ZERO, ZERO}
00278 },
00279 {
00280 MATERIAL_SKID | MATERIAL_SPARK | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00281 Real(0.7),
00282 Real(0.5),
00283 Real(0.0),
00284 0x207010,
00285 CORRUG_STEEL,
00286 DUST_MUD,
00287 {ZERO, ZERO, ZERO}
00288 },
00289 {
00290 MATERIAL_SKID | MATERIAL_SPARK | MATERIAL_CORRUGATED,
00291 Real(0.8),
00292 Real(0.8),
00293 Real(0.4),
00294 0x505050,
00295 CORRUG_STEEL,
00296 DUST_NONE,
00297 {ZERO, ZERO, ZERO}
00298 },
00299 {
00300 MATERIAL_SKID | MATERIAL_SPARK | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00301 Real(0.7),
00302 Real(0.7),
00303 Real(0.2),
00304 0x303030,
00305 CORRUG_PEBBLES,
00306 DUST_GRAVEL,
00307 {ZERO, ZERO, ZERO}
00308 },
00309 {
00310 MATERIAL_SKID | MATERIAL_SPARK | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00311 Real(0.9),
00312 Real(0.6),
00313 Real(0.2),
00314 0x303030,
00315 CORRUG_GRAVEL,
00316 DUST_GRAVEL,
00317 {ZERO, ZERO, ZERO}
00318 },
00319 {
00320 MATERIAL_MOVES | MATERIAL_CORRUGATED,
00321 Real(1.0),
00322 Real(1.0),
00323 Real(0.0),
00324 0x000000,
00325 CORRUG_STEEL,
00326 DUST_NONE,
00327 {-5 * 57.476f, -5 * 25.749f, 5 * 77.676f}
00328 },
00329 {
00330 MATERIAL_MOVES | MATERIAL_CORRUGATED,
00331 Real(1.0),
00332 Real(1.0),
00333 Real(0.0),
00334 0x000000,
00335 CORRUG_STEEL,
00336 DUST_NONE,
00337 {5 * 57.476f, 5 * 25.749f, -5 * 77.676f}
00338 },
00339 {
00340 MATERIAL_SKID | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00341 Real(0.9),
00342 Real(0.6),
00343 Real(0.2),
00344 0x303030,
00345 CORRUG_DIRT1,
00346 DUST_DIRT,
00347 {ZERO, ZERO, ZERO}
00348 },
00349 {
00350 MATERIAL_SKID | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00351 Real(0.9),
00352 Real(0.6),
00353 Real(0.2),
00354 0x303030,
00355 CORRUG_DIRT2,
00356 DUST_DIRT,
00357 {ZERO, ZERO, ZERO}
00358 },
00359 {
00360 MATERIAL_SKID | MATERIAL_CORRUGATED | MATERIAL_DUSTY,
00361 Real(0.9),
00362 Real(0.6),
00363 Real(0.2),
00364 0x303030,
00365 CORRUG_DIRT3,
00366 DUST_DIRT,
00367 {ZERO, ZERO, ZERO}
00368 },
00369 {
00370 MATERIAL_SKID | MATERIAL_SPARK,
00371 Real(0.45),
00372 Real(0.45),
00373 Real(0.2),
00374 0x303030,
00375 CORRUG_NONE,
00376 DUST_NONE,
00377 {ZERO, ZERO, ZERO}
00378 },
00379 {
00380 MATERIAL_SKID | MATERIAL_SPARK,
00381 Real(0.6),
00382 Real(0.6),
00383 Real(0.2),
00384 0x303030,
00385 CORRUG_NONE,
00386 DUST_NONE,
00387 {ZERO, ZERO, ZERO}
00388 },
00389
00390 };
00391
00392
00393 CORRUGATION COL_CorrugationInfo[CORRUG_NTYPES] = {
00394 {
00395 ZERO,
00396 ZERO,
00397 ZERO
00398 },
00399 {
00400 Real(4.0),
00401 Real(70.0),
00402 Real(70.0)
00403 },
00404 {
00405 Real(2.5),
00406 Real(40.0),
00407 Real(40.0)
00408 },
00409 {
00410 Real(1.0),
00411 Real(40.0),
00412 Real(40.0)
00413 },
00414 {
00415 Real(1.0),
00416 Real(80.0),
00417 Real(80.0)
00418 },
00419 {
00420 Real(1.0),
00421 Real(40.0),
00422 Real(40.0)
00423 },
00424 {
00425 Real(1.5),
00426 Real(80.0),
00427 Real(80.0)
00428 },
00429 {
00430 Real(2.0),
00431 Real(100.0),
00432 Real(100.0)
00433 },
00434 };
00435
00436 DUST COL_DustInfo[DUST_NTYPES] = {
00437 {
00438 SPARK_NONE,
00439 ZERO,
00440 ZERO
00441 },
00442 {
00443 SPARK_GRAVEL,
00444 Real(0.2),
00445 Real(0.6)
00446 },
00447 {
00448 SPARK_SAND,
00449 Real(0.2),
00450 Real(0.6)
00451 },
00452 {
00453 SPARK_MUD,
00454 Real(0.2),
00455 Real(0.6)
00456 },
00457 {
00458 SPARK_DIRT,
00459 Real(0.6),
00460 Real(0.8)
00461 }
00462 };
00463
00465
00466
00467
00468
00470
00471 void AdjustBodyColl(COLLINFO_BODY *collInfo, MATERIAL *material)
00472 {
00473 if (material == NULL) return;
00474
00475 if (MaterialMoves(material)) {
00476 VecMinusEqVec(&collInfo->Vel, &material->Vel);
00477 }
00478 }
00479
00481
00482
00483
00484
00486
00487 void AdjustWheelColl(COLLINFO_WHEEL *wheelColl, MATERIAL *material)
00488 {
00489 if (material == NULL) return;
00490
00491
00492 if (MaterialMoves(material)) {
00493 VecMinusEqVec(&wheelColl->Vel, &material->Vel);
00494 }
00495
00496
00497 if (MaterialCorrugated(material)) {
00498 wheelColl->Depth += CorrugationAmp(&COL_CorrugationInfo[material->Corrugation], wheelColl->WorldPos.v[X], wheelColl->WorldPos.v[Z]);
00499 }
00500 }
00501
00503
00504
00506
00507 void COL_DoObjectCollisions(void)
00508 {
00509 OBJECT *obj;
00510
00511 COL_AllObjectColls();
00512
00513
00514
00515 for (obj = OBJ_ObjectHead; obj; obj = obj->next)
00516 {
00517 if (obj->collhandler)
00518 {
00519 obj->collhandler(obj);
00520 }
00521 }
00522
00523 }
00524
00525
00527
00529
00530 void COL_AllObjectColls(void)
00531 {
00532 OBJECT *obj1, *obj2;
00533
00534
00535 COL_NBodyColls = 0;
00536 COL_NBodyDone = 0;
00537 COL_NWheelColls = 0;
00538 COL_NWheelDone = 0;
00539 ClearActivePairInfo();
00540 for (obj1 = OBJ_ObjectHead; obj1 != NULL; obj1 = obj1->next) {
00541 obj1->body.NBodyColls = 0;
00542 obj1->body.BodyCollHead = NULL;
00543 if (obj1->CollType == COLL_TYPE_CAR) {
00544 obj1->player->car.NWheelColls = 0;
00545 obj1->player->car.WheelCollHead = NULL;
00546 }
00547 }
00548
00549
00550 for (obj1 = OBJ_ObjectHead; obj1 != NULL; obj1 = obj1->next) {
00551
00552 Assert(obj1->CollType >= 0 && obj1->CollType < MAX_COLL_TYPES);
00553
00554
00555 if (obj1->body.CollSkin.AllowWorldColls) {
00556 COL_ObjWorldColl[obj1->CollType](obj1);
00557 }
00558
00559
00560 if (!obj1->body.CollSkin.AllowObjColls) continue;
00561
00562 for (obj2 = obj1->next; obj2 != NULL; obj2 = obj2->next) {
00563
00564 Assert(obj2->CollType >= 0 && obj2->CollType < MAX_COLL_TYPES);
00565
00566
00567 if (!obj2->body.CollSkin.AllowObjColls) continue;
00568
00569
00570 if (IsPairTested(obj1, obj2)) continue;
00571 SetPairTested(obj1, obj2);
00572
00573
00574 if (COL_ObjObjColl[obj1->CollType][obj2->CollType](obj1, obj2)) {
00575 SetPairCollided(obj1, obj2);
00576 }
00577 }
00578 }
00579 }
00580
00581
00582 void COL_DummyColl(OBJECT *obj)
00583 {
00584 }
00585
00586
00587 void COL_BodyWorldColl(OBJECT *obj)
00588 {
00589 Assert(obj->CollType == COLL_TYPE_BODY);
00590 DetectBodyWorldColls(&obj->body);
00591 }
00592
00593
00594 void COL_CarWorldColl(OBJECT *obj)
00595 {
00596 Assert(obj->CollType == COLL_TYPE_CAR);
00597 DetectCarWorldColls(&obj->player->car);
00598 }
00599
00600
00601 bool COL_BodyBodyColl(OBJECT *obj1, OBJECT *obj2)
00602 {
00603 Assert(obj1->CollType == COLL_TYPE_BODY && obj2->CollType == COLL_TYPE_BODY);
00604 if (DetectBodyBodyColls(&obj1->body, &obj2->body) > 0) {
00605 return TRUE;
00606 }
00607 return FALSE;
00608
00609 }
00610
00611
00612 bool COL_BodyCarColl(OBJECT *obj1, OBJECT *obj2)
00613 {
00614 Assert(obj1->CollType == COLL_TYPE_BODY && obj2->CollType == COLL_TYPE_CAR);
00615 if (DetectCarBodyColls(&obj2->player->car, &obj1->body) > 0) {
00616 return TRUE;
00617 }
00618 return FALSE;
00619 }
00620
00621
00622 bool COL_CarBodyColl(OBJECT *obj1, OBJECT *obj2)
00623 {
00624 Assert(obj1->CollType == COLL_TYPE_CAR && obj2->CollType == COLL_TYPE_BODY);
00625 if (DetectCarBodyColls(&obj1->player->car, &obj2->body) > 0) {
00626 return TRUE;
00627 }
00628 return FALSE;
00629 }
00630
00631
00632 bool COL_CarCarColl(OBJECT *obj1, OBJECT *obj2)
00633 {
00634 Assert(obj1->CollType == COLL_TYPE_CAR && obj2->CollType == COLL_TYPE_CAR);
00635 if (DetectCarCarColls(&obj1->player->car, &obj2->player->car) > 0) {
00636 return TRUE;
00637 }
00638 return FALSE;
00639 }
00640
00641
00642 bool COL_Dummy2Coll(OBJECT *obj1, OBJECT *obj2)
00643 {
00644 return FALSE;
00645 }
00646
00648
00650
00651 void COL_DummyCollHandler(OBJECT *obj)
00652 {
00653
00654 }
00655
00656
00658
00660
00661 void COL_BodyCollHandler(OBJECT *obj)
00662 {
00663 VEC imp, angImp;
00664 NEWBODY *body = &obj->body;
00665 FIELD_DATA fieldData;
00666
00667
00668 body->NWorldContacts = 0;
00669 body->NOtherContacts = 0;
00670 if (body->LastScrapeTime > MAX_SCRAPE_TIME) {
00671 body->ScrapeMaterial = MATERIAL_NONE;
00672 body->LastScrapeTime = ZERO;
00673 } else {
00674 body->LastScrapeTime += TimeStep;
00675 }
00676
00677
00678 fieldData.ObjectID = obj->ObjID;
00679 fieldData.Priority = obj->FieldPriority;
00680 fieldData.Mass = body->Centre.Mass;
00681 fieldData.Pos = &body->Centre.Pos;
00682 fieldData.Vel = &body->Centre.Vel;
00683 fieldData.Mat = &body->Centre.WMatrix;
00684 fieldData.AngVel = &body->AngVel;
00685 fieldData.Quat = &body->Centre.Quat;
00686 AllFieldImpulses(&fieldData, &imp, &angImp);
00687 VecPlusEqVec(&body->Centre.Impulse, &imp);
00688 VecPlusEqVec(&body->AngImpulse, &angImp);
00689
00690
00691
00692 BodyTurboBoost(body);
00693
00694
00695 if (obj->body.NBodyColls > 0) {
00696 PreProcessBodyColls(body);
00697 if (obj->body.NBodyColls > 0) {
00698 ProcessBodyColls3(body);
00699 PostProcessBodyColls(body);
00700 }
00701 }
00702
00703 }
00704
00706
00708 void COL_CarCollHandler(OBJECT *obj)
00709 {
00710 CAR *car = &obj->player->car;
00711
00712
00713 car->NWheelFloorContacts = 0;
00714 car->NWheelsInContact = 0;
00715
00716
00717 if (obj->player->car.NWheelColls > 0) {
00718 PreProcessCarWheelColls(car);
00719 ProcessCarWheelColls(car);
00720
00721 PostProcessCarWheelColls(car);
00722
00723 }
00724
00725
00726 CarDownForce(car);
00727
00728
00729 #ifdef _PC
00730 SpeedupImpulse(car);
00731 #endif
00732
00733
00734 COL_BodyCollHandler(obj);
00735
00736
00737 SetCarAngResistance(car);
00738 }
00739
00740
00742
00743
00744
00745
00747
00748 NEWCOLLPOLY *CreateCollPolys(short nPolys)
00749 {
00750 return ((NEWCOLLPOLY *)malloc(sizeof(NEWCOLLPOLY) * nPolys));
00751 }
00752
00753 void DestroyCollPolys(NEWCOLLPOLY *polys)
00754 {
00755 free(polys);
00756 }
00757
00758
00760
00761
00762
00763
00765
00766 COLLGRID *CreateCollGrids(long nGrids)
00767 {
00768 int iGrid;
00769 COLLGRID *newGrids;
00770
00771 newGrids = (COLLGRID *)malloc(sizeof(COLLGRID) * nGrids);
00772
00773
00774 if (newGrids != NULL) {
00775 for (iGrid = 0; iGrid < nGrids; iGrid++) {
00776 newGrids[iGrid].NCollPolys = 0;
00777 #ifndef _PSX
00778 newGrids[iGrid].CollPolyPtr = NULL;
00779 #else
00780 newGrids[iGrid].CollPolyIndices = NULL;
00781 #endif
00782 }
00783 }
00784
00785 return newGrids;
00786 }
00787
00788 void DestroyCollGrids()
00789 {
00790 int iGrid;
00791
00792 if (COL_CollGrid == NULL) return;
00793
00794 for (iGrid = 0; iGrid < COL_NCollGrids; iGrid++) {
00795 #ifndef _PSX
00796 free(COL_CollGrid[iGrid].CollPolyPtr);
00797 #else
00798 free(COL_CollGrid[iGrid].CollPolyIndices);
00799 #endif
00800 }
00801
00802 free(COL_CollGrid);
00803 COL_NCollGrids = 0;
00804
00805 }
00806
00807 #ifndef _PSX
00808 NEWCOLLPOLY **CreateCollPolyPtrs(int nPtrs)
00809 {
00810 return (NEWCOLLPOLY **)malloc(nPtrs * sizeof(NEWCOLLPOLY *));
00811 }
00812 #else
00813 short *CreateCollPolyIndices(int nPolys)
00814 {
00815 return (short *)malloc(nPolys * sizeof(short));
00816 }
00817 #endif
00818
00820
00821
00822
00823
00825
00826 long PosToCollGridCoords(VEC *pos, long *offsetX, long *offsetZ)
00827 {
00828 REAL dX, dZ;
00829
00830
00831 if ((COL_CollGridData.XNum == ZERO) && (COL_CollGridData.ZNum == ZERO)) {
00832 return 0;
00833 }
00834
00835
00836 dX = pos->v[X] - COL_CollGridData.XStart;
00837 dZ = pos->v[Z] - COL_CollGridData.ZStart;
00838 *offsetX = Int(DivScalar(dX, COL_CollGridData.GridSize));
00839 *offsetZ = Int(DivScalar(dZ, COL_CollGridData.GridSize));
00840
00841
00842 if ((*offsetX < 0L) || (*offsetX >= COL_CollGridData.XNum) ||
00843 (*offsetZ < 0L) || (*offsetZ >= COL_CollGridData.ZNum))
00844 {
00845 return -1;
00846 }
00847
00848 return *offsetX + NearestInt(COL_CollGridData.XNum) * *offsetZ;
00849 }
00850
00851
00852 long PosToCollGridNum(VEC *pos)
00853 {
00854 REAL dX, dZ;
00855 long offsetX, offsetZ;
00856
00857
00858 if ((COL_CollGridData.XNum == ZERO) && (COL_CollGridData.ZNum == ZERO)) {
00859 return 0;
00860 }
00861
00862
00863 dX = pos->v[X] - COL_CollGridData.XStart;
00864 dZ = pos->v[Z] - COL_CollGridData.ZStart;
00865 offsetX = Int(DivScalar(dX, COL_CollGridData.GridSize));
00866 offsetZ = Int(DivScalar(dZ, COL_CollGridData.GridSize));
00867
00868
00869 if ((offsetX < 0L) || (offsetX >= COL_CollGridData.XNum) ||
00870 (offsetZ < 0L) || (offsetZ >= COL_CollGridData.ZNum))
00871 {
00872 return -1;
00873 }
00874
00875 return offsetX + NearestInt(COL_CollGridData.XNum) * offsetZ;
00876 }
00877
00878 COLLGRID *PosToCollGrid(VEC *pos)
00879 {
00880 int gridNum;
00881
00882 gridNum = PosToCollGridNum(pos);
00883 if (gridNum < 0 ) {
00884 return NULL;
00885 } else {
00886 return &COL_CollGrid[gridNum];
00887 }
00888 }
00889
00890
00892
00893
00894
00895
00897 #ifndef _N64
00898 NEWCOLLPOLY *LoadNewCollPolys(FILE *fp, short *nPolys)
00899 {
00900 NEWCOLLPOLYHDR header;
00901 NEWCOLLPOLY * polys;
00902 size_t nRead;
00903 short iPoly;
00904
00905
00906 nRead = fread(&header, sizeof(NEWCOLLPOLYHDR), 1, fp);
00907 if (nRead < 1) {
00908 return NULL;
00909 }
00910
00911
00912 if ((polys = CreateCollPolys(header.NPolys)) == NULL) {
00913 return NULL;
00914 }
00915
00916
00917 NonPlanarCount = 0;
00918 QuadCollCount = 0;
00919 TriCollCount = 0;
00920 for (iPoly = 0; iPoly < header.NPolys; iPoly++) {
00921 nRead = fread(&polys[iPoly], sizeof(NEWCOLLPOLY), 1, fp);
00922 if (nRead < 1) {
00923 *nPolys = iPoly;
00924 return polys;
00925 }
00926
00927
00928 ExpandBBox(&polys[iPoly].BBox, COLL_EPSILON);
00929
00930 #if USE_DEBUG_ROUTINES
00931
00932 Assert((polys[iPoly].Material < MATERIAL_NTYPES) && (polys[iPoly].Material >= 0));
00933 if (polys[iPoly].Material >= MATERIAL_NTYPES || polys[iPoly].Material < 0) {
00934 polys[iPoly].Material = MATERIAL_DEFAULT;
00935 }
00936
00937 #endif
00938
00939
00940 if (IsPolyQuad(&polys[iPoly])) {
00941 QuadCollCount++;
00942 } else {
00943 TriCollCount++;
00944 }
00945
00946
00947 }
00948
00949
00950
00951
00952
00953 *nPolys = header.NPolys;
00954
00955
00956 return polys;
00957
00958 }
00959
00960
00961 bool LoadGridInfo(FILE *fp)
00962 {
00963 #ifndef _PSX
00964 long iPoly, iGrid, iInst, index;
00965 int instListSize, nextWorldPoly;
00966 long nInstPolys;
00967 #else
00968 short iPoly, iGrid, iInst, index;
00969 short instListSize, nextWorldPoly;
00970 short nInstPolys;
00971 #endif
00972 INSTANCE *instance;
00973 int xCount;
00974 REAL x1, z1;
00975 BBOX bBox;
00976 #ifndef _PSX
00977 int instList[MAX_INSTANCES];
00978 #endif
00979
00980
00981
00982 if (fread(&COL_CollGridData, sizeof(COLLGRID_DATA), 1, fp) < 1) {
00983
00984
00985 COL_CollGridData.XStart = ZERO;
00986 COL_CollGridData.ZStart = ZERO;
00987 COL_CollGridData.XNum = ZERO;
00988 COL_CollGridData.ZNum = ZERO;
00989 COL_CollGridData.GridSize = LARGEDIST;
00990
00991 COL_NCollGrids = 1;
00992 if ((COL_CollGrid = CreateCollGrids(COL_NCollGrids)) == NULL) {
00993 DestroyCollPolys(COL_WorldCollPoly);
00994 COL_WorldCollPoly = NULL;
00995 COL_NWorldCollPolys = 0;
00996 return FALSE;
00997 }
00998 COL_CollGrid[0].NCollPolys = COL_NWorldCollPolys;
00999 COL_CollGrid[0].NWorldPolys = COL_CollGrid[0].NCollPolys;
01000 #ifndef _PSX
01001 COL_CollGrid[0].CollPolyPtr = CreateCollPolyPtrs(COL_CollGrid[0].NCollPolys);
01002 if (COL_CollGrid[0].CollPolyPtr == NULL) {
01003 #else
01004 COL_CollGrid[0].CollPolyIndices = CreateCollPolyIndices(COL_CollGrid[0].NCollPolys);
01005 if (COL_CollGrid[0].CollPolyIndices == NULL) {
01006 #endif
01007 DestroyCollGrids();
01008 DestroyCollPolys(COL_WorldCollPoly);
01009 COL_WorldCollPoly = NULL;
01010 COL_NCollGrids = 0;
01011 COL_NWorldCollPolys = 0;
01012 return FALSE;
01013 }
01014 for (iPoly = 0; iPoly < COL_NWorldCollPolys; iPoly++) {
01015 #ifndef _PSX
01016 COL_CollGrid[0].CollPolyPtr[iPoly] = &COL_WorldCollPoly[iPoly];
01017 #else
01018 COL_CollGrid[0].CollPolyIndices[iPoly] = iPoly;
01019 #endif
01020 }
01021
01022 return FALSE;
01023 }
01024
01025
01026
01027 COL_NCollGrids = NearestInt(COL_CollGridData.XNum) * NearestInt(COL_CollGridData.ZNum);
01028 if ((COL_CollGrid = CreateCollGrids(COL_NCollGrids)) == NULL) {
01029 DestroyCollPolys(COL_WorldCollPoly);
01030 COL_WorldCollPoly = NULL;
01031 COL_NCollGrids = 0;
01032 COL_NWorldCollPolys = 0;
01033 return FALSE;
01034 }
01035
01036 x1 = COL_CollGridData.XStart;
01037 z1 = COL_CollGridData.ZStart;
01038 xCount = 0;
01039
01040 for (iGrid = 0; iGrid < COL_NCollGrids; iGrid++) {
01041
01042
01043 if (fread(&COL_CollGrid[iGrid].NCollPolys, sizeof(COL_CollGrid[iGrid].NCollPolys), 1, fp) < 1) {
01044 DestroyCollGrids();
01045 DestroyCollPolys(COL_WorldCollPoly);
01046 COL_WorldCollPoly = NULL;
01047 COL_NCollGrids = 0;
01048 COL_NWorldCollPolys = 0;
01049 return FALSE;
01050 }
01051
01052
01053 instListSize = 0;
01054 nInstPolys = 0;
01055 #ifndef _PSX
01056 SetBBox(&bBox, x1, x1 + COL_CollGridData.GridSize, -LARGEDIST, LARGEDIST, z1, z1 + COL_CollGridData.GridSize);
01057 for (iInst = 0; iInst < InstanceNum; iInst++) {
01058 if (BBTestXZY(&bBox, (BBOX *)&Instances[iInst].Box)) {
01059 instList[instListSize++] = iInst;
01060 nInstPolys += Instances[iInst].NCollPolys;
01061 }
01062 }
01063 (++xCount) %= NearestInt(COL_CollGridData.XNum);
01064 if (xCount == 0) {
01065 x1 = COL_CollGridData.XStart;
01066 z1 += COL_CollGridData.GridSize;
01067 } else {
01068 x1 += COL_CollGridData.GridSize;
01069 }
01070 #endif
01071
01072
01073 if (COL_CollGrid[iGrid].NCollPolys + nInstPolys == 0) {
01074 #ifndef _PSX
01075 COL_CollGrid[iGrid].CollPolyPtr = NULL;
01076 #else
01077 COL_CollGrid[iGrid].CollPolyIndices = NULL;
01078 #endif
01079 continue;
01080 } else {
01081 #ifndef _PSX
01082 COL_CollGrid[iGrid].CollPolyPtr = CreateCollPolyPtrs(COL_CollGrid[iGrid].NCollPolys + nInstPolys);
01083 if (COL_CollGrid[iGrid].CollPolyPtr == NULL) {
01084 #else
01085 COL_CollGrid[iGrid].CollPolyIndices = CreateCollPolyIndices(COL_CollGrid[iGrid].NCollPolys);
01086 if (COL_CollGrid[iGrid].CollPolyIndices == NULL) {
01087 #endif
01088 DestroyCollGrids();
01089 DestroyCollPolys(COL_WorldCollPoly);
01090 COL_WorldCollPoly = NULL;
01091 COL_NCollGrids = 0;
01092 COL_NWorldCollPolys = 0;
01093 return FALSE;
01094 }
01095 }
01096
01097
01098 for (iPoly = 0; iPoly < COL_CollGrid[iGrid].NCollPolys; iPoly++) {
01099 if (fread(&index, sizeof(index), 1, fp) < 1) {
01100 DestroyCollGrids();
01101 DestroyCollPolys(COL_WorldCollPoly);
01102 COL_WorldCollPoly = NULL;
01103 COL_NCollGrids = 0;
01104 COL_NWorldCollPolys = 0;
01105 return FALSE;
01106 }
01107 #ifndef _PSX
01108 COL_CollGrid[iGrid].CollPolyPtr[iPoly] = &COL_WorldCollPoly[index];
01109 #else
01110 COL_CollGrid[iGrid].CollPolyIndices[iPoly] = index;
01111 #endif
01112 }
01113
01114 #ifndef _PSX
01115
01116 nextWorldPoly = COL_CollGrid[iGrid].NCollPolys;
01117 for (iInst = 0; iInst < instListSize; iInst++) {
01118 instance = &Instances[instList[iInst]];
01119 for (iPoly = 0; iPoly < instance->NCollPolys; iPoly++) {
01120 COL_CollGrid[iGrid].CollPolyPtr[nextWorldPoly++] = instance->CollPoly + iPoly;
01121 }
01122 }
01123 COL_CollGrid[iGrid].NWorldPolys = COL_CollGrid[iGrid].NCollPolys;
01124 COL_CollGrid[iGrid].NCollPolys += nInstPolys;
01125 #else
01126 COL_CollGrid[iGrid].NWorldPolys = COL_CollGrid[iGrid].NCollPolys;
01127 #endif
01128
01129 }
01130
01131 return TRUE;
01132 }
01133 #else
01134
01135 #ifdef _N64
01136 NEWCOLLPOLY *LoadNewCollPolys(FIL *Fil, short *nPolys)
01137 {
01138 NEWCOLLPOLYHDR header;
01139 NEWCOLLPOLY * polys;
01140 size_t nRead;
01141 long ii;
01142
01143 printf("Loading new collision data...\n");
01144
01145 nRead = FFS_Read((char *)&header, sizeof(NEWCOLLPOLYHDR), Fil);
01146 if (nRead < sizeof(NEWCOLLPOLYHDR))
01147 {
01148 return NULL;
01149 }
01150 printf("...number of collison polys is %d\n", header.NPolys);
01151
01152
01153 if ((polys = CreateCollPolys(header.NPolys)) == NULL)
01154 {
01155 return NULL;
01156 }
01157
01158
01159 nRead = FFS_Read((char *)polys, sizeof(NEWCOLLPOLY) * header.NPolys, Fil);
01160 if (nRead < (sizeof(NEWCOLLPOLY) * header.NPolys))
01161 {
01162 DestroyCollPolys(polys);
01163 return NULL;
01164 }
01165 printf("...collison polys use %d bytes\n", sizeof(NEWCOLLPOLY) * header.NPolys);
01166
01167
01168 for (ii = 0; ii < header.NPolys; ii++)
01169 {
01170
01171 ExpandBBox(&polys[ii].BBox, COLL_EPSILON);
01172
01173
01174 #if USE_DEBUG_ROUTINES
01175 Assert((polys[ii].Material < MATERIAL_NTYPES) && (polys[ii].Material >= 0));
01176 if (polys[ii].Material >= MATERIAL_NTYPES || polys[ii].Material < 0) {
01177 polys[ii].Material = MATERIAL_DEFAULT;
01178 }
01179 #endif
01180 }
01181
01182
01183 *nPolys = header.NPolys;
01184 return polys;
01185 }
01186
01187
01188 bool LoadGridInfo(FIL *Fil)
01189 {
01190 int iPoly, iGrid, iInst, index;
01191 #ifdef 0
01192 int instList[MAX_INSTANCES];
01193 INSTANCE *instance;
01194 #endif
01195 int instListSize, nextWorldPoly;
01196 long nInstPolys;
01197 int xCount;
01198 REAL x1, z1;
01199 BBOX bBox;
01200
01201 printf("Load collison data grids...\n");
01202
01203 if (FFS_Read((char *)&COL_CollGridData, sizeof(COLLGRID_DATA), Fil) < sizeof(COLLGRID_DATA))
01204 {
01205
01206 printf("...No grid data found, creating grid system.\n");
01207 COL_CollGridData.XStart = ZERO;
01208 COL_CollGridData.ZStart = ZERO;
01209 COL_CollGridData.XNum = ZERO;
01210 COL_CollGridData.ZNum = ZERO;
01211 COL_CollGridData.GridSize = LARGEDIST;
01212
01213 COL_NCollGrids = 1;
01214 if ((COL_CollGrid = CreateCollGrids(COL_NCollGrids)) == NULL)
01215 {
01216 printf("...collison grids could not be created!\n");
01217 DestroyCollPolys(COL_WorldCollPoly);
01218 COL_NWorldCollPolys = 0;
01219 return FALSE;
01220 }
01221 COL_CollGrid[0].NCollPolys = COL_NWorldCollPolys;
01222 COL_CollGrid[0].CollPolyPtr = CreateCollPolyPtrs(COL_CollGrid[0].NCollPolys);
01223 if (COL_CollGrid[0].CollPolyPtr == NULL)
01224 {
01225 printf("...collison poly ptrs could not be created!\n");
01226 DestroyCollGrids();
01227 DestroyCollPolys(COL_WorldCollPoly);
01228 COL_NCollGrids = 0;
01229 COL_NWorldCollPolys = 0;
01230 return FALSE;
01231 }
01232 for (iPoly = 0; iPoly < COL_NWorldCollPolys; iPoly++)
01233 {
01234 COL_CollGrid[0].CollPolyPtr[iPoly] = &COL_WorldCollPoly[iPoly];
01235 }
01236 return FALSE;
01237 }
01238
01239
01240 COL_NCollGrids = NearestInt(COL_CollGridData.XNum) * NearestInt(COL_CollGridData.ZNum);
01241 printf("...found %d collison grids (%1.0f * %1.0f).\n", COL_NCollGrids, COL_CollGridData.XNum, COL_CollGridData.ZNum);
01242 if ((COL_CollGrid = CreateCollGrids(COL_NCollGrids)) == NULL)
01243 {
01244 printf("...collison grids could not be created!\n");
01245 DestroyCollPolys(COL_WorldCollPoly);
01246 COL_NCollGrids = 0;
01247 COL_NWorldCollPolys = 0;
01248 return FALSE;
01249 }
01250
01251 x1 = COL_CollGridData.XStart;
01252 z1 = COL_CollGridData.ZStart;
01253 xCount = 0;
01254
01255 for (iGrid = 0; iGrid < COL_NCollGrids; iGrid++) {
01256
01257
01258 if (FFS_Read((char *)&COL_CollGrid[iGrid].NCollPolys, sizeof(long), Fil) < 1)
01259 {
01260 DestroyCollGrids();
01261 DestroyCollPolys(COL_WorldCollPoly);
01262 COL_NCollGrids = 0;
01263 COL_NWorldCollPolys = 0;
01264 return FALSE;
01265 }
01266
01267
01268 instListSize = 0;
01269 nInstPolys = 0;
01270 #if 0
01271 SetBBox(&bBox, x1, x1 + COL_CollGridData.GridSize, -LARGEDIST, LARGEDIST, z1, z1 + COL_CollGridData.GridSize);
01272 for (iInst = 0; iInst < InstanceNum; iInst++)
01273 {
01274 if (BBTestXZY(&bBox, (BBOX *)&Instances[iInst].Box))
01275 {
01276 instList[instListSize++] = iInst;
01277 nInstPolys += Instances[iInst].NCollPolys;
01278 }
01279 }
01280 (++xCount) %= NearestInt(COL_CollGridData.XNum);
01281 if (xCount == 0)
01282 {
01283 x1 = COL_CollGridData.XStart;
01284 z1 += COL_CollGridData.GridSize;
01285 }
01286 else
01287 {
01288 x1 += COL_CollGridData.GridSize;
01289 }
01290 #endif
01291
01292 if (COL_CollGrid[iGrid].NCollPolys + nInstPolys == 0)
01293 {
01294 COL_CollGrid[iGrid].CollPolyPtr = NULL;
01295 continue;
01296 }
01297 else
01298 {
01299 COL_CollGrid[iGrid].CollPolyPtr = CreateCollPolyPtrs(COL_CollGrid[iGrid].NCollPolys + nInstPolys);
01300 if (COL_CollGrid[iGrid].CollPolyPtr == NULL)
01301 {
01302 printf("...collison poly ptrs could not be created!\n");
01303 DestroyCollGrids();
01304 DestroyCollPolys(COL_WorldCollPoly);
01305 COL_NCollGrids = 0;
01306 COL_NWorldCollPolys = 0;
01307 return FALSE;
01308 }
01309 }
01310
01311
01312 for (iPoly = 0; iPoly < COL_CollGrid[iGrid].NCollPolys; iPoly++)
01313 {
01314 if (FFS_Read(&index, sizeof(long), Fil) < 1)
01315 {
01316 printf("...failed to read from collsion file.\n");
01317 DestroyCollGrids();
01318 DestroyCollPolys(COL_WorldCollPoly);
01319 COL_NCollGrids = 0;
01320 COL_NWorldCollPolys = 0;
01321 return FALSE;
01322 }
01323 COL_CollGrid[iGrid].CollPolyPtr[iPoly] = &COL_WorldCollPoly[index];
01324 }
01325
01326 #if 0 // !MT! no instancing yet
01327
01328 nextWorldPoly = COL_CollGrid[iGrid].NCollPolys;
01329 for (iInst = 0; iInst < instListSize; iInst++)
01330 {
01331 instance = &Instances[instList[iInst]];
01332 for (iPoly = 0; iPoly < instance->NCollPolys; iPoly++)
01333 {
01334 COL_CollGrid[iGrid].CollPolyPtr[nextWorldPoly++] = instance->CollPoly + iPoly;
01335 }
01336 }
01337 COL_CollGrid[iGrid].NCollPolys += nInstPolys;
01338 #endif
01339 }
01340 return TRUE;
01341 }
01342 #endif
01343 #endif
01344
01346
01347
01348
01349
01351
01352 void ExpandBBox(BBOX *bBox, REAL delta)
01353 {
01354 bBox->XMin -= delta;
01355 bBox->XMax += delta;
01356 bBox->YMin -= delta;
01357 bBox->YMax += delta;
01358 bBox->ZMin -= delta;
01359 bBox->ZMax += delta;
01360 }
01361
01362
01364
01365
01366
01367
01369
01370 #ifdef _PC
01371 static REAL dist[4];
01372 static bool inside[4];
01373 bool SphereCollPoly(VEC *oldPos, VEC *newPos, REAL radius, NEWCOLLPOLY *collPoly, PLANE *plane, VEC *relPos, VEC *worldPos, REAL *depth, REAL *time)
01374 {
01375 REAL oldDist, newDist, dLen;
01376 int nSides, outCount, i;
01377
01378
01379 newDist = VecDotPlane(newPos, &collPoly->Plane);
01380 if (newDist - radius > COLL_EPSILON) return FALSE;
01381
01382
01383 oldDist = VecDotPlane(oldPos, &collPoly->Plane);
01384 if (oldDist < -(radius + COLL_EPSILON)) return FALSE;
01385
01386
01387 outCount = 0;
01388 if (IsPolyQuad(collPoly)) {
01389 nSides = 4;
01390 } else {
01391 nSides = 3;
01392 }
01393 for (i = 0; i < nSides; i++) {
01394 inside[i] = ((dist[i] = VecDotPlane(newPos, &collPoly->EdgePlane[i])) < COLL_EPSILON);
01395 if (!inside[i]) {
01396 outCount++;
01397 }
01398 }
01399
01400
01401
01402 if (outCount == 0) {
01403
01404
01405 *depth = newDist - radius;
01406
01407
01408 if (ApproxEqual(oldDist, newDist)) {
01409 *time = ZERO;
01410 } else {
01411 *time = DivScalar(oldDist, (oldDist - newDist));
01412 }
01413
01414
01415 CopyPlane(&collPoly->Plane, plane);
01416 VecEqScalarVec(relPos, -radius, PlaneNormal(plane));
01417 VecPlusScalarVec(newPos, -newDist, PlaneNormal(plane), worldPos);
01418
01419 return TRUE;
01420 }
01421
01422
01423 if (outCount == 1) {
01424
01425
01426 for (i = 0; i < nSides; i++) {
01427 if (inside[i]) continue;
01428
01429
01430 VecEqScalarVec(PlaneNormal(plane), -dist[i], PlaneNormal(&collPoly->EdgePlane[i]));
01431 VecPlusEqScalarVec(PlaneNormal(plane), -newDist, PlaneNormal(&collPoly->Plane));
01432 dLen = VecLen(PlaneNormal(plane));
01433 if (dLen > (radius)) {
01434 return FALSE;
01435 }
01436 VecPlusVec(PlaneNormal(plane), newPos, worldPos);
01437
01438
01439 *depth = dLen - radius;
01440
01441
01442 if (ApproxEqual(oldDist, newDist)) {
01443 *time = ZERO;
01444 } else {
01445 *time = DivScalar(oldDist, (oldDist - newDist));
01446 }
01447
01448 break;
01449 }
01450
01451
01452
01453 if (!PointInBBox(worldPos, &collPoly->BBox)) {
01454 return FALSE;
01455 }
01456
01457
01458 for (i = 0; i < nSides; i++) {
01459 if (!inside[i]) continue;
01460
01461 if (VecDotPlane(worldPos, &collPoly->EdgePlane[i]) > ZERO) {
01462 return FALSE;
01463 }
01464 }
01465
01466
01467 if (dLen > SMALL_REAL) {
01468
01469 VecDivScalar(PlaneNormal(plane), -dLen);
01470 } else {
01471 CopyPlane(&collPoly->Plane, plane);
01472 }
01473 VecEqScalarVec(relPos, -radius, PlaneNormal(plane));
01474
01475
01476 return TRUE;
01477 }
01478
01479
01480
01481 return FALSE;
01482
01483 }
01484
01485 #else // _PC
01486
01487 bool SphereCollPoly(VEC *oldPos, VEC *newPos, REAL radius, NEWCOLLPOLY *collPoly, PLANE *plane, VEC *relPos, VEC *worldPos, REAL *depth, REAL *time)
01488 {
01489 int ii, nSides;
01490 REAL oldDist, newDist;
01491
01492
01493 newDist = VecDotPlane(newPos, &collPoly->Plane);
01494 if (newDist - radius > COLL_EPSILON) return FALSE;
01495
01496
01497 oldDist = VecDotPlane(oldPos, &collPoly->Plane);
01498 if (oldDist < -(radius + COLL_EPSILON)) return FALSE;
01499
01500
01501 if (oldDist - newDist > SMALL_REAL) {
01502 *time = DivScalar((oldDist - radius), (oldDist - newDist));
01503 } else {
01504 *time = ZERO;
01505 }
01506
01507
01508
01509
01510
01511 if (*time < ZERO) *time = ZERO;
01512
01513
01514 ScalarVecPlusScalarVec((ONE - *time), oldPos, *time, newPos, worldPos);
01515
01516
01517 nSides = (IsPolyQuad(collPoly))? 4: 3;
01518 for (ii = 0; ii < nSides; ii++) {
01519 if (VecDotPlane(worldPos, &collPoly->EdgePlane[ii]) > COLL_EPSILON) return FALSE;
01520 }
01521
01522
01523 *depth = newDist - radius;
01524 CopyPlane(&collPoly->Plane, plane);
01525 VecEqScalarVec(relPos, -radius, PlaneNormal(plane));
01526
01527 return TRUE;
01528 }
01529
01530 #endif
01531
01533
01534
01535
01536
01537
01538
01539
01540
01541
01543
01544 bool LinePlaneIntersect(VEC *lStart, VEC *lEnd, PLANE *plane, REAL *t, REAL *depth)
01545 {
01546 REAL startDotPlane;
01547 REAL endDotPlane;
01548
01549 startDotPlane = VecDotPlane(lStart, plane);
01550 endDotPlane = VecDotPlane(lEnd, plane);
01551
01552
01553 if ((Sign(startDotPlane) == Sign(endDotPlane)) &&
01554 (abs(startDotPlane) > COLL_EPSILON) &&
01555 (abs(endDotPlane) > COLL_EPSILON)) return FALSE;
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 if (ApproxEqual(startDotPlane, endDotPlane)) {
01567 *t = ZERO;
01568 } else {
01569 *t = DivScalar(startDotPlane, (startDotPlane - endDotPlane));
01570 }
01571 *depth = endDotPlane;
01572
01573 return TRUE;
01574 }
01575
01576
01577
01579
01580
01581
01582
01584
01585 bool PosDirPlaneIntersect(VEC *lStart, VEC *dir, PLANE *plane, REAL *t)
01586 {
01587 REAL startDotPlane;
01588 REAL dirDotPlane;
01589
01590 startDotPlane = VecDotPlaneNorm(lStart, plane);
01591 dirDotPlane = VecDotPlaneNorm(dir, plane);
01592
01593
01594 if (abs(dirDotPlane) < SIMILAR_REAL) return FALSE;
01595
01596
01597 *t = - DivScalar((plane->v[D] + startDotPlane), dirDotPlane);
01598 return TRUE;
01599 }
01600
01601
01603
01604
01605
01607
01608 void FreeCollSkin(COLLSKIN *collSkin)
01609 {
01610
01611 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01612 DestroyConvex(collSkin->OldWorldConvex, collSkin->NConvex);
01613 collSkin->WorldConvex = NULL;
01614 collSkin->OldWorldConvex = NULL;
01615
01616 DestroySpheres(collSkin->WorldSphere);
01617 DestroySpheres(collSkin->OldWorldSphere);
01618 collSkin->WorldSphere = NULL;
01619 collSkin->OldWorldSphere = NULL;
01620
01621 DestroyCollPolys(collSkin->CollPoly);
01622 collSkin->CollPoly = NULL;
01623 collSkin->NCollPolys = 0;
01624
01625 }
01626
01628
01629
01630
01632
01633 CONVEX *CreateConvex(INDEX nConvex)
01634 {
01635 int iSkin;
01636 CONVEX *skin;
01637
01638 Assert(nConvex > 0);
01639
01640
01641 if ((skin = (CONVEX *)malloc(sizeof(CONVEX) * nConvex)) == NULL) {
01642 return NULL;
01643 }
01644
01645 for (iSkin = 0; iSkin < nConvex; iSkin++) {
01646 skin[iSkin].NPts = 0;
01647 skin[iSkin].NEdges = 0;
01648 skin[iSkin].NFaces = 0;
01649 skin[iSkin].Pts = NULL;
01650 skin[iSkin].Edges = NULL;
01651 skin[iSkin].Faces = NULL;
01652 }
01653
01654 return skin;
01655 }
01656
01657
01659
01660
01661
01662
01664
01665 bool SetupConvex(CONVEX *skin, INDEX nPts, INDEX extraPts, INDEX nEdges, INDEX nFaces)
01666 {
01667
01668 Assert((nPts > 0) && (nEdges > 0) && (nFaces > 0));
01669
01670
01671 if (nPts != 0) {
01672 if ((skin->Pts = (VERTEX *)malloc(sizeof(VERTEX) * (nPts + extraPts))) == NULL) {
01673 return FALSE;
01674 }
01675 }
01676
01677
01678 if (nEdges != 0) {
01679 if ((skin->Edges = (EDGE *)malloc(sizeof(EDGE) * nEdges)) == NULL) {
01680 free(skin->Pts);
01681 return FALSE;
01682 }
01683 }
01684
01685
01686 if (nFaces != 0) {
01687 if ((skin->Faces = (PLANE *)malloc(sizeof(PLANE) * nFaces)) == NULL) {
01688 free(skin->Edges);
01689 free(skin->Pts);
01690 return FALSE;
01691 }
01692 }
01693
01694 skin->NPts = nPts + extraPts;
01695 skin->NEdges = nEdges;
01696 skin->NFaces = nFaces;
01697
01698 return TRUE;
01699 }
01700
01701
01703
01704
01705
01707
01708 void DestroyConvex(CONVEX *skin, int nSkins)
01709 {
01710 int iSkin;
01711
01712 if ((skin == NULL) || (nSkins ==0)) return;
01713
01714 for (iSkin = 0; iSkin < nSkins; iSkin++) {
01715 free(skin[iSkin].Faces);
01716 free(skin[iSkin].Edges);
01717 free(skin[iSkin].Pts);
01718 }
01719 free(skin);
01720 }
01721
01722 void DestroySpheres(SPHERE *spheres)
01723 {
01724 free(spheres);
01725 }
01726
01728
01729
01730
01731
01733
01734 bool CreateCopyCollSkin(COLLSKIN *collSkin)
01735 {
01736 int iSkin, ii;
01737
01738
01739 if (collSkin->NConvex > 0) {
01740 collSkin->WorldConvex = CreateConvex(collSkin->NConvex);
01741 if (collSkin->WorldConvex == NULL) {
01742 return FALSE;
01743 }
01744 collSkin->OldWorldConvex = CreateConvex(collSkin->NConvex);
01745 if (collSkin->OldWorldConvex == NULL) {
01746 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01747 return FALSE;
01748 }
01749 }
01750
01751
01752 if (collSkin->NSpheres > 0) {
01753 collSkin->WorldSphere = (SPHERE *)malloc(sizeof(SPHERE) * collSkin->NSpheres);
01754 if (collSkin->WorldSphere == NULL) {
01755 DestroyConvex(collSkin->OldWorldConvex, collSkin->NConvex);
01756 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01757 return FALSE;
01758 }
01759 collSkin->OldWorldSphere = (SPHERE *)malloc(sizeof(SPHERE) * collSkin->NSpheres);
01760 if (collSkin->OldWorldSphere == NULL) {
01761 DestroyConvex(collSkin->OldWorldConvex, collSkin->NConvex);
01762 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01763 DestroySpheres(collSkin->WorldSphere);
01764 return FALSE;
01765 }
01766 }
01767
01768
01769 for (iSkin = 0; iSkin < collSkin->NConvex; iSkin++) {
01770
01771
01772 if (!SetupConvex(&collSkin->WorldConvex[iSkin], collSkin->Convex[iSkin].NPts, 0, collSkin->Convex[iSkin].NEdges, collSkin->Convex[iSkin].NFaces)) {
01773 DestroyConvex(collSkin->OldWorldConvex, collSkin->NConvex);
01774 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01775 DestroySpheres(collSkin->WorldSphere);
01776 DestroySpheres(collSkin->OldWorldSphere);
01777 return FALSE;
01778 }
01779 collSkin->WorldConvex[iSkin].NPts = collSkin->Convex[iSkin].NPts;
01780 collSkin->WorldConvex[iSkin].NEdges = collSkin->Convex[iSkin].NEdges;
01781 collSkin->WorldConvex[iSkin].NFaces = collSkin->Convex[iSkin].NFaces;
01782
01783 if (!SetupConvex(&collSkin->OldWorldConvex[iSkin], collSkin->Convex[iSkin].NPts, 0, collSkin->Convex[iSkin].NEdges, collSkin->Convex[iSkin].NFaces)) {
01784 DestroyConvex(collSkin->OldWorldConvex, collSkin->NConvex);
01785 DestroyConvex(collSkin->WorldConvex, collSkin->NConvex);
01786 DestroySpheres(collSkin->OldWorldSphere);
01787 DestroySpheres(collSkin->WorldSphere);
01788 return FALSE;
01789 }
01790 collSkin->OldWorldConvex[iSkin].NPts = collSkin->Convex[iSkin].NPts;
01791 collSkin->OldWorldConvex[iSkin].NEdges = collSkin->Convex[iSkin].NEdges;
01792 collSkin->OldWorldConvex[iSkin].NFaces = collSkin->Convex[iSkin].NFaces;
01793
01794
01795 CopyBBox(&collSkin->Convex[iSkin].BBox, &collSkin->WorldConvex[iSkin].BBox);
01796
01797 CopyBBox(&collSkin->Convex[iSkin].BBox, &collSkin->OldWorldConvex[iSkin].BBox);
01798
01799
01800
01801 for (ii = 0; ii < collSkin->Convex[iSkin].NPts; ii++) {
01802 CopyVec(&collSkin->Convex[iSkin].Pts[ii], &collSkin->WorldConvex[iSkin].Pts[ii]);
01803 CopyVec(&collSkin->Convex[iSkin].Pts[ii], &collSkin->OldWorldConvex[iSkin].Pts[ii]);
01804 }
01805
01806
01807 for (ii = 0; ii < collSkin->Convex[iSkin].NEdges; ii++) {
01808 collSkin->WorldConvex[iSkin].Edges[ii].Vtx[0] = collSkin->Convex[iSkin].Edges[ii].Vtx[0];
01809 collSkin->WorldConvex[iSkin].Edges[ii].Vtx[1] = collSkin->Convex[iSkin].Edges[ii].Vtx[1];
01810 collSkin->OldWorldConvex[iSkin].Edges[ii].Vtx[0] = collSkin->Convex[iSkin].Edges[ii].Vtx[0];
01811 collSkin->OldWorldConvex[iSkin].Edges[ii].Vtx[1] = collSkin->Convex[iSkin].Edges[ii].Vtx[1];
01812 }
01813
01814
01815 for (ii = 0; ii < collSkin->Convex[iSkin].NFaces; ii++) {
01816 CopyPlane(&collSkin->Convex[iSkin].Faces[ii], &collSkin->WorldConvex[iSkin].Faces[ii]);
01817 CopyPlane(&collSkin->Convex[iSkin].Faces[ii], &collSkin->OldWorldConvex[iSkin].Faces[ii]);
01818 }
01819 }
01820
01821
01822 for (iSkin = 0; iSkin < collSkin->NSpheres; iSkin++) {
01823
01824 CopyVec(&collSkin->Sphere[iSkin].Pos, &collSkin->WorldSphere[iSkin].Pos);
01825 collSkin->WorldSphere[iSkin].Radius = collSkin->Sphere[iSkin].Radius;
01826 CopyVec(&collSkin->Sphere[iSkin].Pos, &collSkin->OldWorldSphere[iSkin].Pos);
01827 collSkin->OldWorldSphere[iSkin].Radius = collSkin->Sphere[iSkin].Radius;
01828
01829 }
01830
01831 return TRUE;
01832 }
01833
01835
01836
01837
01838
01839
01841
01842 void BuildWorldSkin(COLLSKIN *bodySkin, VEC *pos, MAT *mat)
01843 {
01844 int iSkin, ii;
01845 VEC tmpVec;
01846 CONVEX *thisBodySkin, *thisWorldSkin;
01847 SPHERE *thisBodySphere, *thisWorldSphere;
01848
01849
01850 for (iSkin = 0; iSkin < bodySkin->NConvex; iSkin++) {
01851 thisBodySkin = &bodySkin->Convex[iSkin];
01852 thisWorldSkin = &bodySkin->WorldConvex[iSkin];
01853
01854
01855
01856
01857
01858 for (ii = 0; ii < thisBodySkin->NPts; ii++) {
01859 VecMulMat(&thisBodySkin->Pts[ii], mat, &tmpVec);
01860 VecPlusVec(&tmpVec, pos, &thisWorldSkin->Pts[ii]);
01861 }
01862
01863
01864 for (ii = 0; ii < thisBodySkin->NFaces; ii++) {
01865 RotTransPlane(&thisBodySkin->Faces[ii], mat, pos, &thisWorldSkin->Faces[ii]);
01866 }
01867
01868
01869 RotTransBBox(&thisBodySkin->BBox, mat, pos, &thisWorldSkin->BBox);
01870 }
01871
01872
01873 for (iSkin = 0; iSkin < bodySkin->NSpheres; iSkin++) {
01874 thisBodySphere = &bodySkin->Sphere[iSkin];
01875 thisWorldSphere = &bodySkin->WorldSphere[iSkin];
01876
01877
01878 VecMulMat(&thisBodySphere->Pos, mat, &thisWorldSphere->Pos);
01879 VecPlusEqVec(&thisWorldSphere->Pos, pos);
01880 }
01881
01882
01883 RotTransBBox(&bodySkin->TightBBox, mat, pos, &bodySkin->BBox);
01884
01885 }
01886
01887
01888
01890
01891
01892
01893
01895
01896 #ifdef _PC
01897 CONVEX *LoadConvex(FILE *fp, INDEX *nSkins, int extraPtsPerEdge)
01898 {
01899 int iSkin, iEdge, iPt, nExtraPts, ptNum;
01900 VEC offset;
01901
01902 COLLSKIN_FILEHDR fileHdr;
01903 COLLSKIN_COLLHDR collHdr;
01904 CONVEX *collSkin;
01905
01906 *nSkins = 0;
01907
01908 if (fp == NULL) {
01909 *nSkins = 0;
01910 return NULL;
01911 }
01912
01913
01914 if (fread(&fileHdr, sizeof(COLLSKIN_FILEHDR), 1, fp) != 1) {
01915 *nSkins = 0;
01916 return NULL;
01917 }
01918 if ((collSkin = CreateConvex(fileHdr.NSkins)) == NULL) {
01919 *nSkins = 0;
01920 return NULL;
01921 }
01922
01923
01924 for (iSkin = 0; iSkin < fileHdr.NSkins; iSkin++) {
01925
01926
01927 if (fread(&collHdr, sizeof(COLLSKIN_COLLHDR), 1, fp) != 1) {
01928 DestroyConvex(collSkin, fileHdr.NSkins);
01929 *nSkins = 0;
01930 return NULL;
01931 }
01932
01933
01934
01935 nExtraPts = collHdr.NEdges * extraPtsPerEdge;
01936
01937
01938 if (!SetupConvex(&collSkin[iSkin], collHdr.NVertices, nExtraPts, collHdr.NEdges, collHdr.NFaces)) {
01939 DestroyConvex(collSkin, fileHdr.NSkins);
01940 *nSkins = 0;
01941 return NULL;
01942 }
01943
01944
01945 if (fread(&collSkin[iSkin].BBox, sizeof(BBOX), 1, fp) != 1) {
01946 DestroyConvex(collSkin, fileHdr.NSkins);
01947 *nSkins = 0;
01948 return NULL;
01949 }
01950
01951 if (fread(&offset, sizeof(VEC), 1, fp) != 1) {
01952 DestroyConvex(collSkin, fileHdr.NSkins);
01953 *nSkins = 0;
01954 return NULL;
01955 }
01956
01957
01958 if (fread(collSkin[iSkin].Pts, sizeof(VERTEX), collHdr.NVertices, fp) != (size_t)collHdr.NVertices) {
01959 DestroyConvex(collSkin, fileHdr.NSkins);
01960 *nSkins = 0;
01961 return NULL;
01962 }
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975 if (fread(collSkin[iSkin].Edges, sizeof(EDGE), collSkin[iSkin].NEdges, fp) != (size_t)collSkin[iSkin].NEdges) {
01976 DestroyConvex(collSkin, fileHdr.NSkins);
01977 *nSkins = 0;
01978 return NULL;
01979 }
01980
01981
01982 if (fread(collSkin[iSkin].Faces, sizeof(PLANE), collSkin[iSkin].NFaces, fp) != (size_t)collSkin[iSkin].NFaces) {
01983 DestroyConvex(collSkin, fileHdr.NSkins);
01984 *nSkins = 0;
01985 return NULL;
01986 }
01987
01988
01989 ptNum = collHdr.NVertices;
01990 for (iEdge = 0; iEdge < collHdr.NEdges; iEdge++) {
01991 for (iPt = 0; iPt < extraPtsPerEdge; iPt++) {
01992 VecPlusVec(
01993 &collSkin[iSkin].Pts[collSkin[iSkin].Edges[iEdge].Vtx[0]],
01994 &collSkin[iSkin].Pts[collSkin[iSkin].Edges[iEdge].Vtx[1]],
01995 &collSkin[iSkin].Pts[ptNum]);
01996 VecMulScalar(&collSkin[iSkin].Pts[ptNum], HALF);
01997 ptNum++;
01998 }
01999 }
02000 Assert(ptNum == collSkin[iSkin].NPts);
02001
02002 }
02003
02004 *nSkins = fileHdr.NSkins;
02005 return collSkin;
02006 }
02007
02008 SPHERE *LoadSpheres(FILE *fp, INDEX *nSpheres)
02009 {
02010 INDEX iSphere;
02011 SPHERE *spheres;
02012 size_t nRead;
02013
02014 Assert(fp != NULL);
02015
02016
02017 nRead = fread(nSpheres, sizeof(INDEX), 1, fp);
02018 if (nRead < 1) {
02019 *nSpheres = 0;
02020 return NULL;
02021 }
02022
02023
02024 spheres = (SPHERE *)malloc(sizeof(SPHERE) * *nSpheres);
02025 if (spheres == NULL) {
02026 *nSpheres = 0;
02027 return NULL;
02028 }
02029
02030
02031
02032
02033
02034 for (iSphere = 0; iSphere < *nSpheres; iSphere++) {
02035 nRead = fread(&spheres[iSphere], sizeof(SPHERE), 1, fp);
02036 if (nRead < 1) {
02037 *nSpheres = iSphere;
02038 return spheres;
02039 }
02040 }
02041
02042 Assert(iSphere == *nSpheres);
02043
02044 return spheres;
02045 }
02046
02047 #elif defined(_PSX)
02048 CONVEX *LoadConvex(FILE *fp, INDEX *nSkins, int extraPtsPerEdge)
02049 {
02050 int iSkin, iEdge, iPt, ptNum;
02051 VEC offset;
02052
02053 COLLSKIN_FILEHDR fileHdr;
02054 COLLSKIN_COLLHDR collHdr;
02055 CONVEX *collSkin;
02056
02057 *nSkins = 0;
02058
02059 if (fp == NULL) {
02060 *nSkins = 0;
02061 return NULL;
02062 }
02063
02064
02065 if (fread(&fileHdr, sizeof(COLLSKIN_FILEHDR), 1, fp) != 1) {
02066 *nSkins = 0;
02067 return NULL;
02068 }
02069 if ((collSkin = CreateConvex(fileHdr.NSkins)) == NULL) {
02070 *nSkins = 0;
02071 return NULL;
02072 }
02073
02074
02075 for (iSkin = 0; iSkin < fileHdr.NSkins; iSkin++) {
02076
02077
02078 if (fread(&collHdr, sizeof(COLLSKIN_COLLHDR), 1, fp) != 1) {
02079 DestroyConvex(collSkin, fileHdr.NSkins);
02080 *nSkins = 0;
02081 return NULL;
02082 }
02083
02084
02085 if (!SetupConvex(&collSkin[iSkin], collHdr.NVertices, 0, collHdr.NEdges, collHdr.NFaces)) {
02086 DestroyConvex(collSkin, fileHdr.NSkins);
02087 *nSkins = 0;
02088 return NULL;
02089 }
02090
02091
02092 if (fread(&collSkin[iSkin].BBox, sizeof(BBOX), 1, fp) != 1) {
02093 DestroyConvex(collSkin, fileHdr.NSkins);
02094 *nSkins = 0;
02095 return NULL;
02096 }
02097
02098 if (fread(&offset, sizeof(VEC), 1, fp) != 1) {
02099 DestroyConvex(collSkin, fileHdr.NSkins);
02100 *nSkins = 0;
02101 return NULL;
02102 }
02103
02104
02105 if (fread(collSkin[iSkin].Pts, sizeof(VERTEX), collHdr.NVertices, fp) != (size_t)collHdr.NVertices) {
02106 DestroyConvex(collSkin, fileHdr.NSkins);
02107 *nSkins = 0;
02108 return NULL;
02109 }
02110
02111
02112 if (fread(collSkin[iSkin].Edges, sizeof(EDGE), collSkin[iSkin].NEdges, fp) != (size_t)collSkin[iSkin].NEdges) {
02113 DestroyConvex(collSkin, fileHdr.NSkins);
02114 *nSkins = 0;
02115 return NULL;
02116 }
02117
02118
02119 if (fread(collSkin[iSkin].Faces, sizeof(PLANE), collSkin[iSkin].NFaces, fp) != (size_t)collSkin[iSkin].NFaces) {
02120 DestroyConvex(collSkin, fileHdr.NSkins);
02121 *nSkins = 0;
02122 return NULL;
02123 }
02124
02125
02126 }
02127
02128 *nSkins = fileHdr.NSkins;
02129 return collSkin;
02130 }
02131
02132 SPHERE *LoadSpheres(FILE *fp, INDEX *nSpheres)
02133 {
02134 INDEX iSphere;
02135 SPHERE *spheres;
02136 size_t nRead;
02137
02138 Assert(fp != NULL);
02139
02140
02141 nRead = fread(nSpheres, sizeof(INDEX), 1, fp);
02142 if (nRead < 1) {
02143 *nSpheres = 0;
02144 return NULL;
02145 }
02146
02147
02148 spheres = (SPHERE *)malloc(sizeof(SPHERE) * *nSpheres);
02149 if (spheres == NULL) {
02150 *nSpheres = 0;
02151 return NULL;
02152 }
02153
02154
02155
02156
02157
02158 for (iSphere = 0; iSphere < *nSpheres; iSphere++) {
02159 nRead = fread(&spheres[iSphere], sizeof(SPHERE), 1, fp);
02160 if (nRead < 1) {
02161 *nSpheres = iSphere;
02162 return spheres;
02163 }
02164 }
02165
02166 Assert(iSphere == *nSpheres);
02167
02168 return spheres;
02169 }
02170
02171 #elif defined(_N64)
02172 CONVEX *LoadConvex(FIL *fp, INDEX *nSkins, int extraPtsPerEdge)
02173 {
02174 int iSkin, iEdge, iPt, nExtraPts, ptNum;
02175
02176 COLLSKIN_FILEHDR fileHdr;
02177 COLLSKIN_COLLHDR collHdr;
02178 CONVEX *collSkin;
02179 VEC arse;
02180
02181 *nSkins = 0;
02182
02183 if (fp == NULL)
02184 {
02185 *nSkins = 0;
02186 return NULL;
02187 }
02188
02189
02190 if (FFS_Read(&fileHdr, sizeof(COLLSKIN_FILEHDR), fp) < sizeof(COLLSKIN_FILEHDR))
02191 {
02192 *nSkins = 0;
02193 return NULL;
02194 }
02195
02196 if ((collSkin = CreateConvex(fileHdr.NSkins)) == NULL)
02197 {
02198 *nSkins = 0;
02199 return NULL;
02200 }
02201
02202
02203 for (iSkin = 0; iSkin < fileHdr.NSkins; iSkin++)
02204 {
02205
02206 if (FFS_Read(&collHdr, sizeof(COLLSKIN_COLLHDR), fp) != sizeof(COLLSKIN_COLLHDR))
02207 {
02208 DestroyConvex(collSkin, fileHdr.NSkins);
02209 *nSkins = 0;
02210 return NULL;
02211 }
02212
02213
02214
02215 nExtraPts = collHdr.NEdges * extraPtsPerEdge;
02216
02217
02218 if (!SetupConvex(&collSkin[iSkin], collHdr.NVertices, nExtraPts, collHdr.NEdges, collHdr.NFaces))
02219 {
02220 DestroyConvex(collSkin, fileHdr.NSkins);
02221 *nSkins = 0;
02222 return NULL;
02223 }
02224
02225
02226 if (FFS_Read(&collSkin[iSkin].BBox, sizeof(BBOX), fp) != sizeof(BBOX))
02227 {
02228 DestroyConvex(collSkin, fileHdr.NSkins);
02229 *nSkins = 0;
02230 return NULL;
02231 }
02232 if (FFS_Read(&arse, sizeof(VEC), fp) != sizeof(VEC))
02233 {
02234 DestroyConvex(collSkin, fileHdr.NSkins);
02235 *nSkins = 0;
02236 return NULL;
02237 }
02238
02239
02240 if (FFS_Read(collSkin[iSkin].Pts, sizeof(VERTEX) * collHdr.NVertices, fp) != (sizeof(VERTEX) * collHdr.NVertices))
02241 {
02242 DestroyConvex(collSkin, fileHdr.NSkins);
02243 *nSkins = 0;
02244 return NULL;
02245 }
02246
02247
02248 if (FFS_Read(collSkin[iSkin].Edges, sizeof(EDGE) * collSkin[iSkin].NEdges, fp) != (sizeof(EDGE) * collSkin[iSkin].NEdges))
02249 {
02250 DestroyConvex(collSkin, fileHdr.NSkins);
02251 *nSkins = 0;
02252 return NULL;
02253 }
02254
02255
02256 if (FFS_Read(collSkin[iSkin].Faces, sizeof(PLANE) * collSkin[iSkin].NFaces, fp) != (sizeof(PLANE) * collSkin[iSkin].NFaces))
02257 {
02258 DestroyConvex(collSkin, fileHdr.NSkins);
02259 *nSkins = 0;
02260 return NULL;
02261 }
02262
02263
02264 ptNum = collHdr.NVertices;
02265 for (iEdge = 0; iEdge < collHdr.NEdges; iEdge++)
02266 {
02267 for (iPt = 0; iPt < extraPtsPerEdge; iPt++)
02268 {
02269 VecPlusVec(
02270 &collSkin[iSkin].Pts[collSkin[iSkin].Edges[iEdge].Vtx[0]],
02271 &collSkin[iSkin].Pts[collSkin[iSkin].Edges[iEdge].Vtx[1]],
02272 &collSkin[iSkin].Pts[ptNum]);
02273 VecMulScalar(&collSkin[iSkin].Pts[ptNum], HALF);
02274 ptNum++;
02275 }
02276 }
02277 Assert(ptNum == collSkin[iSkin].NPts);
02278 }
02279
02280 *nSkins = fileHdr.NSkins;
02281 return collSkin;
02282 }
02283
02284
02285 SPHERE *LoadSpheres(FIL *fp, INDEX *nSpheres)
02286 {
02287 INDEX iSphere;
02288 SPHERE *spheres;
02289 size_t nRead;
02290
02291 Assert(fp != NULL);
02292
02293
02294 nRead = FFS_Read(nSpheres, sizeof(INDEX), fp);
02295 if (nRead < sizeof(INDEX))
02296 {
02297 *nSpheres = 0;
02298 return NULL;
02299 }
02300
02301
02302 spheres = (SPHERE *)malloc(sizeof(SPHERE) * *nSpheres);
02303 if (spheres == NULL)
02304 {
02305 *nSpheres = 0;
02306 return NULL;
02307 }
02308
02309
02310
02311
02312
02313 for (iSphere = 0; iSphere < *nSpheres; iSphere++)
02314 {
02315 nRead = FFS_Read(&spheres[iSphere], sizeof(SPHERE), fp);
02316 if (nRead < sizeof(SPHERE)) {
02317 *nSpheres = iSphere;
02318 return spheres;
02319 }
02320 }
02321
02322 Assert(iSphere == *nSpheres);
02323
02324 return spheres;
02325 }
02326
02327 #endif
02328
02329
02330
02332
02333
02334
02335
02337
02338 bool PointInConvex(VEC *pos, CONVEX *skin, PLANE *plane, REAL *minDepth)
02339 {
02340 int iFace;
02341
02342 REAL depth;
02343
02344 *minDepth = -LARGEDIST;
02345
02346
02347
02348 for (iFace = 0; iFace < skin->NFaces; iFace++) {
02349 depth = VecDotPlane(pos, &skin->Faces[iFace]);
02350 if (depth > COLL_EPSILON) return FALSE;
02351 if (depth > *minDepth) {
02352 *minDepth = depth;
02353 CopyPlane(&skin->Faces[iFace], plane);
02354 }
02355 }
02356
02357 return TRUE;
02358 }
02359
02361
02362
02363
02364
02365
02366
02368
02369 PLANE *LineToConvexColl(VEC *sPos, VEC *ePos, CONVEX *skin, REAL *penDepth, REAL *time)
02370 {
02371 int iFace;
02372 REAL depth, depth2, minDepth, sDist;
02373 REAL minTime, timeDepth;
02374 VEC pos, dR;
02375 PLANE *nearPlane, *entryPlane, plane;
02376
02377 VecMinusVec(ePos, sPos, &dR);
02378
02379
02380 minDepth = -LARGEDIST;
02381 for (iFace = 0; iFace < skin->NFaces; iFace++) {
02382 depth = VecDotPlane(ePos, &skin->Faces[iFace]);
02383 if (depth > COLL_EPSILON) return NULL;
02384 if (depth > minDepth) {
02385 minDepth = depth;
02386 nearPlane = &skin->Faces[iFace];
02387 }
02388 }
02389
02390
02391 minTime = ZERO;
02392 for (iFace = 0; iFace < skin->NFaces; iFace++) {
02393 if (LinePlaneIntersect(sPos, ePos, &skin->Faces[iFace], time, &depth)) {
02394 if (*time > minTime) {
02395 VecPlusScalarVec(sPos, *time, &dR, &pos);
02396 if (PointInConvex(&pos, skin, &plane, &depth2)) {
02397 minTime = *time;
02398 timeDepth = depth;
02399 entryPlane = &skin->Faces[iFace];
02400 }
02401 }
02402 }
02403 }
02404
02405
02406 if (minTime < ONE) {
02407
02408 *penDepth = timeDepth;
02409 *time = minTime;
02410 return entryPlane;
02411 } else {
02412
02413 sDist = VecDotPlane(sPos, nearPlane);
02414 *penDepth = minDepth;
02415 if (ApproxEqual(sDist, minDepth)) {
02416 *time = ZERO;
02417 } else {
02418 *time = DivScalar(sDist, (sDist - minDepth));
02419 }
02420 return nearPlane;
02421 }
02422 }
02423
02424
02425
02426
02428
02429
02430
02431
02433
02434 void ModifyShift(VEC *shift, REAL shiftMag, VEC *normal)
02435 {
02436 #ifndef _PSX
02437 int iR;
02438 REAL newShift;
02439
02440 for (iR = 0; iR < 3; iR++) {
02441 newShift = (shiftMag) * normal->v[iR] ;
02442 if (Sign(shift->v[iR]) == Sign(newShift)) {
02443 if (abs(shift->v[iR]) < abs(newShift)) {
02444 shift->v[iR] = newShift;
02445 }
02446 } else {
02447 shift->v[iR] += newShift;
02448 }
02449 }
02450 #else //_PSX
02451 int iR;
02452 REAL newShift;
02453 REAL *normComp, *shiftComp;
02454
02455 normComp = &normal->v[0];
02456 shiftComp = &shift->v[0];
02457
02458 for (iR = 0; iR < 3; iR++) {
02459 newShift = MulScalar(shiftMag, *normComp);
02460 if (Sign(*shiftComp) == Sign(newShift)) {
02461 if (abs(*shiftComp) < abs(newShift)) {
02462 *shiftComp = newShift;
02463 }
02464 } else {
02465 *shiftComp += newShift;
02466 }
02467 normComp++;
02468 shiftComp++;
02469 }
02470 #endif
02471 }
02472
02473
02475
02476
02477
02478
02479
02481
02482 bool PointInCollPolyBounds(VEC *pt, NEWCOLLPOLY *poly)
02483 {
02484 if (VecDotPlane(pt, &poly->EdgePlane[0]) > COLL_EPSILON) return FALSE;
02485 if (VecDotPlane(pt, &poly->EdgePlane[1]) > COLL_EPSILON) return FALSE;
02486 if (VecDotPlane(pt, &poly->EdgePlane[2]) > COLL_EPSILON) return FALSE;
02487 if (IsPolyQuad(poly)) {
02488 if (VecDotPlane(pt, &poly->EdgePlane[3]) > COLL_EPSILON) return FALSE;
02489 }
02490
02491
02492
02493
02494
02495
02496
02497 return TRUE;
02498 }
02499
02501
02502
02503
02504
02506
02507 bool SphereInCollPolyBounds(VEC *pt, REAL radius, NEWCOLLPOLY *poly)
02508 {
02509 #if TRUE
02510 if (VecDotPlane(pt, &poly->EdgePlane[0]) > (COLL_EPSILON)) return FALSE;
02511 if (VecDotPlane(pt, &poly->EdgePlane[1]) > (COLL_EPSILON)) return FALSE;
02512 if (VecDotPlane(pt, &poly->EdgePlane[2]) > (COLL_EPSILON)) return FALSE;
02513 if (IsPolyQuad(poly)) {
02514 if (VecDotPlane(pt, &poly->EdgePlane[3]) > (COLL_EPSILON)) return FALSE;
02515 }
02516 #else
02517 if (VecDotPlane(pt, &poly->EdgePlane[0]) > (COLL_EPSILON + radius)) return FALSE;
02518 if (VecDotPlane(pt, &poly->EdgePlane[1]) > (COLL_EPSILON + radius)) return FALSE;
02519 if (VecDotPlane(pt, &poly->EdgePlane[2]) > (COLL_EPSILON + radius)) return FALSE;
02520 if (IsPolyQuad(poly)) {
02521 if (VecDotPlane(pt, &poly->EdgePlane[3]) > (COLL_EPSILON + radius)) return FALSE;
02522 }
02523 #endif
02524
02525 return TRUE;
02526 }
02527
02528
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02546
02547 #ifdef _PC
02548 bool SphereConvex(VEC *spherePos,
02549 REAL sphereRad,
02550 CONVEX *skin,
02551 VEC *collPos,
02552 PLANE *collPlane,
02553 REAL *collDepth)
02554 {
02555 bool collided;
02556 int iFace;
02557 REAL dist, maxDist;
02558
02559 maxDist = -LARGEDIST;
02560 collided = FALSE;
02561
02562 for (iFace = 0; iFace < skin->NFaces; iFace++) {
02563
02564
02565 if ((dist = (VecDotPlane(spherePos, &skin->Faces[iFace]) - sphereRad)) > COLL_EPSILON) return FALSE;
02566
02567 if (maxDist < dist) {
02568
02569
02570 VecMinusScalarVec(spherePos, sphereRad, PlaneNormal(&skin->Faces[iFace]), collPos);
02571
02572 maxDist = dist;
02573 collided = TRUE;
02574
02575
02576 *collDepth = maxDist;
02577
02578 CopyPlane(&skin->Faces[iFace], collPlane);
02579 }
02580 }
02581
02582
02583
02584 return collided;
02585 }
02586 #else
02587 bool SphereConvex(VEC *spherePos,
02588 REAL sphereRad,
02589 CONVEX *skin,
02590 VEC *collPos,
02591 PLANE *collPlane,
02592 REAL *collDepth)
02593 {
02594 int iFace;
02595 REAL dist, maxDist;
02596
02597 maxDist = -LARGEDIST;
02598
02599 for (iFace = 0; iFace < skin->NFaces; iFace++) {
02600
02601
02602 if ((dist = (VecDotPlane(spherePos, &skin->Faces[iFace]) - sphereRad)) > COLL_EPSILON) return FALSE;
02603
02604 if (maxDist < dist) {
02605 maxDist = dist;
02606
02607
02608 VecMinusScalarVec(spherePos, sphereRad, PlaneNormal(&skin->Faces[iFace]), collPos);
02609
02610 *collDepth = maxDist;
02611
02612 CopyPlane(&skin->Faces[iFace], collPlane);
02613 }
02614 }
02615
02616
02617
02618 return TRUE;
02619 }
02620 #endif
02621
02623
02624
02625
02626
02628
02629 void MakeTightLocalBBox(COLLSKIN *collSkin)
02630 {
02631 int iSphere, iSkin, iPt;
02632
02633
02634 SetBBox(&collSkin->TightBBox, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST);
02635
02636
02637 for (iSphere = 0; iSphere < collSkin->NSpheres; iSphere++) {
02638 AddSphereToBBox(&collSkin->TightBBox, &collSkin->Sphere[iSphere]);
02639 }
02640
02641
02642 for (iSkin = 0; iSkin < collSkin->NConvex; iSkin++) {
02643
02644
02645 SetBBox(&collSkin->Convex[iSkin].BBox, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST);
02646
02647
02648 for (iPt = 0; iPt < collSkin->Convex[iSkin].NPts; iPt++) {
02649
02650
02651 AddPointToBBox(&collSkin->Convex[iSkin].BBox, &collSkin->Convex[iSkin].Pts[iPt]);
02652
02653 }
02654
02655 }
02656
02657 }
02658
02659
02660
02662
02663
02664
02665
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02710
02711
02712
02713
02715
02716 REAL CorrugationAmp(CORRUGATION *cor, REAL dx, REAL dy)
02717 {
02718 REAL argX, argZ;
02719
02720 #ifndef _PSX
02721 argX = 2.0f * PI * dx / cor->Lx;
02722 argZ = 2.0f * PI * dy / cor->Ly;
02723 #else
02724 argX = DivScalar(dx, cor->Lx) >> (FIXED_PRECISION - 12);
02725 argZ = DivScalar(dy, cor->Ly) >> (FIXED_PRECISION - 12);
02726 #endif
02727
02728 return MulScalar(cor->Amp, (REAL)MulScalar(cos(argX), cos(argZ)));
02729 }
02730
02731
02732
02734
02735
02736
02737
02739
02740 bool LineOfSight(VEC *src, VEC *dest)
02741 {
02742 int iPoly;
02743 long gridNum, endGridNum, dX, dZ, xGrid, zGrid;
02744 REAL t, depth, minT;
02745 VEC dR, intersect;
02746 PLANE face;
02747 COLLGRID *grid;
02748 NEWCOLLPOLY *poly;
02749 bool lastGrid = FALSE;
02750
02751
02752 VecMinusVec(dest, src, &dR);
02753
02754
02755 gridNum = PosToCollGridCoords(src, &xGrid, &zGrid);
02756 endGridNum = PosToCollGridNum(dest);
02757
02758
02759 do {
02760
02761
02762 if ((xGrid >= NearestInt(COL_CollGridData.XNum)) || (zGrid >= NearestInt(COL_CollGridData.ZNum)) || (xGrid < 0) || (zGrid < 0)) {
02763 return TRUE;
02764 }
02765
02766 grid = &COL_CollGrid[gridNum];
02767
02768
02769 for (iPoly = 0; iPoly < grid->NCollPolys; iPoly++) {
02770 #ifndef _PSX
02771 poly = grid->CollPolyPtr[iPoly];
02772 #else
02773 poly = &COL_WorldCollPoly[grid->CollPolyIndices[iPoly]];
02774 #endif
02775
02776 if (!LinePlaneIntersect(src, dest, &poly->Plane, &t, &depth)) continue;
02777 VecPlusScalarVec(src, t, &dR, &intersect);
02778 if (!PointInCollPolyBounds(&intersect, poly)) continue;
02779
02780
02781 return FALSE;
02782 }
02783
02784
02785 if (gridNum == endGridNum) {
02786 lastGrid = TRUE;
02787 } else {
02788
02789
02790
02791 minT = Real(2.0);
02792 if (dR.v[X] < ZERO) {
02793
02794
02795 SetPlane(&face, ONE, ZERO, ZERO, -(COL_CollGridData.XStart + xGrid * COL_CollGridData.GridSize));
02796 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02797 if (t < minT) {
02798 minT = t;
02799 dX = -1;
02800 dZ = 0;
02801 }
02802 }
02803 } else {
02804
02805 SetPlane(&face, -ONE, ZERO, ZERO, (COL_CollGridData.XStart + (xGrid + 1) * COL_CollGridData.GridSize));
02806 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02807 if (t < minT) {
02808 minT = t;
02809 dX = 1;
02810 dZ = 0;
02811 }
02812 }
02813 }
02814 if (dR.v[Z] < ZERO) {
02815
02816
02817 SetPlane(&face, ZERO, ZERO, ONE, -(COL_CollGridData.ZStart + zGrid * COL_CollGridData.GridSize));
02818 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02819 if (t < minT) {
02820 minT = t;
02821 dX = 0;
02822 dZ = -1;
02823 }
02824 }
02825 } else {
02826
02827 SetPlane(&face, ZERO, ZERO, -ONE, (COL_CollGridData.ZStart + (zGrid + 1) * COL_CollGridData.GridSize));
02828 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02829 if (t < minT) {
02830 minT = t;
02831 dX = 0;
02832 dZ = 1;
02833 }
02834 }
02835 }
02836
02837 xGrid += dX;
02838 zGrid += dZ;
02839 if ((xGrid >= COL_CollGridData.XNum) || (zGrid >= COL_CollGridData.ZNum)) {
02840 gridNum = -1;
02841 } else {
02842 gridNum += dX + NearestInt(COL_CollGridData.XNum) * dZ;
02843 }
02844 }
02845
02846 } while ((gridNum != -1) && (!lastGrid));
02847
02848
02849
02850 return TRUE;
02851 }
02852
02853
02855
02856
02857
02858
02860
02861 bool LineOfSightDist(VEC *src, VEC *dest, REAL *minDist, PLANE **plane)
02862 {
02863 int iPoly;
02864 long gridNum, endGridNum, dX, dZ, xGrid, zGrid;
02865 REAL t, depth, minT;
02866 VEC dR, intersect;
02867 PLANE face;
02868 COLLGRID *grid;
02869 NEWCOLLPOLY *poly;
02870 bool lastGrid = FALSE;
02871
02872
02873 VecMinusVec(dest, src, &dR);
02874 *minDist = ONE;
02875
02876
02877 gridNum = PosToCollGridCoords(src, &xGrid, &zGrid);
02878 endGridNum = PosToCollGridNum(dest);
02879
02880
02881 do {
02882
02883
02884 if ((xGrid >= NearestInt(COL_CollGridData.XNum)) || (zGrid >= NearestInt(COL_CollGridData.ZNum)) || (xGrid < 0) || (zGrid < 0)) {
02885 return TRUE;
02886 }
02887
02888 grid = &COL_CollGrid[gridNum];
02889
02890
02891 for (iPoly = 0; iPoly < grid->NCollPolys; iPoly++) {
02892 #ifndef _PSX
02893 poly = grid->CollPolyPtr[iPoly];
02894 #else
02895 poly = &COL_WorldCollPoly[grid->CollPolyIndices[iPoly]];
02896 #endif
02897
02898 if (!LinePlaneIntersect(src, dest, &poly->Plane, &t, &depth)) continue;
02899 if (depth > ZERO) continue;
02900 VecPlusScalarVec(src, t, &dR, &intersect);
02901 if (!PointInCollPolyBounds(&intersect, poly)) continue;
02902
02903
02904 if (t < *minDist) {
02905 *minDist = t;
02906 if (plane) {
02907 *plane = &poly->Plane;
02908 }
02909 }
02910 }
02911
02912
02913 if (gridNum == endGridNum) {
02914 lastGrid = TRUE;
02915 } else {
02916
02917
02918
02919 minT = Real(2.0);
02920 if (dR.v[X] < ZERO) {
02921
02922
02923 SetPlane(&face, ONE, ZERO, ZERO, -(COL_CollGridData.XStart + xGrid * COL_CollGridData.GridSize));
02924 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02925 if (t < minT) {
02926 minT = t;
02927 dX = -1;
02928 dZ = 0;
02929 }
02930 }
02931 } else {
02932
02933 SetPlane(&face, -ONE, ZERO, ZERO, (COL_CollGridData.XStart + (xGrid + 1) * COL_CollGridData.GridSize));
02934 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02935 if (t < minT) {
02936 minT = t;
02937 dX = 1;
02938 dZ = 0;
02939 }
02940 }
02941 }
02942 if (dR.v[Z] < ZERO) {
02943
02944
02945 SetPlane(&face, ZERO, ZERO, ONE, -(COL_CollGridData.ZStart + zGrid * COL_CollGridData.GridSize));
02946 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02947 if (t < minT) {
02948 minT = t;
02949 dX = 0;
02950 dZ = -1;
02951 }
02952 }
02953 } else {
02954
02955 SetPlane(&face, ZERO, ZERO, -ONE, (COL_CollGridData.ZStart + (zGrid + 1) * COL_CollGridData.GridSize));
02956 if (LinePlaneIntersect(src, dest, &face, &t, &depth)) {
02957 if (t < minT) {
02958 minT = t;
02959 dX = 0;
02960 dZ = 1;
02961 }
02962 }
02963 }
02964
02965 xGrid += dX;
02966 zGrid += dZ;
02967 if ((xGrid >= COL_CollGridData.XNum) || (zGrid >= COL_CollGridData.ZNum)) {
02968 gridNum = -1;
02969 } else {
02970 gridNum += dX + NearestInt(COL_CollGridData.XNum) * dZ;
02971 }
02972 }
02973
02974 } while ((gridNum != -1) && (!lastGrid));
02975
02976
02977
02978 return TRUE;
02979 }
02980
02981
02983
02984
02985
02986
02988 #ifdef _PC
02989 bool LineOfSightObj(VEC *src, VEC *dest, REAL *minDist)
02990 {
02991 bool los;
02992 int iWheel;
02993 REAL dist;
02994 BBOX bBox;
02995 OBJECT *obj;
02996
02997
02998 los = TRUE;
02999 *minDist = ONE;
03000
03001 SetBBox(&bBox, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST);
03002 AddPointToBBox(&bBox, src);
03003 AddPointToBBox(&bBox, dest);
03004
03005
03006 for (obj = OBJ_ObjectHead; obj != NULL; obj = obj->next) {
03007
03008
03009 switch (obj->CollType) {
03010
03011 case COLL_TYPE_CAR:
03012 if (!BBTestXZY(&obj->player->car.BBox, &bBox)) continue;
03013 for (iWheel = 0; iWheel < CAR_NWHEELS; iWheel++) {
03014 if (IsWheelPresent(&obj->player->car.Wheel[iWheel])) {
03015 if (!LineOfSightSphere(&obj->player->car.Wheel[iWheel].WPos, obj->player->car.Wheel[iWheel].Radius, src, dest, &dist)) {
03016 los = FALSE;
03017 if (dist < *minDist) {
03018 *minDist = dist;
03019 }
03020 }
03021 }
03022 }
03023 case COLL_TYPE_BODY:
03024 if (!BBTestXZY(&obj->body.CollSkin.BBox, &bBox)) continue;
03025 if (!LineOfSightBody(&obj->body, src, dest, &dist)) {
03026 los = FALSE;
03027 if (dist < *minDist) {
03028 *minDist = dist;
03029 }
03030 }
03031 break;
03032
03033 default:
03034 break;
03035 }
03036 }
03037
03038 return los;
03039 }
03040
03041 bool LineOfSightBody(NEWBODY *body, VEC *src, VEC *dest, REAL *minDist)
03042 {
03043 bool los;
03044 if (body->CollSkin.CollType == BODY_COLL_SPHERE) {
03045 los = LineOfSightSphere(&body->CollSkin.WorldSphere[0].Pos, body->CollSkin.WorldSphere[0].Radius, src, dest, minDist);
03046 return los;
03047 } else {
03048 Assert(body->CollSkin.CollType == BODY_COLL_CONVEX);
03049 los = LineOfSightConvex(body, src, dest, minDist);
03050 return los;
03051 }
03052 }
03053
03054
03055 bool LineOfSightConvex(NEWBODY *body, VEC *src, VEC *dest, REAL *minDist)
03056 {
03057 int iSkin;
03058 REAL dist, depth, time, dRLen, dR2Len, minDepth;
03059 VEC nearPt, dR, dR2;
03060 bool los;
03061
03062 los = TRUE;
03063 *minDist = ONE;
03064 minDepth = LARGEDIST;
03065
03066 dist = NearPointOnLine(src, dest, &body->Centre.Pos, &nearPt);
03067 if (!PointInBBox(&nearPt, &body->CollSkin.BBox)) return TRUE;
03068 VecMinusVec(dest, src, &dR2);
03069 dR2Len = VecLen(&dR2);
03070 VecMinusVec(&nearPt, src, &dR);
03071 dRLen = VecLen(&dR);
03072
03073 for (iSkin = 0; iSkin < body->CollSkin.NConvex; iSkin++) {
03074 if (LineToConvexColl(src, &nearPt, &body->CollSkin.WorldConvex[iSkin], &depth, &time) == NULL) continue;
03075
03076 los = FALSE;
03077 if (depth < minDepth) {
03078 minDepth = depth;
03079 }
03080 }
03081
03082 *minDist = dist + (minDepth / dR2Len);
03083
03084 return los;
03085 }
03086
03087 bool LineOfSightSphere(VEC *sphPos, REAL rad, VEC *src, VEC *dest, REAL *minDist)
03088 {
03089 REAL b, c, d, dRLen;
03090 VEC dR, dS;
03091
03092
03093 VecMinusVec(dest, src, &dR);
03094 dRLen = VecLen(&dR);
03095 VecDivScalar(&dR, dRLen);
03096 VecMinusVec(src, sphPos, &dS);
03097
03098 b = Real(2) * VecDotVec(&dR, &dS);
03099 c = VecDotVec(&dS, &dS) - rad * rad;
03100
03101 d = b * b - (Real(4) * c);
03102
03103 if (d < 0) {
03104 *minDist = ONE;
03105 return TRUE;
03106 }
03107
03108 if (b > 0) {
03109 *minDist = HALF * (-b + (REAL)sqrt(d)) / dRLen;
03110 } else {
03111 *minDist = HALF * (-b - (REAL)sqrt(d)) / dRLen;
03112 }
03113 return FALSE;
03114
03115 }
03116 #endif
03117
03119
03120
03121
03123
03124 int GetCollPolyVertices(NEWCOLLPOLY *poly, VEC *v0, VEC *v1, VEC *v2, VEC *v3)
03125 {
03126
03127 PlaneIntersect3(&poly->Plane, &poly->EdgePlane[0], &poly->EdgePlane[1], v0);
03128 PlaneIntersect3(&poly->Plane, &poly->EdgePlane[1], &poly->EdgePlane[2], v1);
03129 if (IsPolyQuad(poly)) {
03130 PlaneIntersect3(&poly->Plane, &poly->EdgePlane[2], &poly->EdgePlane[3], v2);
03131 PlaneIntersect3(&poly->Plane, &poly->EdgePlane[3], &poly->EdgePlane[0], v3);
03132 } else {
03133 PlaneIntersect3(&poly->Plane, &poly->EdgePlane[2], &poly->EdgePlane[0], v2);
03134 }
03135
03136 return (IsPolyQuad(poly))? 4: 3;
03137 }
03138
03139
03141
03142
03143
03145
03146 void AddPosRadToBBox(BBOX *bBox, VEC *pos, REAL radius)
03147 {
03148 bBox->XMin = Min(bBox->XMin, pos->v[X] - radius);
03149 bBox->XMax = Max(bBox->XMax, pos->v[X] + radius);
03150 bBox->YMin = Min(bBox->YMin, pos->v[Y] - radius);
03151 bBox->YMax = Max(bBox->YMax, pos->v[Y] + radius);
03152 bBox->ZMin = Min(bBox->ZMin, pos->v[Z] - radius);
03153 bBox->ZMax = Max(bBox->ZMax, pos->v[Z] + radius);
03154 }
03155
03157
03158
03159
03161
03162 void AddPointToBBox(BBOX *bBox, VEC *pos)
03163 {
03164 bBox->XMin = Min(bBox->XMin, pos->v[X]);
03165 bBox->XMax = Max(bBox->XMax, pos->v[X]);
03166 bBox->YMin = Min(bBox->YMin, pos->v[Y]);
03167 bBox->YMax = Max(bBox->YMax, pos->v[Y]);
03168 bBox->ZMin = Min(bBox->ZMin, pos->v[Z]);
03169 bBox->ZMax = Max(bBox->ZMax, pos->v[Z]);
03170 }
03171
03172
03174
03175
03176
03178
03179 void RotTransBBox(BBOX *srcBox, MAT *mat, VEC *pos, BBOX *destBox)
03180 {
03181 VEC pt, destPt;
03182
03183
03184 SetBBox(destBox, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST);
03185
03186
03187 SetVec(&pt, srcBox->XMin, srcBox->YMin, srcBox->ZMin);
03188 VecMulMat(&pt, mat, &destPt);
03189 VecPlusEqVec(&destPt, pos);
03190 AddPointToBBox(destBox, &destPt);
03191
03192 SetVec(&pt, srcBox->XMin, srcBox->YMin, srcBox->ZMax);
03193 VecMulMat(&pt, mat, &destPt);
03194 VecPlusEqVec(&destPt, pos);
03195 AddPointToBBox(destBox, &destPt);
03196
03197 SetVec(&pt, srcBox->XMin, srcBox->YMax, srcBox->ZMin);
03198 VecMulMat(&pt, mat, &destPt);
03199 VecPlusEqVec(&destPt, pos);
03200 AddPointToBBox(destBox, &destPt);
03201
03202 SetVec(&pt, srcBox->XMin, srcBox->YMax, srcBox->ZMax);
03203 VecMulMat(&pt, mat, &destPt);
03204 VecPlusEqVec(&destPt, pos);
03205 AddPointToBBox(destBox, &destPt);
03206
03207 SetVec(&pt, srcBox->XMax, srcBox->YMin, srcBox->ZMin);
03208 VecMulMat(&pt, mat, &destPt);
03209 VecPlusEqVec(&destPt, pos);
03210 AddPointToBBox(destBox, &destPt);
03211
03212 SetVec(&pt, srcBox->XMax, srcBox->YMin, srcBox->ZMax);
03213 VecMulMat(&pt, mat, &destPt);
03214 VecPlusEqVec(&destPt, pos);
03215 AddPointToBBox(destBox, &destPt);
03216
03217 SetVec(&pt, srcBox->XMax, srcBox->YMax, srcBox->ZMin);
03218 VecMulMat(&pt, mat, &destPt);
03219 VecPlusEqVec(&destPt, pos);
03220 AddPointToBBox(destBox, &destPt);
03221
03222 SetVec(&pt, srcBox->XMax, srcBox->YMax, srcBox->ZMax);
03223 VecMulMat(&pt, mat, &destPt);
03224 VecPlusEqVec(&destPt, pos);
03225 AddPointToBBox(destBox, &destPt);
03226
03227 }
03228
03229 void TransBBox(BBOX *bBox, VEC *sPos)
03230 {
03231 bBox->XMin += sPos->v[X];
03232 bBox->XMax += sPos->v[X];
03233 bBox->YMin += sPos->v[Y];
03234 bBox->YMax += sPos->v[Y];
03235 bBox->ZMin += sPos->v[Z];
03236 bBox->ZMax += sPos->v[Z];
03237 }
03238
03240
03241
03242
03244
03245 void RotTransCollPolys(NEWCOLLPOLY *collPoly, int nPolys, MAT *rMat, VEC *dPos)
03246 {
03247 int iPoly, iEdge, nEdges;
03248 NEWCOLLPOLY *poly;
03249 PLANE plane;
03250 BBOX bBox;
03251
03252 for (iPoly = 0; iPoly < nPolys; iPoly++) {
03253 poly = &collPoly[iPoly];
03254 nEdges = (IsPolyQuad(poly))? 4: 3;
03255
03256 RotTransPlane(&poly->Plane, rMat, dPos, &plane);
03257 CopyPlane(&plane, &poly->Plane);
03258
03259 for (iEdge = 0; iEdge < nEdges; iEdge++) {
03260
03261 RotTransPlane(&poly->EdgePlane[iEdge], rMat, dPos, &plane);
03262 CopyPlane(&plane, &poly->EdgePlane[iEdge]);
03263
03264 }
03265
03266 RotTransBBox(&poly->BBox, rMat, dPos, &bBox);
03267 CopyBBox(&bBox, &poly->BBox);
03268 }
03269 }
03270
03272
03273
03274
03276
03277 void TransCollPolys(NEWCOLLPOLY *collPoly, int nPolys, VEC *dPos)
03278 {
03279 int iPoly, iEdge, nEdges;
03280 NEWCOLLPOLY *poly;
03281
03282 for (iPoly = 0; iPoly < nPolys; iPoly++) {
03283 poly = &collPoly[iPoly];
03284 nEdges = (IsPolyQuad(poly))? 4: 3;
03285
03286 MovePlane(&poly->Plane, dPos);
03287
03288 for (iEdge = 0; iEdge < nEdges; iEdge++) {
03289
03290 MovePlane(&poly->EdgePlane[iEdge], dPos);
03291
03292 }
03293
03294 TransBBox(&poly->BBox, dPos);
03295 }
03296 }
03297
03298
03300
03301
03302
03304
03305 COLLINFO_BODY *NextBodyCollInfo()
03306 {
03307 if (COL_NBodyColls == MAX_COLLS_BODY) {
03308 return NULL;
03309 } else {
03310 COL_BodyCollInfo[COL_NBodyColls].Prev = COL_BodyCollInfo[COL_NBodyColls].Next = NULL;
03311 COL_BodyCollInfo[COL_NBodyColls].Active = FALSE;
03312 return &COL_BodyCollInfo[COL_NBodyColls];
03313 }
03314 }
03315
03317
03318
03319
03321
03322 COLLINFO_WHEEL *NextWheelCollInfo()
03323 {
03324 if (COL_NWheelColls == MAX_COLLS_BODY) {
03325 return NULL;
03326 } else {
03327 COL_WheelCollInfo[COL_NWheelColls].Prev = COL_WheelCollInfo[COL_NWheelColls].Next = NULL;
03328
03329 return &COL_WheelCollInfo[COL_NWheelColls];
03330 }
03331 }
03332