1 #include "RoutingLumpLoader.h" 2 #include "RoutingLump.h" 3 #include "../../../shared/autoptr.h" 4 #include "ifilesystem.h" 5 #include "gtkutil/dialog.h" 6 #include "radiant_i18n.h" 7 8 #include "../../../shared/ufotypes.h" 9 #include "../../../shared/typedefs.h" 10 #include "../../../game/q_sizes.h" 11 #include "../../../common/qfiles.h" 12 #define COMPILE_MAP 13 typedef int mapTiles_t; 14 #include "../../../common/routing.h" 15 16 namespace routing 17 { 18 19 /** 20 * @param[in] source Source will be set to the end of the compressed data block! 21 * @sa CompressRouting (ufo2map) 22 * @sa CMod_LoadRouting 23 */ CMod_DeCompressRouting(byte ** source,byte * dataStart)24 static int CMod_DeCompressRouting (byte** source, byte* dataStart) 25 { 26 int i, c; 27 byte* data_p; 28 byte* src; 29 30 data_p = dataStart; 31 src = *source; 32 33 while (*src) { 34 if (*src & 0x80) { 35 /* repetitions */ 36 c = *src++ & ~0x80; 37 /* Remember that the total bytes that are the same is c + 2 */ 38 for (i = 0; i < c + 2; i++) 39 *data_p++ = *src; 40 src++; 41 } else { 42 /* identities */ 43 c = *src++; 44 for (i = 0; i < c; i++) 45 *data_p++ = *src++; 46 } 47 } 48 49 src++; 50 *source = src; 51 52 return data_p - dataStart; 53 } 54 55 /** 56 * @brief evaluate access state for given position for given routing data 57 * @param routing The routing tables 58 * @param pos position to evaluate 59 * @return access state as enum value for later rendering 60 */ evaluateAccessState(const Routing & routing,const pos3_t pos,const int actorSize)61 static EAccessState evaluateAccessState (const Routing &routing, const pos3_t pos, const int actorSize) 62 { 63 const int height = QuantToModel(routing.getCeiling(actorSize, pos[0], pos[1], pos[2] & (PATHFINDING_HEIGHT - 1)) 64 - routing.getFloor(actorSize, pos[0], pos[1], pos[2] & (PATHFINDING_HEIGHT - 1))); 65 if (height >= PLAYER_STANDING_HEIGHT) 66 return ACC_STAND; 67 else if (height >= PLAYER_CROUCHING_HEIGHT) 68 return ACC_CROUCH; 69 else 70 return ACC_DISABLED; 71 } 72 evaluateConnectionState(const Routing & routing,const pos3_t pos,const int actorSize,const EDirection direction)73 static EConnectionState evaluateConnectionState (const Routing &routing, const pos3_t pos, 74 const int actorSize, const EDirection direction) 75 { 76 byte route = 0; 77 byte stepup = 0; 78 79 switch (direction) { 80 case DIR_WEST: 81 route = RT_CONN_NY(routing,actorSize,pos[0],pos[1],pos[2]); 82 stepup = RT_STEPUP_NY(routing,actorSize,pos[0],pos[1],pos[2]); 83 break; 84 case DIR_NORTHWEST: 85 route = RT_CONN_PX_NY(routing,actorSize,pos[0],pos[1],pos[2]); 86 stepup = RT_STEPUP_PX_NY(routing,actorSize,pos[0],pos[1],pos[2]); 87 break; 88 case DIR_NORTH: 89 route = RT_CONN_PX(routing,actorSize,pos[0],pos[1],pos[2]); 90 stepup = RT_STEPUP_PX(routing,actorSize,pos[0],pos[1],pos[2]); 91 break; 92 case DIR_NORTHEAST: 93 route = RT_CONN_PX_PY(routing,actorSize,pos[0],pos[1],pos[2]); 94 stepup = RT_STEPUP_PX_PY(routing,actorSize,pos[0],pos[1],pos[2]); 95 break; 96 case DIR_EAST: 97 route = RT_CONN_PY(routing,actorSize,pos[0],pos[1],pos[2]); 98 stepup = RT_STEPUP_PY(routing,actorSize,pos[0],pos[1],pos[2]); 99 break; 100 case DIR_SOUTHEAST: 101 route = RT_CONN_NX_PY(routing,actorSize,pos[0],pos[1],pos[2]); 102 stepup = RT_STEPUP_NX_PY(routing,actorSize,pos[0],pos[1],pos[2]); 103 break; 104 case DIR_SOUTH: 105 route = RT_CONN_NX(routing,actorSize,pos[0],pos[1],pos[2]); 106 stepup = RT_STEPUP_NX(routing,actorSize,pos[0],pos[1],pos[2]); 107 break; 108 case DIR_SOUTHWEST: 109 route = RT_CONN_NX_NY(routing,actorSize,pos[0],pos[1],pos[2]); 110 stepup = RT_STEPUP_NX_NY(routing,actorSize,pos[0],pos[1],pos[2]); 111 break; 112 case MAX_DIRECTIONS: 113 break; 114 } 115 116 if (stepup == PATHFINDING_NO_STEPUP) 117 return CON_DISABLE; 118 else if (route >= ModelCeilingToQuant(PLAYER_STANDING_HEIGHT)) 119 return CON_WALKABLE; 120 else if (route >= ModelCeilingToQuant(PLAYER_CROUCHING_HEIGHT)) 121 return CON_CROUCHABLE; 122 else 123 return CON_DISABLE; 124 } 125 126 /** 127 * @brief evaluate map data to set access and connectivity state to given lump entry. 128 * @param entry entry to fill values into 129 * @param routing The routing tables 130 * @param pos position to evaluate 131 */ FillRoutingLumpEntry(RoutingLumpEntry & entry,Routing & routing,pos3_t pos)132 static void FillRoutingLumpEntry (RoutingLumpEntry &entry, Routing &routing, pos3_t pos) 133 { 134 entry.setAccessState(evaluateAccessState(routing, pos, ACTOR_SIZE_NORMAL)); 135 for (EDirection direction = DIR_WEST; direction < MAX_DIRECTIONS; direction++) { 136 entry.setConnectionState(direction, evaluateConnectionState(routing, pos, ACTOR_SIZE_NORMAL, direction)); 137 } 138 } 139 140 /** 141 * @param[in] l Routing lump ... (routing data lump from bsp file) 142 * @param[in] sX The x position on the world plane (grid position) - values from -(PATHFINDING_WIDTH/2) up to PATHFINDING_WIDTH/2 are allowed 143 * @param[in] sY The y position on the world plane (grid position) - values from -(PATHFINDING_WIDTH/2) up to PATHFINDING_WIDTH/2 are allowed 144 * @param[in] sZ The height level on the world plane (grid position) - values from 0 - PATHFINDING_HEIGHT are allowed 145 * @sa CM_AddMapTile 146 * @todo TEST z-level routing 147 */ CMod_LoadRouting(RoutingLump & routingLump,const std::string & name,const lump_t * l,byte * cModelBase,int sX,int sY,int sZ)148 static void CMod_LoadRouting (RoutingLump& routingLump, const std::string& name, const lump_t* l, 149 byte* cModelBase, int sX, int sY, int sZ) 150 { 151 static Routing tempMap; 152 static Routing clMap; 153 static MapTile curTile; 154 byte* source; 155 int length; 156 int x, y, z, size; 157 int minX, minY, minZ; 158 int maxX, maxY, maxZ; 159 unsigned int i; 160 double start, end; 161 const int targetLength = sizeof(curTile.wpMins) + sizeof(curTile.wpMaxs) + sizeof(tempMap); 162 163 start = time(NULL); 164 165 if (!GUINT32_TO_LE(l->filelen)) { 166 g_error("CMod_LoadRouting: Map has NO routing lump"); 167 return; 168 } 169 170 source = cModelBase + GUINT32_TO_LE(l->fileofs); 171 172 i = CMod_DeCompressRouting(&source, (byte*) curTile.wpMins); 173 length = i; 174 i = CMod_DeCompressRouting(&source, (byte*) curTile.wpMaxs); 175 length += i; 176 i = CMod_DeCompressRouting(&source, (byte*) &tempMap); 177 length += i; 178 179 if (length != targetLength) { 180 g_error("CMod_LoadRouting: Map has BAD routing lump; expected %i got %i", targetLength, length); 181 return; 182 } 183 184 /* endian swap possibly necessary */ 185 for (i = 0; i < 3; i++) { 186 curTile.wpMins[i] = GUINT32_TO_LE(curTile.wpMins[i]); 187 curTile.wpMaxs[i] = GUINT32_TO_LE(curTile.wpMaxs[i]); 188 } 189 190 g_debug("wpMins:(%i, %i, %i) wpMaxs:(%i, %i, %i)\n", curTile.wpMins[0], curTile.wpMins[1], curTile.wpMins[2], 191 curTile.wpMaxs[0], curTile.wpMaxs[1], curTile.wpMaxs[2]); 192 193 /* Things that need to be done: 194 * The floor, ceiling, and route data can be copied over from the map. 195 * All data must be regenerated for cells with overlapping content or where new 196 * model data is adjacent to a cell with existing model data. */ 197 198 /* Copy the routing information into our master table */ 199 minX = std::max(curTile.wpMins[0], 0); 200 minY = std::max(curTile.wpMins[1], 0); 201 minZ = std::max(curTile.wpMins[2], 0); 202 maxX = std::min(curTile.wpMaxs[0], PATHFINDING_WIDTH - 1); 203 maxY = std::min(curTile.wpMaxs[1], PATHFINDING_WIDTH - 1); 204 maxZ = std::min(curTile.wpMaxs[2], PATHFINDING_HEIGHT - 1); 205 206 /** @todo check whether we need this copy code */ 207 for (size = 0; size < ACTOR_MAX_SIZE; size++) 208 /* Adjust starting x and y by size to catch large actor cell overlap. */ 209 for (y = minY - size; y <= maxY; y++) 210 for (x = minX - size; x <= maxX; x++) { 211 /* Just incase x or y start negative. */ 212 if (x < 0 || y < 0) 213 continue; 214 for (z = minZ; z <= maxZ; z++) { 215 clMap.copyPosData(tempMap, size + 1, x, y, z, sX, sY, sZ); 216 } 217 /* Update the reroute table */ 218 /*if (!reroute[size][y][x]) { 219 reroute[size][y][x] = numTiles + 1; 220 } else { 221 reroute[size][y][x] = ROUTING_NOT_REACHABLE; 222 }*/ 223 } 224 225 g_message("Done copying data.\n"); 226 for (size = 0; size < 1; size++) 227 for (x = minX; x <= maxX; x++) 228 for (y = minY; y <= maxY; y++) 229 for (z = minZ; z <= maxZ; z++) { 230 pos3_t pos = { static_cast<pos_t>(x), static_cast<pos_t>(y), static_cast<pos_t>(z) }; 231 vec3_t vect; 232 PosToVec(pos,vect); 233 /**@todo add other data to constructor: accessibility + connection states */ 234 RoutingLumpEntry entry = RoutingLumpEntry(Vector3(vect), (z + 1)); 235 FillRoutingLumpEntry(entry, clMap, pos); 236 /**@todo perhaps there is a better way than creating a const object for adding */ 237 const RoutingLumpEntry toAdd = RoutingLumpEntry(entry); 238 routingLump.add(toAdd); 239 } 240 end = time(NULL); 241 g_message("Loaded routing for tile %s in %5.1fs\n", name.c_str(), end - start); 242 } 243 loadRoutingLump(ArchiveFile & file)244 void RoutingLumpLoader::loadRoutingLump (ArchiveFile& file) 245 { 246 /* load the file */ 247 InputStream &stream = file.getInputStream(); 248 const std::size_t size = file.size(); 249 byte* buf = (byte*) malloc(size + 1); 250 dBspHeader_t* header = (dBspHeader_t*) buf; 251 stream.read(buf, size); 252 253 CMod_LoadRouting(_routingLump, file.getName(), &header->lumps[LUMP_ROUTING], (byte*) buf, 0, 0, 0); 254 free(buf); 255 } 256 loadRouting(const std::string & bspFileName)257 void RoutingLumpLoader::loadRouting (const std::string& bspFileName) 258 { 259 /**@todo try to reduce loading, store latest file + mtime and load only if that changed */ 260 // Open an ArchiveFile to load 261 AutoPtr<ArchiveFile> file(GlobalFileSystem().openFile(bspFileName)); 262 if (file) { 263 // Load the model and return the RenderablePtr 264 _routingLump = RoutingLump(); 265 loadRoutingLump(*file); 266 } else { 267 gtkutil::errorDialog(_("No compiled version of the map found")); 268 } 269 } 270 RoutingLumpLoader()271 RoutingLumpLoader::RoutingLumpLoader () 272 { 273 } 274 getRoutingLump()275 routing::RoutingLump& RoutingLumpLoader::getRoutingLump () 276 { 277 return _routingLump; 278 } 279 ~RoutingLumpLoader()280 RoutingLumpLoader::~RoutingLumpLoader () 281 { 282 } 283 } 284