private void OpenClick(object sender, EventArgs e) { try { var dlg = openFileDialog.ShowDialog(); if (dlg != DialogResult.OK) return; var file = openFileDialog.OpenFile(); using (var blp = new BlpFile(file)) { bmp = blp.GetBitmap(0); } var graphics = panel1.CreateGraphics(); graphics.Clear(panel1.BackColor); graphics.DrawImage(bmp, 0, 0); button3.Enabled = true; } catch (FileNotFoundException fe) { MessageBox.Show("The 'example.blp' was not found!"); } }
public override void Work() { bool success = false; try { foreach (string path in paths) { string newFile = Path.Combine(dest, Path.GetFileNameWithoutExtension(path) + ".png"); Log.Write("Exporting {0} -> {1}", path, newFile); using (BlpFile blp = new BlpFile(File.OpenRead(path))) { Bitmap bmp = blp.GetBitmap(0); bmp.Save(newFile, ImageFormat.Png); bmp.Dispose(); } } success = true; } catch (Exception e) { // We have failed, the elders will be disappointed. Log.Write("BLP to PNG export failed: {0}.", e.Message); } EventManager.Trigger_ExportBLPtoPNGComplete(success); }
private void displayImage(string file) { currentImage = null; UI_PreviewStatus.Hide(); using (var blp = new BlpFile(File.OpenRead(file))) currentImage = blp.GetBitmap(0); Graphics gfx = UI_ImagePreview.CreateGraphics(); gfx.Clear(UI_ImagePreview.BackColor); gfx.DrawImage(currentImage, 0, 0); UI_ExportButton.Show(); currentImageName = file; }
public void addTexture(int extID, string file) { int width = 0; int height = 0; byte[] data = null; fileMapping.Add(extID, file); using (BlpFile raw = new BlpFile(File.OpenRead(file))) { Bitmap bitmap = raw.GetBitmap(0); width = bitmap.Width; height = bitmap.Height; int length = width * height * 4; var rawData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, bitmap.PixelFormat); data = new byte[length]; Marshal.Copy(rawData.Scan0, data, 0, length); bitmap.UnlockBits(rawData); bitmap.Dispose(); } uint[] intID = new uint[1]; gl.GenTextures(1, intID); gl.BindTexture(OpenGL.GL_TEXTURE_2D, intID[0]); gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, OpenGL.GL_RGBA, width, height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE, data); gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR); gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR_MIPMAP_LINEAR); mapping.Add(extID, intID); gl.GenerateMipmapEXT(OpenGL.GL_TEXTURE_2D); Log.Write("TextureManager: {0} assigned to GL with @ {1}", file, intID[0]); }
public async void UpdateMainWindowIcons(double margin) { if (adapter == null || main.selectedID == 0) // adapter.query below caused unhandled exception with main.selectedID as 0. { return; } DataRow res; try { res = adapter.query(string.Format("SELECT `SpellIconID`,`ActiveIconID` FROM `{0}` WHERE `ID` = '{1}'", adapter.Table, main.selectedID)).Rows[0]; } catch (Exception) { return; } UInt32 iconInt = UInt32.Parse(res[0].ToString()); UInt32 iconActiveInt = UInt32.Parse(res[1].ToString()); UInt32 selectedRecord = UInt32.MaxValue; for (UInt32 i = 0; i < header.RecordCount; ++i) { if (body.records[i].ID == iconInt) { selectedRecord = i; break; } if (body.records[i].ID == iconActiveInt) { selectedRecord = i; break; } } string icon = ""; int offset = 0; try { if (selectedRecord == UInt32.MaxValue) { throw new Exception("The icon for this spell does not exist in the SpellIcon.dbc"); } offset = (int)body.records[selectedRecord].Name; while (body.StringBlock[offset] != '\0') { icon += body.StringBlock[offset++]; } if (!File.Exists(icon + ".blp")) { throw new Exception("File could not be found: " + "Icons\\" + icon + ".blp"); } } catch (Exception ex) { main.Dispatcher.Invoke(new Action(() => main.HandleErrorMessage(ex.Message))); return; } FileStream fileStream = new FileStream(icon + ".blp", FileMode.Open); SereniaBLPLib.BlpFile image; image = new SereniaBLPLib.BlpFile(fileStream); Bitmap bit = image.getBitmap(0); await Task.Factory.StartNew(() => { main.CurrentIcon.Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bit.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(bit.Width, bit.Height)); }, CancellationToken.None, TaskCreationOptions.None, main.UIScheduler); image.close(); fileStream.Close(); if (!loadedAllIcons) { loadedAllIcons = true; int currentOffset = 1; string[] icons = body.StringBlock.Split('\0'); int iconIndex = 0; int columnsUsed = icons.Length / 11; int rowsToDo = columnsUsed / 2; for (int j = -rowsToDo; j <= rowsToDo; ++j) { for (int i = -5; i < 6; ++i) { ++iconIndex; if (iconIndex >= icons.Length - 1) { break; } int this_icons_offset = currentOffset; currentOffset += icons[iconIndex].Length + 1; if (!File.Exists(icons[iconIndex] + ".blp")) { Console.WriteLine("Warning: Icon not found: " + icons[iconIndex] + ".blp"); continue; } bool loaded = false; try { fileStream = new FileStream(icons[iconIndex] + ".blp", FileMode.Open); image = new BlpFile(fileStream); bit = image.getBitmap(0); loaded = true; } catch (Exception e) { Console.WriteLine($"Error loading image, unsupported BLP format: {icons[iconIndex]}.blp\n{e.Message}\n{e}"); } if (!loaded) { image?.close(); fileStream?.Close(); continue; } await Task.Factory.StartNew(() => { System.Windows.Controls.Image temp = new System.Windows.Controls.Image(); temp.Width = iconSize == null ? 32 : iconSize.Value; temp.Height = iconSize == null ? 32 : iconSize.Value; temp.Margin = iconMargin == null ? new System.Windows.Thickness(margin, 0, 0, 0) : iconMargin.Value; temp.VerticalAlignment = VerticalAlignment.Top; temp.HorizontalAlignment = HorizontalAlignment.Left; temp.Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bit.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(bit.Width, bit.Height)); temp.Name = "Index_" + this_icons_offset; temp.ToolTip = icons[iconIndex]; temp.MouseDown += this.ImageDown; main.IconGrid.Children.Add(temp); }, CancellationToken.None, TaskCreationOptions.None, main.UIScheduler); image.close(); fileStream.Close(); } } } }
static int RunAndReturnExitCode(Options opts) { if (!Directory.Exists(opts.OutputPath)) { Directory.CreateDirectory(opts.OutputPath); } CASCHandler cascHandler; if (opts.UseOnline) { cascHandler = CASCHandler.OpenOnlineStorage(opts.OnlineProduct, opts.OnlineRegion); } else if (opts.StoragePath != null) { cascHandler = CASCHandler.OpenLocalStorage(opts.StoragePath); } else { throw new Exception("StoragePath required if not using online mode!"); } cascHandler.Root.SetFlags(LocaleFlags.All_WoW, ContentFlags.None); foreach (var map in opts.Maps) { try { Console.WriteLine("-- processing {0}", map); System.Drawing.Bitmap[,] tiles = new System.Drawing.Bitmap[64, 64]; bool[,] had_tile = new bool[64, 64]; bool[,] wdt_claims_tile = new bool[64, 64]; var wdt_name = Path.Combine("world", "maps", map, String.Format("{0}.wdt", map)); try { using (Stream stream = cascHandler.OpenFile(wdt_name)) { using (BinaryReader reader = new BinaryReader(stream)) { while (reader.BaseStream.Position != reader.BaseStream.Length) { var magic = reader.ReadUInt32(); var size = reader.ReadUInt32(); var pos = reader.BaseStream.Position; if (magic == mk("MPHD")) { var flags = reader.ReadUInt32(); if ((flags & 1) == 1) { throw new Exception("map claims to be WMO only, skipping!"); } } else if (magic == mk("MAIN")) { for (int x = 0; x < 64; ++x) { for (int y = 0; y < 64; ++y) { wdt_claims_tile[y, x] = (reader.ReadUInt32() & 1) == 1; reader.ReadUInt32(); } } } reader.BaseStream.Position = pos + size; } } } } catch (FileNotFoundException) { throw new Exception(String.Format("failed loading {0}, skipping!", wdt_name)); } var tile_size = 256; for (int x = 0; x < 64; ++x) { for (int y = 0; y < 64; ++y) { had_tile[x, y] = false; try { var blp_name = Path.Combine("world", "minimaps", map, String.Format("map{0:00}_{1:00}.blp", x, y)); using (Stream stream = cascHandler.OpenFile(blp_name)) { var blp = new SereniaBLPLib.BlpFile(stream); tiles[x, y] = blp.GetBitmap(0); if (tiles[x, y].Height != tiles[x, y].Width) { throw new Exception("non-square minimap?!"); } } had_tile[x, y] = true; } catch (FileNotFoundException) { tiles[x, y] = new System.Drawing.Bitmap(tile_size, tile_size); } var size_per_mcnk = tiles[x, y].Height / 16f; var g = System.Drawing.Graphics.FromImage(tiles[x, y]); var impassable_brush = new System.Drawing.Drawing2D.HatchBrush (System.Drawing.Drawing2D.HatchStyle.DiagonalCross , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.Yellow) , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.Red) ); var wdt_border_brush = new System.Drawing.Drawing2D.HatchBrush (System.Drawing.Drawing2D.HatchStyle.DiagonalCross , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.DarkBlue) , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.Red) ); var wdt_border_pen = new System.Drawing.Pen (wdt_border_brush, size_per_mcnk); var unreferenced_brush = new System.Drawing.Drawing2D.HatchBrush (System.Drawing.Drawing2D.HatchStyle.DiagonalCross , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.DarkBlue) , System.Drawing.Color.FromArgb(255 / 2, System.Drawing.Color.Green) ); try { var adt_name = Path.Combine("World", "Maps", map, String.Format("{0}_{1}_{2}.adt", map, x, y)); using (Stream stream = cascHandler.OpenFile(adt_name)) { using (BinaryReader reader = new BinaryReader(stream)) { while (reader.BaseStream.Position != reader.BaseStream.Length) { var magic = reader.ReadUInt32(); var size = reader.ReadUInt32(); var pos = reader.BaseStream.Position; if (magic == mk("MCNK")) { var flags = reader.ReadUInt32(); var sub_x = reader.ReadUInt32(); var sub_y = reader.ReadUInt32(); if ((flags & 2) == 2) { g.FillRectangle(impassable_brush, size_per_mcnk * sub_x, size_per_mcnk * sub_y, size_per_mcnk, size_per_mcnk); } } reader.BaseStream.Position = pos + size; } } } had_tile[x, y] = true; } catch (FileNotFoundException) { g.FillRectangle(wdt_border_brush, 0, 0, tiles[x, y].Height, tiles[x, y].Height); } if (wdt_claims_tile[x, y]) { if (x == 0 || !wdt_claims_tile[x - 1, y]) { g.DrawLine(wdt_border_pen, 0, 0, 0, tiles[x, y].Height); } if (x == 63 || !wdt_claims_tile[x + 1, y]) { g.DrawLine(wdt_border_pen, tiles[x, y].Height, 0, tiles[x, y].Height, tiles[x, y].Height); } if (y == 0 || !wdt_claims_tile[x, y - 1]) { g.DrawLine(wdt_border_pen, 0, 0, tiles[x, y].Height, 0); } if (y == 63 || !wdt_claims_tile[x, y + 1]) { g.DrawLine(wdt_border_pen, 0, tiles[x, y].Height, tiles[x, y].Height, tiles[x, y].Height); } } else if (had_tile[x, y]) { g.FillRectangle(unreferenced_brush, 0, 0, tiles[x, y].Height, tiles[x, y].Height); } } } int min_x = 64; int min_y = 64; int max_x = -1; int max_y = -1; for (int x = 0; x < 64; ++x) { for (int y = 0; y < 64; ++y) { if (had_tile[x, y]) { min_x = Math.Min(min_x, x); min_y = Math.Min(min_y, y); max_x = Math.Max(max_x, x + 1); max_y = Math.Max(max_y, y + 1); } } } var overall = new System.Drawing.Bitmap(tile_size * (max_x - min_x), tile_size * (max_y - min_y)); var overall_graphics = System.Drawing.Graphics.FromImage(overall); for (int x = min_x; x <= max_x; ++x) { for (int y = min_y; y <= max_y; ++y) { if (had_tile[x, y]) { overall_graphics.DrawImage(tiles[x, y], (x - min_x) * tile_size, (y - min_y) * tile_size, tile_size, tile_size); } } } var output_file = Path.Combine(opts.OutputPath, String.Format("{0}.png", map)); System.IO.File.Delete(output_file); overall.Save(output_file, System.Drawing.Imaging.ImageFormat.Png); } catch (Exception ex) { Console.WriteLine("--- {0}", ex.Message); } } return(0); }
private void PreviewBlp(CASCFile file) { using (var stream = _casc.OpenFile(file.Hash)) { var blp = new BlpFile(stream); var bitmap = blp.GetBitmap(0); var form = new ImagePreviewForm(bitmap); form.Show(); } }
public override void Work() { LogWrite("Beginning export of {0}...", mapName); TextureBox texProvider = new TextureBox(); WaveFrontWriter ob = new WaveFrontWriter(fileName, texProvider, true, true, false); try { if (!Program.IsCASCReady) throw new MapExportException("CASC file engine is not loaded."); string wdtPath = string.Format(@"World\Maps\{0}\{0}.wdt", mapName); Program.CASCEngine.SaveFileTo(wdtPath, Constants.TEMP_DIRECTORY); WDTFile headerFile = new WDTFile(Path.Combine(Constants.TEMP_DIRECTORY, wdtPath)); headerFile.parse(); if (!headerFile.Chunks.Any(c => c.ChunkID == Formats.WDT.Chunk_MPHD.Magic)) throw new MapExportException("Invalid map header (WDT)"); // ToDo: Check if world WMO exists and load it. // Ensure we have a MAIN chunk before trying to process terrain. Formats.WDT.Chunk_MAIN mainChunk = (Formats.WDT.Chunk_MAIN)headerFile.Chunks.Where(c => c.ChunkID == Formats.WDT.Chunk_MAIN.Magic).FirstOrDefault(); Formats.WDT.Chunk_MPHD headerChunk = (Formats.WDT.Chunk_MPHD)headerFile.Chunks.Where(c => c.ChunkID == Formats.WDT.Chunk_MPHD.Magic).FirstOrDefault(); if (mainChunk != null && headerChunk != null) { // Pre-calculate UV mapping for terrain. UV[,,] uvMaps = new UV[8,8,5]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { float uTL = 1 - (0.125f * x); float vTL = 1 - (0.125f * y); float uBR = uTL - 0.125f; float vBR = vTL - 0.125f; int aX = 7 - x; uvMaps[aX, y, 0] = new UV(uBR, vTL); // TL uvMaps[aX, y, 1] = new UV(uBR, vBR); // TR uvMaps[aX, y, 2] = new UV(uTL, vTL); // BL uvMaps[aX, y, 3] = new UV(uTL, vBR); // BR uvMaps[aX, y, 4] = new UV(uTL - 0.0625f, vTL - 0.0625f); } } int meshIndex = 1; int wmoIndex = 1; // Create a directory for map data (alpha maps, etc). string dataDirRaw = string.Format("{0}.data", Path.GetFileNameWithoutExtension(fileName)); string dataDir = Path.Combine(Path.GetDirectoryName(fileName), dataDirRaw); if (!Directory.Exists(dataDir)) Directory.CreateDirectory(dataDir); Dictionary<byte[], uint> texCache = new Dictionary<byte[], uint>(new ByteArrayComparer()); for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { if (mainChunk.map[x, y] && ShouldInclude(x, y)) { string pathBase = string.Format(@"World\Maps\{0}\{0}_{1}_{2}", mapName, x, y); string adtPath = pathBase + ".adt"; string texPath = pathBase + "_tex0.adt"; string objPath = pathBase + "_obj0.adt"; Program.CASCEngine.SaveFileTo(adtPath, Constants.TEMP_DIRECTORY); Program.CASCEngine.SaveFileTo(texPath, Constants.TEMP_DIRECTORY); Program.CASCEngine.SaveFileTo(objPath, Constants.TEMP_DIRECTORY); string adtTempPath = Path.Combine(Constants.TEMP_DIRECTORY, adtPath); string texTempPath = Path.Combine(Constants.TEMP_DIRECTORY, texPath); string objTempPath = Path.Combine(Constants.TEMP_DIRECTORY, objPath); try { ADTFile adt = new ADTFile(adtTempPath, ADTFileType.ROOT); adt.parse(); ADTFile tex = new ADTFile(texTempPath, ADTFileType.TEX); tex.parse(); ADTFile obj = new ADTFile(objTempPath, ADTFileType.OBJ); obj.parse(); // Textures Chunk_MTEX texChunk = (Chunk_MTEX)tex.getChunk(Chunk_MTEX.Magic); uint texIndex = 0; Bitmap[] textureData = new Bitmap[texChunk.textures.count()]; foreach (KeyValuePair<int, string> texture in texChunk.textures.raw()) { string texFile = texture.Value; string tempPath = Path.Combine(Constants.TEMP_DIRECTORY, texFile); if (!File.Exists(tempPath)) Program.CASCEngine.SaveFileTo(texFile, Constants.TEMP_DIRECTORY); using (BlpFile blp = new BlpFile(File.OpenRead(tempPath))) textureData[texIndex] = blp.GetBitmap(0); texIndex++; } Chunk_MCNK[] soupChunks = adt.getChunksByID(Chunk_MCNK.Magic).Cast<Chunk_MCNK>().ToArray(); Chunk_MCNK[] layerChunks = tex.getChunksByID(Chunk_MCNK.Magic).Cast<Chunk_MCNK>().ToArray(); // Terrain for (int i = 0; i < 256; i++) { Chunk_MCNK soupChunk = soupChunks[i]; Chunk_MCNK layerChunk = layerChunks[i]; // Terrain chunks Chunk_MCVT hmChunk = (Chunk_MCVT)soupChunk.getChunk(Chunk_MCVT.Magic); Chunk_MCNR nChunk = (Chunk_MCNR)soupChunk.getChunk(Chunk_MCNR.Magic); // Texture chunks Chunk_MCLY layers = (Chunk_MCLY)layerChunk.getChunk(Chunk_MCLY.Magic); // Alpha mapping Chunk_MCAL alphaMapChunk = (Chunk_MCAL)layerChunk.getChunk(Chunk_MCAL.Magic, false); string texFileName = string.Format("baked_{0}_{1}_{2}.png", x, y, i); string texFilePath = Path.Combine(dataDir, texFileName); EventManager.Trigger_LoadingPrompt(string.Format("Rendering tile {0} at {1},{2}...", i + 1, x, y)); uint texFaceIndex = 0; if (!File.Exists(texFilePath)) { Bitmap bmpBase = new Bitmap(layers.layers.Length > 0 ? textureData[layers.layers[0].textureID] : blank); using (Graphics baseG = Graphics.FromImage(bmpBase)) using (ImageAttributes att = new ImageAttributes()) { att.SetWrapMode(WrapMode.TileFlipXY); baseG.CompositingQuality = CompositingQuality.HighQuality; baseG.InterpolationMode = InterpolationMode.HighQualityBicubic; baseG.CompositingMode = CompositingMode.SourceOver; for (int mI = 1; mI < layers.layers.Length; mI++) // First layer never has an alpha map { byte[,] alphaMap; MCLYLayer layer = layers.layers[mI]; bool headerFlagSet = ((headerChunk.flags & 0x4) == 0x4) || ((headerChunk.flags & 0x80) == 0x80); bool layerFlagSet = ((layer.flags & 0x200) == 0x200); bool fixAlphaMap = !((soupChunk.flags & 0x200) == 0x200); if (layerFlagSet) alphaMap = alphaMapChunk.parse(Chunk_MCAL.CompressType.COMPRESSED, layer.ofsMCAL, fixAlphaMap); else alphaMap = alphaMapChunk.parse(headerFlagSet ? Chunk_MCAL.CompressType.UNCOMPRESSED_4096 : Chunk_MCAL.CompressType.UNCOMPRESSED_2048, layer.ofsMCAL, fixAlphaMap); Bitmap bmpRawTex = textureData[layer.textureID]; Bitmap bmpAlphaMap = new Bitmap(64, 64); for (int drawX = 0; drawX < 64; drawX++) for (int drawY = 0; drawY < 64; drawY++) bmpAlphaMap.SetPixel(drawX, drawY, Color.FromArgb(alphaMap[drawX, drawY], 0, 0, 0)); Bitmap bmpAlphaMapScaled = new Bitmap(bmpRawTex.Width, bmpRawTex.Height); using (Graphics g = Graphics.FromImage(bmpAlphaMapScaled)) { g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.CompositingMode = CompositingMode.SourceCopy; g.DrawImage(bmpAlphaMap, new Rectangle(0, 0, bmpAlphaMapScaled.Width, bmpAlphaMapScaled.Height), 0, 0, bmpAlphaMap.Width, bmpAlphaMap.Height, GraphicsUnit.Pixel, att); } bmpAlphaMap.Dispose(); Bitmap bmpTex = new Bitmap(bmpRawTex.Width, bmpRawTex.Height); for (int drawX = 0; drawX < bmpRawTex.Width; drawX++) { for (int drawY = 0; drawY < bmpRawTex.Height; drawY++) { // Hacky fix to flip the texture. // Remove this if we fix the terrain read-order. int sourceX = (bmpRawTex.Width - 1) - drawX; //int sourceY = (bmpRawTex.Height - 1) - drawY; bmpTex.SetPixel(sourceX, drawY, Color.FromArgb( bmpAlphaMapScaled.GetPixel(drawX, drawY).A, bmpRawTex.GetPixel(drawX, drawY).R, bmpRawTex.GetPixel(drawX, drawY).G, bmpRawTex.GetPixel(drawX, drawY).B )); } } bmpAlphaMapScaled.Dispose(); baseG.DrawImage(bmpTex, 0, 0, bmpBase.Width, bmpBase.Height); } using (MemoryStream str = new MemoryStream()) using (MD5 md5 = MD5.Create()) { bmpBase.Save(str, ImageFormat.Png); byte[] raw = md5.ComputeHash(str.ToArray()); uint cacheID; if (texCache.TryGetValue(raw, out cacheID)) { // Cache found, use that instead. texFaceIndex = cacheID; } else { // No cache found, store new. bmpBase.Save(texFilePath); texProvider.addTexture(-1, Path.Combine(dataDirRaw, texFileName)); cacheID = (uint)texProvider.LastIndex; texFaceIndex = cacheID; texCache.Add(raw, cacheID); } } bmpBase.Dispose(); } } Mesh mesh = new Mesh("Terrain Mesh #" + meshIndex); meshIndex++; int v = 0; float pX = soupChunk.position.X; float pY = -soupChunk.position.Y; float pZ = soupChunk.position.Z; int ofs = 10; for (int sX = 8; sX > 0; sX--) { for (int sY = 1; sY < 9; sY++) { int cIndex = ofs - 1; int blIndex = cIndex - 9; int tlIndex = cIndex + 8; float tr = hmChunk.vertices[tlIndex + 1]; float tl = hmChunk.vertices[tlIndex]; float br = hmChunk.vertices[blIndex + 1]; float bl = hmChunk.vertices[blIndex]; float c = hmChunk.vertices[cIndex]; float oX = pX + (sX * ADTFile.TILE_SIZE); float oY = pY + (sY * ADTFile.TILE_SIZE); // Apply UV mapping for (int uv = 0; uv < 5; uv++) mesh.addUV(uvMaps[sX - 1, sY - 1, uv]); // Apply verts mesh.addVert(new Position(oX, tl + pZ, oY)); mesh.addVert(new Position(oX, tr + pZ, oY + ADTFile.TILE_SIZE)); mesh.addVert(new Position(oX + ADTFile.TILE_SIZE, bl + pZ, oY)); mesh.addVert(new Position(oX + ADTFile.TILE_SIZE, br + pZ, oY + ADTFile.TILE_SIZE)); mesh.addVert(new Position(oX + (ADTFile.TILE_SIZE / 2), c + pZ, oY + (ADTFile.TILE_SIZE / 2))); // Normals mesh.addNormal(nChunk.normals[tlIndex]); mesh.addNormal(nChunk.normals[tlIndex + 1]); mesh.addNormal(nChunk.normals[blIndex]); mesh.addNormal(nChunk.normals[blIndex + 1]); mesh.addNormal(nChunk.normals[cIndex]); // Faces mesh.addFace(texFaceIndex, v, v + 2, v + 4); mesh.addFace(texFaceIndex, v + 1, v + 3, v + 4); mesh.addFace(texFaceIndex, v, v + 1, v + 4); mesh.addFace(texFaceIndex, v + 2, v + 3, v + 4); v += 5; ofs += 1; } ofs += 9; } ob.addMesh(mesh); } // Parse WMO objects that appear in the world. EventManager.Trigger_LoadingPrompt("Constructing buildings..."); Chunk_MWID wmoIndexChunk = (Chunk_MWID)obj.getChunk(Chunk_MWID.Magic, false); Chunk_MWMO wmoModelChunk = (Chunk_MWMO)obj.getChunk(Chunk_MWMO.Magic, false); Chunk_MODF wmoRefChunk = (Chunk_MODF)obj.getChunk(Chunk_MODF.Magic, false); if (wmoIndexChunk != null && wmoModelChunk != null && wmoRefChunk != null) { foreach (Chunk_MODF.MODFEntry entry in wmoRefChunk.entries) { string wmoModel = wmoModelChunk.objects.get((int)wmoIndexChunk.offsets[entry.entry]); List<CASCFile> groupSearch = CASCSearch.Search(Path.Combine(Path.GetDirectoryName(wmoModel), Path.GetFileNameWithoutExtension(wmoModel)), CASCSearch.SearchType.STARTS_WITH); if (groupSearch.Count > 0) { // Set-up root/group files for the WMO. WMOFile wmo = null; List<WMOFile> groupFiles = new List<WMOFile>(groupSearch.Count - 1); string rootName = Path.GetFileName(wmoModel).ToLower(); foreach (CASCFile file in groupSearch) { Program.CASCEngine.SaveFileTo(file.FullName, Constants.TEMP_DIRECTORY); string tempPath = Path.Combine(Constants.TEMP_DIRECTORY, file.FullName); if (file.FullName.ToLower().EndsWith(rootName)) wmo = new WMOFile(tempPath, true); else groupFiles.Add(new WMOFile(tempPath, false)); } foreach (WMOFile groupFile in groupFiles) wmo.addGroupFile(groupFile); groupFiles.Clear(); wmo.parse(); // Export/register textures needed for this WMO. Formats.WMO.Chunk_MOTX wmoTexChunk = (Formats.WMO.Chunk_MOTX)wmo.getChunk(Formats.WMO.Chunk_MOTX.Magic); Dictionary<int, int> wmoTexMap = new Dictionary<int, int>(); foreach (KeyValuePair<int, string> node in wmoTexChunk.textures.raw()) { string tempPath = Path.Combine(Constants.TEMP_DIRECTORY, node.Value); string dumpPath = Path.Combine(Path.GetDirectoryName(node.Value), Path.GetFileNameWithoutExtension(node.Value) + ".png"); // Extract if (!File.Exists(tempPath)) Program.CASCEngine.SaveFileTo(node.Value, Constants.TEMP_DIRECTORY); // Convert using (BlpFile blp = new BlpFile(File.OpenRead(tempPath))) using (Bitmap bmp = blp.GetBitmap(0)) { string dumpLoc = Path.Combine(dataDir, dumpPath); Directory.CreateDirectory(Path.GetDirectoryName(dumpLoc)); bmp.Save(dumpLoc); } // Register texProvider.addTexture(-1, Path.Combine(dataDirRaw, dumpPath)); wmoTexMap.Add(node.Key, texProvider.LastIndex); } Formats.WMO.Chunk_MOGN wmoNameChunk = (Formats.WMO.Chunk_MOGN)wmo.getChunk(Formats.WMO.Chunk_MOGN.Magic); Formats.WMO.Chunk_MOMT wmoMatChunk = (Formats.WMO.Chunk_MOMT)wmo.getChunk(Formats.WMO.Chunk_MOMT.Magic); foreach (Chunk_Base rawChunk in wmo.getChunksByID(Formats.WMO.Chunk_MOGP.Magic)) { Formats.WMO.Chunk_MOGP chunk = (Formats.WMO.Chunk_MOGP)rawChunk; string meshName = wmoNameChunk.data.get((int)chunk.groupNameIndex); // Skip antiportals. if (meshName.ToLower().Equals("antiportal")) continue; Mesh mesh = new Mesh(string.Format("WMO{0}_{1}", wmoIndex, meshName)); // Populate mesh with vertices. Formats.WMO.Chunk_MOVT vertChunk = (Formats.WMO.Chunk_MOVT)chunk.getChunk(Formats.WMO.Chunk_MOVT.Magic); foreach (Position vertPos in vertChunk.vertices) mesh.addVert(new Position(entry.position.X + vertPos.X, entry.position.Y + vertPos.Y, entry.position.Z + vertPos.Z)); // Populate mesh with UVs. Formats.WMO.Chunk_MOTV uvChunk = (Formats.WMO.Chunk_MOTV)chunk.getChunk(Formats.WMO.Chunk_MOTV.Magic); foreach (UV uv in uvChunk.uvData) mesh.addUV(uv); // Populate mesh with normals. Formats.WMO.Chunk_MONR normChunk = (Formats.WMO.Chunk_MONR)chunk.getChunk(Formats.WMO.Chunk_MONR.Magic); foreach (Position norm in normChunk.normals) mesh.addNormal(norm); // Populate mesh with triangles (faces). Formats.WMO.Chunk_MOVI faceChunk = (Formats.WMO.Chunk_MOVI)chunk.getChunk(Formats.WMO.Chunk_MOVI.Magic); Formats.WMO.Chunk_MOPY faceMatChunk = (Formats.WMO.Chunk_MOPY)chunk.getChunk(Formats.WMO.Chunk_MOPY.Magic); for (int i = 0; i < faceChunk.positions.Length; i++) { Formats.WMO.FacePosition position = faceChunk.positions[i]; Formats.WMO.FaceInfo info = faceMatChunk.faceInfo[i]; if (info.materialID != 0xFF) // 0xFF (255) identifies a collision face. { Material mat = wmoMatChunk.materials[info.materialID]; uint texID = (uint)wmoTexMap[(int)mat.texture1.offset]; mesh.addFace(texID, mat.texture2.colour, position.point1, position.point2, position.point3); } } Log.Write("CreateWMOMesh (ADT): " + mesh.ToAdvancedString()); ob.addMesh(mesh); } } } } } catch (ADTException ex) { LogWrite("Unable to process tile {0},{1} due to exception: {2}", x, y, ex.Message); LogWrite(ex.StackTrace); } } } } EventManager.Trigger_LoadingPrompt(new Random().Next(100) == 42 ? "Reticulating splines..." : "Writing terrain data to file..."); ob.Write(); ob.Close(); } // Job's done. EventManager.Trigger_MapExportDone(true); } catch (Exception e) { ob.Close(); EventManager.Trigger_MapExportDone(false, e.Message + e.StackTrace); } }
private void PreviewBlp(string fullName) { var stream = cascHandler.OpenFile(fullName, LocaleFlags.All); var blp = new BlpFile(stream); var bitmap = blp.GetBitmap(0); var form = new ImagePreviewForm(bitmap); form.Show(); }
public override void Work() { MapCanvasTile[,] tiles = canvas.Images; int rowCount = tiles.GetLength(1); int colCount = tiles.GetLength(0); ImageInfo info = new ImageInfo((colCount * canvas.MaxTiles) * 256, (rowCount * canvas.MaxTiles) * 256, 8, false); PngWriter writer = new PngWriter(File.OpenWrite(fileName), info); int lineOfs = 0; int tileLines = 256 * canvas.MaxTiles; int canvasCols = (colCount * canvas.MaxTiles) * 256; for (int tileY = 0; tileY < rowCount; tileY++) { Color[,] rows = new Color[tileLines, canvasCols]; for (int tileX = 0; tileX < colCount; tileX++) { List<MapCanvasTile.SubTile> subTiles = tiles[tileX, tileY].tiles; subTiles.Sort((a, b) => a.CompareTo(b)); for (int subTileY = 0; subTileY < canvas.MaxTiles; subTileY++) { for (int subTileX = 0; subTileX < canvas.MaxTiles; subTileX++) { int subTileIndex = (subTileX * canvas.MaxTiles) + subTileY; if (subTileIndex < subTiles.Count) { using (BlpFile blp = new BlpFile(File.OpenRead(subTiles[subTileIndex].File))) using (Bitmap bmp = blp.GetBitmap(0)) { for (int pY = 0; pY < 256; pY++) for (int pX = 0; pX < 256; pX++) rows[pY + (subTileY * 256), pX + (subTileX * 256) + (tileX * (256 * canvas.MaxTiles))] = bmp.GetPixel(pX, pY); } } } } } for (int iLine = 0; iLine < tileLines; iLine++) { byte[] compRow = new byte[canvasCols * 3]; for (int iCol = 0; iCol < canvasCols; iCol++) { Color color = rows[iLine, iCol]; int ofs = 3 * iCol; compRow[ofs] = color.R; compRow[ofs + 1] = color.G; compRow[ofs + 2] = color.B; } writer.WriteRowByte(compRow, lineOfs); lineOfs++; } } writer.End(); EventManager.Trigger_MapExportDone2D(); }