示例#1
0
        private void ReadPmd(BinaryReader r)
        {
            // specifically check if the user passed in a 
            // pmg file by accident
            r.BaseStream.Position = 1;
            var pmgSigCheck = ReadPmgSignature(r);
            if(pmgSigCheck == PmgSignature)
            {
                throw new ArgumentException("Pass a pmd file, not a pmg file.");
            }
            r.BaseStream.Position = 0;

            var version = r.ReadUInt32();
            if (version != PmdVersion)
            {
                throw new NotSupportedException($"pmd version {version} is not supported.");
            }

            var materialCount = r.ReadUInt32();
            var lookCount = r.ReadUInt32();
            var pieceCount = r.ReadUInt32();
            var variantCount = r.ReadUInt32();
            var partCount = r.ReadUInt32();
            var attribsCount = r.ReadUInt32();

            var attribsValuesSize = r.ReadUInt32();
            var materialBlockSize = r.ReadUInt32();

            var lookOffset = r.ReadUInt32();
            var variantOffset = r.ReadUInt32();
            var partAttribsOffset = r.ReadUInt32();
            var attribsValuesOffset = r.ReadUInt32();
            var attribsHeaderOffset = r.ReadUInt32();
            var materialOffsetsOffset = r.ReadUInt32();
            var materialDataOffset = r.ReadUInt32();

            // look names
            Looks.Clear();
            for (int i = 0; i < lookCount; i++)
            {
                Looks.Add(new Look(r.ReadToken()));
            }

            // variant names
            Variants.Clear();
            for (int i = 0; i < variantCount; i++)
            {
                Variants.Add(new Variant(r.ReadToken()));
            }

            // "partAttribs"
            // TODO: what is this?
            for (int i = 0; i < partCount; i++)
            {
                var from = r.ReadInt32();
                var to = r.ReadInt32();
            }

            // attribs header
            // each variant has the same attribs
            for (int i = 0; i < attribsCount; i++)
            {
                var name = r.ReadToken();
                var type = r.ReadInt32();
                var offset = r.ReadInt32();
                foreach (var variant in Variants)
                {
                    var attrib = new PartAttribute();
                    variant.Attributes.Add(attrib);
                    attrib.Tag = name;
                    attrib.Type = type;
                }
            }

            // attribs values
            // TODO: Find out if there are any files where a part has 
            // more than one attrib or if "visible" is actually the only attrib
            // that exists
            for (int i = 0; i < variantCount; i++)
            {
                for (int j = 0; j < attribsCount; j++)
                {
                    Variants[i].Attributes[j].Value = r.ReadUInt32();
                }
            }

            // material offsets; I think we can get away with ignoring this?
            var materialsOffset = new List<uint>();
            for (int i = 0; i < lookCount * materialCount; i++)
            {
                materialsOffset.Add(r.ReadUInt32());
            }

            // look material paths
            var materialsData = r.ReadBytes((int)materialBlockSize);
            var materials = StringUtils.CStringBytesToList(materialsData);
            for(int i = 0; i < Looks.Count; i++)
            {
                Looks[i].Materials.AddRange(
                    materials.GetRange(i * (int)materialCount, (int)materialCount)
                    );
            }       
        }