00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Assert.h>
00023
00024 #include "XForm3d.h"
00025 #include "BaseType.h"
00026 #include "GBSPFile.h"
00027 #include "World.h"
00028 #include "System.h"
00029 #include "Plane.h"
00030 #include "Trace.h"
00031 #include "ExtBox.h"
00032 #include "Actor.h"
00033
00034 #define ON_EPSILON (0.1f)
00035
00036
00037
00038
00039
00040
00041 static int32 GPlaneNum;
00042 static GFX_Plane GlobalPlane;
00043 static int32 GlobalNode;
00044 static int32 GlobalSide;
00045 static geVec3d GlobalI;
00046 static geFloat GRatio;
00047 static int32 GlobalLeaf;
00048 static int32 GlobalLeaf;
00049
00050 static GBSP_BSPData *BSPData;
00051
00052
00053 static uint32 gContents;
00054
00055 static BOOL UseMinsMaxs;
00056
00057 static BOOL HitSet;
00058 static int32 GlobalNNode[2]={0x696C6345,0x21657370};
00059
00060 int32 NumExactCast;
00061 int32 NumBBoxCast;
00062 int32 NumGetContents;
00063
00064
00065
00066
00067 static geBoolean BSPIntersect(geVec3d *Front, geVec3d *Back, int32 Node);
00068
00069
00070
00071 static geActor *Trace_ActorCollide(geWorld *World,
00072 const geVec3d *Mins, const geVec3d *Maxs,
00073 const geVec3d *Front,const geVec3d *Back,
00074 geVec3d *CollisionPoint,GFX_Plane *BestPlane,
00075 uint32 UserFlags, GE_CollisionCB *CollisionCB, void *Context, geFloat *BestD )
00076 {
00077 int i,Count;
00078 World_Actor *WA;
00079 geVec3d RayDirection;
00080 geFloat RayLength;
00081 geFloat Dist;
00082 geActor *BestActor = NULL;
00083 geVec3d FakeMins = {-1.0f, -1.0f, -1.0f};
00084 geVec3d FakeMaxs = { 1.0f, 1.0f, 1.0f};
00085 int32 k;
00086 geVec3d OMins, OMaxs;
00087
00088 if (!Mins)
00089 Mins = &FakeMins;
00090
00091 if (!Maxs)
00092 Maxs = &FakeMaxs;
00093
00094 geVec3d_Subtract(Back,Front,&RayDirection);
00095 RayLength = geVec3d_Normalize(&RayDirection);
00096
00097 Count = World->ActorCount;
00098 WA = &(World->ActorArray[0]);
00099
00100 Trace_GetMoveBox(Mins, Maxs, Front, Back, &OMins, &OMaxs);
00101
00102 for (i=0; i<Count; i++, WA++)
00103 {
00104 geExtBox B;
00105 geVec3d Normal;
00106
00107
00108 if (!(WA->Flags & GE_ACTOR_COLLIDE) || !(WA->UserFlags & UserFlags) )
00109 continue;
00110
00111 if (CollisionCB && !CollisionCB(NULL, WA->Actor, Context))
00112 continue;
00113
00114 if (!geActor_GetExtBox(WA->Actor, &B))
00115 continue;
00116
00117 for (k=0; k<3; k++)
00118 {
00119 if (geVec3d_GetElement(&OMaxs, k) < geVec3d_GetElement(&B.Min, k))
00120 break;
00121
00122 if (geVec3d_GetElement(&OMins, k) > geVec3d_GetElement(&B.Max, k))
00123 break;
00124 }
00125
00126 if (k != 3)
00127 continue;
00128
00129 geVec3d_Subtract(&B.Min, Maxs, &B.Min);
00130 geVec3d_Subtract(&B.Max, Mins, &B.Max);
00131
00132 if (!geExtBox_RayCollision( &B, Front, Back, &Dist, &Normal ))
00133 continue;
00134
00135
00136 if (Dist < 0.0f)
00137 Dist = 0.0f;
00138 if (Dist > 1.0f)
00139 Dist = 1.0f;
00140
00141 Dist *= RayLength;
00142
00143 if (Dist < *BestD)
00144 {
00145 BestActor = WA->Actor;
00146 *BestD = Dist;
00147 BestPlane->Normal = Normal;
00148
00149 geVec3d_AddScaled(Front,&RayDirection,Dist,CollisionPoint);
00150 BestPlane->Dist = geVec3d_DotProduct(CollisionPoint,&Normal);
00151
00152 BestPlane->Type = PLANE_ANY;
00153 }
00154 }
00155
00156 return BestActor;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 geBoolean Trace_GEWorldCollision(geWorld *World, const geVec3d *Mins, const geVec3d *Maxs, const geVec3d *Front, const geVec3d *Back, uint32 Contents, uint32 CollideFlags, uint32 UserFlags, GE_CollisionCB *CollisionCB, void *Context, GE_Collision *Col)
00166 {
00167 geVec3d I;
00168 GFX_Plane Plane;
00169 geWorld_Model *Model;
00170 Mesh_RenderQ *Mesh;
00171 geActor *Actor;
00172
00173 assert(World != NULL);
00174 assert(World->CurrentBSP != NULL);
00175 assert(Front != NULL);
00176 assert(Back!= NULL);
00177 assert(Contents);
00178
00179
00180 gContents = Contents;
00181
00182 BSPData = &World->CurrentBSP->BSPData;
00183
00184
00185 Model = NULL;
00186 Mesh = NULL;
00187 Actor = NULL;
00188
00189 Col->Model = NULL;
00190 Col->Mesh = NULL;
00191 Col->Actor = NULL;
00192
00193 if (Mins && Maxs)
00194 {
00195 NumBBoxCast++;
00196 if (Trace_WorldCollisionBBox(World, Mins, Maxs, Front, Back, CollideFlags, &I, &Plane, &Model, &Mesh, &Actor, UserFlags, CollisionCB, Context))
00197 {
00198
00199 Col->Impact = I;
00200 Col->Plane.Normal = Plane.Normal;
00201 Col->Plane.Dist = Plane.Dist;
00202
00203 Col->Model = Model;
00204 Col->Mesh = (geMesh*)Mesh;
00205 Col->Actor = Actor;
00206
00207 Col->Ratio = GRatio;
00208 return GE_TRUE;
00209 }
00210 }
00211 else
00212 {
00213 NumExactCast++;
00214
00215 if (Trace_WorldCollisionExact(World, Front, Back, CollideFlags, &I, &Plane, &Model, &Mesh, &Actor, UserFlags, CollisionCB, Context))
00216 {
00217 Col->Impact = I;
00218 Col->Plane.Normal = Plane.Normal;
00219 Col->Plane.Dist = Plane.Dist;
00220
00221 Col->Model = Model;
00222 Col->Mesh = (geMesh*)Mesh;
00223 Col->Actor = Actor;
00224
00225 Col->Ratio = GRatio;
00226
00227 return GE_TRUE;
00228 }
00229 }
00230 return GE_FALSE;
00231 }
00232
00233
00234
00235
00236 geBoolean Trace_WorldCollisionExact(geWorld *World,
00237 const geVec3d *Front,
00238 const geVec3d *Back,
00239 uint32 Flags,
00240 geVec3d *Impact,
00241 GFX_Plane *Plane,
00242 geWorld_Model **Model,
00243 Mesh_RenderQ **Mesh,
00244 geActor **Actor,
00245 uint32 UserFlags,
00246 GE_CollisionCB *CollisionCB,
00247 void *Context)
00248 {
00249 int32 i, b;
00250 geVec3d NewFront1, NewBack1;
00251 geVec3d NewFront2, NewBack2;
00252 geWorld_Model *Models, *BestModel;
00253 GFX_Plane BestPlane, Plane2;
00254 Mesh_RenderQ *BestMesh=NULL;
00255 geActor *BestActor=NULL;
00256 geVec3d OMins, OMaxs, Vect, Impact2, BestI;
00257 static geVec3d MMins = {-1.0f, -1.0f, -1.0f};
00258 static geVec3d MMaxs = { 1.0f, 1.0f, 1.0f};
00259 geBoolean Hit;
00260 geFloat Dist, BestD;
00261
00262 assert(World != NULL);
00263 assert(World->CurrentBSP != NULL);
00264 assert(Front != NULL);
00265 assert(Back!= NULL);
00266
00267 BSPData = &World->CurrentBSP->BSPData;
00268 Models = World->CurrentBSP->Models;
00269
00270
00271 if (Model)
00272 *Model = NULL;
00273 if (Mesh)
00274 *Mesh = NULL;
00275 if (Actor)
00276 *Actor = NULL;
00277
00278 BestD = 99999.0f;
00279 BestModel = NULL;
00280 BestMesh = NULL;
00281 Hit = GE_FALSE;
00282
00283 if (Flags & GE_COLLIDE_ACTORS)
00284 {
00285 BestActor = Trace_ActorCollide(World,NULL, NULL, Front,Back,&Impact2, &Plane2, UserFlags, CollisionCB, Context, &BestD);
00286 if (BestActor != NULL)
00287 {
00288 BestI = Impact2;
00289 BestPlane = Plane2;
00290 Hit = GE_TRUE;
00291 }
00292 }
00293
00294 if (!(Flags & GE_COLLIDE_MODELS))
00295 goto NoModels;
00296
00297 Trace_GetMoveBox(&MMins, &MMaxs, Front, Back, &OMins, &OMaxs);
00298
00299 for (i = 0; i < BSPData->NumGFXModels; i++, Models++)
00300 {
00301
00302 if (CollisionCB && !CollisionCB(Models, NULL, Context))
00303 continue;
00304
00305 for (b=0; b<3; b++)
00306 {
00307 if (VectorToSUB(OMaxs, b) < VectorToSUB(Models->TMins, b))
00308 break;
00309 if (VectorToSUB(OMins, b) > VectorToSUB(Models->TMaxs, b))
00310 break;
00311 }
00312
00313 if (b != 3)
00314 continue;
00315
00316
00317 geVec3d_Subtract(Front, &Models->Pivot, &NewFront1);
00318 geVec3d_Subtract(Back , &Models->Pivot, &NewBack1);
00319
00320
00321 geXForm3d_TransposeTransform(&Models->XForm, &NewFront1, &NewFront2);
00322 geXForm3d_TransposeTransform(&Models->XForm, &NewBack1 , &NewBack2);
00323
00324
00325 geVec3d_Add(&NewFront2, &Models->Pivot, &NewFront1);
00326 geVec3d_Add(&NewBack2 , &Models->Pivot, &NewBack1);
00327
00328 HitSet = FALSE;
00329
00330 if (BSPIntersect(&NewFront1, &NewBack1, BSPData->GFXModels[i].RootNode[0]))
00331 {
00332
00333 geXForm3d_Rotate(&Models->XForm, &GlobalPlane.Normal, &GlobalPlane.Normal);
00334
00335
00336 geVec3d_Subtract(&GlobalI, &Models->Pivot, &GlobalI);
00337 geXForm3d_Transform(&Models->XForm, &GlobalI, &GlobalI);
00338 geVec3d_Add(&GlobalI, &Models->Pivot, &GlobalI);
00339
00340
00341 GlobalPlane.Dist = geVec3d_DotProduct(&GlobalPlane.Normal, &GlobalI);
00342
00343 geVec3d_Subtract(&GlobalI, Front, &Vect);
00344 Dist = geVec3d_Length(&Vect);
00345
00346 if (Dist < BestD)
00347 {
00348 BestD = Dist;
00349 BestI = GlobalI;
00350
00351 BestPlane = GlobalPlane;
00352 if (GlobalSide)
00353 {
00354 geVec3d_Inverse(&BestPlane.Normal);
00355 BestPlane.Dist = -BestPlane.Dist;
00356 BestPlane.Type = PLANE_ANY;
00357 }
00358
00359 BestMesh = NULL;
00360 BestActor = NULL;
00361 BestModel = Models;
00362 Hit = GE_TRUE;
00363 }
00364 }
00365
00366 if ((Flags & GE_COLLIDE_NO_SUB_MODELS))
00367 goto NoModels;
00368 }
00369
00370 NoModels:
00371
00372 if (Hit)
00373 {
00374 if (Impact)
00375 *Impact = BestI;
00376 if (Plane)
00377 *Plane = BestPlane;
00378 if (Model)
00379 *Model = BestModel;
00380 if (Mesh)
00381 *Mesh = BestMesh;
00382 if (Actor)
00383 *Actor = BestActor;
00384 return GE_TRUE;
00385 }
00386
00387 return GE_FALSE;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 geBoolean Trace_WorldCollisionExact2( geWorld *World,
00397 const geVec3d *Front,
00398 const geVec3d *Back,
00399 geVec3d *Impact,
00400 int32 *Node,
00401 int32 *Plane,
00402 int32 *Side)
00403 {
00404 int32 i;
00405 geVec3d NewFront1, NewBack1;
00406 geVec3d NewFront2, NewBack2;
00407 geWorld_Model *Models;
00408
00409 assert(World != NULL);
00410 assert(World->CurrentBSP != NULL);
00411 assert(Front != NULL);
00412 assert(Back!= NULL);
00413
00414 BSPData = &World->CurrentBSP->BSPData;
00415 Models = World->CurrentBSP->Models;
00416
00417 GPlaneNum = -1;
00418
00419 gContents = GE_CONTENTS_SOLID_CLIP;
00420
00421 for (i = 0; i < BSPData->NumGFXModels; i++)
00422 {
00423
00424
00425 geVec3d_Subtract(Front, &Models[i].Pivot, &NewFront1);
00426 geVec3d_Subtract(Back , &Models[i].Pivot, &NewBack1);
00427
00428
00429 geXForm3d_TransposeTransform(&Models[i].XForm, &NewFront1, &NewFront2);
00430 geXForm3d_TransposeTransform(&Models[i].XForm, &NewBack1 , &NewBack2);
00431
00432
00433 geVec3d_Add(&NewFront2, &Models[i].Pivot, &NewFront1);
00434 geVec3d_Add(&NewBack2 , &Models[i].Pivot, &NewBack1);
00435
00436 HitSet = FALSE;
00437
00438 if (BSPIntersect(&NewFront1, &NewBack1, BSPData->GFXModels[i].RootNode[0]))
00439 {
00440 if (GPlaneNum == -1)
00441 return FALSE;
00442
00443 if (Impact) *Impact = GlobalI;
00444 if (Node) *Node = GlobalNode;
00445 if (Plane) *Plane = GPlaneNum;
00446 if (Side) *Side = GlobalSide;
00447
00448 return GE_TRUE;
00449 }
00450 }
00451
00452 return GE_FALSE;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 static geBoolean BSPIntersect(geVec3d *Front, geVec3d *Back, int32 Node)
00464 {
00465 geFloat Fd, Bd, Dist;
00466 int32 Side;
00467 geVec3d I;
00468 GFX_Plane *Plane;
00469 int32 Contents;
00470
00471 if (Node < 0)
00472 {
00473 Contents = BSPData->GFXLeafs[-(Node+1)].Contents;
00474
00475 if (Contents & gContents)
00476 return GE_TRUE;
00477
00478 return GE_FALSE;
00479 }
00480
00481 Plane = &BSPData->GFXPlanes[BSPData->GFXNodes[Node].PlaneNum];
00482
00483 Fd = Plane_PlaneDistanceFast(Plane, Front);
00484 Bd = Plane_PlaneDistanceFast(Plane, Back);
00485
00486 if (Fd >= 0 && Bd >= 0)
00487 return(BSPIntersect(Front, Back, BSPData->GFXNodes[Node].Children[0]));
00488 if (Fd < 0 && Bd < 0)
00489 return(BSPIntersect(Front, Back, BSPData->GFXNodes[Node].Children[1]));
00490
00491 Side = Fd < 0;
00492 Dist = Fd / (Fd - Bd);
00493
00494 I.X = Front->X + Dist * (Back->X - Front->X);
00495 I.Y = Front->Y + Dist * (Back->Y - Front->Y);
00496 I.Z = Front->Z + Dist * (Back->Z - Front->Z);
00497
00498
00499
00500
00501
00502 if (BSPIntersect(Front, &I, BSPData->GFXNodes[Node].Children[Side]))
00503 return GE_TRUE;
00504 else if (BSPIntersect(&I, Back, BSPData->GFXNodes[Node].Children[!Side]))
00505 {
00506 if (!HitSet)
00507 {
00508 GPlaneNum = BSPData->GFXNodes[Node].PlaneNum;
00509 GlobalPlane = BSPData->GFXPlanes[GPlaneNum];
00510 GlobalSide = Side;
00511 GlobalI = I;
00512 GlobalNode = Node;
00513 GRatio = Dist;
00514 HitSet = TRUE;
00515 }
00516 return GE_TRUE;
00517 }
00518
00519 return GE_FALSE;
00520 }
00521
00522
00523
00524
00525 static GFX_BNode *MiscBNodes;
00526 static GFX_Node *MiscNodes;
00527 static GFX_Plane *MiscPlanes;
00528 static GFX_Leaf *MiscLeafs;
00529 static GFX_LeafSide *MiscSides;
00530
00531 static geVec3d GMins1, GMaxs1;
00532 static geVec3d GMins2, GMaxs2;
00533 static geVec3d GFront, GBack;
00534 static BOOL LeafHit;
00535 static geFloat BestDist;
00536
00537 static geBoolean BSPIntersectMisc(geVec3d *Front, geVec3d *Back, int32 Node)
00538 {
00539 geFloat Fd, Bd, Dist;
00540 uint8 Side;
00541 GFX_Plane Plane;
00542 geVec3d I;
00543
00544 if (Node == BSP_CONTENTS_SOLID)
00545 return GE_TRUE;
00546 if (Node < 0)
00547 return GE_FALSE;
00548
00549 Plane = MiscPlanes[MiscBNodes[Node].PlaneNum];
00550 Plane.Type = PLANE_ANY;
00551
00552 if (UseMinsMaxs)
00553 {
00554 if (Plane.Normal.X > 0)
00555 Plane.Dist -= Plane.Normal.X * GMins1.X;
00556 else
00557 Plane.Dist -= Plane.Normal.X * GMaxs1.X;
00558
00559 if (Plane.Normal.Y > 0)
00560 Plane.Dist -= Plane.Normal.Y * GMins1.Y;
00561 else
00562 Plane.Dist -= Plane.Normal.Y * GMaxs1.Y;
00563
00564 if (Plane.Normal.Z > 0)
00565 Plane.Dist -= Plane.Normal.Z * GMins1.Z;
00566 else
00567 Plane.Dist -= Plane.Normal.Z * GMaxs1.Z;
00568 }
00569
00570 Fd = Plane_PlaneDistanceFast(&Plane, Front);
00571 Bd = Plane_PlaneDistanceFast(&Plane, Back);
00572
00573 if (Fd >= 0 && Bd >= 0)
00574 return(BSPIntersectMisc(Front, Back, MiscBNodes[Node].Children[0]));
00575 if (Fd < 0 && Bd < 0)
00576 return(BSPIntersectMisc(Front, Back, MiscBNodes[Node].Children[1]));
00577
00578 Side = Fd < 0;
00579 Dist = Fd / (Fd - Bd);
00580
00581 I.X = Front->X + Dist * (Back->X - Front->X);
00582 I.Y = Front->Y + Dist * (Back->Y - Front->Y);
00583 I.Z = Front->Z + Dist * (Back->Z - Front->Z);
00584
00585
00586
00587
00588
00589 if (BSPIntersectMisc(Front, &I, MiscBNodes[Node].Children[Side]))
00590 return TRUE;
00591 else if (BSPIntersectMisc(&I, Back, MiscBNodes[Node].Children[!Side]))
00592 {
00593 if (!HitSet)
00594 {
00595 GPlaneNum = MiscBNodes[Node].PlaneNum;
00596 GlobalPlane = Plane;
00597 GlobalSide = Side;
00598 GlobalI = I;
00599 GRatio = Dist;
00600 HitSet = TRUE;
00601 }
00602 return GE_TRUE;
00603 }
00604
00605 return GE_FALSE;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614 geBoolean Trace_MiscCollision(GFX_BNode *BNodes, GFX_Plane *Planes, const geVec3d *Mins, const geVec3d *Maxs, const geVec3d *Front, const geVec3d *Back, geXForm3d *XForm, geVec3d *I, GFX_Plane *P)
00615 {
00616 geVec3d NewFront, NewBack;
00617 geVec3d Trans;
00618
00619 GPlaneNum = -1;
00620
00621
00622 MiscBNodes = BNodes;
00623 MiscPlanes = Planes;
00624
00625 if (Mins && Maxs)
00626 {
00627 GMins1 = *Mins;
00628 GMaxs1 = *Maxs;
00629 UseMinsMaxs = TRUE;
00630 }
00631 else
00632 UseMinsMaxs = FALSE;
00633
00634
00635 Trans.X = XForm->Translation.X;
00636 Trans.Y = XForm->Translation.Y;
00637 Trans.Z = XForm->Translation.Z;
00638
00639 geVec3d_Subtract(Front, &Trans, &NewFront);
00640 geVec3d_Subtract(Back, &Trans, &NewBack);
00641
00642 HitSet = FALSE;
00643
00644 if (BSPIntersectMisc(&NewFront, &NewBack, 0))
00645 {
00646 if (!HitSet)
00647 return GE_FALSE;
00648
00649 geVec3d_Add(&GlobalI, &Trans, &GlobalI);
00650
00651 if (I) *I = GlobalI;
00652 if (P)
00653 {
00654 *P = GlobalPlane;
00655
00656 P->Dist += geVec3d_DotProduct(&Trans, &P->Normal);
00657 }
00658
00659 return GE_TRUE;
00660 }
00661
00662 return GE_FALSE;
00663 }
00664
00665
00666
00667
00668 static geBoolean BSPIntersectMisc2(const geVec3d *Front, const geVec3d *Back, int32 Node)
00669 {
00670 geFloat Fd, Bd, Dist;
00671 uint8 Side;
00672 GFX_Plane Plane;
00673 geVec3d I;
00674
00675 if (Node == BSP_CONTENTS_SOLID)
00676 return GE_TRUE;
00677 if (Node < 0)
00678 return GE_FALSE;
00679
00680 Plane = MiscPlanes[MiscBNodes[Node].PlaneNum];
00681 Plane.Type = PLANE_ANY;
00682
00683 Fd = Plane_PlaneDistanceFast(&Plane, Front);
00684 Bd = Plane_PlaneDistanceFast(&Plane, Back);
00685
00686 if (Fd >= 0 && Bd >= 0)
00687 return(BSPIntersectMisc2(Front, Back, MiscBNodes[Node].Children[0]));
00688 if (Fd < 0 && Bd < 0)
00689 return(BSPIntersectMisc2(Front, Back, MiscBNodes[Node].Children[1]));
00690
00691 Side = Fd < 0;
00692 Dist = Fd / (Fd - Bd);
00693
00694 I.X = Front->X + Dist * (Back->X - Front->X);
00695 I.Y = Front->Y + Dist * (Back->Y - Front->Y);
00696 I.Z = Front->Z + Dist * (Back->Z - Front->Z);
00697
00698
00699
00700
00701
00702 if (BSPIntersectMisc2(Front, &I, MiscBNodes[Node].Children[Side]))
00703 return TRUE;
00704 else if (BSPIntersectMisc2(&I, Back, MiscBNodes[Node].Children[!Side]))
00705 {
00706 if (!HitSet)
00707 {
00708 GPlaneNum = MiscBNodes[Node].PlaneNum;
00709 GlobalPlane = Plane;
00710 GlobalSide = Side;
00711 GlobalI = I;
00712 GRatio = Dist;
00713 HitSet = TRUE;
00714 }
00715 return GE_TRUE;
00716 }
00717
00718 return GE_FALSE;
00719 }
00720
00721
00722
00723
00724 geBoolean Trace_MiscCollision2(GFX_BNode *BNodes, GFX_Plane *Planes, const geVec3d *Front, const geVec3d *Back, geVec3d *I, int32 *P)
00725 {
00726 GPlaneNum = -1;
00727
00728
00729 MiscBNodes = BNodes;
00730 MiscPlanes = Planes;
00731
00732 HitSet = FALSE;
00733
00734 if (BSPIntersectMisc2(Front, Back, 0))
00735 {
00736 if (!HitSet || GPlaneNum == -1)
00737 return GE_FALSE;
00738
00739 if (I)
00740 *I = GlobalI;
00741 if (P)
00742 *P = GPlaneNum;
00743
00744 return GE_TRUE;
00745 }
00746
00747 return GE_FALSE;
00748 }
00749
00750
00751
00752
00753
00754
00755 int32 Trace_BoxOnPlaneSide(const geVec3d *Mins, const geVec3d *Maxs, GFX_Plane *Plane)
00756 {
00757 int32 Side;
00758 int32 i;
00759 geVec3d Corners[2];
00760 geFloat Dist1, Dist2;
00761
00762
00763 if (Plane->Type < PLANE_ANYX)
00764 {
00765 Side = 0;
00766 if (VectorToSUB(*Maxs, Plane->Type) >= Plane->Dist)
00767 Side |= PSIDE_FRONT;
00768 if (VectorToSUB(*Mins, Plane->Type) < Plane->Dist)
00769 Side |= PSIDE_BACK;
00770 return Side;
00771 }
00772
00773
00774 for (i=0 ; i<3 ; i++)
00775 {
00776 if (VectorToSUB(Plane->Normal, i) < 0)
00777 {
00778 VectorToSUB(Corners[0], i) = VectorToSUB(*Mins, i);
00779 VectorToSUB(Corners[1], i) = VectorToSUB(*Maxs, i);
00780 }
00781 else
00782 {
00783 VectorToSUB(Corners[1], i) = VectorToSUB(*Mins, i);
00784 VectorToSUB(Corners[0], i) = VectorToSUB(*Maxs, i);
00785 }
00786 }
00787
00788 Dist1 = geVec3d_DotProduct(&Plane->Normal, &Corners[0]) - Plane->Dist;
00789 Dist2 = geVec3d_DotProduct(&Plane->Normal, &Corners[1]) - Plane->Dist;
00790
00791 Side = 0;
00792 if (Dist1 >= 0)
00793 Side = PSIDE_FRONT;
00794 if (Dist2 < 0)
00795 Side |= PSIDE_BACK;
00796
00797 return Side;
00798 }
00799
00800
00801
00802
00803
00804 void Trace_ExpandPlaneForBox(GFX_Plane *Plane, geVec3d *Mins, geVec3d *Maxs)
00805 {
00806 geVec3d *Normal;
00807
00808 Normal = &Plane->Normal;
00809
00810 if (Normal->X > 0)
00811 Plane->Dist -= Normal->X * Mins->X;
00812 else
00813 Plane->Dist -= Normal->X * Maxs->X;
00814
00815 if (Normal->Y > 0)
00816 Plane->Dist -= Normal->Y * Mins->Y;
00817 else
00818 Plane->Dist -= Normal->Y * Maxs->Y;
00819
00820 if (Normal->Z > 0)
00821 Plane->Dist -= Normal->Z * Mins->Z;
00822 else
00823 Plane->Dist -= Normal->Z * Maxs->Z;
00824 }
00825
00826
00827
00828
00829 static geBoolean PointInLeafSides(const geVec3d *Pos, const GFX_Leaf *Leaf)
00830 {
00831 int32 i, f;
00832 GFX_Plane Plane;
00833 geFloat Dist;
00834
00835 f = Leaf->FirstSide;
00836
00837 for (i=0; i< Leaf->NumSides; i++)
00838 {
00839 Plane = MiscPlanes[MiscSides[i+f].PlaneNum];
00840 Plane.Type = PLANE_ANY;
00841
00842 if (MiscSides[i+f].PlaneSide)
00843 {
00844 geVec3d_Inverse(&Plane.Normal);
00845 Plane.Dist = -Plane.Dist;
00846 }
00847
00848
00849 Trace_ExpandPlaneForBox(&Plane, &GMins1, &GMaxs1);
00850
00851 Dist = Plane_PlaneDistanceFast(&Plane, Pos);
00852
00853 if (Dist >= 0.0f)
00854 return GE_FALSE;
00855 }
00856
00857 return GE_TRUE;
00858 }
00859
00860
00861
00862
00863 BOOL IntersectLeafSides_r(geVec3d *Front, geVec3d *Back, int32 Leaf, int32 Side, int32 PSide)
00864 {
00865 geFloat Fd, Bd, Dist;
00866 GFX_Plane Plane;
00867 int32 RSide, Side2;
00868 geVec3d I, Vec;
00869
00870 if (!PSide)
00871 return FALSE;
00872
00873 if (Side >= MiscLeafs[Leaf].NumSides)
00874 return TRUE;
00875
00876 RSide = MiscLeafs[Leaf].FirstSide + Side;
00877
00878 Plane = MiscPlanes[MiscSides[RSide].PlaneNum];
00879 Plane.Type = PLANE_ANY;
00880
00881 if (MiscSides[RSide].PlaneSide)
00882 {
00883 geVec3d_Inverse(&Plane.Normal);
00884 Plane.Dist = -Plane.Dist;
00885 }
00886
00887
00888 Trace_ExpandPlaneForBox(&Plane, &GMins1, &GMaxs1);
00889
00890 Fd = Plane_PlaneDistanceFast(&Plane, Front);
00891 Bd = Plane_PlaneDistanceFast(&Plane, Back);
00892
00893 #if 1
00894 if (Fd >= 0 && Bd >= 0)
00895 return IntersectLeafSides_r(Front, Back, Leaf, Side+1, 0);
00896
00897 if (Fd < 0 && Bd < 0)
00898 return IntersectLeafSides_r(Front, Back, Leaf, Side+1, 1);
00899 #else
00900 if ((Fd >= ON_EPSILON && Bd >= ON_EPSILON) || (Bd > Fd && Fd >= 0) )
00901 return IntersectLeafSides_r(Front, Back, Leaf, Side+1, 0);
00902
00903 if ((Fd < -ON_EPSILON && Bd < -ON_EPSILON) || (Bd < Fd && Fd <= 0))
00904 return IntersectLeafSides_r(Front, Back, Leaf, Side+1, 1);
00905 #endif
00906
00907
00908
00909
00910
00911 Side2 = Fd < 0;
00912
00913 if (Fd < 0)
00914 Dist = (Fd + ON_EPSILON)/(Fd-Bd);
00915 else
00916 Dist = (Fd - ON_EPSILON)/(Fd-Bd);
00917
00918 if (Dist < 0.0f)
00919 Dist = 0.0f;
00920
00921 if (Dist > 1.0f)
00922 Dist = 1.0f;
00923
00924 I.X = Front->X + Dist * (Back->X - Front->X);
00925 I.Y = Front->Y + Dist * (Back->Y - Front->Y);
00926 I.Z = Front->Z + Dist * (Back->Z - Front->Z);
00927
00928
00929 if (IntersectLeafSides_r(Front, &I, Leaf, Side+1, Side2))
00930 {
00931 LeafHit = TRUE;
00932 return TRUE;
00933 }
00934 else if (IntersectLeafSides_r(&I, Back, Leaf, Side+1, !Side2))
00935 {
00936 geVec3d_Subtract(&I, &GFront, &Vec);
00937 Dist = geVec3d_Length(&Vec);
00938
00939
00940 if (Dist < BestDist && !HitSet)
00941 {
00942 GlobalI = I;
00943 GlobalLeaf = Leaf;
00944 BestDist = Dist;
00945 GlobalPlane = Plane;
00946 GRatio = Dist;
00947 HitSet = TRUE;
00948 }
00949 LeafHit = TRUE;
00950 return TRUE;
00951 }
00952
00953 return FALSE;
00954 }
00955
00956
00957
00958
00959 BOOL IntersectLeafSides2(geVec3d *Pos, int32 Leaf)
00960 {
00961 GFX_Plane Plane;
00962 int32 i;
00963 geFloat Dist;
00964
00965 for (i=0; i< MiscLeafs[Leaf].NumSides; i++)
00966 {
00967 Plane = MiscPlanes[MiscSides[MiscLeafs[Leaf].FirstSide+i].PlaneNum];
00968
00969 if (!MiscSides[MiscLeafs[Leaf].FirstSide+i].PlaneSide)
00970 {
00971 geVec3d_Inverse(&Plane.Normal);
00972 Plane.Dist = -Plane.Dist;
00973 }
00974
00975 Dist = geVec3d_DotProduct(&Plane.Normal, Pos) - Plane.Dist;
00976
00977 if (Dist >= 25.0f)
00978 return FALSE;
00979 }
00980
00981 LeafHit = TRUE;
00982 return TRUE;
00983 }
00984
00985
00986
00987
00988 static void FindClosestLeafIntersection_r(int32 Node)
00989 {
00990 int32 Leaf, Side, Contents;
00991
00992 if (Node < 0)
00993 {
00994 Leaf = -(Node+1);
00995 Contents = MiscLeafs[Leaf].Contents;
00996
00997
00998 if (!(Contents & gContents))
00999 return;
01000
01001 HitSet = FALSE;
01002
01003 if (!MiscLeafs[Leaf].NumSides)
01004 return;
01005
01006 IntersectLeafSides_r(&GFront, &GBack, Leaf, 0, 1);
01007
01008
01009 return;
01010 }
01011
01012 Side = Trace_BoxOnPlaneSide(&GMins2, &GMaxs2, &MiscPlanes[MiscNodes[Node].PlaneNum]);
01013
01014
01015 if (Side & PSIDE_FRONT)
01016 FindClosestLeafIntersection_r(MiscNodes[Node].Children[0]);
01017
01018 if (Side & PSIDE_BACK)
01019 FindClosestLeafIntersection_r(MiscNodes[Node].Children[1]);
01020 }
01021
01022 #define SIDE_SPACE 0.1f
01023
01024
01025
01026
01027
01028 geBoolean Trace_WorldCollisionBBox( geWorld *World,
01029 const geVec3d *Mins, const geVec3d *Maxs,
01030 const geVec3d *Front, const geVec3d *Back,
01031 uint32 Flags,
01032 geVec3d *I, GFX_Plane *P,
01033 geWorld_Model **Model,
01034 Mesh_RenderQ **Mesh,
01035 geActor **Actor,
01036 uint32 UserFlags,
01037 GE_CollisionCB *CollisionCB,
01038 void *Context)
01039 {
01040 geWorld_Model *Models;
01041 geVec3d NewFront, NewBack, OMins, OMaxs, BestI, Vect;
01042 geVec3d Impact;
01043 int32 i, b;
01044 geFloat Dist, BestD;
01045 Mesh_RenderQ *BestMesh;
01046 #ifdef MESHES
01047 Mesh_RenderQ *Mesh2;
01048 #endif
01049 geActor *BestActor;
01050 geWorld_Model *BestModel;
01051 GFX_Plane BestPlane, Plane2;
01052 geBoolean Hit;
01053
01054 if (Model)
01055 *Model = NULL;
01056 if (Mesh)
01057 *Mesh = NULL;
01058 if (Actor)
01059 *Actor = NULL;
01060
01061 BestD = 99999.0f;
01062 BestMesh = NULL;
01063 BestModel = NULL;
01064 BestActor = NULL;
01065 Hit = GE_FALSE;
01066
01067
01068 if (Flags & GE_COLLIDE_MESHES)
01069 {
01070 #ifdef MESHES
01071 if (Mesh_MeshCollisionAll(World, Mins, Maxs, Front, Back, &Impact, &Plane2, &Mesh2, UserFlags))
01072 {
01073 geVec3d_Subtract(&Impact, Front, &Vect);
01074 Dist = geVec3d_Length(&Vect);
01075 if (Dist < BestD)
01076 {
01077 BestD = Dist;
01078 BestI = Impact;
01079 BestMesh = Mesh2;
01080 BestPlane = Plane2;
01081 Hit = GE_TRUE;
01082 }
01083 }
01084 #endif
01085 }
01086
01087
01088 if (Flags & GE_COLLIDE_ACTORS)
01089 {
01090 BestActor = Trace_ActorCollide(World, Mins,Maxs, Front,Back,&Impact,&Plane2,UserFlags, CollisionCB, Context, &BestD);
01091 if (BestActor != NULL)
01092 {
01093 BestI = Impact;
01094 BestPlane = Plane2;
01095 Hit = GE_TRUE;
01096 }
01097 }
01098
01099
01100
01101 GMins1 = *Mins;
01102 GMaxs1 = *Maxs;
01103
01104 GFront = *Front;
01105 GBack = *Back;
01106
01107 BSPData = &World->CurrentBSP->BSPData;
01108 Models = World->CurrentBSP->Models;
01109
01110 MiscNodes = BSPData->GFXNodes;
01111 MiscPlanes = BSPData->GFXPlanes;
01112 MiscLeafs = BSPData->GFXLeafs;
01113 MiscSides = BSPData->GFXLeafSides;
01114
01115 assert(MiscNodes != NULL);
01116 assert(MiscPlanes != NULL);
01117 assert(MiscLeafs != NULL);
01118 assert(MiscSides != NULL);
01119
01120 if (!(Flags & GE_COLLIDE_MODELS))
01121 goto NoModels;
01122
01123 Trace_GetMoveBox(Mins, Maxs, Front, Back, &OMins, &OMaxs);
01124
01125
01126
01127 for (i = 0; i < BSPData->NumGFXModels; i++, Models++)
01128 {
01129
01130
01131 if (CollisionCB && !CollisionCB(Models, NULL, Context))
01132 continue;
01133
01134 for (b=0; b<3; b++)
01135 {
01136 if (VectorToSUB(OMaxs, b) < VectorToSUB(Models->TMins, b))
01137 break;
01138 if (VectorToSUB(OMins, b) > VectorToSUB(Models->TMaxs, b))
01139 break;
01140 }
01141
01142 if (b != 3)
01143 continue;
01144
01145
01146
01147 BestDist = 9999.0f;
01148 LeafHit = FALSE;
01149
01150 geVec3d_Subtract(Front, &Models->Pivot, &GFront);
01151 geVec3d_Subtract(Back , &Models->Pivot, &GBack);
01152
01153
01154 geXForm3d_TransposeTransform(&Models->XForm, &GFront, &NewFront);
01155 geXForm3d_TransposeTransform(&Models->XForm, &GBack , &NewBack);
01156
01157
01158 geVec3d_Add(&NewFront, &Models->Pivot, &GFront);
01159 geVec3d_Add(&NewBack , &Models->Pivot, &GBack);
01160
01161
01162
01163 Trace_GetMoveBox(Mins, Maxs, &GFront, &GBack, &GMins2, &GMaxs2);
01164
01165 FindClosestLeafIntersection_r(BSPData->GFXModels[i].RootNode[0]);
01166
01167 if (LeafHit)
01168 {
01169
01170
01171 geXForm3d_Rotate(&Models->XForm, &GlobalPlane.Normal, &GlobalPlane.Normal);
01172
01173
01174 geVec3d_Subtract(&GlobalI, &Models->Pivot, &GlobalI);
01175 geXForm3d_Transform(&Models->XForm, &GlobalI, &NewFront);
01176
01177 geVec3d_Add(&NewFront, &Models->Pivot, &GlobalI);
01178
01179
01180 GlobalPlane.Dist = geVec3d_DotProduct(&GlobalPlane.Normal, &GlobalI);
01181
01182 geVec3d_Subtract(&GlobalI, Front, &Vect);
01183
01184 Dist = geVec3d_Length(&Vect);
01185 if (Dist < BestD)
01186 {
01187 BestD = Dist;
01188 BestI = GlobalI;
01189 BestPlane = GlobalPlane;
01190 BestModel = Models;
01191 BestMesh = NULL;
01192 BestActor = NULL;
01193 Hit = GE_TRUE;
01194 }
01195 }
01196
01197 if ((Flags & GE_COLLIDE_NO_SUB_MODELS))
01198 goto NoModels;
01199
01200 }
01201
01202 NoModels:
01203
01204 if (Hit)
01205 {
01206 if (I)
01207 *I = BestI;
01208 if (P)
01209 *P = BestPlane;
01210 if (Mesh)
01211 *Mesh = BestMesh;
01212 if (Model)
01213 *Model = BestModel;
01214 if (Actor)
01215 *Actor = BestActor;
01216 return GE_TRUE;
01217 }
01218
01219 return GE_FALSE;
01220 }
01221
01222
01223
01224
01225 geBoolean Trace_TestModelMove( geWorld *World,
01226 geWorld_Model *Model,
01227 const geXForm3d *DXForm,
01228 const geVec3d *Mins, const geVec3d *Maxs,
01229 const geVec3d *In, geVec3d *Out)
01230 {
01231 geVec3d NewFront, NewBack, Original;
01232
01233 assert(World != NULL);
01234 assert(Model != NULL);
01235
01236 BSPData = &World->CurrentBSP->BSPData;
01237
01238 MiscNodes = BSPData->GFXNodes;
01239 MiscPlanes = BSPData->GFXPlanes;
01240 MiscLeafs = BSPData->GFXLeafs;
01241 MiscSides = BSPData->GFXLeafSides;
01242
01243 assert(MiscNodes != NULL);
01244 assert(MiscPlanes != NULL);
01245 assert(MiscLeafs != NULL);
01246 assert(MiscSides != NULL);
01247
01248 Original = *In;
01249
01250 GMins1 = *Mins;
01251 GMaxs1 = *Maxs;
01252
01253
01254 geVec3d_Subtract(In, &Model->Pivot, &GFront);
01255 GBack = GFront;
01256
01257
01258 geXForm3d_TransposeTransform(&Model->XForm, &GFront, &NewFront);
01259
01260 geXForm3d_TransposeTransform(DXForm, &GBack, &NewBack);
01261
01262
01263 geVec3d_Add(&NewFront, &Model->Pivot, &GFront);
01264 geVec3d_Add(&NewBack , &Model->Pivot, &GBack);
01265
01266
01267 Trace_GetMoveBox(Mins, Maxs, &GFront, &GBack, &GMins2, &GMaxs2);
01268
01269 BestDist = 9999.0f;
01270 LeafHit = FALSE;
01271
01272 FindClosestLeafIntersection_r(BSPData->GFXModels[Model->GFXModelNum].RootNode[0]);
01273
01274 if (LeafHit)
01275 {
01276 GE_Collision Collision;
01277
01278
01279 geXForm3d_Rotate(DXForm, &GlobalPlane.Normal, &GlobalPlane.Normal);
01280
01281
01282 geVec3d_Subtract(&GlobalI, &Model->Pivot, &NewFront);
01283 geXForm3d_Transform(DXForm, &NewFront, &GlobalI);
01284 geVec3d_Add(&GlobalI, &Model->Pivot, &NewFront);
01285 GlobalI = NewFront;
01286
01287
01288 GlobalPlane.Dist = geVec3d_DotProduct(&GlobalPlane.Normal, &GlobalI);
01289
01290 geVec3d_MA(&GlobalI, ON_EPSILON, &GlobalPlane.Normal, &GlobalI);
01291
01292
01293 if (Trace_GEWorldCollision(World, Mins, Maxs, In, &GlobalI, GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL, 0xffffffff, NULL, NULL, &Collision))
01294 {
01295 *Out = Original;
01296 return GE_FALSE;
01297 }
01298
01299 *Out = GlobalI;
01300
01301 return GE_TRUE;
01302 }
01303
01304 *Out = Original;
01305
01306 return GE_TRUE;
01307 }
01308
01309
01310
01311
01312 static
01313 geBoolean Trace_ModelCollisionBBox(geWorld *World,
01314 geWorld_Model *Model,
01315 const geXForm3d *DXForm,
01316 const geVec3d *Mins, const geVec3d *Maxs,
01317 const geVec3d *In,
01318 geVec3d *ImpactPoint)
01319 {
01320
01321
01322 geVec3d NewFront, NewBack;
01323
01324 assert(World != NULL);
01325 assert(Model != NULL);
01326 BSPData = &World->CurrentBSP->BSPData;
01327 MiscNodes = BSPData->GFXNodes;
01328 MiscPlanes = BSPData->GFXPlanes;
01329 MiscLeafs = BSPData->GFXLeafs;
01330 MiscSides = BSPData->GFXLeafSides;
01331 assert(MiscNodes != NULL);
01332 assert(MiscPlanes != NULL);
01333 assert(MiscLeafs != NULL);
01334 assert(MiscSides != NULL);
01335
01336
01337
01338 GMins1 = *Mins;
01339 GMaxs1 = *Maxs;
01340
01341
01342 geVec3d_Subtract(In, &Model->Pivot, &GFront);
01343 GBack = GFront;
01344
01345 geXForm3d_TransposeTransform(&Model->XForm, &GFront, &NewFront);
01346
01347 geXForm3d_TransposeTransform(DXForm, &GBack, &NewBack);
01348
01349 geVec3d_Add(&NewFront, &Model->Pivot, &GFront);
01350 geVec3d_Add(&NewBack , &Model->Pivot, &GBack);
01351
01352 Trace_GetMoveBox(Mins, Maxs, &GFront, &GBack, &GMins2, &GMaxs2);
01353
01354 BestDist = 9999.0f;
01355 LeafHit = FALSE;
01356 FindClosestLeafIntersection_r(BSPData->GFXModels[Model->GFXModelNum].RootNode[0]);
01357 if (LeafHit)
01358 {
01359
01360 geXForm3d_Rotate(DXForm, &GlobalPlane.Normal, &GlobalPlane.Normal);
01361
01362
01363
01364
01365
01366
01367
01368 geVec3d_Subtract(&GlobalI, &Model->Pivot, &GlobalI);
01369 geXForm3d_Transform(DXForm, &GlobalI, &NewFront);
01370 geVec3d_Add(&NewFront, &Model->Pivot, &GlobalI);
01371
01372
01373 GlobalPlane.Dist = geVec3d_DotProduct(&GlobalPlane.Normal, &GlobalI);
01374 geVec3d_MA(&GlobalI, ON_EPSILON, &GlobalPlane.Normal, &GlobalI);
01375 *ImpactPoint = GlobalI;
01376 return GE_TRUE;
01377 }
01378 return GE_FALSE;
01379 }
01380
01381
01382
01383 geBoolean Trace_ModelCollision(geWorld *World,
01384 geWorld_Model *Model,
01385 const geXForm3d *DXForm,
01386 GE_Collision *Collision,
01387 geVec3d *ImpactPoint)
01388 {
01389 geExtBox ExtBox;
01390 geVec3d Pos;
01391 geXForm3d myXForm;
01392 #ifdef MESHES
01393 Mesh_RenderQ * CollidableMesh;
01394 Mesh_CollidableMeshIterator Iter;
01395 #endif
01396 gContents = GE_CONTENTS_SOLID_CLIP;
01397 memset(Collision, 0, sizeof(GE_Collision));
01398
01399 #ifdef MESHES
01400 CollidableMesh = Mesh_FirstCollidableMesh(World, &Iter, 0xffffffff);
01401 while (CollidableMesh)
01402 {
01403 Mesh_MeshGetBox(World, CollidableMesh->MeshDef, &Mins, &Maxs);
01404 Mesh_MeshGetPosition(CollidableMesh, &Pos);
01405 if (Trace_ModelCollisionBBox(World, Model, DXForm, &Mins, &Maxs, &Pos, ImpactPoint))
01406 {
01407 Collision->Mesh = (geMesh *)CollidableMesh;
01408 return GE_TRUE;
01409 }
01410 CollidableMesh = Mesh_NextCollidableMesh(&Iter, 0xffffffff);
01411 }
01412 #endif
01413 {
01414 int i,Count;
01415 World_Actor *WA;
01416
01417 geActor *BestActor;
01418 geFloat BestActorDist;
01419 geVec3d PossibleImpactPoint;
01420 BestActor = NULL;
01421 BestActorDist = 9999.0f;
01422
01423
01424 Count = World->ActorCount;
01425 WA = &(World->ActorArray[0]);
01426 for (i=0; i < Count; i++, WA++)
01427 {
01428
01429 if ( (WA->Flags & GE_ACTOR_COLLIDE) )
01430 {
01431
01432
01433
01434 geActor_GetNonWorldExtBox(WA->Actor,&ExtBox);
01435 geActor_GetPosition(WA->Actor, &Pos);
01436
01437 geActor_GetBoneTransform(WA->Actor, NULL, &myXForm);
01438 geVec3d_Copy(&myXForm.Translation, &Pos);
01439 geVec3d_Subtract(&ExtBox.Min, &Pos, &ExtBox.Min);
01440 geVec3d_Subtract(&ExtBox.Max, &Pos, &ExtBox.Max);
01441
01442
01443 if (Trace_ModelCollisionBBox(World, Model, DXForm, &(ExtBox.Min), &(ExtBox.Max), &Pos, &PossibleImpactPoint))
01444 {
01445
01446 if (GlobalPlane.Dist < BestActorDist)
01447 {
01448 BestActorDist = GlobalPlane.Dist;
01449 BestActor = WA->Actor;
01450 (*ImpactPoint) = PossibleImpactPoint;
01451 Collision->Plane.Normal = GlobalPlane.Normal;
01452 Collision->Plane.Dist = GlobalPlane.Dist;
01453 Collision->Ratio = geVec3d_DistanceBetween(&DXForm->Translation, &Model->XForm.Translation);
01454 }
01455
01456 }
01457
01458
01459 }
01460 }
01461
01462 if (BestActor) {
01463 Collision->Actor = BestActor;
01464 return GE_TRUE;
01465 }
01466
01467 }
01468 return GE_FALSE;
01469 }
01470
01471
01472
01473
01474
01475
01476 void Trace_GetMoveBox(const geVec3d *Mins, const geVec3d *Maxs, const geVec3d *Front, const geVec3d *Back, geVec3d *OMins, geVec3d *OMaxs)
01477 {
01478 int32 i;
01479
01480 assert(Mins);
01481 assert(Maxs);
01482 assert(Front);
01483 assert(Back);
01484
01485 for (i=0 ; i<3 ; i++)
01486 {
01487 if (VectorToSUB(*Back, i) > VectorToSUB(*Front, i))
01488 {
01489 VectorToSUB(*OMins, i) = VectorToSUB(*Front, i) + VectorToSUB(*Mins, i) - 1.0f;
01490 VectorToSUB(*OMaxs, i) = VectorToSUB(*Back, i) + VectorToSUB(*Maxs, i) + 1.0f;
01491 }
01492 else
01493 {
01494 VectorToSUB(*OMins, i) = VectorToSUB(*Back, i) + VectorToSUB(*Mins, i) - 1.0f;
01495 VectorToSUB(*OMaxs, i) = VectorToSUB(*Front, i) + VectorToSUB(*Maxs, i) + 1.0f;
01496 }
01497 }
01498 }
01499
01500
01501 static geBoolean VisibleLeaf;
01502
01503
01504
01505 static void BBoxInVisibleLeaf_r(geWorld *World, geVec3d *Mins, geVec3d *Maxs, int32 Node)
01506 {
01507 int32 Leaf, Side;
01508
01509 if (VisibleLeaf)
01510 return;
01511
01512 if (Node < 0)
01513 {
01514 Leaf = -(Node+1);
01515
01516 if (World->CurrentBSP->LeafData[Leaf].VisFrame == World->CurFrameStatic)
01517 VisibleLeaf = TRUE;
01518
01519 return;
01520 }
01521
01522 Side = Trace_BoxOnPlaneSide(Mins, Maxs, &MiscPlanes[MiscNodes[Node].PlaneNum]);
01523
01524
01525 if (Side & PSIDE_FRONT)
01526 BBoxInVisibleLeaf_r(World, Mins, Maxs, MiscNodes[Node].Children[0]);
01527
01528 if (Side & PSIDE_BACK)
01529 BBoxInVisibleLeaf_r(World, Mins, Maxs, MiscNodes[Node].Children[1]);
01530 }
01531
01532 geBoolean Trace_BBoxInVisibleLeaf(geWorld *World, geVec3d *Mins, geVec3d *Maxs)
01533 {
01534 VisibleLeaf = FALSE;
01535
01536 MiscNodes = World->CurrentBSP->BSPData.GFXNodes;
01537 MiscPlanes = World->CurrentBSP->BSPData.GFXPlanes;
01538
01539 BBoxInVisibleLeaf_r(World, Mins, Maxs, 0);
01540
01541 return VisibleLeaf;
01542 }
01543
01544
01545
01546
01547
01548 geBoolean Trace_InverseTreeFromBox(geVec3d *Mins, geVec3d *Maxs, GFX_BNode *BNodes, GFX_Plane *Planes)
01549 {
01550 int32 i,j,n;
01551 geFloat Bounds[2][3];
01552 GFX_Plane *Plane;
01553
01554 for (i=0; i< 3; i++)
01555 {
01556 Bounds[0][i] = VectorToSUB(*Mins, i);
01557 Bounds[1][i] = VectorToSUB(*Maxs, i);
01558 }
01559
01560
01561 for (i=0; i< 3; i++)
01562 {
01563 for (j=0; j< 2; j++)
01564 {
01565 n = j*3 + i;
01566
01567 Plane = &Planes[n];
01568
01569 memset(Plane, 0, sizeof(GFX_Plane));
01570
01571 if (!j)
01572 {
01573 VectorToSUB(Plane->Normal, i) = 1.0f;
01574 Plane->Dist = Bounds[j][i];
01575 }
01576 else
01577 {
01578 VectorToSUB(Plane->Normal, i) = -1.0f;
01579 Plane->Dist = -Bounds[j][i];
01580 }
01581
01582 Plane->Type = PLANE_ANY;
01583
01584
01585
01586
01587 BNodes[n].PlaneNum = n;
01588
01589 BNodes[n].Children[1] = BSP_CONTENTS_SOLID;
01590
01591 if (n == 5)
01592 BNodes[n].Children[0] = BSP_CONTENTS_EMPTY;
01593 else
01594 BNodes[n].Children[0] = n+1;
01595 }
01596 }
01597
01598 return GE_TRUE;
01599 }
01600
01601
01602
01603
01604
01605
01606 int32 Plane_FindBNodeContents( const GFX_BNode *Nodes,
01607 const GFX_Plane *Planes,
01608 int32 Node,
01609 const geVec3d *POV)
01610 {
01611 geFloat Dist;
01612
01613 while (Node >= 0)
01614 {
01615 Dist = Plane_PlaneDistanceFast(&Planes[Nodes[Node].PlaneNum], POV);
01616
01617 if (Dist < 0)
01618 Node = Nodes[Node].Children[1];
01619 else
01620 Node = Nodes[Node].Children[0];
01621 }
01622
01623 return Node;
01624 }
01625
01626
01627
01628
01629
01630 static void FillContents_r(int32 Node, const geVec3d *Pos, uint32 *Contents)
01631 {
01632 int32 Side;
01633
01634 if (Node < 0)
01635 {
01636 int32 Leaf;
01637
01638 Leaf = -(Node+1);
01639 if (PointInLeafSides(Pos, &MiscLeafs[Leaf]))
01640 *Contents |= MiscLeafs[Leaf].Contents;
01641 return;
01642 }
01643
01644 Side = Trace_BoxOnPlaneSide(&GMins2, &GMaxs2, &MiscPlanes[MiscNodes[Node].PlaneNum]);
01645
01646
01647 if (Side & PSIDE_FRONT)
01648 FillContents_r(MiscNodes[Node].Children[0], Pos, Contents);
01649
01650 if (Side & PSIDE_BACK)
01651 FillContents_r(MiscNodes[Node].Children[1], Pos, Contents);
01652 }
01653
01654
01655
01656
01657
01658
01659 geBoolean Trace_GetContents(geWorld *World, const geVec3d *Pos, const geVec3d *Mins, const geVec3d *Maxs, uint32 Flags, uint32 UserFlags, GE_CollisionCB *CollisionCB, void *Context, GE_Contents *Contents)
01660 {
01661 Mesh_RenderQ *MeshHit;
01662 geActor *ActorHit;
01663 geExtBox MeshExtBox;
01664 geVec3d TMins, TMaxs;
01665 geBoolean Hit;
01666 int32 i, k;
01667 uint32 NewContents, FinalContents;
01668 geWorld_Model *Models, *ModelHit;
01669 GFX_Model *GFXModels;
01670
01671 assert(World);
01672 assert(Contents);
01673
01674 MeshHit = NULL;
01675 ModelHit = NULL;
01676 FinalContents = 0;
01677 Hit = GE_FALSE;
01678
01679 BSPData = &World->CurrentBSP->BSPData;
01680
01681
01682 geVec3d_Add(Mins, Pos, &TMins);
01683 geVec3d_Add(Maxs, Pos, &TMaxs);
01684
01685 NumGetContents++;
01686
01687 if (Flags & GE_COLLIDE_ACTORS)
01688 {
01689 int32 Count;
01690 World_Actor *WA;
01691
01692 Count = World->ActorCount;
01693 WA = &(World->ActorArray[0]);
01694
01695 for (i=0; i<Count; i++, WA++)
01696 {
01697
01698
01699 if (!(WA->Flags & GE_ACTOR_COLLIDE) || !(WA->UserFlags & UserFlags) )
01700 continue;
01701
01702 if (CollisionCB && !CollisionCB(NULL, WA->Actor, Context))
01703 continue;
01704
01705
01706 if (geActor_GetExtBox(WA->Actor,&MeshExtBox)==GE_FALSE)
01707 continue;
01708
01709 for (k=0; k<3; k++)
01710 {
01711 if (geVec3d_GetElement(&TMaxs,k) < geVec3d_GetElement(&(MeshExtBox.Min),k)-1)
01712 break;
01713 if (geVec3d_GetElement(&TMins,k) > geVec3d_GetElement(&(MeshExtBox.Max),k)+1)
01714 break;
01715 }
01716
01717 if (k != 3)
01718 continue;
01719
01720 ActorHit = WA->Actor;
01721 Hit = GE_TRUE;
01722 break;
01723 }
01724 }
01725
01726 if (!(Flags & GE_COLLIDE_MODELS))
01727 goto NoModels;
01728
01729 MiscNodes = World->CurrentBSP->BSPData.GFXNodes;
01730 MiscPlanes = World->CurrentBSP->BSPData.GFXPlanes;
01731 MiscLeafs = World->CurrentBSP->BSPData.GFXLeafs;
01732 MiscSides = BSPData->GFXLeafSides;
01733
01734 Models = World->CurrentBSP->Models;
01735 GFXModels = World->CurrentBSP->BSPData.GFXModels;
01736
01737 GMins1 = *Mins;
01738 GMaxs1 = *Maxs;
01739
01740 GMins2 = TMins;
01741 GMaxs2 = TMaxs;
01742
01743 for (i = 0; i < BSPData->NumGFXModels; i++, Models++, GFXModels++)
01744 {
01745 geVec3d TPos;
01746
01747 if (CollisionCB && !CollisionCB(Models, NULL, Context))
01748 continue;
01749
01750 if (i > 0)
01751 {
01752 for (k=0; k<3; k++)
01753 {
01754 if (VectorToSUB(TMaxs, k) < VectorToSUB(Models->TMins, k))
01755 break;
01756 if (VectorToSUB(TMins, k) > VectorToSUB(Models->TMaxs, k))
01757 break;
01758 }
01759
01760 if (k != 3)
01761 continue;
01762 }
01763
01764 geVec3d_Subtract(Pos, &Models->RealCenter, &TPos);
01765
01766
01767 geXForm3d_TransposeTransform(&Models->XForm, &TPos, &TPos);
01768
01769
01770
01771 geVec3d_Add(&TPos, &Models->RealCenter, &TPos);
01772
01773
01774 NewContents = 0;
01775
01776 FillContents_r(GFXModels->RootNode[0], &TPos, &NewContents);
01777
01778 if (NewContents && !ModelHit)
01779 {
01780 ModelHit = Models;
01781 Hit = GE_TRUE;
01782 }
01783
01784 if (NewContents & GE_CONTENTS_SOLID_CLIP)
01785 {
01786 ModelHit = Models;
01787 }
01788
01789
01790 FinalContents |= NewContents;
01791
01792 if ((Flags & GE_COLLIDE_NO_SUB_MODELS))
01793 goto NoModels;
01794 }
01795
01796 NoModels:
01797
01798 if (Hit)
01799 {
01800 Contents->Contents = FinalContents;
01801 Contents->Mesh = (geMesh*)MeshHit;
01802 Contents->Model = ModelHit;
01803 Contents->Actor = ActorHit;
01804 return GE_TRUE;
01805 }
01806
01807
01808 memset(Contents, 0, sizeof(GE_Contents));
01809
01810 return GE_FALSE;
01811 }
01812
01813
01814
01815
01816
01817
01818 static GFX_Plane *TreePlanes;
01819 static GFX_Node *TreeNodes;
01820 static GFX_Leaf *TreeLeafs;
01821
01822 void Trace_SetupIntersect(geWorld *World)
01823 {
01824 BSPData = &World->CurrentBSP->BSPData;
01825
01826 TreePlanes = BSPData->GFXPlanes;
01827 TreeNodes = BSPData->GFXNodes;
01828 TreeLeafs = BSPData->GFXLeafs;
01829 }
01830
01831
01832
01833
01834
01835 geBoolean Trace_IntersectWorldBSP(geVec3d *Front, geVec3d *Back, int32 Node)
01836 {
01837 geFloat Fd, Bd, Dist;
01838 int32 Side;
01839 geVec3d I;
01840 GFX_Plane *Plane;
01841 int32 Contents;
01842
01843 gContents = GE_CONTENTS_SOLID_CLIP;
01844
01845 if (Node < 0)
01846 {
01847 Contents = TreeLeafs[-(Node+1)].Contents;
01848
01849 if (Contents & gContents)
01850 return GE_TRUE;
01851 return GE_FALSE;
01852 }
01853
01854 Plane = &TreePlanes[TreeNodes[Node].PlaneNum];
01855
01856 Fd = Plane_PlaneDistanceFast(Plane, Front);
01857 Bd = Plane_PlaneDistanceFast(Plane, Back);
01858
01859 if (Fd >= 0 && Bd >= 0)
01860 return(BSPIntersect(Front, Back, TreeNodes[Node].Children[0]));
01861 if (Fd < 0 && Bd < 0)
01862 return(BSPIntersect(Front, Back, TreeNodes[Node].Children[1]));
01863
01864 Side = Fd < 0;
01865 Dist = Fd / (Fd - Bd);
01866
01867 I.X = Front->X + Dist * (Back->X - Front->X);
01868 I.Y = Front->Y + Dist * (Back->Y - Front->Y);
01869 I.Z = Front->Z + Dist * (Back->Z - Front->Z);
01870
01871
01872
01873
01874
01875 if (BSPIntersect(Front, &I, TreeNodes[Node].Children[Side]))
01876 return GE_TRUE;
01877 else if (BSPIntersect(&I, Back, TreeNodes[Node].Children[!Side]))
01878 {
01879 return GE_TRUE;
01880 }
01881
01882 return GE_FALSE;
01883 }
01884
01885 static geVec3d gStart, gEnd;
01886 static GFX_Plane gPlane;
01887
01888 geBoolean Trace_CollideBeam(int32 Node, geVec3d *s, geVec3d *e, geFloat Radius)
01889 {
01890 geFloat dd, sDist, eDist;
01891 geVec3d tempVec, tempVec2;
01892 geBoolean FrontLeaf, BackLeaf;
01893 GFX_Plane *Plane;
01894
01895 if(Node < 0)
01896 {
01897
01898 return !(!(BSPData->GFXLeafs[-(Node+1)].Contents & gContents));
01899 }
01900 Plane =&BSPData->GFXPlanes[BSPData->GFXNodes[Node].PlaneNum];
01901
01902
01903 sDist =Plane_PlaneDistanceFast(Plane, s);
01904 eDist =Plane_PlaneDistanceFast(Plane, e);
01905
01906
01907 if(*((uint32 *)&sDist) & 0x80000000)
01908 {
01909 if(sDist < -Radius)
01910 {
01911 if(*((uint32 *)&eDist) & 0x80000000)
01912 {
01913 if(eDist < -Radius)
01914 {
01915
01916 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
01917 }
01918 else
01919 {
01920
01921
01922
01923 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
01924
01925
01926 if(*((uint32 *)&dd) & 0x80000000)
01927 {
01928 dd =0.0f;
01929 }
01930
01931 geVec3d_Subtract(e, s, &tempVec);
01932 geVec3d_Scale(&tempVec, dd, &tempVec2);
01933 geVec3d_Add(s, &tempVec2, &tempVec);
01934
01935
01936 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], &tempVec, e, Radius);
01937 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
01938 }
01939 }
01940 else
01941 {
01942 if(eDist > Radius)
01943 {
01944
01945
01946
01947 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
01948
01949 geVec3d_Subtract(e, s, &tempVec);
01950 geVec3d_Scale(&tempVec, dd, &tempVec2);
01951 geVec3d_Add(s, &tempVec2, &tempVec);
01952
01953
01954 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], &tempVec, e, Radius);
01955
01956
01957
01958 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
01959
01960
01961 if(*((uint32 *)&dd) & 0x80000000)
01962 {
01963 dd =0.0f;
01964 }
01965
01966 geVec3d_Subtract(e, s, &tempVec);
01967 geVec3d_Scale(&tempVec, dd, &tempVec2);
01968 geVec3d_Add(e, &tempVec2, &tempVec);
01969
01970
01971 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, &tempVec, Radius);
01972 }
01973 else
01974 {
01975
01976
01977
01978 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
01979
01980
01981 if(*((uint32 *)&dd) & 0x80000000)
01982 {
01983 dd =0.0f;
01984 }
01985
01986 geVec3d_Subtract(e, s, &tempVec);
01987 geVec3d_Scale(&tempVec, dd, &tempVec2);
01988 geVec3d_Add(s, &tempVec2, &tempVec);
01989
01990
01991 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], &tempVec, e, Radius);
01992 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
01993 }
01994 }
01995 }
01996 else
01997 {
01998 if(*((uint32 *)&eDist) & 0x80000000)
01999 {
02000 if(eDist < -Radius)
02001 {
02002
02003
02004
02005 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
02006
02007
02008 if(*((uint32 *)&dd) & 0x80000000)
02009 {
02010 dd =0.0f;
02011 }
02012
02013 geVec3d_Subtract(e, s, &tempVec);
02014 geVec3d_Scale(&tempVec, dd, &tempVec2);
02015 geVec3d_Add(e, &tempVec2, &tempVec);
02016
02017
02018 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, &tempVec, Radius);
02019 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02020 }
02021 else
02022 {
02023
02024 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02025 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02026 }
02027 }
02028 else
02029 {
02030 if(eDist > Radius)
02031 {
02032
02033 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02034
02035
02036
02037 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
02038
02039
02040 if(*((uint32 *)&dd) & 0x80000000)
02041 {
02042 dd =0.0f;
02043 }
02044
02045 geVec3d_Subtract(e, s, &tempVec);
02046 geVec3d_Scale(&tempVec, dd, &tempVec2);
02047 geVec3d_Add(e, &tempVec2, &tempVec);
02048
02049
02050 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, &tempVec, Radius);
02051 }
02052 else
02053 {
02054
02055 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02056 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02057 }
02058 }
02059 }
02060 }
02061 else
02062 {
02063 if(sDist > Radius)
02064 {
02065 if(!(*((uint32 *)&eDist) & 0x80000000))
02066 {
02067 if(eDist > Radius)
02068 {
02069
02070 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02071 }
02072 else
02073 {
02074
02075 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02076
02077
02078
02079 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
02080
02081
02082 if(*((uint32 *)&dd) & 0x80000000)
02083 {
02084 dd =0.0f;
02085 }
02086
02087 geVec3d_Subtract(e, s, &tempVec);
02088 geVec3d_Scale(&tempVec, dd, &tempVec2);
02089 geVec3d_Add(e, &tempVec2, &tempVec);
02090
02091
02092 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], &tempVec, e, Radius);
02093 }
02094 }
02095 else
02096 {
02097 if(eDist < -Radius)
02098 {
02099
02100
02101
02102 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
02103
02104 geVec3d_Subtract(e, s, &tempVec);
02105 geVec3d_Scale(&tempVec, dd, &tempVec2);
02106 geVec3d_Add(e, &tempVec2, &tempVec);
02107
02108
02109 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, &tempVec, Radius);
02110
02111
02112
02113 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
02114
02115
02116 if(*((uint32 *)&dd) & 0x80000000)
02117 {
02118 dd =0.0f;
02119 }
02120
02121 geVec3d_Subtract(e, s, &tempVec);
02122 geVec3d_Scale(&tempVec, dd, &tempVec2);
02123 geVec3d_Add(s, &tempVec2, &tempVec);
02124
02125
02126 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], &tempVec, e, Radius);
02127 }
02128 else
02129 {
02130
02131 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02132
02133
02134
02135 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
02136
02137
02138 if(*((uint32 *)&dd) & 0x80000000)
02139 {
02140 dd =0.0f;
02141 }
02142
02143 geVec3d_Subtract(e, s, &tempVec);
02144 geVec3d_Scale(&tempVec, dd, &tempVec2);
02145 geVec3d_Add(s, &tempVec2, &tempVec);
02146
02147
02148 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], &tempVec, e, Radius);
02149 }
02150 }
02151 }
02152 else
02153 {
02154 if(!(*((uint32 *)&eDist) & 0x80000000))
02155 {
02156 if(eDist > Radius)
02157 {
02158
02159 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02160
02161
02162
02163 dd=(sDist-Radius)/((sDist-Radius)-(eDist-Radius));
02164
02165
02166 if(*((uint32 *)&dd) & 0x80000000)
02167 {
02168 dd =0.0f;
02169 }
02170
02171 geVec3d_Subtract(e, s, &tempVec);
02172 geVec3d_Scale(&tempVec, dd, &tempVec2);
02173 geVec3d_Add(e, &tempVec2, &tempVec);
02174
02175
02176 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, &tempVec, Radius);
02177 }
02178 else
02179 {
02180
02181 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02182 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02183 }
02184 }
02185 else
02186 {
02187 if(eDist < -Radius)
02188 {
02189
02190
02191
02192 dd=(sDist+Radius)/((sDist+Radius)-(eDist+Radius));
02193
02194
02195 if(*((uint32 *)&dd) & 0x80000000)
02196 {
02197 dd =0.0f;
02198 }
02199
02200 geVec3d_Subtract(e, s, &tempVec);
02201 geVec3d_Scale(&tempVec, dd, &tempVec2);
02202 geVec3d_Add(e, &tempVec2, &tempVec);
02203
02204
02205 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, &tempVec, Radius);
02206 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02207 }
02208 else
02209 {
02210
02211 FrontLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[0], s, e, Radius);
02212 BackLeaf =Trace_CollideBeam(BSPData->GFXNodes[Node].Children[1], s, e, Radius);
02213 }
02214 }
02215 }
02216 }
02217
02218
02219
02220 if(BackLeaf && !FrontLeaf)
02221 {
02222 gStart =*s;
02223 gEnd =*e;
02224 gPlane =*Plane;
02225 }
02226
02227
02228 return GE_FALSE;
02229 }
02230
02231
02232
02233
02234
02235
02236
02237
02238 static void FillContents_tr(geWorld *World, int32 Node, const geVec3d *Pos, char *texname)
02239 {
02240 int32 Side;
02241
02242 if (Node < 0)
02243 {
02244 int32 Leaf;
02245
02246 Leaf = -(Node+1);
02247 if (PointInLeafSides(Pos, &MiscLeafs[Leaf]))
02248 {
02249
02250
02251 {
02252
02253
02254 char str[100];
02255 sprintf(str,"Leaf : %d\n",Leaf);
02256 OutputDebugString(str);
02257
02258
02259
02260
02261
02262 }
02263 }
02264 return;
02265 }
02266
02267 Side = Trace_BoxOnPlaneSide(&GMins2, &GMaxs2, &MiscPlanes[MiscNodes[Node].PlaneNum]);
02268
02269
02270 if (Side & PSIDE_FRONT)
02271 FillContents_tr(World, MiscNodes[Node].Children[0], Pos, texname);
02272
02273 if (Side & PSIDE_BACK)
02274 FillContents_tr(World, MiscNodes[Node].Children[1], Pos, texname);
02275 }
02276
02277
02278
02279
02280
02281
02282 geBoolean Trace_GetTexureName(geWorld *World, const geVec3d *Pos, const geVec3d *Mins, const geVec3d *Maxs, char *TexName)
02283 {
02284 geVec3d TMins, TMaxs;
02285 geBoolean Hit;
02286 int32 i, k;
02287 geWorld_Model *Models, *ModelHit;
02288 GFX_Model *GFXModels;
02289
02290 assert(World);
02291
02292 ModelHit = NULL;
02293 Hit = GE_FALSE;
02294
02295 BSPData = &World->CurrentBSP->BSPData;
02296
02297
02298 geVec3d_Add(Mins, Pos, &TMins);
02299 geVec3d_Add(Maxs, Pos, &TMaxs);
02300
02301 MiscNodes = World->CurrentBSP->BSPData.GFXNodes;
02302 MiscPlanes = World->CurrentBSP->BSPData.GFXPlanes;
02303 MiscLeafs = World->CurrentBSP->BSPData.GFXLeafs;
02304 MiscSides = BSPData->GFXLeafSides;
02305
02306 Models = World->CurrentBSP->Models;
02307 GFXModels = World->CurrentBSP->BSPData.GFXModels;
02308
02309 GMins1 = *Mins;
02310 GMaxs1 = *Maxs;
02311
02312 GMins2 = TMins;
02313 GMaxs2 = TMaxs;
02314
02315 for (i = 0; i < BSPData->NumGFXModels; i++, Models++, GFXModels++)
02316 {
02317 geVec3d TPos;
02318
02319 if (i > 0)
02320 {
02321 for (k=0; k<3; k++)
02322 {
02323 if (VectorToSUB(TMaxs, k) < VectorToSUB(Models->TMins, k))
02324 break;
02325 if (VectorToSUB(TMins, k) > VectorToSUB(Models->TMaxs, k))
02326 break;
02327 }
02328
02329 if (k != 3)
02330 continue;
02331 }
02332
02333 geVec3d_Subtract(Pos, &Models->RealCenter, &TPos);
02334
02335
02336 geXForm3d_TransposeTransform(&Models->XForm, &TPos, &TPos);
02337
02338
02339
02340 geVec3d_Add(&TPos, &Models->RealCenter, &TPos);
02341
02342 FillContents_tr(World, GFXModels->RootNode[0], &TPos, TexName);
02343
02344 if (!ModelHit)
02345 {
02346 ModelHit = Models;
02347 Hit = GE_TRUE;
02348 }
02349 }
02350
02351 if (Hit)
02352 {
02353 return GE_TRUE;
02354 }
02355
02356 return GE_FALSE;
02357 }
02358
02359