Пример #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);
        }