routing.c

Go to the documentation of this file.
00001 
00005 /*
00006 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 Copyright (C) 1997-2001 Id Software, Inc.
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019 See the GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00024 
00025 */
00026 
00027 
00028 #include "bsp.h"
00029 #include "../../common/routing.h"
00030 
00031 static const vec3_t move_vec[4] = {
00032     { UNIT_SIZE,          0, 0},
00033     {-UNIT_SIZE,          0, 0},
00034     {         0,  UNIT_SIZE, 0},
00035     {         0, -UNIT_SIZE, 0} };
00036 
00038 static routing_t Nmap[ACTOR_MAX_SIZE]; 
00041 static ipos3_t wpMins, wpMaxs;
00042 
00043 
00047 static int CheckUnit (unsigned int unitnum)
00048 {
00049     int new_z;
00050 
00051     /* get coordinates of that unit */
00052     const int z = unitnum % PATHFINDING_HEIGHT;
00053     const int y = (unitnum / PATHFINDING_HEIGHT) % PATHFINDING_WIDTH;
00054     const int x = (unitnum / PATHFINDING_HEIGHT / PATHFINDING_WIDTH) % PATHFINDING_WIDTH;
00055     const int actorSize = unitnum / PATHFINDING_HEIGHT / PATHFINDING_WIDTH / PATHFINDING_WIDTH;
00056 
00057     /* test bounds - the size adjustment is needed because large actor cells occupy multiple cell units. */
00058     if (x > wpMaxs[0] - actorSize || y > wpMaxs[1] - actorSize
00059      || x < wpMins[0] || y < wpMins[1]) {
00060         /* don't enter - outside world */
00061         return 0;
00062     }
00063 
00064     /* Com_Printf("%i %i %i %i\n", x, y, z, size); */
00065     /* Call the common CheckUnit function */
00066     new_z = RT_CheckCell(&mapTiles, Nmap, actorSize + 1, x, y, z, NULL);
00067 
00068     /* Com_Printf("z:%i nz:%i\n", z, new_z); */
00069 
00070     /* new_z should never be above z. */
00071     assert(new_z <= z);
00072 
00073     /* Adjust unitnum if this check adjusted multiple cells. */
00074     return new_z - z;
00075 }
00076 
00081 static void CheckUnitThread (unsigned int unitnum)
00082 {
00083     const int basenum = unitnum * PATHFINDING_HEIGHT;
00084     int newnum;
00085     for (newnum = basenum + PATHFINDING_HEIGHT - 1; newnum >= basenum; newnum--)
00086         newnum += CheckUnit(newnum);
00087 }
00088 
00089 
00093 static void CheckConnectionsThread (unsigned int unitnum)
00094 {
00095     /* get coordinates of that unit */
00096     const int numDirs = CORE_DIRECTIONS / (1 + RT_IS_BIDIRECTIONAL);
00097     const int dir = (unitnum % numDirs) * (RT_IS_BIDIRECTIONAL ? 2 : 1);
00098     const int y = (unitnum / numDirs) % PATHFINDING_WIDTH;
00099     const int x = (unitnum / numDirs / PATHFINDING_WIDTH) % PATHFINDING_WIDTH;
00100     const int actorSize = unitnum / numDirs / PATHFINDING_WIDTH / PATHFINDING_WIDTH;
00101 
00102     /* test bounds - the size adjustment is needed because large actor cells occupy multiple cell units. */
00103     if (x > wpMaxs[0] - actorSize || y > wpMaxs[1] - actorSize
00104      || x < wpMins[0] || y < wpMins[1] ) {
00105         /* don't enter - outside world */
00106         /* Com_Printf("x%i y%i z%i dir%i size%i (%i, %i, %i) (%i, %i, %i)\n", x, y, z, dir, size, wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]); */
00107         return;
00108     }
00109 
00110     Verb_Printf(VERB_EXTRA, "%i %i %i %i (%i, %i, %i) (%i, %i, %i)\n", x, y, dir, actorSize, wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]);
00111 
00112     RT_UpdateConnectionColumn(&mapTiles, Nmap, actorSize + 1, x, y, dir, NULL);
00113 
00114     /* Com_Printf("z:%i nz:%i\n", z, new_z); */
00115 }
00116 
00117 
00124 void DoRouting (void)
00125 {
00126     int i;
00127     byte *data;
00128     vec3_t mins, maxs;
00129     pos3_t pos;
00130 
00131     /* Turn on trace debugging if requested. */
00132     if (config.generateDebugTrace)
00133         debugTrace = qtrue;
00134 
00135     /* Record the current mapTiles[0] state so we can remove all CLIPS when done. */
00136     PushInfo();
00137 
00138     /* build tracing structure */
00139     EmitBrushes();
00140     EmitPlanes(); 
00142     MakeTracingNodes(LEVEL_ACTORCLIP + 1);
00143 
00144     /* Reset the whole block of map data to 0 */
00145     memset(Nmap, 0, sizeof(Nmap));
00146 
00147     /* get world bounds for optimizing */
00148     RT_GetMapSize(&mapTiles, mins, maxs);
00149     /* Com_Printf("Vectors: (%f, %f, %f) to (%f, %f, %f)\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]); */
00150     VecToPos(mins, wpMins);
00151     VecToPos(maxs, wpMaxs);
00152 
00153     /* Verify the world extents are not lopsided. */
00154     assert(wpMins[0] <= wpMaxs[0]);
00155     assert(wpMins[1] <= wpMaxs[1]);
00156     assert(wpMins[2] <= wpMaxs[2]);
00157 
00158     /* scan area heights */
00159     RunSingleThreadOn(CheckUnitThread, PATHFINDING_WIDTH * PATHFINDING_WIDTH * ACTOR_MAX_SIZE, config.verbosity >= VERB_NORMAL, "UNITCHECK");
00160 
00161     /* scan connections */
00162     RunSingleThreadOn(CheckConnectionsThread, PATHFINDING_WIDTH * PATHFINDING_WIDTH * (CORE_DIRECTIONS / (1 + RT_IS_BIDIRECTIONAL)) * (ACTOR_MAX_SIZE), config.verbosity >= VERB_NORMAL, "CONNCHECK");
00163 
00164     /* Try to shrink the world bounds along the x and y coordinates */
00165     for (i = 0; i < 2; i++) {
00166         /* Increase the mins */
00167         while (wpMaxs[i] > wpMins[i]) {
00168             VectorSet(pos, wpMins[0], wpMins[1], wpMaxs[2]);
00169             for (pos[i] = wpMins[i]; pos[i] <= wpMaxs[i]; pos[i]++) {
00170                 if (RT_FLOOR(Nmap, 1, pos[0], pos[1], wpMaxs[2]) + wpMaxs[2] * CELL_HEIGHT != -1)
00171                     break;
00172             }
00173             if (pos[i] <= wpMaxs[i])
00174                 break;
00175             wpMins[i ^ 1]++;
00176         }
00177         /* Increase the mins */
00178         while (wpMaxs[i] > wpMins[i]) {
00179             VectorCopy(wpMaxs, pos);
00180             for (pos[i] = wpMins[i]; pos[i] <= wpMaxs[i]; pos[i]++) {
00181                 if (RT_FLOOR(Nmap, 1, pos[0], pos[1], wpMaxs[2]) + wpMaxs[2] * CELL_HEIGHT != -1)
00182                     break;
00183             }
00184             if (pos[i] <= wpMaxs[i])
00185                 break;
00186             wpMaxs[i ^ 1]--;
00187         }
00188     }
00189 
00190     /* Output the floor trace file if set */
00191     if (config.generateTraceFile) {
00192         RT_WriteCSVFiles(Nmap, baseFilename, wpMins, wpMaxs);
00193     }
00194 
00195     /* store the data */
00196     data = curTile->routedata;
00197     for (i = 0; i < 3; i++)
00198         wpMins[i] = LittleLong(wpMins[i]);
00199     data = CompressRouting((byte*)wpMins, data, sizeof(wpMins));
00200     for (i = 0; i < 3; i++)
00201         wpMaxs[i] = LittleLong(wpMaxs[i]);
00202     data = CompressRouting((byte*)wpMaxs, data, sizeof(wpMaxs));
00203     data = CompressRouting((byte*)Nmap, data, sizeof(Nmap));
00204 
00205     curTile->routedatasize = data - curTile->routedata;
00206 
00207     /* Ensure that we did not exceed our allotment of memory for this data. */
00208     assert(curTile->routedatasize <= MAX_MAP_ROUTING);
00209 
00210     /* Remove the CLIPS fom the tracing structure by resetting it. */
00211     PopInfo();
00212 }

Generated by  doxygen 1.6.2