Exemplo n.º 1
0
        public WorldModel(string directory, string modelName)
        {
            var filePath = Path.Combine(directory, "vmaps", $"{modelName}.vmo");

            using (var reader = new BinaryReader(File.OpenRead(filePath)))
            {
                reader.BaseStream.Position += 8;

                if (reader.ReadInt32() == 0x444F4D57)   // WMOD
                {
                    var chunkSize = reader.ReadInt32(); // 8
                    RootWmoID = reader.ReadInt32();
                }

                if (reader.ReadInt32() == 0x444F4D47) // GMOD
                {
                    GroupModels = new GroupModel[reader.ReadInt32()];
                    for (var i = 0; i < GroupModels.Length; ++i)
                    {
                        GroupModels[i] = new GroupModel(reader)
                        {
                            Program                   = ShaderProgramCache.Instance.Get("wmo"),
                            VerticeAttribute          = "vertexPosition_modelSpace",
                            InstancePositionAttribute = "instance_position",
                        };
                    }

                    if (reader.ReadInt32() == 0x48494247) // GIH
                    {
                        GroupTree = new BIH(reader);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public VMapLoader(string directory, int mapID)
        {
            Directory = directory;

            using (var reader = new BinaryReader(File.OpenRead(Path.Combine(directory, "vmaps", $"{mapID:D3}.vmtree"))))
            {
                if (reader == null)
                {
                    return;
                }

                MapID = mapID;

                reader.BaseStream.Position += 8;
                IsTiled = reader.ReadByte() == 1;

                if (reader.ReadInt32() == 0x45444F4E) // NODE
                {
                    BIH = new BIH(reader);
                }

                if (!IsTiled && reader.ReadInt32() == 0x4A424F47) // GOBJ
                {
                    GlobalModel = new ModelSpawn(directory, reader);
                }
            }
        }
Exemplo n.º 3
0
        public GroupModel(BinaryReader reader)
        {
            var bbox = reader.Read <float>(6);
            // var boundingBoxLo = reader.Read<Vector3>();
            // var boundingBoxHi = reader.Read<Vector3>();
            var mogpFlags  = reader.ReadInt32();
            var groupWmoID = reader.ReadInt32();

            if (reader.ReadInt32() == 0x54524556) // VERT
            {
                var chunkSize = reader.ReadInt32();
                var count     = reader.ReadInt32();
                if (count == 0)
                {
                    return;
                }

                Vertices = reader.Read <Vector3>(count);
            }

            if (reader.ReadInt32() == 0x4D495254) // TRIM
            {
                var chunkSize = reader.ReadInt32();
                var count     = reader.ReadInt32();

                Indices = reader.Read <uint>(count * 3);
            }

            if (reader.ReadInt32() == 0x4849424D) // MBIH
            {
                Tree = new BIH(reader);
            }

            if (reader.ReadInt32() == 0x5551494C) // LIQU
            {
                var chunkSize = reader.ReadInt32();
                if (chunkSize == 0)
                {
                    return;
                }

                var tileX = reader.ReadInt32();
                var tileY = reader.ReadInt32();
                reader.BaseStream.Position += SizeCache <Vector3> .Size;
                reader.BaseStream.Position += 4;
                reader.BaseStream.Position += 4 * (tileX + 1) * (tileY + 1);
                reader.BaseStream.Position += tileX * tileY;
            }
        }
Exemplo n.º 4
0
        public GroupModel(BinaryReader reader)
        {
            reader.BaseStream.Position += 2 * SizeCache <Vector3> .Size; // BBox
            var mogpFlags  = reader.ReadInt32();
            var groupWmoID = reader.ReadInt32();

            if (reader.ReadInt32() == 0x54524556) // VERT
            {
                var chunkSize = reader.ReadInt32();
                var count     = reader.ReadInt32();
                if (count == 0)
                {
                    return;
                }

                _modelVertices = reader.Read <Vector3>(count);
            }

            if (reader.ReadInt32() == 0x4D495254) // TRIM
            {
                var chunkSize = reader.ReadInt32();
                var count     = reader.ReadInt32();

                _modelIndices = reader.Read <uint>(count * 3);
            }

            if (reader.ReadInt32() == 0x4849424D) // MBIH
            {
                BIH.Skip(reader);
            }

            if (reader.ReadInt32() == 0x5551494C) // LIQU
            {
                var chunkSize = reader.ReadInt32();
                if (chunkSize == 0)
                {
                    return;
                }

                var tileX = reader.ReadInt32();
                var tileY = reader.ReadInt32();
                reader.BaseStream.Position += SizeCache <Vector3> .Size;
                reader.BaseStream.Position += 4;
                reader.BaseStream.Position += 4 * (tileX + 1) * (tileY + 1);
                reader.BaseStream.Position += tileX * tileY;
            }
        }
Exemplo n.º 5
0
        public BuildingsLoader(string directory, int mapID)
        {
            _directory = directory;
            _mapId     = mapID;

            using (var reader = new BinaryReader(File.OpenRead(Path.Combine(directory, "vmaps", $"{mapID:D3}.vmtree"))))
            {
                reader.BaseStream.Position += 8; // Skip signature
                _isTiled = reader.ReadByte() == 1;

                if (reader.ReadInt32() == 0x45444F4E) // NODE
                {
                    BIH.Skip(reader);
                }

                if (!_isTiled && reader.ReadInt32() == 0x4A424F47) // GOBJ
                {
                    // load global model
                }
            }
        }
Exemplo n.º 6
0
        public bool convertWorld2()
        {
            bool success = readMapSpawns();

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

            float invTileSize = 1.0f / 533.33333f;

            // 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))
                        {
                            continue;
                        }
                    }

                    mapSpawns.Add(entry);
                    spawnedModelFiles.Add(entry.name);

                    var tileEntries = Convert.ToBoolean(entry.flags & ModelFlags.ParentSpawn) ? mapSpawn.ParentTileEntries : mapSpawn.TileEntries;

                    AxisAlignedBox bounds = entry.iBound;
                    Vector2        low    = new Vector2(bounds.Lo.X * invTileSize, bounds.Lo.Y * invTileSize);
                    Vector2        high   = new Vector2(bounds.Hi.X * invTileSize, bounds.Hi.Y * invTileSize);
                    for (uint x = (ushort)low.X; x <= (ushort)high.X; ++x)
                    {
                        for (uint y = (ushort)low.Y; y <= (ushort)high.Y; ++y)
                        {
                            tileEntries.Add(StaticMapTree.PackTileID(x, y), new TileSpawn(entry.ID, entry.flags));
                        }
                    }
                }

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

                // ===> possibly move this code to StaticMapTree class

                // 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);

                    // Nodes
                    writer.WriteString("NODE");
                    pTree.writeToFile(writer);

                    // spawn id to index map
                    writer.WriteString("SIDX");
                    writer.Write(mapSpawns.Count);
                    for (int i = 0; i < mapSpawns.Count; ++i)
                    {
                        writer.Write(mapSpawns[i].ID);
                        writer.Write(i);
                    }
                }

                // write map tile files, similar to ADT files, only with extra BIH tree node info
                foreach (var key in mapSpawn.TileEntries.Keys)
                {
                    var spawnList = mapSpawn.TileEntries[key];

                    uint x, y;
                    StaticMapTree.UnpackTileID(key, out x, out y);
                    string tilefilename = $"{iDestDir}/{mapPair.Key:D4}_{y:D2}_{x:D2}.vmtile";
                    using (BinaryWriter writer = new BinaryWriter(File.Open(tilefilename, FileMode.Create, FileAccess.Write)))
                    {
                        var parentTileEntries = mapPair.Value.ParentTileEntries[key];

                        int nSpawns = spawnList.Count + parentTileEntries.Count;

                        // file header
                        writer.WriteString(SharedConst.VMAP_MAGIC);
                        // write number of tile spawns
                        writer.Write(nSpawns);
                        // write tile spawns
                        foreach (var tileSpawn in spawnList)
                        {
                            ModelSpawn.WriteToFile(writer, mapPair.Value.UniqueEntries[tileSpawn.Id]);
                        }

                        foreach (var spawnItr in parentTileEntries)
                        {
                            ModelSpawn.WriteToFile(writer, mapPair.Value.UniqueEntries[spawnItr.Id]);
                        }
                    }
                }
            }

            // 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);
        }
Exemplo n.º 7
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);
        }