示例#1
0
        public static void ExportTextures(ForgelightGame forgelightGame, CnkLOD chunk, string directory)
        {
            string name = Path.GetFileNameWithoutExtension(chunk.Name);

            if (name == null)
            {
                return;
            }

            directory += "/" + name.Split('_')[0];

            if (!Directory.Exists(directory + @"/Textures"))
            {
                Directory.CreateDirectory(directory + @"/Textures");
            }

            MontageSettings montageSettings = new MontageSettings();

            montageSettings.TileGeometry    = new MagickGeometry(2, 2);
            montageSettings.Geometry        = new MagickGeometry(512, 512);
            montageSettings.BackgroundColor = MagickColor.FromRgba(0, 0, 0, 0);
            montageSettings.BorderColor     = MagickColor.FromRgba(0, 0, 0, 0);
            montageSettings.BorderWidth     = 0;

            //TODO Code Duplication
            //Color Map
            string colorMapPath = directory + @"/Textures/" + name + "_colornx" + ".dds";

            if (!File.Exists(colorMapPath))
            {
                using (MagickImageCollection stitchedColorMap = new MagickImageCollection())
                {
                    foreach (CnkLOD.Texture texture in chunk.Textures)
                    {
                        MagickImage textureQuad = new MagickImage(texture.ColorNXMap.ToArray());
                        stitchedColorMap.Add(textureQuad);
                    }

                    using (MagickImage result = stitchedColorMap.Montage(montageSettings))
                    {
                        result.Write(colorMapPath);
                    }
                }
            }

            //TODO code duplication
            //Specular map
            string specMapPath = directory + @"/Textures/" + name + "_specny" + ".dds";

            if (!File.Exists(specMapPath))
            {
                using (MagickImageCollection stitchedSpecMap = new MagickImageCollection())
                {
                    foreach (CnkLOD.Texture texture in chunk.Textures)
                    {
                        MagickImage textureQuad = new MagickImage(texture.SpecNyMap.ToArray());
                        stitchedSpecMap.Add(textureQuad);
                    }

                    using (MagickImage result = stitchedSpecMap.Montage(montageSettings))
                    {
                        result.Write(specMapPath);
                    }
                }
            }
        }
示例#2
0
        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);
        }
示例#3
0
        public static void ExportChunk(ForgelightGame forgelightGame, CnkLOD chunk, string directory)
        {
            string name = Path.GetFileNameWithoutExtension(chunk.Name);

            if (name == null)
            {
                return;
            }

            directory += "/" + name.Split('_')[0];

            if (!Directory.Exists(directory + "/Textures"))
            {
                Directory.CreateDirectory(directory + "/Textures");
            }

            //Textures
            try
            {
                //Material
                if (!File.Exists(directory + @"\" + name + @".mtl"))
                {
                    string[] mtl =
                    {
                        "newmtl " + name,
                        "Ka 1.000000 1.000000 1.000000",
                        "Kd 1.000000 1.000000 1.000000",
                        "Ks 0.000000 0.000000 0.000000",
                        "d 1.0",
                        "illum 1",
                        "map_Ka " + name + "_colornx" + ".dds",
                        "map_Kd " + name + "_colornx" + ".dds",
                        "map_d " + name + "_colornx" + ".dds",
                        "map_Ks " + name + "_colornx" + ".dds",
                        "map_Ns " + name + "_specny" + ".dds"
                    };

                    File.WriteAllLines(directory + @"\" + name + @".mtl", mtl);
                }
            }
            catch (IOException) {}

            //Heighmaps
            //Texture2D image = new Texture2D((int) chunk.VertsPerSide, (int) chunk.VertsPerSide);

            //byte[] imageData = image.GetRawTextureData();

            //for (int i = 0; i < chunk.HeightMaps.Count; i++)
            //{
            //    Dictionary<int, CnkLOD.HeightMap> heightmap = chunk.HeightMaps[i];

            //    uint n = chunk.VertsPerSide*chunk.VertsPerSide;

            //    for (int j = 0; j < n; j++)
            //    {
            //        int height = heightmap[j].Val1 + 4096;

            //        imageData[j*4] = (byte) (height >> 8);
            //        imageData[j*4 + 1] = (byte) (height & 0xFF);
            //        imageData[j*4 + 2] = 0;
            //        imageData[j*4 + 3] = 255;
            //    }

            //    image.LoadRawTextureData(imageData);
            //}

            //Geometry
            string path = directory + @"\" + name + ".obj";

            if (!File.Exists(path))
            {
                using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write))
                {
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        try
                        {
                            List <string> vertices = new List <string>();
                            List <string> uvs      = new List <string>();
                            List <string> faces    = new List <string>();

                            streamWriter.WriteLine("mtllib " + name + ".mtl");
                            streamWriter.WriteLine("o " + name);
                            streamWriter.WriteLine("g " + name);

                            for (int i = 0; i < 4; i++)
                            {
                                uint vertexOffset = chunk.RenderBatches[i].VertexOffset;
                                uint vertextCount = chunk.RenderBatches[i].VertexCount;

                                for (uint j = 0; j < vertextCount; j++)
                                {
                                    int    k          = (int)(vertexOffset + j);
                                    double x          = chunk.Vertices[k].X + (i >> 1) * 64;
                                    double y          = chunk.Vertices[k].Y + (i % 2) * 64;
                                    double heightNear = (double)chunk.Vertices[k].HeightNear / 64;

                                    vertices.Add("v " + x + " " + heightNear + " " + y);
                                    uvs.Add("vt " + (y / 128) + " " + (1 - x / 128));
                                }
                            }

                            for (int i = 0; i < 4; i++)
                            {
                                int  indexOffset  = (int)chunk.RenderBatches[i].IndexOffset;
                                uint indexCount   = chunk.RenderBatches[i].IndexCount;
                                uint vertexOffset = chunk.RenderBatches[i].VertexOffset;

                                for (int j = 0; j < indexCount; j += 3)
                                {
                                    uint v0 = chunk.Indices[j + indexOffset] + vertexOffset;
                                    uint v1 = chunk.Indices[j + indexOffset + 1] + vertexOffset;
                                    uint v2 = chunk.Indices[j + indexOffset + 2] + vertexOffset;

                                    faces.Add("f " + (v2 + 1) + "/" + (v2 + 1) + " " + (v1 + 1) + "/" + (v1 + 1) + " " +
                                              (v0 + 1) + "/" + (v0 + 1));
                                }
                            }

                            foreach (string vertex in vertices)
                            {
                                streamWriter.WriteLine(vertex);
                            }

                            foreach (string uv in uvs)
                            {
                                streamWriter.WriteLine(uv);
                            }

                            streamWriter.WriteLine("usemtl " + name);

                            foreach (string face in faces)
                            {
                                streamWriter.WriteLine(face);
                            }

                            return;
                        }
                        catch (Exception e)
                        {
                            Debug.LogError("Chunk export failed for: " + name + "\n" +
                                           e.Message + "\n" +
                                           e.StackTrace);
                        }
                    }
                }
            }
        }