public static DestinyItemArrangement Load(BinaryReader reader)
    {
        var arrangement = new DestinyItemArrangement();

        // read bobs
        int bobCount = reader.ReadInt32();

        arrangement.Bobs = Enumerable.Range(0, bobCount)
                           .Select(i => DestinyItemBob.Load(reader)).ToList();

        // read arrangement ID
        arrangement.Id = reader.ReadString();

        // read textures
        int plateSetCount = reader.ReadInt32();

        if (plateSetCount > 0)
        {
            arrangement.DiffuseTexture   = reader.ReadBytes(reader.ReadInt32());
            arrangement.NormalTexture    = reader.ReadBytes(reader.ReadInt32());
            arrangement.GearstackTexture = reader.ReadBytes(reader.ReadInt32());
        }

        return(arrangement);
    }
    public static DestinyItemBob Load(BinaryReader reader)
    {
        var bob = new DestinyItemBob();

        // read texture coordinate scale and offset
        var textureScale  = new Vector2(reader.ReadSingle(), reader.ReadSingle());
        var textureOffset = new Vector2(reader.ReadSingle(), reader.ReadSingle());

        // read bob header
        int bitCount = reader.ReadInt32();

        if (bitCount == 0)
        {
            return(bob);
        }

        bob.IsTriangleList = reader.ReadInt32() == 3;
        int vertexCount = reader.ReadInt32();

        // read index buffer
        int indexCount = reader.ReadInt32();

        bob.Indices = Enumerable.Range(0, indexCount)
                      .Select(i => (int)reader.ReadInt16()).ToArray();

        // read vertices
        int vertexBufferCount = reader.ReadInt32();

        bob.Vertices = Enumerable.Range(0, vertexCount)
                       .Select(i => new DestinyItemVertex()).ToArray();
        for (int i = 0; i < vertexBufferCount; i++)
        {
            int elementCount = reader.ReadInt32();
            var elements     = Enumerable.Range(0, elementCount).Select(
                e => DestinyItemStreamElement.Load(reader)).ToList();
            foreach (var vertex in bob.Vertices)
            {
                foreach (var element in elements)
                {
                    element.ModifyVertex(vertex, element.ReadValue(reader));
                }
            }
        }

        // post-process vertices
        foreach (var vertex in bob.Vertices)
        {
            var normalizedUV  = (vertex.UV * 2f) - Vector2.one;
            var transformedUV = (normalizedUV * textureScale) + textureOffset;
            vertex.SetUV(new Vector2(transformedUV.x, 1f - transformedUV.y));
        }

        // read bits
        bob.Bits = Enumerable.Range(0, bitCount)
                   .Select(i => DestinyItemBit.Load(reader)).ToList();

        return(bob);
    }