Example #1
0
        public static void ReadTXID(BinaryReader reader, M2Model model, uint chunkSize)
        {
            var txidSize = chunkSize / 4;

            for (var i = 0; i < txidSize; ++i)
            {
                var fileDataId = reader.ReadUInt32();

                if (!TextureFileIds.Contains(fileDataId))
                {
                    var m2Texture   = new M2Texture();
                    var textureData = new TextureData();

                    using (var blpStream = CASC.OpenFile(fileDataId))
                    {
                        var blp     = new BLP();
                        var blpData = blp.GetUncompressed(blpStream);
                        var blpInfo = blp.GetInfo();

                        textureData.HasMipmaps    = blpInfo.hasMipmaps;
                        textureData.Width         = blpInfo.width;
                        textureData.Height        = blpInfo.height;
                        textureData.RawData       = blpData;
                        textureData.TextureFormat = blpInfo.textureFormat;

                        m2Texture.TextureData = textureData;
                        m2Texture.FileDataId  = fileDataId;

                        TextureFileIds.Add(fileDataId);
                    }

                    model.Textures.Add(m2Texture);
                }
            }
        }
Example #2
0
        public static void ReadM2(uint fileDataId, M2Model model)
        {
            var stream = CASC.OpenFile(fileDataId);

            if (stream == null)
            {
                return;
            }

            using (var reader = new BinaryReader(stream))
            {
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    var chunkId   = (Chunks)reader.ReadUInt32().Flip();
                    var chunkSize = reader.ReadUInt32();

                    switch (chunkId)
                    {
                    case Chunks.MD21:
                        ReadMD20(reader, model);
                        reader.BaseStream.Position = 8 + chunkSize;
                        break;

                    case Chunks.SFID:
                        ReadSFID(reader, chunkSize);
                        break;

                    case Chunks.TXID:
                        ReadTXID(reader, model, chunkSize);
                        break;

                    default:
                        reader.Skip(chunkSize);
                        Debug.Log($"Skipping {chunkId} (0x{chunkId:X}) with size: {chunkSize}..");
                        break;
                    }
                }
            }
        }
Example #3
0
        public static void ReadMD20(BinaryReader reader, M2Model model)
        {
            var magic = reader.ReadUInt32().Flip();

            if (magic != (uint)Chunks.MD20)
            {
                throw new Exception($"{model.FileDataId} has invalid MD20 magic! {magic:X}");
            }

            var version = reader.ReadUInt32();

            if (version < 272)
            {
                throw new Exception($"{model.FileDataId} has invalid version! {version}");
            }

            // Get the model name
            var name   = reader.ReadM2Array();
            var oldPos = reader.BaseStream.Position;

            reader.BaseStream.Position = name.Offset + 8;
            model.ModelName            = new string(reader.ReadChars((int)name.Size)).Replace("\0", "");
            reader.BaseStream.Position = oldPos;

            var flags                   = reader.ReadUInt32();
            var globalLoops             = reader.ReadM2Array();
            var sequences               = reader.ReadM2Array();
            var sequencesLookups        = reader.ReadM2Array();
            var bones                   = reader.ReadM2Array();
            var keyBoneLookup           = reader.ReadM2Array();
            var vertices                = reader.ReadM2Array();
            var skinCount               = reader.ReadInt32();
            var colors                  = reader.ReadM2Array();
            var textures                = reader.ReadM2Array();
            var textureWeights          = reader.ReadM2Array();
            var textureTransforms       = reader.ReadM2Array();
            var replacableTextureLookup = reader.ReadM2Array();
            var materials               = reader.ReadM2Array();
            var boneLookupTable         = reader.ReadM2Array();
            var textureLookupTable      = reader.ReadM2Array();

            reader.BaseStream.Position = 8 + vertices.Offset;
            for (var i = 0; i < vertices.Size; ++i)
            {
                var position = new Vector3
                {
                    x = reader.ReadSingle() / WorldConstants.WorldScale,
                    y = reader.ReadSingle() / WorldConstants.WorldScale,
                    z = reader.ReadSingle() / WorldConstants.WorldScale,
                };

                model.MeshData.Vertices.Add(new Vector3(-position.x, position.z, -position.y));
                model.MeshData.BoneWeights.Add(new []
                {
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f
                });
                model.MeshData.BoneIndices.Add(new int[] { reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte() });

                var normalPosition = new Vector3
                {
                    x = reader.ReadSingle() * WorldConstants.WorldScale,
                    y = reader.ReadSingle() * WorldConstants.WorldScale,
                    z = reader.ReadSingle() * WorldConstants.WorldScale
                };
                model.MeshData.Normals.Add(new Vector3(-normalPosition.x, normalPosition.z, -normalPosition.y));
                model.MeshData.TexCoords.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle()));
                model.MeshData.TexCoords2.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle()));
            }

            reader.BaseStream.Position = 8 + textureLookupTable.Offset;
            for (var i = 0; i < textureLookupTable.Size; ++i)
            {
                model.TextureLookupTable.Add(reader.ReadUInt16());
            }
        }