Beispiel #1
0
        // Chunk Data //
        public void ReadMCNKObj(BinaryReader reader, int MCNKchunkNumber, uint MCNKsize)
        {
            if (reader.BaseStream.Length == reader.BaseStream.Position)
            {
                return;
            }

            long MCNKchnkPos    = reader.BaseStream.Position;
            long streamPosition = reader.BaseStream.Position;

            while (streamPosition < MCNKchnkPos + MCNKsize)
            {
                reader.BaseStream.Position = streamPosition;
                ADTChunkId chunkID   = (ADTChunkId)reader.ReadInt32();
                uint       chunkSize = reader.ReadUInt32();
                streamPosition = reader.BaseStream.Position + chunkSize;
                switch (chunkID)
                {
                case ADTChunkId.MCRD:
                    ReadMCRD(reader, MCNKchunkNumber, chunkSize);     // MCNK.nDoodadRefs into the file's MDDF
                    break;

                case ADTChunkId.MCRW:
                    ReadMCRW(reader, MCNKchunkNumber, chunkSize);     // MCNK.nMapObjRefs into the file's MODF
                    break;

                default:
                    SkipUnknownChunk(reader, chunkID, chunkSize);
                    break;
                }
            }
        }
Beispiel #2
0
        // Move the stream forward upon finding unknown chunks //
        public static void SkipUnknownChunk(Stream stream, ADTChunkId chunkID, uint chunkSize)
        {
            // if (Enum.IsDefined(typeof(ADTChunkId), chunkID))
            //     Debug.Log($"Missing chunk ID : {chunkID}");

            stream.Seek(chunkSize, SeekOrigin.Current);
        }
Beispiel #3
0
        // Move the stream forward upon finding unknown chunks //
        public static void SkipUnknownChunk(BinaryReader reader, ADTChunkId chunkID, uint chunkSize)
        {
            if (Enum.IsDefined(typeof(ADTChunkId), chunkID))
            {
                Debug.Log($"Missing chunk ID : {chunkID}");
            }

            reader.BaseStream.Seek(chunkSize, SeekOrigin.Current);
        }
Beispiel #4
0
        // Terrain Texture Parser //
        private static void ParseADT_Tex(uint TexFileDataId, CASCHandler Handler, uint WdtFileDataId)
        {
            ADTTex t = new ADTTex();
            int    MCNKchunkNumber = 0;
            long   StreamPos       = 0;

            using (var stream = Handler.OpenFile(TexFileDataId))
                using (var reader = new BinaryReader(stream))
                {
                    while (StreamPos < stream.Length)
                    {
                        stream.Position = StreamPos;
                        ADTChunkId chunkID   = (ADTChunkId)reader.ReadInt32();
                        uint       chunkSize = reader.ReadUInt32();

                        StreamPos = stream.Position + chunkSize;

                        switch (chunkID)
                        {
                        case ADTChunkId.MVER:
                            t.ReadMVER(reader); // ADT file version
                            break;

                        case ADTChunkId.MAMP:
                            t.ReadMAMP(reader); // Single value - texture size = 64
                            break;

                        case ADTChunkId.MCNK:
                        {
                            t.ReadMCNKtex(reader, WdtFileDataId, MCNKchunkNumber, chunkSize);     // Texture Data - 256chunks
                            MCNKchunkNumber++;
                        }
                        break;

                        case ADTChunkId.MTXP:
                            t.ReadMTXP(reader, chunkSize);
                            break;

                        case ADTChunkId.MHID:
                            t.ReadMHID(reader, chunkSize, Handler);
                            break;

                        case ADTChunkId.MDID:
                            t.ReadMDID(reader, chunkSize, Handler);
                            break;

                        default:
                            SkipUnknownChunk(stream, chunkID, chunkSize);
                            break;
                        }
                    }
                }
        }
Beispiel #5
0
        // Terrain Mesh Parser //
        private static void ParseADT_Main(uint RootAdtFileDataId, CASCHandler Handler)  // MS version
        {
            ADTRoot r = new ADTRoot();
            int     MCNKchunkNumber = 0;
            long    StreamPos       = 0;

            using (var stream = Handler.OpenFile(RootAdtFileDataId))
                using (var reader = new BinaryReader(stream))
                {
                    while (StreamPos < stream.Length)
                    {
                        stream.Position = StreamPos;
                        ADTChunkId chunkID   = (ADTChunkId)reader.ReadInt32();
                        uint       chunkSize = reader.ReadUInt32();

                        StreamPos = stream.Position + chunkSize;

                        switch (chunkID)
                        {
                        case ADTChunkId.MVER:
                            r.ReadMVER(reader); // ADT file version
                            break;

                        case ADTChunkId.MHDR:
                            r.ReadMHDR(reader); // Offsets for specific chunks 0000 if chunks don't exist.
                            break;

                        // case ADTChunkId.MH2O:
                        //     r.ReadMH2O(reader, chunkSize); // Water Data
                        //     break;
                        case ADTChunkId.MCNK:
                        {
                            r.ReadMCNK(reader, MCNKchunkNumber, chunkSize);     // Terrain Data - 256chunks
                            MCNKchunkNumber++;
                        }
                        break;

                        case ADTChunkId.MFBO:
                            r.ReadMFBO(reader); // FlightBounds plane & Death plane
                            break;

                        default:
                            SkipUnknownChunk(stream, chunkID, chunkSize);
                            break;
                        }
                    }
                }
        }
Beispiel #6
0
        // Terrain Models Parser //
        public static void ParseADT_Obj(uint OBJFileDataId, CASCHandler Handler)
        {
            ADTObj o = new ADTObj();
            int    MCNKchunkNumber = 0;
            long   StreamPos       = 0;

            using (var stream = Handler.OpenFile(OBJFileDataId))
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    while (stream.Position < stream.Length)
                    {
                        stream.Position = StreamPos;
                        ADTChunkId chunkID   = (ADTChunkId)reader.ReadInt32();
                        uint       chunkSize = reader.ReadUInt32();

                        StreamPos = stream.Position + chunkSize;

                        switch (chunkID)
                        {
                        case ADTChunkId.MVER:
                            o.ReadMVER(reader); // ADT file version
                            break;

                        case ADTChunkId.MDDF:
                            o.ReadMDDF(reader, chunkSize); // Placement information for doodads (M2 models).
                            break;

                        case ADTChunkId.MODF:
                            o.ReadMODF(reader, chunkSize); // Placement information for WMOs.
                            break;

                        case ADTChunkId.MCNK:
                        {
                            o.ReadMCNKObj(reader, MCNKchunkNumber, chunkSize);     // 256chunks
                            MCNKchunkNumber++;
                        }
                        break;

                        default:
                            SkipUnknownChunk(stream, chunkID, chunkSize);
                            break;
                        }
                    }
                }
        }
Beispiel #7
0
        public void ReadMCNKtex(BinaryReader reader, uint WdtFileDataId, int MCNKchunkNumber, uint MCNKsize)
        {
            if (reader.BaseStream.Length == reader.BaseStream.Position)
            {
                return;
            }

            ADTTexData.TextureChunkData chunkData = new ADTTexData.TextureChunkData();

            long MCNKchnkPos    = reader.BaseStream.Position;
            long streamPosition = reader.BaseStream.Position;

            while (streamPosition < MCNKchnkPos + MCNKsize)
            {
                reader.BaseStream.Position = streamPosition;
                ADTChunkId chunkID   = (ADTChunkId)reader.ReadInt32();
                uint       chunkSize = reader.ReadUInt32();
                streamPosition = reader.BaseStream.Position + chunkSize;
                switch (chunkID)
                {
                case ADTChunkId.MCLY:
                    ReadMCLY(reader, chunkData, chunkSize);     // texture layers
                    break;

                case ADTChunkId.MCSH:
                    ReadMCSH(reader, chunkData);     // static shadow maps
                    break;

                case ADTChunkId.MCAL:
                    ReadMCAL(reader, WdtFileDataId, chunkData);     // alpha layers
                    break;

                case ADTChunkId.MCMT:
                    ReadMCMT(reader);
                    break;

                default:
                    SkipUnknownChunk(reader, chunkID, chunkSize);
                    break;
                }
            }
            ADTTexData.textureBlockData.textureChunksData.Add(chunkData);
        }
Beispiel #8
0
        public void ReadMCNK(BinaryReader reader, int MCNKchunkNumber, uint MCNKsize)
        {
            Flags f = new Flags();

            ADTRootData.MeshChunkData chunkData = new ADTRootData.MeshChunkData();
            long MCNKchnkPos = reader.BaseStream.Position;

            // <Header> - 128 bytes
            chunkData.flags = f.ReadMCNKflags(reader);

            chunkData.IndexX  = reader.ReadUInt32();
            chunkData.IndexY  = reader.ReadUInt32();
            chunkData.nLayers = reader.ReadUInt32();                                    // maximum 4
            uint nDoodadRefs = reader.ReadUInt32();

            chunkData.holes_high_res = reader.ReadUInt64();                             // only used with flags.high_res_holes
            uint ofsLayer    = reader.ReadUInt32();
            uint ofsRefs     = reader.ReadUInt32();
            uint ofsAlpha    = reader.ReadUInt32();
            uint sizeAlpha   = reader.ReadUInt32();
            uint ofsShadow   = reader.ReadUInt32();                                     // only with flags.has_mcsh
            uint sizeShadow  = reader.ReadUInt32();
            uint areaid      = reader.ReadUInt32();                                     // in alpha: both zone id and sub zone id, as uint16s.
            uint nMapObjRefs = reader.ReadUInt32();

            chunkData.holes_low_res = reader.ReadUInt16();
            ushort unknown_but_used = reader.ReadUInt16();                              // in alpha: padding

            byte[] ReallyLowQualityTextureingMap = new byte[16];                        // uint2_t[8][8] "predTex", It is used to determine which detail doodads to show. Values are an array of two bit
            for (int b = 0; b < 16; b++)
            {
                ReallyLowQualityTextureingMap[b] = reader.ReadByte();
            }
            // unsigned integers, naming the layer.
            ulong noEffectDoodad = reader.ReadUInt64();                                 // WoD: may be an explicit MCDD chunk
            int   ofsSndEmitters = reader.ReadInt32();
            int   nSndEmitters   = reader.ReadInt32();                                  // will be set to 0 in the client if ofsSndEmitters doesn't point to MCSE!
            int   ofsLiquid      = reader.ReadInt32();
            int   sizeLiquid     = reader.ReadInt32();                                  // 8 when not used; only read if >8.

            // in alpha, remainder is padding but unused.
            chunkData.MeshPosition = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            int ofsMCCV = reader.ReadInt32();                                           // only with flags.has_mccv, had uint32_t textureId; in ObscuR's structure.
            int ofsMCLV = reader.ReadInt32();                                           // introduced in Cataclysm
            int unused  = reader.ReadInt32();                                           // currently unused

            // </header>

            if (!chunkData.flags.has_mccv)
            {
                FillMCCV(chunkData);                                                    // fill vertex shading with 127...
            }
            long streamPosition = reader.BaseStream.Position;

            while (streamPosition < MCNKchnkPos + MCNKsize)
            {
                reader.BaseStream.Position = streamPosition;
                ADTChunkId chunkId   = (ADTChunkId)reader.ReadInt32();
                uint       chunkSize = reader.ReadUInt32();
                streamPosition = reader.BaseStream.Position + chunkSize;
                switch (chunkId)
                {
                case ADTChunkId.MCVT:
                    ReadMCVT(reader, chunkData);     // vertex heights
                    break;

                case ADTChunkId.MCLV:
                    ReadMCLV(reader, chunkData);     // chunk lighting
                    break;

                case ADTChunkId.MCCV:
                    ReadMCCV(reader, chunkData);     // vertex shading
                    break;

                case ADTChunkId.MCNR:
                    ReadMCNR(reader, chunkData);     // normals
                    break;

                case ADTChunkId.MCSE:
                    ReadMCSE(reader, chunkData, chunkSize);     // sound emitters
                    break;

                case ADTChunkId.MCBB:
                    ReadMCBB(reader, chunkData, chunkSize);
                    break;

                case ADTChunkId.MCDD:
                    ReadMCDD(reader, chunkData, chunkSize);
                    break;

                default:
                    SkipUnknownChunk(reader, chunkId, chunkSize);
                    break;
                }
            }
            ADTRootData.meshBlockData.meshChunksData.Add(chunkData);
        }