Exemplo n.º 1
0
        public ValveTextureFile(Stream stream, bool onlyHeader = false)
        {
            Header = LumpReader <TextureHeader> .ReadSingleFromStream(stream);

            var readCount = Marshal.SizeOf <TextureHeader>();

            ZSliceCount = 1;

            if (Header.MajorVersion > 7 || Header.MajorVersion == 7 && Header.MinorVersion >= 2)
            {
                ZSliceCount = stream.ReadByte() | (stream.ReadByte() << 8);
                readCount  += 2;
            }

            MipmapCount = Header.MipMapCount;
            FrameCount  = Header.Frames;
            FaceCount   = (Header.Flags & TextureFlags.ENVMAP) != 0 ? 6 : 1;

            if (onlyHeader)
            {
                return;
            }

            var thumbSize = GetImageDataSize(Header.LowResWidth, Header.LowResHeight, 1, 1, Header.LowResFormat);

            VtfResource[] resources = null;
            var           buffer    = new byte[8];

            if (Header.MajorVersion > 7 || Header.MajorVersion == 7 && Header.MinorVersion >= 3)
            {
                Skip(stream, 3);
                readCount += 3;

                stream.Read(buffer, 0, 4);
                readCount += 4;

                var resourceCount = BitConverter.ToInt32(buffer, 0);

                // Probably padding?
                stream.Read(buffer, 0, 8);
                readCount += 8;

                resources = LumpReader <VtfResource> .ReadLumpFromStream(stream, resourceCount);

                readCount += Marshal.SizeOf <VtfResource>() * resourceCount;
            }

            if (resources == null || resources.Length == 0)
            {
                resources    = new VtfResource[2];
                resources[0] = new VtfResource(VtfResourceType.LowResImage, Header.HeaderSize);
                resources[1] = new VtfResource(VtfResourceType.HiResImage, Header.HeaderSize + (uint)thumbSize);
            }

            Skip(stream, Header.HeaderSize - readCount);
            readCount = (int)Header.HeaderSize;

            switch (Header.HiResFormat)
            {
            case TextureFormat.DXT1:
            case TextureFormat.DXT3:
            case TextureFormat.DXT5:
            case TextureFormat.I8:
            case TextureFormat.IA88:
            case TextureFormat.BGR888:
            case TextureFormat.RGB888:
            case TextureFormat.RGB888_BLUESCREEN:
            case TextureFormat.ABGR8888:
            case TextureFormat.BGRA8888:
            case TextureFormat.RGBA8888:
            case TextureFormat.RGBA16161616F:
                break;

            default:
                throw new NotImplementedException($"VTF format: {Header.HiResFormat}");
            }

            _imageData = new ImageData[MipmapCount * FrameCount * FaceCount * ZSliceCount];

            var offset = 0;

            for (var mipmap = MipmapCount - 1; mipmap >= 0; --mipmap)
            {
                var length = GetImageDataSize(Header.Width >> mipmap, Header.Height >> mipmap, 1, 1, Header.HiResFormat);

                for (var frame = 0; frame < FrameCount; ++frame)
                {
                    for (var face = 0; face < FaceCount; ++face)
                    {
                        for (var zslice = 0; zslice < ZSliceCount; ++zslice)
                        {
                            var index = GetImageDataIndex(mipmap, frame, face, zslice);
                            _imageData[index] = new ImageData(offset, length);
                            offset           += length;
                        }
                    }
                }
            }

            var hiResEntry = resources.First(x => x.Type == VtfResourceType.HiResImage);

            Skip(stream, hiResEntry.Data - readCount);

            _hiResPixelData = new byte[offset];
            stream.Read(_hiResPixelData, 0, offset);
        }
Exemplo n.º 2
0
        public StudioModelFile(Stream stream)
        {
            _header = LumpReader <Header> .ReadSingleFromStream(stream);

            if (_header.Id != 0x54534449)
            {
                throw new Exception("Not a MDL file.");
            }

            _materials               = new StudioTexture[_header.NumTextures];
            _materialNames           = new string[_header.NumTextures];
            _cachedFullMaterialPaths = new string[_header.NumTextures];

            stream.Seek(_header.TextureIndex, SeekOrigin.Begin);
            LumpReader <StudioTexture> .ReadLumpFromStream(stream, _header.NumTextures, (index, tex) =>
            {
                _materials[index] = tex;

                stream.Seek(tex.NameIndex, SeekOrigin.Current);
                _materialNames[index] = ReadNullTerminatedString(stream).Replace('\\', '/') + ".vmt";
            });

            _materialPaths = new string[_header.NumCdTextures];

            stream.Seek(_header.CdTextureIndex, SeekOrigin.Begin);
            LumpReader <int> .ReadLumpFromStream(stream, _header.NumCdTextures, (index, cdTex) =>
            {
                stream.Seek(cdTex, SeekOrigin.Begin);
                _materialPaths[index] = ReadNullTerminatedString(stream).Replace('\\', '/');
            });

            _bodyParts     = new StudioBodyPart[_header.NumBodyParts];
            _bodyPartNames = new string[_header.NumBodyParts];

            var modelList = new List <StudioModel>();
            var meshList  = new List <StudioMesh>();

            stream.Seek(_header.BodyPartIndex, SeekOrigin.Begin);
            LumpReader <StudioBodyPart> .ReadLumpFromStream(stream, _header.NumBodyParts, (partIndex, part) =>
            {
                var partPos = stream.Position;

                stream.Seek(partPos + part.NameIndex, SeekOrigin.Begin);
                _bodyPartNames[partIndex] = ReadNullTerminatedString(stream);

                stream.Seek(partPos + part.ModelIndex, SeekOrigin.Begin);

                // Now indexes into array of models
                part.ModelIndex = modelList.Count;

                LumpReader <StudioModel> .ReadLumpFromStream(stream, part.NumModels, (modelIndex, model) =>
                {
                    var modelPos = stream.Position;

                    stream.Seek(modelPos + model.MeshIndex, SeekOrigin.Begin);

                    model.MeshIndex = meshList.Count;
                    LumpReader <StudioMesh> .ReadLumpFromStream(stream, model.NumMeshes, (meshIndex, mesh) =>
                    {
                        mesh.ModelIndex = modelIndex;
                        meshList.Add(mesh);
                    });

                    modelList.Add(model);
                });

                _bodyParts[partIndex] = part;
            });

            _models = modelList.ToArray();
            _meshes = meshList.ToArray();
        }