예제 #1
0
        private void ReadPmg(BinaryReader r)
        {
            var version = r.ReadByte();
            if (version != PmgVersion)
            {
                throw new NotSupportedException($"pmg version {version} is not supported.");
            }

            var signature = ReadPmgSignature(r);
            if (signature != PmgSignature)
            {
                throw new InvalidDataException($"Not a pmg file? Expected '{PmgSignature}', got '{signature}'");
            }

            var pieceCount = r.ReadUInt32();
            var partCount = r.ReadUInt32();
            var boneCount = r.ReadUInt32();
            var weightWidth = r.ReadInt32();
            var locatorCount = r.ReadUInt32();
            var skeletonHash = r.ReadUInt64();

            BoundingBoxCenter = r.ReadVector3();
            BoundingBoxDiagonalSize = r.ReadSingle();
            BoundingBox = new AxisAlignedBox();
            BoundingBox.Deserialize(r);

            var skeletonOffset = r.ReadUInt32();
            var partsOffset = r.ReadUInt32();
            var locatorsOffset = r.ReadUInt32();
            var piecesOffset = r.ReadUInt32();

            var stringPoolOffset = r.ReadUInt32();
            var stringPoolSize = r.ReadUInt32();
            var vertexPoolOffset = r.ReadUInt32();
            var vertexPoolSize = r.ReadUInt32();
            var indexPoolOffset = r.ReadUInt32();
            var indexPoolSize = r.ReadUInt32();

            Skeleton = r.ReadObjectList<Bone>(boneCount);

            // jump ahead and read all locators & pieces first
            r.BaseStream.Position = locatorsOffset;
            var locators = r.ReadObjectList<Locator>(locatorCount);
            var pieces = r.ReadObjectList<Piece>(pieceCount);

            // then return to parts and assign the locators and pieces right away
            r.BaseStream.Position = partsOffset;
            for (int i = 0; i < partCount; i++)
            {
                var part = new Part();
                part.Name = r.ReadToken();

                var piecesCount = r.ReadUInt32();
                var piecesIndex = r.ReadUInt32();
                part.Pieces = pieces.GetRange((int)piecesIndex, (int)piecesCount);

                var locatorsCount = r.ReadUInt32();
                var locatorsIndex = r.ReadUInt32();
                part.Locators = locators.GetRange((int)locatorsIndex, (int)locatorsCount);

                Parts.Add(part);
            }

            // TODO: what is this?
            r.BaseStream.Position = stringPoolOffset;
            if (stringPoolSize > 0)
            {
                r.BaseStream.Position = stringPoolOffset;
                var stringsBytes = r.ReadBytes((int)stringPoolSize);
                strings = StringUtils.CStringBytesToList(stringsBytes);
            }
        }
예제 #2
0
        /// <summary>
        /// ! BE ADVISED ! <br />
        /// I usually prefer deserialization to be forward-only,
        /// but with this particular file structure, the reader
        /// has to jump back and forth a few times.
        /// </summary>
        /// <param name="r"></param>
        public void Deserialize(BinaryReader r)
        {
            var edges        = r.ReadUInt32();
            var verts        = r.ReadUInt32();
            var texCoordMask = r.ReadUInt32(); // what is this even used for?

            TextureCoordinateWidth = r.ReadInt32();
            Material                = r.ReadUInt32();
            BoundingBoxCenter       = r.ReadVector3();
            BoundingBoxDiagonalSize = r.ReadSingle();
            BoundingBox             = new AxisAlignedBox();
            BoundingBox.Deserialize(r);

            // TODO: Why does this even point to when the
            // model has no bones??
            // used values are 36, 44 and 52?
            skeletonOffset_temp = r.ReadInt32();
            var vertPositionOffset   = r.ReadInt32();
            var vertNormalOffset     = r.ReadInt32();
            var vertTexcoordOffset   = r.ReadInt32();
            var vertColorOffset      = r.ReadInt32();
            var vertColor2Offset     = r.ReadInt32();
            var vertTangentOffset    = r.ReadInt32();
            var vertBoneIndexOffset  = r.ReadInt32();
            var vertBoneWeightOffset = r.ReadInt32();
            var indexOffset          = r.ReadInt32();

            UseTangents           = (vertTangentOffset != Unused);
            UseSecondaryColor     = (vertColor2Offset != Unused);
            UseTextureCoordinates = (vertTexcoordOffset != Unused);
            UseBoneIndexes        = (vertBoneIndexOffset != Unused);
            UseBoneWeights        = (vertBoneWeightOffset != Unused);

            var prevStreamPosition = r.BaseStream.Position;

            r.BaseStream.Position = vertPositionOffset;

            for (int i = 0; i < verts; i++)
            {
                var vertex = new Vertex(r.ReadVector3(), r.ReadVector3());

                if (vertTangentOffset != Unused)
                {
                    vertex.Tangent = r.ReadVector4();
                }
                vertex.Color = r.ReadColor();
                if (vertColor2Offset != Unused)
                {
                    vertex.SecondaryColor = r.ReadColor();
                }
                if (vertTexcoordOffset != Unused)
                {
                    vertex.TextureCoordinates = r.ReadObjectList <Vector2>((uint)TextureCoordinateWidth);
                }
                if (vertBoneIndexOffset != Unused)
                {
                    vertex.BoneIndexes = r.ReadBytes(4);
                }
                if (vertBoneWeightOffset != Unused)
                {
                    vertex.BoneWeights = r.ReadBytes(4);
                }

                Vertices.Add(vertex);
            }

            r.BaseStream.Position = indexOffset;
            for (int i = 0; i < edges / 3; i++)
            {
                var t = new Triangle();
                t.Deserialize(r);
                Triangles.Add(t);
            }

            r.BaseStream.Position = prevStreamPosition;
        }