Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Note : Quake 3 deals with multiple plane collisions in the DLL
- void c_BSP::RecursiveTrace(const int &NodeIndex, D3DXVECTOR3 &Start, D3DXVECTOR3 &End, const float &StartFraction, const float &EndFraction, s_Trace &Trace)
- {
- int PlaneIndex, i;
- float StartDistance, EndDistance, InvLength, MidpointFraction, TempFraction, offset;
- D3DXVECTOR3 MidpointVec, offsetVec;
- if( Trace.CollisionFraction <= StartFraction ) return;
- if(NodeIndex<0) {
- //This is a leaf
- //Check the Brushes
- for(i=0;i<Leaf[~NodeIndex].numLeafBrush;++i) {
- CheckBrush( Trace, &Brush[LeafBrush[Leaf[~NodeIndex].firstLeafBrush+i].index] );
- }
- // if( Leaf[~NodeIndex].CurveBrush >=0 ) CheckCurveBrush( &CurveBrush[Leaf[~NodeIndex].CurveBrush] );
- return;
- }
- PlaneIndex = Node[NodeIndex].PlaneIndex;
- StartDistance = Plane[PlaneIndex].Dot( Start ) - Plane[PlaneIndex].dist;
- EndDistance = Plane[PlaneIndex].Dot( End ) - Plane[PlaneIndex].dist;
- //Trace Box
- if(!Trace.TracePointOnly) {
- offsetVec.x = (Plane[PlaneIndex].normal.x<0) ? Trace.BoxMax.x : Trace.BoxMin.x;
- offsetVec.y = (Plane[PlaneIndex].normal.y<0) ? Trace.BoxMax.y : Trace.BoxMin.y;
- offsetVec.z = (Plane[PlaneIndex].normal.z<0) ? Trace.BoxMax.z : Trace.BoxMin.z;
- offset = - Plane[PlaneIndex].Dot( offsetVec );
- }
- else offset = 0.0f;
- #if 0
- RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
- RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
- return;
- #endif
- //if trace line is in front of plane
- if(StartDistance>offset+EPSILON && EndDistance>offset+EPSILON) {
- RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
- // if(NumNodeCache<MAX_NODECACHE) TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childFront;
- }
- //if trace line is in behind plane
- else if(StartDistance<-offset-EPSILON && EndDistance<-offset-EPSILON) {
- RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
- // if(NumNodeCache<MAX_NODECACHE) TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childBack;
- }
- //else trace line is intersecting with plane
- else {
- //Check closest child first (ie. node on same side as Start)
- if(StartDistance<EndDistance) { //InvLength is -ve
- InvLength = 1.0f / ( StartDistance - EndDistance ); //End->Start
- //Create Midpoint
- //TempFraction is the midpoint between this func's start and end, not the original start & end
- //TempFraction is placed EPSILON+offset **AFTER** the node plane, to avoid rounding errors
- //Reference : Q2 source for TempFraction (cmodel.c line 1298)
- TempFraction = (StartDistance-offset+EPSILON)*InvLength;
- TempFraction = max(0.0f, TempFraction);
- TempFraction = min(1.0f, TempFraction);
- MidpointVec = Start + (End-Start)*TempFraction;
- //MidpointFraction is the fractional position of this new midpoint, between the original start & end
- MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
- RecursiveTrace( Node[NodeIndex].childBack, Start, MidpointVec, StartFraction, MidpointFraction, Trace);
- //check further child
- //Adjust the temporary midpoint to EPSILON+offset on the other side of the plane
- TempFraction = (StartDistance+offset+EPSILON)*InvLength;
- TempFraction = min(1.0f, TempFraction);
- TempFraction = max(0.0f, TempFraction);
- MidpointVec = Start + (End-Start)*TempFraction;
- MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
- RecursiveTrace( Node[NodeIndex].childFront, MidpointVec, End, MidpointFraction, EndFraction, Trace);
- }
- else if(StartDistance>EndDistance) { //InvLength is +ve
- InvLength = 1.0f / ( StartDistance - EndDistance ); //End->Start
- //Create Midpoint
- TempFraction = (StartDistance+offset+EPSILON)*InvLength;
- TempFraction = max(0.0f, TempFraction);
- TempFraction = min(1.0f, TempFraction);
- MidpointVec = Start + (End-Start)*TempFraction;
- MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
- RecursiveTrace( Node[NodeIndex].childFront, Start, MidpointVec, StartFraction, MidpointFraction, Trace);
- //check further child
- //WHY IS THIS ONE - EPSILON? (random bugs if +)
- TempFraction = (StartDistance-offset-EPSILON)*InvLength;
- TempFraction = max(0.0f, TempFraction);
- TempFraction = min(1.0f, TempFraction);
- MidpointVec = Start + (End-Start)*TempFraction;
- MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
- RecursiveTrace( Node[NodeIndex].childBack, MidpointVec, End, MidpointFraction, EndFraction, Trace);
- }
- else { //StartDistance==EndDistance
- //Traverse both sides
- RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
- RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
- }
- /* if(NumNodeCache<MAX_NODECACHE) {
- TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childFront;
- if(NumNodeCache<MAX_NODECACHE) {
- TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childBack;
- }
- }*/
- }
- }
- //This algorithm has to be *just* right, otherwise we get randomly stuck in walls
- //Things which have to be set which I don't know why
- // if( (StartDistance>0.0f) && (EndDistance>=StartDistance) )
- // why can't EndDistance>0.0f?
- // for E, why is TempFraction = StartDistance + EPSILON / ...?
- // shouldn't it be a - so E is infront of the plane?
- void c_BSP::CheckBrush( s_Trace &Trace, s_DQBrush *pBrush )
- {
- int i, temp, PlaneIndex, PossibleCollisionBrushSideIndex;
- BOOL StartIsOutside, EndIsOutside;
- float StartDistance, EndDistance, TempFraction, S, E, BoxDistOffset;
- D3DXVECTOR3 offset;
- if( !(Texture[pBrush->texture].contents & Trace.ContentMask) ) return;
- // if( pBrush->TraceCount == TraceCount ) return;
- // pBrush->TraceCount = TraceCount;
- if( pBrush->numBrushSide <= 0 ) return;
- S = -1.0f;
- E = 1.0f;
- StartIsOutside = FALSE;
- EndIsOutside = FALSE;
- for(i=0;i<pBrush->numBrushSide;++i) {
- temp = pBrush->firstBrushSide + i;
- PlaneIndex = BrushSide[temp].plane;
- if(!Trace.TracePointOnly) {
- offset.x = (Plane[PlaneIndex].normal.x<0) ? Trace.BoxMax.x : Trace.BoxMin.x;
- offset.y = (Plane[PlaneIndex].normal.y<0) ? Trace.BoxMax.y : Trace.BoxMin.y;
- offset.z = (Plane[PlaneIndex].normal.z<0) ? Trace.BoxMax.z : Trace.BoxMin.z;
- BoxDistOffset = - Plane[PlaneIndex].Dot( offset );
- }
- else BoxDistOffset = 0.0f;
- StartDistance = Plane[PlaneIndex].Dot( (*Trace.Start) ) - Plane[PlaneIndex].dist - BoxDistOffset;
- EndDistance = Plane[PlaneIndex].Dot( (*Trace.End) ) - Plane[PlaneIndex].dist - BoxDistOffset;
- if(StartDistance>0.0f) StartIsOutside = TRUE;
- if(EndDistance>0.0f) EndIsOutside = TRUE;
- if( (StartDistance>0.0f) && (EndDistance>=StartDistance) )
- //both sides infront of brush, hence are outside
- return;
- else if( (StartDistance<=0.0f) && (EndDistance<=0.0f) )
- continue;
- //if trace is entering brushside
- if( StartDistance>EndDistance ) {
- //Set the collision fraction to a point slightly infront of the brushside plane
- TempFraction = (StartDistance - EPSILON)/( StartDistance - EndDistance );
- if(TempFraction>S) {
- S = TempFraction;
- PossibleCollisionBrushSideIndex = temp;
- }
- }
- //trace is leaving brushside
- else if(StartDistance<EndDistance) {
- //Set collision fraction slightly infront of plane
- TempFraction = (StartDistance + EPSILON)/( StartDistance - EndDistance );
- if(TempFraction<E) {
- E = TempFraction;
- }
- }
- else { //StartDistance==EndDistance
- //do nothing
- }
- }
- //Check if start is inside the brush
- if(StartIsOutside == FALSE) {
- Trace.StartSolid = TRUE;
- if(EndIsOutside == FALSE) {
- Trace.AllSolid = TRUE;
- }
- return;
- }
- //if collision with brush :
- if(S<E) {
- if( S>-1.0f && S<Trace.CollisionFraction ) {
- Trace.CollisionFraction = max( 0.0f, min( 1.0f, S ) );
- Trace.Plane.normal = Plane[BrushSide[PossibleCollisionBrushSideIndex].plane].normal;
- Trace.Plane.dist = Plane[BrushSide[PossibleCollisionBrushSideIndex].plane].dist;
- Trace.SurfaceFlags = Texture[BrushSide[PossibleCollisionBrushSideIndex].texture].flags | Texture[pBrush->texture].flags;
- Trace.contents = Texture[BrushSide[PossibleCollisionBrushSideIndex].texture].contents | Texture[pBrush->texture].contents;
- Trace.EntityNum = ENTITYNUM_WORLD;
- }
- }
- return;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement