From 24d30dab84f93a200ad3acad6302327379f5031c Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 27 Apr 2018 20:23:52 +0200 Subject: Core/VMAPS: Fixed vmaps in single WMO instances like ragefire chasm * Fixed some models not always being spawned because they only appear in one tile file but are large enough to cross tile boundaries (lava in Firelands at Ragnaros place) Closes #21879 --- src/common/Collision/Maps/MapTree.cpp | 62 +++--------- src/common/Collision/Maps/MapTree.h | 2 - src/common/Collision/Maps/TileAssembler.cpp | 152 +++++++++++----------------- src/common/Collision/Maps/TileAssembler.h | 20 ++-- src/common/Collision/Models/ModelInstance.h | 5 +- src/common/Collision/VMapDefinitions.h | 4 +- src/tools/vmap4_extractor/adtfile.cpp | 20 ++-- src/tools/vmap4_extractor/adtfile.h | 4 +- src/tools/vmap4_extractor/model.cpp | 36 +++---- src/tools/vmap4_extractor/model.h | 5 +- src/tools/vmap4_extractor/modelheaders.h | 8 +- src/tools/vmap4_extractor/vec3d.h | 7 ++ src/tools/vmap4_extractor/vmapexport.cpp | 4 +- src/tools/vmap4_extractor/vmapexport.h | 5 +- src/tools/vmap4_extractor/wdtfile.cpp | 8 +- src/tools/vmap4_extractor/wmo.cpp | 31 ++---- src/tools/vmap4_extractor/wmo.h | 3 +- 17 files changed, 151 insertions(+), 225 deletions(-) (limited to 'src') 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(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 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 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>& 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 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 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; ssecond->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 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(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& 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 #include +#include #include #include @@ -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 UniqueEntryMap; - typedef std::multimap 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 UniqueEntries; + std::map> TileEntries; + std::map> ParentTileEntries; }; - typedef std::map MapData; + typedef std::deque MapData; //=============================================== struct TC_COMMON_API GroupModel_Raw @@ -101,7 +108,6 @@ namespace VMAP private: std::string iDestDir; std::string iSrcDir; - G3D::Table iUniqueNameIds; MapData mapData; std::set 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... diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index aea160fa884..8c16b751b80 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -84,10 +84,10 @@ ADTFile::ADTFile(char* filename, bool cache) : _file(CascStorage, filename, fals dirfileCache = nullptr; } -bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId) +bool ADTFile::init(uint32 map_num, uint32 originalMapId) { if (dirfileCache) - return initFromCache(map_num, tileX, tileY, originalMapId); + return initFromCache(map_num, originalMapId); if (_file.isEof()) return false; @@ -180,13 +180,13 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa _file.read(&doodadDef, sizeof(ADT::MDDF)); if (!(doodadDef.Flags & 0x40)) { - Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); + Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, originalMapId, dirfile, dirfileCache); } else { std::string fileName = Trinity::StringFormat("FILE%08X.xxx", doodadDef.Id); ExtractSingleModel(fileName); - Doodad::Extract(doodadDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); + Doodad::Extract(doodadDef, fileName.c_str(), map_num, originalMapId, dirfile, dirfileCache); } } @@ -204,15 +204,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa _file.read(&mapObjDef, sizeof(ADT::MODF)); if (!(mapObjDef.Flags & 0x8)) { - MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); - Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); + MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), false, map_num, originalMapId, dirfile, dirfileCache); + Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache); } else { std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id); ExtractSingleWmo(fileName); - MapObject::Extract(mapObjDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); - Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); + MapObject::Extract(mapObjDef, fileName.c_str(), false, map_num, originalMapId, dirfile, dirfileCache); + Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache); } } @@ -229,7 +229,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa return true; } -bool ADTFile::initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId) +bool ADTFile::initFromCache(uint32 map_num, uint32 originalMapId) { if (dirfileCache->empty()) return true; @@ -245,8 +245,6 @@ bool ADTFile::initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 o for (ADTOutputCache const& cached : *dirfileCache) { fwrite(&map_num, sizeof(uint32), 1, dirfile); - fwrite(&tileX, sizeof(uint32), 1, dirfile); - fwrite(&tileY, sizeof(uint32), 1, dirfile); uint32 flags = cached.Flags; if (map_num != originalMapId) flags |= MOD_PARENT_SPAWN; diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 349879daec2..58e1cf7420e 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -69,8 +69,8 @@ public: ~ADTFile(); std::vector WmoInstanceNames; std::vector ModelInstanceNames; - bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId); - bool initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId); + bool init(uint32 map_num, uint32 originalMapId); + bool initFromCache(uint32 map_num, uint32 originalMapId); }; char const* GetPlainName(char const* FileName); diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index cfe5584921a..8ad88ae5994 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -60,6 +60,7 @@ bool Model::open() } memcpy(&header, f.getBuffer() + m2start, sizeof(ModelHeader)); + bounds = header.collisionBox; if (header.nBoundingTriangles > 0) { f.seek(m2start); @@ -96,18 +97,18 @@ bool Model::ConvertToVMAPModel(const char * outfilename) uint32 nVertices = header.nBoundingVertices; fwrite(&nVertices, sizeof(int), 1, output); uint32 nofgroups = 1; - fwrite(&nofgroups,sizeof(uint32), 1, output); - fwrite(N,4*3,1,output);// rootwmoid, flags, groupid - fwrite(N,sizeof(float),3*2,output);//bbox, only needed for WMO currently - fwrite(N,4,1,output);// liquidflags - fwrite("GRP ",4,1,output); + fwrite(&nofgroups, sizeof(uint32), 1, output); + fwrite(N, 4 * 3, 1, output);// rootwmoid, flags, groupid + fwrite(&bounds, sizeof(AaBox3D), 1, output);//bbox, only needed for WMO currently + fwrite(N, 4, 1, output);// liquidflags + fwrite("GRP ", 4, 1, output); uint32 branches = 1; int wsize; wsize = sizeof(branches) + sizeof(uint32) * branches; fwrite(&wsize, sizeof(int), 1, output); - fwrite(&branches,sizeof(branches), 1, output); + fwrite(&branches, sizeof(branches), 1, output); uint32 nIndexes = header.nBoundingTriangles; - fwrite(&nIndexes,sizeof(uint32), 1, output); + fwrite(&nIndexes, sizeof(uint32), 1, output); fwrite("INDX",4, 1, output); wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes; fwrite(&wsize, sizeof(int), 1, output); @@ -147,14 +148,12 @@ bool Model::ConvertToVMAPModel(const char * outfilename) return true; } - Vec3D fixCoordSystem(Vec3D const& v) { return Vec3D(v.x, v.z, -v.y); } -void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, - FILE* pDirfile, std::vector* dirfileCache) +void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) { char tempname[512]; sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName); @@ -179,15 +178,11 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint uint16 nameSet = 0;// not used for models uint32 uniqueId = GenerateUniqueObjectId(doodadDef.UniqueId, 0); uint32 tcflags = MOD_M2; - if (tileX == 65 && tileY == 65) - tcflags |= MOD_WORLDSPAWN; if (mapID != originalMapId) tcflags |= MOD_PARENT_SPAWN; - //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name + //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); - fwrite(&tileX, sizeof(uint32), 1, pDirfile); - fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&tcflags, sizeof(uint32), 1, pDirfile); fwrite(&nameSet, sizeof(uint16), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); @@ -225,7 +220,7 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint } } -void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, +void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) { if (wmo.DoodadSet >= doodadData.Sets.size()) @@ -234,6 +229,9 @@ void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, u G3D::Vector3 wmoPosition(wmo.Position.z, wmo.Position.x, wmo.Position.y); G3D::Matrix3 wmoRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::toRadians(wmo.Rotation.y), G3D::toRadians(wmo.Rotation.x), G3D::toRadians(wmo.Rotation.z)); + if (isGlobalWmo) + wmoPosition += G3D::Vector3(533.33333f * 32, 533.33333f * 32, 0.0f); + uint16 doodadId = 0; WMO::MODS const& doodadSetData = doodadData.Sets[wmo.DoodadSet]; for (uint16 doodadIndex : doodadData.References) @@ -290,15 +288,11 @@ void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, u uint16 nameSet = 0; // not used for models uint32 uniqueId = GenerateUniqueObjectId(wmo.UniqueId, doodadId); uint32 tcflags = MOD_M2; - if (tileX == 65 && tileY == 65) - tcflags |= MOD_WORLDSPAWN; if (mapID != originalMapId) tcflags |= MOD_PARENT_SPAWN; - //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name + //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); - fwrite(&tileX, sizeof(uint32), 1, pDirfile); - fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&tcflags, sizeof(uint32), 1, pDirfile); fwrite(&nameSet, sizeof(uint16), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index f1e83606471..9e7bb60c0b3 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -45,6 +45,7 @@ public: ModelHeader header; Vec3D* vertices; uint16* indices; + AaBox3D bounds; bool open(); bool ConvertToVMAPModel(char const* outfilename); @@ -55,10 +56,10 @@ public: namespace Doodad { - void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, + void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); - void ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, + void ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); } diff --git a/src/tools/vmap4_extractor/modelheaders.h b/src/tools/vmap4_extractor/modelheaders.h index 213e6a57519..d85a72f697f 100644 --- a/src/tools/vmap4_extractor/modelheaders.h +++ b/src/tools/vmap4_extractor/modelheaders.h @@ -19,7 +19,8 @@ #ifndef MODELHEADERS_H #define MODELHEADERS_H -#include "cascfile.h" // integer typedefs +#include "Define.h" +#include "vec3d.h" #pragma pack(push,1) @@ -65,7 +66,10 @@ struct ModelHeader uint32 ofsTransLookup; uint32 nTexAnimLookup; uint32 ofsTexAnimLookup; - float floats[14]; + AaBox3D boundingBox; + float boundingSphereRadius; + AaBox3D collisionBox; + float collisionSphereRadius; uint32 nBoundingTriangles; uint32 ofsBoundingTriangles; uint32 nBoundingVertices; diff --git a/src/tools/vmap4_extractor/vec3d.h b/src/tools/vmap4_extractor/vec3d.h index ae64bdad615..dd1dbe0387c 100644 --- a/src/tools/vmap4_extractor/vec3d.h +++ b/src/tools/vmap4_extractor/vec3d.h @@ -142,6 +142,13 @@ class AaBox3D public: Vec3D min; Vec3D max; + + AaBox3D& operator+=(Vec3D const& offset) + { + min += offset; + max += offset; + return *this; + } }; class Vec2D diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 57949336dc8..dc4af89d0b8 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -280,14 +280,14 @@ void ParsMapFiles() bool success = false; if (ADTFile* ADT = WDT->GetMap(x, y)) { - success = ADT->init(itr->first, x, y, itr->first); + success = ADT->init(itr->first, itr->first); WDT->FreeADT(ADT); } if (!success && parentWDT) { if (ADTFile* ADT = parentWDT->GetMap(x, y)) { - ADT->init(itr->first, x, y, itr->second.parent_id); + ADT->init(itr->first, itr->second.parent_id); parentWDT->FreeADT(ADT); } } diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index 74221e17a27..1666e5846d8 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -26,9 +26,8 @@ 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 }; struct WMODoodadData; diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index ba2689ed657..dc63aa4f6b3 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -112,15 +112,15 @@ bool WDTFile::init(uint32 mapId) _file.read(&mapObjDef, sizeof(ADT::MODF)); if (!(mapObjDef.Flags & 0x8)) { - MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr); - Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, mapId, 65, 65, mapId, dirfile, nullptr); + MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), true, mapId, mapId, dirfile, nullptr); + Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, true, mapId, mapId, dirfile, nullptr); } else { std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id); ExtractSingleWmo(fileName); - MapObject::Extract(mapObjDef, fileName.c_str(), mapId, 65, 65, mapId, dirfile, nullptr); - Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, mapId, 65, 65, mapId, dirfile, nullptr); + MapObject::Extract(mapObjDef, fileName.c_str(), true, mapId, mapId, dirfile, nullptr); + Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, true, mapId, mapId, dirfile, nullptr); } } } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 01cd164bec3..57eb2d15d92 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -533,7 +533,7 @@ WMOGroup::~WMOGroup() delete [] LiquBytes; } -void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) +void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) { // destructible wmo, do not dump. we can handle the vmap for these // in dynamic tree (gameobject vmaps) @@ -544,10 +544,9 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin char tempname[512]; sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName); - FILE *input; - input = fopen(tempname, "r+b"); + FILE* input = fopen(tempname, "r+b"); - if(!input) + if (!input) { printf("WMOInstance::WMOInstance: couldn't open %s\n", tempname); return; @@ -561,35 +560,27 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin if (count != 1 || nVertices == 0) return; - Vec3D position = mapObjDef.Position; - - float x, z; - x = position.x; - z = position.z; - if (x == 0 && z == 0) - { - position.x = 533.33333f * 32; - position.z = 533.33333f * 32; - } - position = fixCoords(position); + Vec3D position = fixCoords(mapObjDef.Position); AaBox3D bounds; bounds.min = fixCoords(mapObjDef.Bounds.min); bounds.max = fixCoords(mapObjDef.Bounds.max); + if (isGlobalWmo) + { + position += Vec3D(533.33333f * 32, 533.33333f * 32, 0.0f); + bounds += Vec3D(533.33333f * 32, 533.33333f * 32, 0.0f); + } + float scale = 1.0f; if (mapObjDef.Flags & 0x4) scale = mapObjDef.Scale / 1024.0f; uint32 uniqueId = GenerateUniqueObjectId(mapObjDef.UniqueId, 0); uint32 flags = MOD_HAS_BOUND; - if (tileX == 65 && tileY == 65) - flags |= MOD_WORLDSPAWN; if (mapID != originalMapId) flags |= MOD_PARENT_SPAWN; - //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name + //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); - fwrite(&tileX, sizeof(uint32), 1, pDirfile); - fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&flags, sizeof(uint32), 1, pDirfile); fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 6e290c1d548..0b34b2a0c1b 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -160,7 +160,8 @@ public: namespace MapObject { - void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); + void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, + FILE* pDirfile, std::vector* dirfileCache); } #endif -- cgit v1.2.3