Core/VMAPS: Fixed vmaps in single WMO instances like ragefire chasm
authorShauren <shauren.trinity@gmail.com>
Fri, 27 Apr 2018 18:23:52 +0000 (20:23 +0200)
committerShauren <shauren.trinity@gmail.com>
Fri, 27 Apr 2018 18:23:52 +0000 (20:23 +0200)
* 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

17 files changed:
src/common/Collision/Maps/MapTree.cpp
src/common/Collision/Maps/MapTree.h
src/common/Collision/Maps/TileAssembler.cpp
src/common/Collision/Maps/TileAssembler.h
src/common/Collision/Models/ModelInstance.h
src/common/Collision/VMapDefinitions.h
src/tools/vmap4_extractor/adtfile.cpp
src/tools/vmap4_extractor/adtfile.h
src/tools/vmap4_extractor/model.cpp
src/tools/vmap4_extractor/model.h
src/tools/vmap4_extractor/modelheaders.h
src/tools/vmap4_extractor/vec3d.h
src/tools/vmap4_extractor/vmapexport.cpp
src/tools/vmap4_extractor/vmapexport.h
src/tools/vmap4_extractor/wdtfile.cpp
src/tools/vmap4_extractor/wmo.cpp
src/tools/vmap4_extractor/wmo.h

index 24874412a22cd589fd26c1bb286350413e6d8ea5..ce8ff8deb557b6f370866f2384639d75d3bf02a9 100644 (file)
@@ -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);
index d762f804132762104053d0e052966e421729f36d..596a4ae0296aaeacf53737979d8f86cbd54ed63d 100644 (file)
@@ -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);
 
index b0bee33b4b24b670afaabae49f7e85c7317f296b..47dfadd09473bf3ab44d086d96a1b25eb3b876b5 100644 (file)
@@ -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;
index 35aa90ef9f28b885652b5e9fd7e34780e1a7bf53..d7b48924d433dfff83a99b5889ff253ce4888918 100644 (file)
@@ -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;
 
index 1edf3b0f4429d74f53c2a45c99df71912b633d21..04fe5b06c7b978877f7527205ded7d6fa3d4d20b 100644 (file)
@@ -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
index a70b76ce450542e2346bb177430ab81728c086f1..15a8257ebdc952194f9b2005a3cd45e67375a104 100644 (file)
@@ -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...
index aea160fa8841b3253b6a7012c14bb639e4ae1375..8c16b751b80d2bb02e50445cf22272fd9fd4515c 100644 (file)
@@ -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;
index 349879daec29d1230e58e8cd90dac03a166df021..58e1cf7420ea0540c8eeb680fa1de5815ae00435 100644 (file)
@@ -69,8 +69,8 @@ public:
     ~ADTFile();
     std::vector<std::string> WmoInstanceNames;
     std::vector<std::string> 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);
index cfe5584921a39e713de926a9e05c10c9a8333700..8ad88ae5994ec242a11540bfa512d54fac98f508 100644 (file)
@@ -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<ADTOutputCache>* dirfileCache)
+void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* 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<ADTOutputCache>* 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);
index f1e83606471e41bff6069e351448272d5faa5812..9e7bb60c0b3b53602115d7cd5ae3d6ff060ccac8 100644 (file)
@@ -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<ADTOutputCache>* 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<ADTOutputCache>* dirfileCache);
 }
 
index 213e6a57519d20007d5244d53ed6eeea47ed6689..d85a72f697ffaf804aef29358e4693d7814331ac 100644 (file)
@@ -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;
index ae64bdad615e11035227e5931cef0dde3710d700..dd1dbe0387c6daf90aa5c664cde0f43492939567 100644 (file)
@@ -142,6 +142,13 @@ class AaBox3D
 public:
     Vec3D min;
     Vec3D max;
+
+    AaBox3D& operator+=(Vec3D const& offset)
+    {
+        min += offset;
+        max += offset;
+        return *this;
+    }
 };
 
 class Vec2D
index 57949336dc87b4f911dae03eec4d689714936a56..dc4af89d0b8a2afd3325b81f8439852393037262 100644 (file)
@@ -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);
                         }
                     }
index 74221e17a27d8c861c1ad191cae6bd758cafc505..1666e5846d8f06319f0ef4b43d63ecb2b44b2d53 100644 (file)
@@ -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;
index ba2689ed65751332338cf005f94f9264e36e7f9b..dc63aa4f6b3660524f9ee9efd01542d94783ef76 100644 (file)
@@ -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);
                     }
                 }
             }
index 01cd164bec3db021b7556a72e9aa05ff1769d13a..57eb2d15d92624ca0c15071d6119cf4e9aaea8bd 100644 (file)
@@ -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<ADTOutputCache>* dirfileCache)
+void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* 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);
index 6e290c1d548c8ee9256ecb2537d21ff5a50bf88e..0b34b2a0c1ba540e289e653e325f7951d06b5c4d 100644 (file)
@@ -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<ADTOutputCache>* dirfileCache);
+    void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, bool isGlobalWmo, uint32 mapID, uint32 originalMapId,
+        FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
 }
 
 #endif