diff options
Diffstat (limited to 'src/common/Collision')
-rw-r--r-- | src/common/Collision/Maps/MapTree.cpp | 62 | ||||
-rw-r--r-- | src/common/Collision/Maps/MapTree.h | 2 | ||||
-rw-r--r-- | src/common/Collision/Maps/TileAssembler.cpp | 152 | ||||
-rw-r--r-- | src/common/Collision/Maps/TileAssembler.h | 20 | ||||
-rw-r--r-- | src/common/Collision/Models/ModelInstance.h | 5 | ||||
-rw-r--r-- | src/common/Collision/VMapDefinitions.h | 4 |
6 files changed, 88 insertions, 157 deletions
diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 24874412a22..ce8ff8deb55 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -120,9 +120,8 @@ namespace VMAP return intersectionCallBack.result; } - StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) : - iMapID(mapID), iIsTiled(false), iTreeValues(NULL), - iNTreeValues(0), iBasePath(basePath) + StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) + : iMapID(mapID), iTreeValues(NULL), iNTreeValues(0), iBasePath(basePath) { if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') { @@ -270,22 +269,19 @@ namespace VMAP /// @todo check magic number when implemented... char tiled; char chunk[8]; - if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) + if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) { fclose(rf); return false; } - if (tiled) + FILE* tf = OpenMapTileFile(basePath, mapID, tileX, tileY, vm).File; + if (!tf) + success = false; + else { - FILE* tf = OpenMapTileFile(basePath, mapID, tileX, tileY, vm).File; - if (!tf) + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) success = false; - else - { - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - success = false; - fclose(tf); - } + fclose(tf); } fclose(rf); return success; @@ -303,39 +299,14 @@ namespace VMAP return false; char chunk[8]; - char tiled = '\0'; - if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 && - readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) + if (readChunk(rf, chunk, VMAP_MAGIC, 8) && + readChunk(rf, chunk, "NODE", 4) && + iTree.readFromFile(rf)) { iNTreeValues = iTree.primCount(); iTreeValues = new ModelInstance[iNTreeValues]; - success = readChunk(rf, chunk, "GOBJ", 4); - } - - iIsTiled = tiled != '\0'; - - // global model spawns - // only non-tiled maps have them, and if so exactly one (so far at least...) - ModelSpawn spawn; -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); -#endif - if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) - { - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - TC_LOG_DEBUG("maps", "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); - if (model) - { - // assume that global model always is the first and only tree value (could be improved...) - iTreeValues[0] = ModelInstance(spawn, model); - iLoadedSpawns[0] = 1; - } - else - { - success = false; - TC_LOG_ERROR("misc", "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); - } + success = true; } if (success) @@ -376,13 +347,6 @@ namespace VMAP bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) { - if (!iIsTiled) - { - // currently, core creates grids for all maps, whether it has terrain tiles or not - // so we need "fake" tile loads to know when we can unload map geometry - iLoadedTiles[packTileID(tileX, tileY)] = false; - return true; - } if (!iTreeValues) { TC_LOG_ERROR("misc", "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index d762f804132..596a4ae0296 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -43,7 +43,6 @@ namespace VMAP typedef std::unordered_map<uint32, uint32> loadedSpawnMap; private: uint32 iMapID; - bool iIsTiled; BIH iTree; ModelInstance* iTreeValues; // the tree entries uint32 iNTreeValues; @@ -87,7 +86,6 @@ namespace VMAP void UnloadMap(VMapManager2* vm); bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); - bool isTiled() const { return iIsTiled; } uint32 numLoadedTiles() const { return uint32(iLoadedTiles.size()); } void getModelInstances(ModelInstance* &models, uint32 &count); diff --git a/src/common/Collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp index b0bee33b4b2..47dfadd0947 100644 --- a/src/common/Collision/Maps/TileAssembler.cpp +++ b/src/common/Collision/Maps/TileAssembler.cpp @@ -48,7 +48,7 @@ namespace VMAP { Vector3 out = pIn * iScale; out = iRotation * out; - return(out); + return out; } //================================================================= @@ -57,12 +57,10 @@ namespace VMAP : iDestDir(pDestDirName), iSrcDir(pSrcDirName) { boost::filesystem::create_directory(iDestDir); - //init(); } TileAssembler::~TileAssembler() { - //delete iCoordModelMapping; } bool TileAssembler::convertWorld2() @@ -71,32 +69,39 @@ namespace VMAP if (!success) return false; + float constexpr invTileSize = 1.0f / 533.33333f; + // export Map data - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) + while (!mapData.empty()) { + MapSpawns data = std::move(mapData.front()); + mapData.pop_front(); + // build global map tree std::vector<ModelSpawn*> mapSpawns; - UniqueEntryMap::iterator entry; - printf("Calculating model bounds for map %u...\n", map_iter->first); - for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) + mapSpawns.reserve(data.UniqueEntries.size()); + printf("Calculating model bounds for map %u...\n", data.MapId); + for (auto entry = data.UniqueEntries.begin(); entry != data.UniqueEntries.end(); ++entry) { // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail if (entry->second.flags & MOD_M2) - { if (!calculateTransformedBound(entry->second)) continue; - } - else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ - { - /// @todo remove extractor hack and uncomment below line: - //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); - entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); - } + mapSpawns.push_back(&entry->second); spawnedModelFiles.insert(entry->second.name); + + std::map<uint32, std::set<TileSpawn>>& tileEntries = (entry->second.flags & MOD_PARENT_SPAWN) ? data.ParentTileEntries : data.TileEntries; + + G3D::AABox const& bounds = entry->second.iBound; + G3D::Vector2int16 low(int16(bounds.low().x * invTileSize), int16(bounds.low().y * invTileSize)); + G3D::Vector2int16 high(int16(bounds.high().x * invTileSize), int16(bounds.high().y * invTileSize)); + for (int x = low.x; x <= high.x; ++x) + for (int y = low.y; y <= high.y; ++y) + tileEntries[StaticMapTree::packTileID(x, y)].emplace(entry->second.ID, entry->second.flags); } - printf("Creating map tree for map %u...\n", map_iter->first); + printf("Creating map tree for map %u...\n", data.MapId); BIH pTree; try @@ -113,7 +118,7 @@ namespace VMAP // write map tree file std::stringstream mapfilename; - mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(4) << map_iter->first << ".vmtree"; + mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(4) << data.MapId << ".vmtree"; FILE* mapfile = fopen(mapfilename.str().c_str(), "wb"); if (!mapfile) { @@ -124,24 +129,13 @@ namespace VMAP //general info if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; - uint32 globalTileID = StaticMapTree::packTileID(65, 65); - pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID); - char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO - if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; // Nodes if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; if (success) success = pTree.writeToFile(mapfile); - // global map spawns (WDT), if any (most instances) - if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; - - for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) - { - success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second.Id]); - } // spawn id to index map - if (success && fwrite("SIDX", 4, 1, mapfile) != 1) success = false; uint32 mapSpawnsSize = mapSpawns.size(); + if (success && fwrite("SIDX", 4, 1, mapfile) != 1) success = false; if (success && fwrite(&mapSpawnsSize, sizeof(uint32), 1, mapfile) != 1) success = false; for (uint32 i = 0; i < mapSpawnsSize; ++i) { @@ -153,37 +147,30 @@ namespace VMAP // <==== - // write map tile files, similar to ADT files, only with extra BSP tree node info - TileMap &tileEntries = map_iter->second->TileEntries; - TileMap::iterator tile; - for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) + // write map tile files, similar to ADT files, only with extra BIH tree node info + for (auto tileItr = data.TileEntries.begin(); tileItr != data.TileEntries.end(); ++tileItr) { - if (tile->second.Flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... - continue; - if (tile->second.Flags & MOD_PARENT_SPAWN) // tile belongs to parent map - continue; - uint32 nSpawns = tileEntries.count(tile->first); - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << iDestDir << '/' << std::setw(4) << map_iter->first << '_'; uint32 x, y; - StaticMapTree::unpackTileID(tile->first, x, y); - tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile"; - if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb")) + StaticMapTree::unpackTileID(tileItr->first, x, y); + std::string tileFileName = Trinity::StringFormat("%s/%04u_%02u_%02u.vmtile", iDestDir.c_str(), data.MapId, y, x); + if (FILE* tileFile = fopen(tileFileName.c_str(), "wb")) { + std::set<TileSpawn> const& parentTileEntries = data.ParentTileEntries[tileItr->first]; + + uint32 nSpawns = tileItr->second.size() + parentTileEntries.size(); + // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; + if (success && fwrite(VMAP_MAGIC, 1, 8, tileFile) != 8) success = false; // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; + if (success && fwrite(&nSpawns, sizeof(uint32), 1, tileFile) != 1) success = false; // write tile spawns - for (uint32 s=0; s<nSpawns; ++s) - { - if (s) - ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second.Id]; - success = success && ModelSpawn::writeToFile(tilefile, spawn2); - } - fclose(tilefile); + for (auto spawnItr = tileItr->second.begin(); spawnItr != tileItr->second.end() && success; ++spawnItr) + success = ModelSpawn::writeToFile(tileFile, data.UniqueEntries[spawnItr->Id]); + + for (auto spawnItr = parentTileEntries.begin(); spawnItr != parentTileEntries.end() && success; ++spawnItr) + success = ModelSpawn::writeToFile(tileFile, data.UniqueEntries[spawnItr->Id]); + + fclose(tileFile); } } } @@ -203,11 +190,6 @@ namespace VMAP } } - //cleanup: - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) - { - delete map_iter->second; - } return success; } @@ -221,34 +203,35 @@ namespace VMAP return false; } printf("Read coordinate mapping...\n"); - uint32 mapID, tileX, tileY, check=0; - G3D::Vector3 v1, v2; - ModelSpawn spawn; + uint32 mapID, check=0; + std::map<uint32, MapSpawns> data; while (!feof(dirf)) { check = 0; - // read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name + // read mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name check += fread(&mapID, sizeof(uint32), 1, dirf); if (check == 0) // EoF... break; - check += fread(&tileX, sizeof(uint32), 1, dirf); - check += fread(&tileY, sizeof(uint32), 1, dirf); + + ModelSpawn spawn; if (!ModelSpawn::readFromFile(dirf, spawn)) break; - MapSpawns *current; - MapData::iterator map_iter = mapData.find(mapID); - if (map_iter == mapData.end()) + auto map_iter = data.emplace(std::piecewise_construct, std::forward_as_tuple(mapID), std::forward_as_tuple()); + if (map_iter.second) { + map_iter.first->second.MapId = mapID; printf("spawning Map %u\n", mapID); - mapData[mapID] = current = new MapSpawns(); } - else - current = map_iter->second; - current->UniqueEntries.emplace(spawn.ID, spawn); - current->TileEntries.insert(pair<uint32, TileSpawn>(StaticMapTree::packTileID(tileX, tileY), TileSpawn{ spawn.ID, spawn.flags })); + map_iter.first->second.UniqueEntries.emplace(spawn.ID, spawn); } + + mapData.resize(data.size()); + auto dst = mapData.begin(); + for (auto src = data.begin(); src != data.end(); ++src, ++dst) + *dst = std::move(src->second); + bool success = (ferror(dirf) == 0); fclose(dirf); return success; @@ -274,29 +257,10 @@ namespace VMAP printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); AABox modelBound; - bool boundEmpty=true; - - for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... - { - std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; - - if (vertices.empty()) - { - std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; - continue; - } - uint32 nvectors = vertices.size(); - for (uint32 i = 0; i < nvectors; ++i) - { - Vector3 v = modelPosition.transform(vertices[i]); + modelBound.merge(modelPosition.transform(raw_model.groupsArray[0].bounds.low())); + modelBound.merge(modelPosition.transform(raw_model.groupsArray[0].bounds.high())); - if (boundEmpty) - modelBound = AABox(v, v), boundEmpty=false; - else - modelBound.merge(v); - } - } spawn.iBound = modelBound + spawn.iPos; spawn.flags |= MOD_HAS_BOUND; return true; diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h index 35aa90ef9f2..d7b48924d43 100644 --- a/src/common/Collision/Maps/TileAssembler.h +++ b/src/common/Collision/Maps/TileAssembler.h @@ -21,6 +21,7 @@ #include <G3D/Vector3.h> #include <G3D/Matrix3.h> +#include <deque> #include <map> #include <set> @@ -54,20 +55,26 @@ namespace VMAP struct TileSpawn { + TileSpawn() : Id(0), Flags(0) { } + TileSpawn(uint32 id, uint32 flags) : Id(id), Flags(flags) { } + uint32 Id; uint32 Flags; - }; - typedef std::map<uint32, ModelSpawn> UniqueEntryMap; - typedef std::multimap<uint32, TileSpawn> TileMap; + bool operator<(TileSpawn const& right) const { return Id < right.Id; } + }; struct TC_COMMON_API MapSpawns { - UniqueEntryMap UniqueEntries; - TileMap TileEntries; + MapSpawns() { } + + uint32 MapId; + std::map<uint32, ModelSpawn> UniqueEntries; + std::map<uint32 /*packedTileId*/, std::set<TileSpawn>> TileEntries; + std::map<uint32 /*packedTileId*/, std::set<TileSpawn>> ParentTileEntries; }; - typedef std::map<uint32, MapSpawns*> MapData; + typedef std::deque<MapSpawns> MapData; //=============================================== struct TC_COMMON_API GroupModel_Raw @@ -101,7 +108,6 @@ namespace VMAP private: std::string iDestDir; std::string iSrcDir; - G3D::Table<std::string, unsigned int > iUniqueNameIds; MapData mapData; std::set<std::string> spawnedModelFiles; diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index 1edf3b0f442..04fe5b06c7b 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -35,9 +35,8 @@ namespace VMAP enum ModelFlags { MOD_M2 = 1, - MOD_WORLDSPAWN = 1 << 1, - MOD_HAS_BOUND = 1 << 2, - MOD_PARENT_SPAWN = 1 << 3 + MOD_HAS_BOUND = 1 << 1, + MOD_PARENT_SPAWN = 1 << 2 }; class TC_COMMON_API ModelSpawn diff --git a/src/common/Collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h index a70b76ce450..15a8257ebdc 100644 --- a/src/common/Collision/VMapDefinitions.h +++ b/src/common/Collision/VMapDefinitions.h @@ -25,8 +25,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.7"; - const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.8"; + const char RAW_VMAP_MAGIC[] = "VMAP048"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... |