Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.38 KB | None | 0 0
  1. //Note : Quake 3 deals with multiple plane collisions in the DLL
  2. void c_BSP::RecursiveTrace(const int &NodeIndex, D3DXVECTOR3 &Start, D3DXVECTOR3 &End, const float &StartFraction, const float &EndFraction, s_Trace &Trace)
  3. {
  4.     int PlaneIndex, i;
  5.     float StartDistance, EndDistance, InvLength, MidpointFraction, TempFraction, offset;
  6.     D3DXVECTOR3 MidpointVec, offsetVec;
  7.  
  8.     if( Trace.CollisionFraction <= StartFraction ) return;
  9.  
  10.     if(NodeIndex<0) {
  11.         //This is a leaf
  12.         //Check the Brushes
  13.         for(i=0;i<Leaf[~NodeIndex].numLeafBrush;++i) {
  14.             CheckBrush( Trace, &Brush[LeafBrush[Leaf[~NodeIndex].firstLeafBrush+i].index] );
  15.         }
  16. //      if( Leaf[~NodeIndex].CurveBrush >=0 ) CheckCurveBrush( &CurveBrush[Leaf[~NodeIndex].CurveBrush] );
  17.         return;
  18.     }
  19.  
  20.     PlaneIndex = Node[NodeIndex].PlaneIndex;
  21.     StartDistance = Plane[PlaneIndex].Dot( Start ) - Plane[PlaneIndex].dist;
  22.     EndDistance = Plane[PlaneIndex].Dot( End ) - Plane[PlaneIndex].dist;
  23.  
  24.     //Trace Box
  25.     if(!Trace.TracePointOnly) {
  26.         offsetVec.x = (Plane[PlaneIndex].normal.x<0) ? Trace.BoxMax.x : Trace.BoxMin.x;
  27.         offsetVec.y = (Plane[PlaneIndex].normal.y<0) ? Trace.BoxMax.y : Trace.BoxMin.y;
  28.         offsetVec.z = (Plane[PlaneIndex].normal.z<0) ? Trace.BoxMax.z : Trace.BoxMin.z;
  29.         offset = - Plane[PlaneIndex].Dot( offsetVec );
  30.     }
  31.     else offset = 0.0f;
  32.  
  33. #if 0
  34.     RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
  35.     RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
  36.     return;
  37. #endif
  38.  
  39.     //if trace line is in front of plane
  40.     if(StartDistance>offset+EPSILON && EndDistance>offset+EPSILON) {
  41.         RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
  42. //      if(NumNodeCache<MAX_NODECACHE) TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childFront;
  43.     }
  44.  
  45.     //if trace line is in behind plane
  46.     else if(StartDistance<-offset-EPSILON && EndDistance<-offset-EPSILON) {
  47.         RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
  48. //      if(NumNodeCache<MAX_NODECACHE) TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childBack;
  49.     }
  50.  
  51.     //else trace line is intersecting with plane
  52.     else {
  53.        
  54.         //Check closest child first (ie. node on same side as Start)
  55.         if(StartDistance<EndDistance) {     //InvLength is -ve
  56.             InvLength = 1.0f / ( StartDistance - EndDistance );     //End->Start
  57.  
  58.             //Create Midpoint
  59.  
  60.             //TempFraction is the midpoint between this func's start and end, not the original start & end
  61.             //TempFraction is placed EPSILON+offset **AFTER** the node plane, to avoid rounding errors
  62.             //Reference : Q2 source for TempFraction (cmodel.c line 1298)
  63.             TempFraction =  (StartDistance-offset+EPSILON)*InvLength;
  64.             TempFraction = max(0.0f, TempFraction);
  65.             TempFraction = min(1.0f, TempFraction);
  66.             MidpointVec = Start + (End-Start)*TempFraction;
  67.             //MidpointFraction is the fractional position of this new midpoint, between the original start & end
  68.             MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
  69.  
  70.             RecursiveTrace( Node[NodeIndex].childBack, Start, MidpointVec, StartFraction, MidpointFraction, Trace);
  71.  
  72.             //check further child
  73.             //Adjust the temporary midpoint to EPSILON+offset on the other side of the plane
  74.             TempFraction = (StartDistance+offset+EPSILON)*InvLength;
  75.             TempFraction = min(1.0f, TempFraction);
  76.             TempFraction = max(0.0f, TempFraction);
  77.             MidpointVec = Start + (End-Start)*TempFraction;
  78.             MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
  79.  
  80.             RecursiveTrace( Node[NodeIndex].childFront, MidpointVec, End, MidpointFraction, EndFraction, Trace);
  81.         }
  82.         else if(StartDistance>EndDistance) {    //InvLength is +ve
  83.             InvLength = 1.0f / ( StartDistance - EndDistance );     //End->Start
  84.  
  85.             //Create Midpoint
  86.             TempFraction = (StartDistance+offset+EPSILON)*InvLength;
  87.             TempFraction = max(0.0f, TempFraction);
  88.             TempFraction = min(1.0f, TempFraction);
  89.             MidpointVec = Start + (End-Start)*TempFraction;
  90.             MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
  91.             RecursiveTrace( Node[NodeIndex].childFront, Start, MidpointVec, StartFraction, MidpointFraction, Trace);
  92.  
  93.             //check further child
  94.             //WHY IS THIS ONE - EPSILON? (random bugs if +)
  95.             TempFraction = (StartDistance-offset-EPSILON)*InvLength;
  96.             TempFraction = max(0.0f, TempFraction);
  97.             TempFraction = min(1.0f, TempFraction);
  98.             MidpointVec = Start + (End-Start)*TempFraction;
  99.             MidpointFraction = StartFraction + (EndFraction-StartFraction)*TempFraction;
  100.             RecursiveTrace( Node[NodeIndex].childBack, MidpointVec, End, MidpointFraction, EndFraction, Trace);
  101.         }
  102.         else { //StartDistance==EndDistance
  103.             //Traverse both sides
  104.             RecursiveTrace( Node[NodeIndex].childFront, Start, End, StartFraction, EndFraction, Trace );
  105.             RecursiveTrace( Node[NodeIndex].childBack, Start, End, StartFraction, EndFraction, Trace );
  106.         }          
  107.  
  108. /*      if(NumNodeCache<MAX_NODECACHE) {
  109.             TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childFront;
  110.            
  111.             if(NumNodeCache<MAX_NODECACHE) {
  112.                 TraceNodeCache[NumNodeCache++] = Node[NodeIndex].childBack;
  113.             }
  114.         }*/
  115.     }
  116. }
  117.  
  118. //This algorithm has to be *just* right, otherwise we get randomly stuck in walls
  119. //Things which have to be set which I don't know why
  120. //  if( (StartDistance>0.0f) && (EndDistance>=StartDistance) )
  121. //      why can't EndDistance>0.0f?
  122. //  for E, why is TempFraction = StartDistance + EPSILON / ...?
  123. //  shouldn't it be a - so E is infront of the plane?
  124.  
  125. void c_BSP::CheckBrush( s_Trace &Trace, s_DQBrush *pBrush )
  126. {
  127.     int i, temp, PlaneIndex, PossibleCollisionBrushSideIndex;
  128.     BOOL StartIsOutside, EndIsOutside;
  129.     float StartDistance, EndDistance, TempFraction, S, E, BoxDistOffset;
  130.     D3DXVECTOR3 offset;
  131.  
  132.     if( !(Texture[pBrush->texture].contents & Trace.ContentMask) ) return;
  133.    
  134. //  if( pBrush->TraceCount == TraceCount ) return;
  135. //  pBrush->TraceCount = TraceCount;
  136.  
  137.     if( pBrush->numBrushSide <= 0 ) return;
  138.  
  139.     S = -1.0f;
  140.     E = 1.0f;
  141.     StartIsOutside = FALSE;
  142.     EndIsOutside = FALSE;
  143.  
  144.     for(i=0;i<pBrush->numBrushSide;++i) {
  145.         temp = pBrush->firstBrushSide + i;
  146.  
  147.         PlaneIndex = BrushSide[temp].plane;
  148.         if(!Trace.TracePointOnly) {
  149.             offset.x = (Plane[PlaneIndex].normal.x<0) ? Trace.BoxMax.x : Trace.BoxMin.x;
  150.             offset.y = (Plane[PlaneIndex].normal.y<0) ? Trace.BoxMax.y : Trace.BoxMin.y;
  151.             offset.z = (Plane[PlaneIndex].normal.z<0) ? Trace.BoxMax.z : Trace.BoxMin.z;
  152.             BoxDistOffset = - Plane[PlaneIndex].Dot( offset );
  153.         }
  154.         else BoxDistOffset = 0.0f;
  155.        
  156.         StartDistance = Plane[PlaneIndex].Dot( (*Trace.Start) ) - Plane[PlaneIndex].dist - BoxDistOffset;
  157.         EndDistance = Plane[PlaneIndex].Dot( (*Trace.End) ) - Plane[PlaneIndex].dist - BoxDistOffset;
  158.  
  159.         if(StartDistance>0.0f) StartIsOutside = TRUE;
  160.         if(EndDistance>0.0f) EndIsOutside = TRUE;
  161.  
  162.         if( (StartDistance>0.0f) && (EndDistance>=StartDistance) )
  163.             //both sides infront of brush, hence are outside
  164.             return;
  165.         else if( (StartDistance<=0.0f) && (EndDistance<=0.0f) )
  166.             continue;
  167.  
  168.         //if trace is entering brushside
  169.         if( StartDistance>EndDistance ) {
  170.             //Set the collision fraction to a point slightly infront of the brushside plane
  171.             TempFraction = (StartDistance - EPSILON)/( StartDistance - EndDistance );
  172.  
  173.             if(TempFraction>S) {
  174.                 S = TempFraction;
  175.                 PossibleCollisionBrushSideIndex = temp;
  176.             }
  177.         }
  178.         //trace is leaving brushside
  179.         else if(StartDistance<EndDistance) {
  180.             //Set collision fraction slightly infront of plane
  181.             TempFraction = (StartDistance + EPSILON)/( StartDistance - EndDistance );
  182.  
  183.             if(TempFraction<E) {
  184.                 E = TempFraction;
  185.             }
  186.         }
  187.         else { //StartDistance==EndDistance
  188.             //do nothing
  189.         }
  190.  
  191.     }
  192.  
  193.     //Check if start is inside the brush
  194.     if(StartIsOutside == FALSE) {
  195.         Trace.StartSolid = TRUE;
  196.         if(EndIsOutside == FALSE) {
  197.             Trace.AllSolid = TRUE;
  198.         }
  199.         return;
  200.     }
  201.  
  202.     //if collision with brush :
  203.     if(S<E) {
  204.         if( S>-1.0f && S<Trace.CollisionFraction ) {
  205.             Trace.CollisionFraction = max( 0.0f, min( 1.0f, S ) );
  206.             Trace.Plane.normal = Plane[BrushSide[PossibleCollisionBrushSideIndex].plane].normal;
  207.             Trace.Plane.dist = Plane[BrushSide[PossibleCollisionBrushSideIndex].plane].dist;
  208.             Trace.SurfaceFlags  = Texture[BrushSide[PossibleCollisionBrushSideIndex].texture].flags | Texture[pBrush->texture].flags;
  209.             Trace.contents      = Texture[BrushSide[PossibleCollisionBrushSideIndex].texture].contents | Texture[pBrush->texture].contents;
  210.             Trace.EntityNum     = ENTITYNUM_WORLD;
  211.         }
  212.     }
  213.     return;
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement