Beispiel #1
0
        public bool Deserialize(BinaryStream stream, AssetManager assetManager)
        {
            // Header
            string magic = stream.ReadString(3);

            Assert.AreEqual(MAGIC, magic, "Chunk header mismatch!");

            int lodLevel = Convert.ToInt32(stream.ReadString(1));

            Assert.AreNotEqual(0, lodLevel, "Use the CNK0 serializer for LOD0 terrain chunks.");

            Version = stream.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)Version))
            {
                Debug.LogWarning("Could not decode chunk " + Name + ". Unknown cnk version " + Version);
                return(false);
            }

            ChunkType = (ChunkType)Version;

            DecompressedSize = stream.ReadUInt32();
            CompressedSize   = stream.ReadUInt32();

            // Read the compressed buffer.
            stream.ReadBytes(CompressedBuffer, (int)CompressedSize);

            // Decompression
            // Make sure our buffer is large enough.
            DecompressedBuffer.PrepareBuffer((int)DecompressedSize);

            // Perform decompression using Lzham.
            InflateReturnCode result = LzhamInterop.DecompressForgelightData(CompressedBuffer.Data, CompressedSize, DecompressedBuffer.Data, DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid, or something went wrong.
                return(false);
            }

            using (MemoryStream decompressedStream = new MemoryStream(DecompressedBuffer.Data, 0, (int)DecompressedSize))
            {
                //Textures
                uint textureCount = decompressedStream.ReadUInt32();
                Textures.PrepareBuffer((int)textureCount);

                for (int i = 0; i < textureCount; i++)
                {
                    Texture texture = Textures[i];

                    if (texture == null)
                    {
                        texture     = new Texture();
                        Textures[i] = texture;
                    }

                    uint colorNxMapSize = decompressedStream.ReadUInt32();
                    texture.ColorNXMap = assetManager.CreateAsset <Dds>(decompressedStream.ReadBytes((int)colorNxMapSize));

                    uint specNyMapSize = decompressedStream.ReadUInt32();
                    texture.SpecNyMap = assetManager.CreateAsset <Dds>(decompressedStream.ReadBytes((int)specNyMapSize));

                    uint extraData1Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData1, (int)extraData1Size);

                    uint extraData2Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData2, (int)extraData2Size);

                    uint extraData3Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData3, (int)extraData3Size);

                    uint extraData4Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData4, (int)extraData4Size);
                }

                //Verts Per Side
                VertsPerSide = decompressedStream.ReadUInt32();

                //Height Maps
                uint heightMapCount = decompressedStream.ReadUInt32();

                int n = (int)(heightMapCount / 4);

                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        Dictionary <int, HeightMap> entry;

                        if (!HeightMaps.ContainsKey(i))
                        {
                            entry         = new Dictionary <int, HeightMap>();
                            HeightMaps[i] = entry;
                        }

                        else
                        {
                            entry = HeightMaps[i];
                        }

                        HeightMap heightMapData = new HeightMap();
                        heightMapData.Val1 = decompressedStream.ReadInt16();
                        heightMapData.Val2 = decompressedStream.Read1Byte();
                        heightMapData.Val3 = decompressedStream.Read1Byte();

                        entry[j] = heightMapData;
                    }
                }

                //Indices
                uint indexCount = decompressedStream.ReadUInt32();

                for (int i = 0; i < indexCount; i++)
                {
                    Indices.Add(decompressedStream.ReadUInt16());
                }

                //Verts
                uint vertCount = decompressedStream.ReadUInt32();

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = decompressedStream.ReadInt16();
                    vertex.Y          = decompressedStream.ReadInt16();
                    vertex.HeightFar  = decompressedStream.ReadInt16();
                    vertex.HeightNear = decompressedStream.ReadInt16();
                    vertex.Color      = decompressedStream.ReadUInt32();

                    Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = decompressedStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = decompressedStream.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = decompressedStream.ReadUInt32();
                        renderBatch.IndexCount   = decompressedStream.ReadUInt32();
                        renderBatch.VertexOffset = decompressedStream.ReadUInt32();
                        renderBatch.VertexCount  = decompressedStream.ReadUInt32();

                        RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = decompressedStream.ReadBytes(320).ToList();

                        OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        UnknownShorts1.Add(decompressedStream.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        UnknownVectors1.Add(new Vector3(decompressedStream.ReadSingle(), decompressedStream.ReadSingle(),
                                                        decompressedStream.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = decompressedStream.ReadUInt32();

                    if (tileOccluderCount > 16)
                    {
                        throw new ArgumentOutOfRangeException();
                    }

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = decompressedStream.ReadBytes(64).ToList();

                        TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (Exception)
                {
                    // Some of these may have been populated from the "try".
                    RenderBatches.Clear();
                    OptimizedDraws.Clear();
                    UnknownShorts1.Clear();
                    UnknownVectors1.Clear();
                    TileOccluderInfos.Clear();

                    decompressedStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = decompressedStream.ReadUInt32();
                        renderBatch.IndexCount   = decompressedStream.ReadUInt32();
                        renderBatch.VertexOffset = decompressedStream.ReadUInt32();
                        renderBatch.VertexCount  = decompressedStream.ReadUInt32();

                        RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = decompressedStream.ReadBytes(320).ToList();

                        OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        UnknownShorts1.Add(decompressedStream.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        UnknownVectors1.Add(new Vector3(decompressedStream.ReadSingle(), decompressedStream.ReadSingle(),
                                                        decompressedStream.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = decompressedStream.ReadUInt32();

                    if (tileOccluderCount > 16)
                    {
                        return(false);
                    }

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = decompressedStream.ReadBytes(64).ToList();

                        TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(true);
        }
        public bool InitializeFromStream(string name, string displayName, MemoryStream stream)
        {
            using (BinaryReader binaryReader = new BinaryReader(stream))
            {
                Name        = name;
                DisplayName = displayName;

                //Header
                byte[] magic = binaryReader.ReadBytes(4);

                if (magic[0] != 'C' ||
                    magic[1] != 'N' ||
                    magic[2] != 'K' /* ||
                                     * magic[3] != '1'*/)
                {
                    return(false);
                }

                Version = binaryReader.ReadUInt32();

                if (!Enum.IsDefined(typeof(ChunkType), (int)Version))
                {
                    Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + Version);
                    return(false);
                }

                ChunkType = (ChunkType)Version;

                DecompressedSize = binaryReader.ReadUInt32();
                CompressedSize   = binaryReader.ReadUInt32();

                // Decompression
                // Make sure our buffers are large enough.
                if (CompressedBuffer.Length < CompressedSize)
                {
                    Array.Resize(ref CompressedBuffer, (int)CompressedSize);
                }

                if (DecompressedBuffer.Length < DecompressedSize)
                {
                    Array.Resize(ref DecompressedBuffer, (int)DecompressedSize);
                }

                // Read the compressed buffer.
                binaryReader.Read(CompressedBuffer, 0, (int)CompressedSize);

                // Perform decompression using Lzham.
                InflateReturnCode result = LzhamInterop.DecompressForgelightData(CompressedBuffer, CompressedSize, DecompressedBuffer, DecompressedSize);

                if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
                {
                    //This chunk is invalid, or something went wrong.
                    return(false);
                }
            }

            using (MemoryStream decompressedStream = new MemoryStream(DecompressedBuffer, 0, (int)DecompressedSize))
            {
                using (BinaryReader binaryReader = new BinaryReader(decompressedStream))
                {
                    //Textures
                    uint textureCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < textureCount; i++)
                    {
                        Texture texture = new Texture();

                        uint colorNxMapSize = binaryReader.ReadUInt32();
                        if (colorNxMapSize > 0)
                        {
                            texture.ColorNXMap = binaryReader.ReadBytes((int)colorNxMapSize).ToList();
                        }

                        uint specNyMapSize = binaryReader.ReadUInt32();
                        if (specNyMapSize > 0)
                        {
                            texture.SpecNyMap = binaryReader.ReadBytes((int)specNyMapSize).ToList();
                        }

                        uint extraData1Size = binaryReader.ReadUInt32();
                        if (extraData1Size > 0)
                        {
                            texture.ExtraData1 = binaryReader.ReadBytes((int)extraData1Size).ToList();
                        }

                        uint extraData2Size = binaryReader.ReadUInt32();
                        if (extraData2Size > 0)
                        {
                            texture.ExtraData2 = binaryReader.ReadBytes((int)extraData2Size).ToList();
                        }

                        uint extraData3Size = binaryReader.ReadUInt32();
                        if (extraData3Size > 0)
                        {
                            texture.ExtraData3 = binaryReader.ReadBytes((int)extraData3Size).ToList();
                        }

                        uint extraData4Size = binaryReader.ReadUInt32();
                        if (extraData4Size > 0)
                        {
                            texture.ExtraData4 = binaryReader.ReadBytes((int)extraData4Size).ToList();
                        }

                        Textures.Add(texture);
                    }

                    //Verts Per Side
                    VertsPerSide = binaryReader.ReadUInt32();

                    //Height Maps
                    uint heightMapCount = binaryReader.ReadUInt32();

                    int n = (int)(heightMapCount / 4);

                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            Dictionary <int, HeightMap> entry;

                            if (!HeightMaps.ContainsKey(i))
                            {
                                entry         = new Dictionary <int, HeightMap>();
                                HeightMaps[i] = entry;
                            }

                            else
                            {
                                entry = HeightMaps[i];
                            }

                            HeightMap heightMapData = new HeightMap();
                            heightMapData.Val1 = binaryReader.ReadInt16();
                            heightMapData.Val2 = binaryReader.ReadByte();
                            heightMapData.Val3 = binaryReader.ReadByte();

                            entry[j] = heightMapData;
                        }
                    }

                    //Indices
                    uint indexCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < indexCount; i++)
                    {
                        Indices.Add(binaryReader.ReadUInt16());
                    }

                    //Verts
                    uint vertCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < vertCount; i++)
                    {
                        Vertex vertex = new Vertex();

                        vertex.X          = binaryReader.ReadInt16();
                        vertex.Y          = binaryReader.ReadInt16();
                        vertex.HeightFar  = binaryReader.ReadInt16();
                        vertex.HeightNear = binaryReader.ReadInt16();
                        vertex.Color      = binaryReader.ReadUInt32();

                        Vertices.Add(vertex);
                    }

                    //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                    long offset = binaryReader.BaseStream.Position;
                    try
                    {
                        //Render Batches
                        uint renderBatchCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < renderBatchCount; i++)
                        {
                            RenderBatch renderBatch = new RenderBatch();

                            if (ChunkType == ChunkType.H1Z1_Planetside2V2)
                            {
                                renderBatch.Unknown = binaryReader.ReadUInt32();
                            }

                            renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                            renderBatch.IndexCount   = binaryReader.ReadUInt32();
                            renderBatch.VertexOffset = binaryReader.ReadUInt32();
                            renderBatch.VertexCount  = binaryReader.ReadUInt32();

                            RenderBatches.Add(renderBatch);
                        }

                        //Optimized Draw
                        uint optimizedDrawCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < optimizedDrawCount; i++)
                        {
                            OptimizedDraw optimizedDraw = new OptimizedDraw();
                            optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                            OptimizedDraws.Add(optimizedDraw);
                        }

                        //Unknown Data
                        uint unknownShort1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownShort1Count; i++)
                        {
                            UnknownShorts1.Add(binaryReader.ReadUInt16());
                        }

                        //Unknown Data
                        uint unknownVectors1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownVectors1Count; i++)
                        {
                            UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(),
                                                            binaryReader.ReadSingle()));
                        }

                        //Tile Occluder Info
                        uint tileOccluderCount = binaryReader.ReadUInt32();

                        if (tileOccluderCount > 16)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        for (int i = 0; i < tileOccluderCount; i++)
                        {
                            TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                            tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                            TileOccluderInfos.Add(tileOccluderInfo);
                        }
                    }
                    catch (Exception)
                    {
                        // Some of these may have been populated from the "try".
                        RenderBatches.Clear();
                        OptimizedDraws.Clear();
                        UnknownShorts1.Clear();
                        UnknownVectors1.Clear();
                        TileOccluderInfos.Clear();

                        binaryReader.BaseStream.Position = offset;

                        //Render Batches
                        uint renderBatchCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < renderBatchCount; i++)
                        {
                            RenderBatch renderBatch = new RenderBatch();

                            renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                            renderBatch.IndexCount   = binaryReader.ReadUInt32();
                            renderBatch.VertexOffset = binaryReader.ReadUInt32();
                            renderBatch.VertexCount  = binaryReader.ReadUInt32();

                            RenderBatches.Add(renderBatch);
                        }

                        //Optimized Draw
                        uint optimizedDrawCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < optimizedDrawCount; i++)
                        {
                            OptimizedDraw optimizedDraw = new OptimizedDraw();
                            optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                            OptimizedDraws.Add(optimizedDraw);
                        }

                        //Unknown Data
                        uint unknownShort1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownShort1Count; i++)
                        {
                            UnknownShorts1.Add(binaryReader.ReadUInt16());
                        }

                        //Unknown Data
                        uint unknownVectors1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownVectors1Count; i++)
                        {
                            UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(),
                                                            binaryReader.ReadSingle()));
                        }

                        //Tile Occluder Info
                        uint tileOccluderCount = binaryReader.ReadUInt32();

                        if (tileOccluderCount > 16)
                        {
                            return(false);
                        }

                        for (int i = 0; i < tileOccluderCount; i++)
                        {
                            TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                            tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                            TileOccluderInfos.Add(tileOccluderInfo);
                        }
                    }
                }
            }

            return(true);
        }
        public static Cnk0 LoadFromStream(string name, string displayName, MemoryStream stream)
        {
            Cnk0         chunk        = new Cnk0();
            BinaryReader binaryReader = new BinaryReader(stream);

            chunk.Name        = name;
            chunk.DisplayName = displayName;
            //Header
            byte[] magic = binaryReader.ReadBytes(4);

            if (magic[0] != 'C' ||
                magic[1] != 'N' ||
                magic[2] != 'K' ||
                magic[3] != '0')
            {
                return(null);
            }

            chunk.Version = binaryReader.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)chunk.Version))
            {
                Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + chunk.Version);
                return(null);
            }

            chunk.ChunkType = (ChunkType)chunk.Version;

            chunk.DecompressedSize = binaryReader.ReadUInt32();
            chunk.CompressedSize   = binaryReader.ReadUInt32();

            //Decompression
            byte[] compressedBuffer   = binaryReader.ReadBytes((int)chunk.CompressedSize);
            byte[] decompressedBuffer = new byte[chunk.DecompressedSize];

            InflateReturnCode result = LzhamInterop.DecompressForgelightData(compressedBuffer, chunk.CompressedSize, decompressedBuffer, chunk.DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid.
                return(null);
            }

            using (MemoryStream decompressedStream = new MemoryStream(decompressedBuffer))
            {
                binaryReader = new BinaryReader(decompressedStream);

                //Tiles
                uint tileCount = binaryReader.ReadUInt32();
                chunk.Tiles = new List <Tile>((int)tileCount);

                for (int i = 0; i < tileCount; i++)
                {
                    Tile tile = new Tile();

                    tile.X           = binaryReader.ReadInt32();
                    tile.Y           = binaryReader.ReadInt32();
                    tile.UnknownInt1 = binaryReader.ReadInt32();
                    tile.UnknownInt2 = binaryReader.ReadInt32();

                    uint ecosCount = binaryReader.ReadUInt32();

                    if (ecosCount > 0)
                    {
                        tile.Ecos = new List <Tile.Eco>((int)ecosCount);

                        for (int j = 0; j < ecosCount; j++)
                        {
                            Tile.Eco eco = new Tile.Eco();

                            eco.ID = binaryReader.ReadUInt32();

                            uint florasCount = binaryReader.ReadUInt32();
                            eco.Floras = new List <Tile.Eco.Flora>((int)florasCount);

                            for (int k = 0; k < florasCount; k++)
                            {
                                Tile.Eco.Flora flora = new Tile.Eco.Flora();

                                uint layersCount = binaryReader.ReadUInt32();
                                flora.Layers = new List <Tile.Eco.Flora.Layer>((int)layersCount);

                                for (int l = 0; l < layersCount; l++)
                                {
                                    Tile.Eco.Flora.Layer layer = new Tile.Eco.Flora.Layer();

                                    layer.UnknownUint1 = binaryReader.ReadUInt32();
                                    layer.UnknownUint2 = binaryReader.ReadUInt32();

                                    flora.Layers.Add(layer);
                                }

                                eco.Floras.Add(flora);
                            }

                            tile.Ecos.Add(eco);
                        }
                    }

                    tile.Index       = binaryReader.ReadUInt32();
                    tile.UnknownInt3 = binaryReader.ReadUInt32();

                    uint imageSize = binaryReader.ReadUInt32();
                    if (imageSize > 0)
                    {
                        tile.ImageData = binaryReader.ReadBytes((int)imageSize).ToList();
                    }

                    uint layerTexturesCount = binaryReader.ReadUInt32();
                    if (layerTexturesCount > 0)
                    {
                        tile.LayerTextures = binaryReader.ReadBytes((int)layerTexturesCount).ToList();
                    }

                    chunk.Tiles.Add(tile);
                }

                //Unknown Data
                chunk.UnknownInt1 = binaryReader.ReadInt32();

                uint unknownCount = binaryReader.ReadUInt32();
                chunk.UnknownArray1 = new List <Unknown1>((int)unknownCount);

                for (int i = 0; i < unknownCount; i++)
                {
                    Unknown1 unknown1 = new Unknown1();

                    unknown1.Height       = binaryReader.ReadInt16();
                    unknown1.UnknownByte1 = binaryReader.ReadByte();
                    unknown1.UnknownByte2 = binaryReader.ReadByte();

                    chunk.UnknownArray1.Add(unknown1);
                }

                //Indices
                uint indexCount = binaryReader.ReadUInt32();
                chunk.Indices = new List <ushort>((int)indexCount);

                for (int i = 0; i < indexCount; i++)
                {
                    chunk.Indices.Add(binaryReader.ReadUInt16());
                }

                //Verts
                uint vertCount = binaryReader.ReadUInt32();
                chunk.Vertices = new List <Vertex>((int)vertCount);

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = binaryReader.ReadInt16();
                    vertex.Y          = binaryReader.ReadInt16();
                    vertex.HeightFar  = binaryReader.ReadInt16();
                    vertex.HeightNear = binaryReader.ReadInt16();
                    vertex.Color1     = binaryReader.ReadUInt32();
                    vertex.Color2     = binaryReader.ReadUInt32();

                    chunk.Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = binaryReader.BaseStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (chunk.ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = binaryReader.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (EndOfStreamException)
                {
                    binaryReader.BaseStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(chunk);
        }
        public static CnkLOD LoadFromStream(string name, string displayName, MemoryStream stream)
        {
            CnkLOD       chunk        = new CnkLOD();
            BinaryReader binaryReader = new BinaryReader(stream);

            chunk.Name        = name;
            chunk.DisplayName = displayName;
            //Header
            byte[] magic = binaryReader.ReadBytes(4);

            if (magic[0] != 'C' ||
                magic[1] != 'N' ||
                magic[2] != 'K' /* ||
                                 * magic[3] != '1'*/)
            {
                return(null);
            }

            chunk.Version = binaryReader.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)chunk.Version))
            {
                Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + chunk.Version);
                return(null);
            }

            chunk.ChunkType = (ChunkType)chunk.Version;

            chunk.DecompressedSize = binaryReader.ReadUInt32();
            chunk.CompressedSize   = binaryReader.ReadUInt32();

            //Decompression
            byte[] compressedBuffer   = binaryReader.ReadBytes((int)chunk.CompressedSize);
            byte[] decompressedBuffer = new byte[chunk.DecompressedSize];

            InflateReturnCode result = LzhamInterop.DecompressForgelightData(compressedBuffer, chunk.CompressedSize, decompressedBuffer, chunk.DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid.
                return(null);
            }

            using (MemoryStream decompressedStream = new MemoryStream(decompressedBuffer))
            {
                binaryReader = new BinaryReader(decompressedStream);

                //Textures
                uint textureCount = binaryReader.ReadUInt32();
                chunk.Textures = new List <Texture>((int)textureCount);

                for (int i = 0; i < textureCount; i++)
                {
                    Texture texture = new Texture();

                    uint colorNxMapSize = binaryReader.ReadUInt32();
                    if (colorNxMapSize > 0)
                    {
                        texture.ColorNXMap = binaryReader.ReadBytes((int)colorNxMapSize).ToList();
                    }

                    uint specNyMapSize = binaryReader.ReadUInt32();
                    if (specNyMapSize > 0)
                    {
                        texture.SpecNyMap = binaryReader.ReadBytes((int)specNyMapSize).ToList();
                    }

                    uint extraData1Size = binaryReader.ReadUInt32();
                    if (extraData1Size > 0)
                    {
                        texture.ExtraData1 = binaryReader.ReadBytes((int)extraData1Size).ToList();
                    }

                    uint extraData2Size = binaryReader.ReadUInt32();
                    if (extraData2Size > 0)
                    {
                        texture.ExtraData2 = binaryReader.ReadBytes((int)extraData2Size).ToList();
                    }

                    uint extraData3Size = binaryReader.ReadUInt32();
                    if (extraData3Size > 0)
                    {
                        texture.ExtraData3 = binaryReader.ReadBytes((int)extraData3Size).ToList();
                    }

                    uint extraData4Size = binaryReader.ReadUInt32();
                    if (extraData4Size > 0)
                    {
                        texture.ExtraData4 = binaryReader.ReadBytes((int)extraData4Size).ToList();
                    }

                    chunk.Textures.Add(texture);
                }

                //Verts Per Side
                chunk.VertsPerSide = binaryReader.ReadUInt32();

                //Height Maps
                uint heightMapCount = binaryReader.ReadUInt32();

                int n = (int)(heightMapCount / 4);

                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        Dictionary <int, HeightMap> entry;

                        if (!chunk.HeightMaps.ContainsKey(i))
                        {
                            entry = new Dictionary <int, HeightMap>();
                            chunk.HeightMaps[i] = entry;
                        }

                        else
                        {
                            entry = chunk.HeightMaps[i];
                        }

                        HeightMap heightMapData = new HeightMap();
                        heightMapData.Val1 = binaryReader.ReadInt16();
                        heightMapData.Val2 = binaryReader.ReadByte();
                        heightMapData.Val3 = binaryReader.ReadByte();

                        entry[j] = heightMapData;
                    }
                }

                //Indices
                uint indexCount = binaryReader.ReadUInt32();
                chunk.Indices = new List <ushort>((int)indexCount);

                for (int i = 0; i < indexCount; i++)
                {
                    chunk.Indices.Add(binaryReader.ReadUInt16());
                }

                //Verts
                uint vertCount = binaryReader.ReadUInt32();
                chunk.Vertices = new List <Vertex>((int)vertCount);

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = binaryReader.ReadInt16();
                    vertex.Y          = binaryReader.ReadInt16();
                    vertex.HeightFar  = binaryReader.ReadInt16();
                    vertex.HeightNear = binaryReader.ReadInt16();
                    vertex.Color      = binaryReader.ReadUInt32();

                    chunk.Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = binaryReader.BaseStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (chunk.ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = binaryReader.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (Exception)
                {
                    binaryReader.BaseStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(chunk);
        }