Mauzen

LOS test for custom walls

Jul 17th, 2012
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 4.21 KB | None | 0 0
  1. #define IsValidWallObject(%1)       (wallplanes[%1][PLANE_POS][0] == 0.0 && wallplanes[%1][PLANE_POS][1] == 0.0)
  2.  
  3. enum PlaneEnum {
  4.     Float:  PLANE_POS[3],       // Position of the plane / of the wall object
  5.     Float:  PLANE_COORD[4],     // Representation of the plane in coordinate form
  6.     Float:  PLANE_BUFFER[4]     // Buffers minimum/maximum x and min/max z values for later use
  7. }
  8.  
  9. new wallplanes[400][PlaneEnum];
  10.  
  11. CreateWallObject(modelid, Float:x, Float:y, Float:z, Float:rX, Float:rY, Float:rZ)
  12. {
  13.     // Creating the real object
  14.     new obid = CreateObject(modelid, x, y, z, rX, rY, rZ);
  15.     if (obid == INVALID_OBJECT_ID) {
  16.         return INVALID_OBJECT_ID;
  17.     }
  18.    
  19.     // Converting the wall to a plane
  20.     // E: x1*a + x2*b + x3*c = d
  21.     // Store position
  22.     wallplanes[obid][PLANE_POS][0] = x;
  23.     wallplanes[obid][PLANE_POS][1] = y;
  24.     wallplanes[obid][PLANE_POS][2] = z;
  25.    
  26.     // Get params for coordinate representation, a b c d
  27.     wallplanes[obid][PLANE_COORD][0] = floatsin(rZ, degrees);                          
  28.     wallplanes[obid][PLANE_COORD][1] = floatcos(rZ, degrees);
  29.     wallplanes[obid][PLANE_COORD][2] = 0; // Easy case where walls always are vertical with no x rotation
  30.     wallplanes[obid][PLANE_COORD][3] = x * wallplanes[obid][PLANE_COORD][0] + y * wallplanes[obid][PLANE_COORD][1];
  31.    
  32.     // Somehow retrieve the size
  33.     new Float:size[4];
  34.     GetWallObjectSize(modelid, size);
  35.    
  36.     // Buffer some values for boost in checks
  37.     wallplanes[obid][PLANE_BUFFER][0] = x + wallplanes[obid][PLANE_COORD][0] * size[0];
  38.     wallplanes[obid][PLANE_BUFFER][1] = x + wallplanes[obid][PLANE_COORD][0] * size[2];
  39.     // if xmin is greater than xmax (rotation > 180°) swap them
  40.     if (wallplanes[obid][PLANE_BUFFER][0] > wallplanes[obid][PLANE_BUFFER][1]) {
  41.         new Float:temp = wallplanes[obid][PLANE_BUFFER][0];
  42.         wallplanes[obid][PLANE_BUFFER][0] = wallplanes[obid][PLANE_BUFFER][1];
  43.         wallplanes[obid][PLANE_BUFFER][1] = temp;
  44.     }
  45.     wallplanes[obid][PLANE_BUFFER][2] = z + size[1];
  46.     wallplanes[obid][PLANE_BUFFER][3] = z + size[3];
  47.    
  48.     // Done!
  49.     return obid;
  50. }
  51.  
  52. stock GetWallObjectSize(modelid, Float:size[])
  53. {  
  54.     // Somehow retrive and store the size
  55.     // e.g. with a constant array containing the size for all wall objects
  56.     #pragma unused modelid
  57.     // And NOT this way:
  58.     size[0] = -0.5;
  59.     size[1] = -0.5;
  60.     size[2] = 0.5;
  61.     size[3] = 0.5;
  62.    
  63.     // Data should look like this:
  64.     // [0],[1]: X/Z-offset from the position pointing to the bottom left corner of the wall
  65.     // [2],[3]: X/Z-offset from the position pointing to the top right corner of the wall
  66. }
  67.  
  68.  
  69. stock IsLOSFree(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2)
  70. {
  71.     // Calculate the vector between the two points
  72.     new Float:u, Float:v, Float:w;
  73.     u = x2 - x1;
  74.     v = y2 - y1;
  75.     w = z2 - z1;
  76.    
  77.     // Preload some used variables
  78.     new Float:lambda;
  79.     new Float:x, /*Float:y,*/ Float:z; // y not needed in this example, just x/z are used for checks
  80.     // Loop through ALL valid wallobjects
  81.     // This could be optimized e.g. by only checking objects in an area around the points etc
  82.     // or at least using foreach instead of IsValidWallObject
  83.     for (new i = 0; i < 400; i++) {
  84.         if (!IsValidWallObject(i)) continue;
  85.        
  86.         // This actually calculates where the vector cuts the plane
  87.         // lambda = (a*x1 + b*y1 + c*z1 - d) / (u*a + v*b + w*c)
  88.         lambda = (wallplanes[i][PLANE_COORD][0] * x1 + wallplanes[i][PLANE_COORD][1] * y1 + wallplanes[i][PLANE_COORD][2] * z1)
  89.             / (u * wallplanes[i][PLANE_COORD][0] + v * wallplanes[i][PLANE_COORD][1] + w * wallplanes[i][PLANE_COORD][2]);
  90.            
  91.            
  92.         // lambda > 1 -> Point of intersection is behind point 2 and so not interesting
  93.         if (lambda > 1.0 || lambda < 0.0) continue;
  94.    
  95.         // Calculate the actual coordinates of the intersection
  96.         x = x1 + u * lambda;
  97.         //y = y1 + v * lambda; // Not needed as this example just uses x for checking
  98.         z = z1 + w * lambda;
  99.        
  100.         // Now check if it lies on the wall, or next to it
  101.         // Check x and z areas
  102.         if (x < wallplanes[i][PLANE_BUFFER][0] || x > wallplanes[i][PLANE_BUFFER][1]        // < xmin or > xmax
  103.             || z < wallplanes[i][PLANE_BUFFER][2] || z > wallplanes[i][PLANE_BUFFER][3])    // < zmin or > zmax
  104.                 continue;
  105.        
  106.         // Else the point is on the wall, and so the LOS is blocked
  107.         return false;
  108.     }
  109.     // Passed all checks for all walls, so the LOS is free
  110.     return true;
  111. }
Advertisement
Add Comment
Please, Sign In to add comment