Пример #1
0
        void buildMap(uint mapID)
        {
            var tiles = getTileList(mapID);

            // make sure we process maps which don't have tiles
            if (tiles.Count == 0)
            {
                // convert coord bounds to grid bounds
                getGridBounds(mapID, out uint minX, out uint minY, out uint maxX, out uint maxY);

                // add all tiles within bounds to tile list.
                for (uint i = minX; i <= maxX; ++i)
                {
                    for (uint j = minY; j <= maxY; ++j)
                    {
                        uint packTileId = StaticMapTree.packTileID(i, j);
                        if (!tiles.Contains(packTileId))
                        {
                            tiles.Add(packTileId);
                            ++m_totalTiles;
                        }
                    }
                }
            }

            if (!tiles.Empty())
            {
                // build navMesh
                dtNavMesh navMesh;
                buildNavMesh(mapID, out navMesh);
                if (navMesh == null)
                {
                    Console.WriteLine($"[Map {mapID:D4}] Failed creating navmesh!");
                    m_totalTilesProcessed += tiles.Count;
                    return;
                }

                // now start building mmtiles for each tile
                Console.WriteLine($"[Map {mapID:D4}] We have {tiles.Count} tiles.                          ");
                foreach (var it in tiles)
                {
                    // unpack tile coords
                    StaticMapTree.unpackTileID(it, out uint tileX, out uint tileY);

                    ++m_totalTilesProcessed;
                    if (shouldSkipTile(mapID, tileX, tileY))
                    {
                        continue;
                    }

                    buildTile(mapID, tileX, tileY, navMesh);
                }
            }

            Console.WriteLine($"[Map {mapID:D4}] Complete!");
        }
Пример #2
0
        public bool convertWorld2()
        {
            bool success = readMapSpawns();

            if (!success)
            {
                return(false);
            }

            // export Map data
            foreach (var mapPair in mapData)
            {
                var mapSpawn = mapPair.Value;
                // build global map tree
                List <ModelSpawn> mapSpawns = new List <ModelSpawn>();

                Console.WriteLine($"Calculating model bounds for map {mapPair.Key}...");
                foreach (var entry in mapSpawn.UniqueEntries.Values)
                {
                    // 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 (Convert.ToBoolean(entry.flags & ModelFlags.M2))
                    {
                        if (!calculateTransformedBound(entry))
                        {
                            break;
                        }
                    }
                    else if (Convert.ToBoolean(entry.flags & ModelFlags.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.iBound = entry.iBound + new Vector3(533.33333f * 32, 533.33333f * 32, 0.0f);
                    }
                    mapSpawns.Add(entry);
                    spawnedModelFiles.Add(entry.name);
                }

                Console.WriteLine($"Creating map tree for map {mapPair.Key}...");
                BIH pTree = new BIH();

                try
                {
                    pTree.build(mapSpawns, BoundsTrait.getBounds);
                }
                catch (Exception e)
                {
                    Console.Write($"Exception {e.Message} when calling pTree.build");
                    return(false);
                }

                // ===> possibly move this code to StaticMapTree class
                Dictionary <uint, uint> modelNodeIdx = new Dictionary <uint, uint>();
                for (uint i = 0; i < mapSpawns.Count; ++i)
                {
                    modelNodeIdx.Add(mapSpawns[(int)i].ID, i);
                }

                // write map tree file
                string mapfilename = $"{iDestDir}/{mapPair.Key:D4}.vmtree";
                using (BinaryWriter writer = new BinaryWriter(File.Open(mapfilename, FileMode.Create, FileAccess.Write)))
                {
                    //general info
                    writer.WriteString(SharedConst.VMAP_MAGIC);
                    uint globalTileID = StaticMapTree.packTileID(65, 65);
                    var  globalRange  = mapSpawn.TileEntries.LookupByKey(globalTileID);
                    bool isTiled      = globalRange.Count == 0; // only maps without terrain (tiles) have global WMO
                    writer.Write(isTiled);

                    // Nodes
                    writer.WriteString("NODE");
                    pTree.writeToFile(writer);
                    // global map spawns (WDT), if any (most instances)
                    writer.WriteString("GOBJ");

                    foreach (var glob in globalRange)
                    {
                        ModelSpawn.writeToFile(writer, mapSpawn.UniqueEntries[glob]);
                    }
                }

                // write map tile files, similar to ADT files, only with extra BSP tree node info
                var tileEntries = mapSpawn.TileEntries;
                foreach (var key in tileEntries.Keys)
                {
                    ModelSpawn spawn = mapSpawn.UniqueEntries[tileEntries[key].First()];
                    if (Convert.ToBoolean(spawn.flags & ModelFlags.WorldSpawn)) // WDT spawn, saved as tile 65/65 currently...
                    {
                        continue;
                    }

                    string tilefilename = $"{iDestDir}/{mapPair.Key:D4}_";
                    uint   x, y;
                    StaticMapTree.unpackTileID(key, out x, out y);
                    tilefilename += $"{x:D2}_{y:D2}.vmtile";
                    using (BinaryWriter writer = new BinaryWriter(File.Open(tilefilename, FileMode.Create, FileAccess.Write)))
                    {
                        // file header
                        writer.WriteString(SharedConst.VMAP_MAGIC);
                        // write number of tile spawns
                        writer.Write(tileEntries[key].Count);
                        // write tile spawns
                        foreach (var nSpawn in tileEntries[key])
                        {
                            ModelSpawn spawn2 = mapSpawn.UniqueEntries[nSpawn];
                            ModelSpawn.writeToFile(writer, spawn2);
                            // MapTree nodes to update when loading tile:
                            var nIdx = modelNodeIdx[spawn2.ID];
                            writer.Write(nIdx);
                        }
                    }
                }
                // break; //test, extract only first map; TODO: remvoe this line
            }

            // add an object models, listed in temp_gameobject_models file
            exportGameobjectModels();
            // export objects
            Console.WriteLine("Converting Model Files");
            foreach (var mfile in spawnedModelFiles)
            {
                Console.WriteLine($"Converting {mfile}");
                convertRawFile(mfile);
            }

            return(success);
        }
Пример #3
0
        void buildNavMesh(uint mapID, out dtNavMesh navMesh)
        {
            var tiles = getTileList(mapID);

            // old code for non-statically assigned bitmask sizes:
            ///*** calculate number of bits needed to store tiles & polys ***/
            //int tileBits = dtIlog2(dtNextPow2(tiles.size()));
            //if (tileBits < 1) tileBits = 1;                                     // need at least one bit!
            //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;

            int polyBits = (int)DT_POLY_BITS;

            int maxTiles        = tiles.Count;
            int maxPolysPerTile = 1 << polyBits;

            /***          calculate bounds of map         ***/

            uint tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0;

            foreach (var it in tiles)
            {
                StaticMapTree.unpackTileID(it, out uint tileX, out uint tileY);

                if (tileX > tileXMax)
                {
                    tileXMax = tileX;
                }
                else if (tileX < tileXMin)
                {
                    tileXMin = tileX;
                }

                if (tileY > tileYMax)
                {
                    tileYMax = tileY;
                }
                else if (tileY < tileYMin)
                {
                    tileYMin = tileY;
                }
            }

            // use Max because '32 - tileX' is negative for values over 32
            float[] bmin;
            float[] bmax;
            getTileBounds(tileXMax, tileYMax, null, 0, out bmin, out bmax);

            /***       now create the navmesh       ***/

            // navmesh creation params
            dtNavMeshParams navMeshParams = new dtNavMeshParams();

            navMeshParams.tileWidth  = SharedConst.GRID_SIZE;
            navMeshParams.tileHeight = SharedConst.GRID_SIZE;
            rcVcopy(navMeshParams.orig, bmin);
            navMeshParams.maxTiles = maxTiles;
            navMeshParams.maxPolys = maxPolysPerTile;

            navMesh = new dtNavMesh();
            Console.WriteLine($"[Map {mapID:D4}] Creating navMesh...");
            if (dtStatusFailed(navMesh.init(navMeshParams)))
            {
                Console.WriteLine($"[Map {mapID:D4}] Failed creating navmesh!");
                return;
            }

            string fileName = $"mmaps/{mapID:D4}.mmap";

            using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create, FileAccess.Write)))
            {
                // now that we know navMesh params are valid, we can write them to file
                writer.Write(navMeshParams.orig[0]);
                writer.Write(navMeshParams.orig[1]);
                writer.Write(navMeshParams.orig[2]);
                writer.Write(navMeshParams.tileWidth);
                writer.Write(navMeshParams.tileHeight);
                writer.Write(navMeshParams.maxTiles);
                writer.Write(navMeshParams.maxPolys);
            }
        }