public static TEXData GetVFX(int offset, string datName) { int datNum = ((offset / 8) & 0x0F) / 2; var VFXData = Helper.GetType2DecompressedData(offset, datNum, datName); TEXData texData = new TEXData(); texData.TexOffset = offset; using (BinaryReader br = new BinaryReader(new MemoryStream(VFXData))) { br.BaseStream.Seek(4, SeekOrigin.Begin); texData.Type = br.ReadInt32(); texData.Width = br.ReadInt16(); texData.Height = br.ReadInt16(); br.ReadBytes(2); texData.MipCount = br.ReadInt16(); br.ReadBytes(64); var rawData = br.ReadBytes(VFXData.Length - 80); texData.TypeString = Info.TextureTypes[texData.Type]; TextureToBitmap(rawData, texData); texData.TEXDatName = datName; } return(texData); }
/// <summary> /// Creates the header for the texture info from the data to be imported. /// </summary> /// <param name="texData">Data for the currently displayed texture.</param> /// <param name="newWidth">The width of the DDS texture to be imported.</param> /// <param name="newHeight">The height of the DDS texture to be imported.</param> /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param> /// <returns>The created header data.</returns> private static List <byte> MakeTextureInfoHeader(TEXData texData, int newWidth, int newHeight, int newMipCount) { List <byte> headerData = new List <byte>(); headerData.AddRange(BitConverter.GetBytes((short)0)); headerData.AddRange(BitConverter.GetBytes((short)128)); headerData.AddRange(BitConverter.GetBytes((short)texData.Type)); headerData.AddRange(BitConverter.GetBytes((short)0)); headerData.AddRange(BitConverter.GetBytes((short)newWidth)); headerData.AddRange(BitConverter.GetBytes((short)newHeight)); headerData.AddRange(BitConverter.GetBytes((short)1)); headerData.AddRange(BitConverter.GetBytes((short)newMipCount)); headerData.AddRange(BitConverter.GetBytes(0)); headerData.AddRange(BitConverter.GetBytes(1)); headerData.AddRange(BitConverter.GetBytes(2)); int mipLength; if (texData.Type == TextureTypes.DXT1) { mipLength = (newWidth * newHeight) / 2; } else if (texData.Type == TextureTypes.DXT5 || texData.Type == TextureTypes.A8) { mipLength = newWidth * newHeight; } else if (texData.Type == TextureTypes.A1R5G5B5 || texData.Type == TextureTypes.A4R4G4B4) { mipLength = (newWidth * newHeight) * 2; } else { mipLength = (newWidth * newHeight) * 4; } int combinedLength = 80; for (int i = 0; i < newMipCount; i++) { headerData.AddRange(BitConverter.GetBytes(combinedLength)); combinedLength = combinedLength + mipLength; if (mipLength > 16) { mipLength = mipLength / 4; } else { mipLength = 16; } } int padding = 80 - headerData.Count; headerData.AddRange(new byte[padding]); return(headerData); }
/// <summary> /// Creates a bitmap from the texture data. /// </summary> /// <param name="decompressedData">The decompressed data of the texture.</param> /// <param name="textureType">The textures type.</param> /// <param name="width">The textures width.</param> /// <param name="height">The textures height.</param> /// <returns>The created bitmap.</returns> //public static Bitmap TextureToBitmap(byte[] decompressedData, int textureType, int width, int height) public static void TextureToBitmap(byte[] decompressedData, TEXData texData) { BitmapSource bmpSource; var width = texData.Width; var height = texData.Height; Tuple <BitmapSource, BitmapSource> bmps = null; byte[] decompressedTextureData; switch (texData.Type) { case TextureTypes.DXT1: decompressedTextureData = DxtUtil.DecompressDxt1(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.DXT3: decompressedTextureData = DxtUtil.DecompressDxt3(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.DXT5: decompressedTextureData = DxtUtil.DecompressDxt5(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.A8: case TextureTypes.L8: bmpSource = Read8bitBitmapImage(decompressedData, width, height); bmps = new Tuple <BitmapSource, BitmapSource>(bmpSource, bmpSource); break; case TextureTypes.A4R4G4B4: bmps = Read4444BMPSource(decompressedData, width, height); break; case TextureTypes.A1R5G5B5: bmps = Read5551BMPSource(decompressedData, width, height); break; case TextureTypes.A8R8G8B8: case TextureTypes.X8R8G8B8: bmps = Read32bitBitmapImageAlpha(decompressedData, width, height); break; //case TextureTypes.A16B16G16R16F: // bmp = ReadRGBAFImage(decompressedData, width, height); // break; } texData.BMPSouceAlpha = bmps.Item1; texData.BMPSouceNoAlpha = bmps.Item2; }
/// <summary> /// Updates the displayed image /// </summary> /// <remarks> /// This is called when an image has either been imported or enabled/disabled /// </remarks> /// <param name="offset">The new offset for the image.</param> /// <param name="isColor">Is the image being udpated a color set.</param> public void UpdateImage(int offset, bool isColor) { if (isColor) { var colorBMP = MTRL.GetColorBitmap(offset); TextureType = "A16B16G16R16F"; TextureDimensions = "(4 x 16)"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(colorBMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); var removeAlphaBitmap = SetAlpha(colorBMP, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); colorBMP.Dispose(); removeAlphaBitmap.Dispose(); } else { if (SelectedMap.ID.Contains("vfx")) { texData = TEX.GetVFX(offset); } else { texData = TEX.GetTex(offset); } TextureType = texData.TypeString; TextureDimensions = "(" + texData.Width + " x " + texData.Height + ")"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(texData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); var removeAlphaBitmap = SetAlpha(texData.BMP, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); texData.Dispose(); removeAlphaBitmap.Dispose(); } if (AlphaChecked) { ImageSource = alphaBitmap; } else { ImageSource = noAlphaBitmap; } }
public static byte[] GetRawVFX(TEXData td) { int datNum = ((td.TexOffset / 8) & 0x0F) / 2; var VFXData = Helper.GetType2DecompressedData(td.TexOffset, datNum, td.TEXDatName); using (BinaryReader br = new BinaryReader(new MemoryStream(VFXData))) { br.BaseStream.Seek(4, SeekOrigin.Begin); var type = br.ReadInt32(); var width = br.ReadInt16(); var height = br.ReadInt16(); br.ReadBytes(2); var mipCount = br.ReadInt16(); br.ReadBytes(64); return(br.ReadBytes(VFXData.Length - 80)); } }
/// <summary> /// Reads and parses data from the DDS file to be imported. /// </summary> /// <param name="br">The currently active BinaryReader.</param> /// <param name="texData">Data for the currently displayed texture.</param> /// <param name="newWidth">The width of the DDS texture to be imported.</param> /// <param name="newHeight">The height of the DDS texture to be imported.</param> /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param> /// <returns>A tuple containing the compressed DDS data, a list of offsets to the mipmap parts, a list with the number of parts per mipmap.</returns> private static Tuple <List <byte>, List <short>, List <short> > ReadDDS(BinaryReader br, TEXData texData, int newWidth, int newHeight, int newMipCount) { List <byte> compressedDDS = new List <byte>(); List <short> mipPartOffsets = new List <short>(); List <short> mipPartCount = new List <short>(); int mipLength; if (texData.Type == TextureTypes.DXT1) { mipLength = (newWidth * newHeight) / 2; } else if (texData.Type == TextureTypes.DXT5 || texData.Type == TextureTypes.A8) { mipLength = newWidth * newHeight; } else if (texData.Type == TextureTypes.A1R5G5B5 || texData.Type == TextureTypes.A4R4G4B4) { mipLength = (newWidth * newHeight) * 2; } else { mipLength = (newWidth * newHeight) * 4; } br.BaseStream.Seek(128, SeekOrigin.Begin); for (int i = 0; i < newMipCount; i++) { int mipParts = (int)Math.Ceiling(mipLength / 16000f); mipPartCount.Add((short)mipParts); if (mipParts > 1) { for (int j = 0; j < mipParts; j++) { int uncompLength; byte[] compressed; bool comp = true; if (j == mipParts - 1) { uncompLength = mipLength % 16000; } else { uncompLength = 16000; } var uncompBytes = br.ReadBytes(uncompLength); compressed = Compressor(uncompBytes); if (compressed.Length > uncompLength) { compressed = uncompBytes; comp = false; } compressedDDS.AddRange(BitConverter.GetBytes(16)); compressedDDS.AddRange(BitConverter.GetBytes(0)); if (!comp) { compressedDDS.AddRange(BitConverter.GetBytes(32000)); } else { compressedDDS.AddRange(BitConverter.GetBytes(compressed.Length)); } compressedDDS.AddRange(BitConverter.GetBytes(uncompLength)); compressedDDS.AddRange(compressed); int padding = 128 - (compressed.Length % 128); compressedDDS.AddRange(new byte[padding]); mipPartOffsets.Add((short)(compressed.Length + padding + 16)); } } else { int uncompLength; byte[] compressed; bool comp = true; if (mipLength != 16000) { uncompLength = mipLength % 16000; } else { uncompLength = 16000; } var uncompBytes = br.ReadBytes(uncompLength); compressed = Compressor(uncompBytes); if (compressed.Length > uncompLength) { compressed = uncompBytes; comp = false; } compressedDDS.AddRange(BitConverter.GetBytes(16)); compressedDDS.AddRange(BitConverter.GetBytes(0)); if (!comp) { compressedDDS.AddRange(BitConverter.GetBytes(32000)); } else { compressedDDS.AddRange(BitConverter.GetBytes(compressed.Length)); } compressedDDS.AddRange(BitConverter.GetBytes(uncompLength)); compressedDDS.AddRange(compressed); int padding = 128 - (compressed.Length % 128); compressedDDS.AddRange(new byte[padding]); mipPartOffsets.Add((short)(compressed.Length + padding + 16)); } if (mipLength > 32) { mipLength = mipLength / 4; } else { mipLength = 8; } } return(new Tuple <List <byte>, List <short>, List <short> >(compressedDDS, mipPartOffsets, mipPartCount)); }
/// <summary> /// Imports the items texture into a dat file /// </summary> /// <param name="texData">Data for the currently displayed texture</param> /// <param name="category">The items category</param> /// <param name="itemName">The items name</param> /// <param name="internalFilePath">The internal file path of the texture map</param> /// <returns>The offset in which the data was placed</returns> public static int ImportTexture(TEXData texData, string category, string subCategory, string itemName, string internalFilePath) { int textureType, lineNum = 0, offset = 0; bool inModList = false; JsonEntry modEntry = null; string dxPath = Path.GetFileNameWithoutExtension(internalFilePath); var savePath = Properties.Settings.Default.Save_Directory + "/" + category + "/" + itemName + "/" + dxPath + ".dds"; if (category.Equals("UI")) { savePath = Properties.Settings.Default.Save_Directory + "/" + category + "/" + subCategory + "/" + dxPath + ".dds"; } if (File.Exists(savePath)) { try { using (StreamReader sr = new StreamReader(Properties.Settings.Default.Modlist_Directory)) { string line; while ((line = sr.ReadLine()) != null) { modEntry = JsonConvert.DeserializeObject <JsonEntry>(line); if (modEntry.fullPath.Equals(internalFilePath)) { inModList = true; break; } lineNum++; } } } catch (Exception ex) { FlexibleMessageBox.Show("Error Accessing .modlist File \n" + ex.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error); } using (BinaryReader br = new BinaryReader(File.OpenRead(savePath))) { br.BaseStream.Seek(12, SeekOrigin.Begin); var newHeight = br.ReadInt32(); var newWidth = br.ReadInt32(); br.ReadBytes(8); var newMipCount = br.ReadInt32(); br.BaseStream.Seek(80, SeekOrigin.Begin); var textureFlags = br.ReadInt32(); var texType = br.ReadInt32(); try { textureType = Info.DDSType[texType]; } catch (Exception e) { FlexibleMessageBox.Show("DDS Type (" + texType + ") not recognized \n" + e.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error); return(0); } if (textureFlags == 2 && textureType == 5200) { textureType = TextureTypes.A8; } else if (textureFlags == 65 && textureType == 5200) { int bpp = br.ReadInt32(); if (bpp == 32) { textureType = TextureTypes.A8R8G8B8; } else { int red = br.ReadInt32(); if (red == 31744) { textureType = TextureTypes.A1R5G5B5; } else if (red == 3840) { textureType = TextureTypes.A4R4G4B4; } } } if (textureType == texData.Type) { List <byte> newTEX = new List <byte>(); int uncompressedLength = (int)new FileInfo(savePath).Length - 128; var DDSInfo = ReadDDS(br, texData, newWidth, newHeight, newMipCount); newTEX.AddRange(MakeType4DATHeader(texData, DDSInfo.Item2, DDSInfo.Item3, uncompressedLength, newMipCount, newWidth, newHeight)); newTEX.AddRange(MakeTextureInfoHeader(texData, newWidth, newHeight, newMipCount)); newTEX.AddRange(DDSInfo.Item1); offset = WriteToDat(newTEX, modEntry, inModList, internalFilePath, category, itemName, lineNum, texData.TEXDatName); } else { FlexibleMessageBox.Show("Incorrect file type \nExpected: " + Info.TextureTypes[texData.Type] + " Given: " + Info.TextureTypes[textureType], "Texture format error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } else { FlexibleMessageBox.Show("Could not find file \n" + savePath, "File read Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return(offset); }
/// <summary> /// Imports VFX files /// </summary> /// <param name="category">The category of the item</param> /// <param name="itemName">The selected items name</param> /// <param name="internalFilePath">The full path of the internal file</param> public static int ImportVFX(TEXData texData, string category, string itemName, string internalFilePath) { JsonEntry modEntry = null; int textureType, newHeight, newWidth, newMipCount; int lineNum = 0; int newOffset = 0; bool inModList = false; string dxPath = Path.GetFileNameWithoutExtension(internalFilePath); var savePath = Properties.Settings.Default.Save_Directory + "/" + category + "/" + itemName + "/" + dxPath + ".dds"; if (File.Exists(savePath)) { List <byte> newVFX = new List <byte>(); List <byte> uncompressedVFX = new List <byte>(); List <byte> headerData = new List <byte>(); List <byte> dataBlocks = new List <byte>(); try { using (StreamReader sr = new StreamReader(Properties.Settings.Default.Modlist_Directory)) { string line; while ((line = sr.ReadLine()) != null) { modEntry = JsonConvert.DeserializeObject <JsonEntry>(line); if (modEntry.fullPath.Equals(internalFilePath)) { inModList = true; break; } lineNum++; } } } catch (Exception ex) { FlexibleMessageBox.Show("Error Accessing .modlist File \n" + ex.Message, "ImportTex Error " + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Error); } using (BinaryReader br = new BinaryReader(File.OpenRead(savePath))) { br.BaseStream.Seek(12, SeekOrigin.Begin); newHeight = br.ReadInt32(); newWidth = br.ReadInt32(); br.ReadBytes(8); newMipCount = br.ReadInt32(); br.BaseStream.Seek(80, SeekOrigin.Begin); var textureFlags = br.ReadInt32(); textureType = Info.DDSType[br.ReadInt32()]; if (textureFlags == 2 && textureType == 5200) { textureType = TextureTypes.A8; } if (textureType == texData.Type) { br.BaseStream.Seek(128, SeekOrigin.Begin); uncompressedVFX.AddRange(MakeTextureInfoHeader(texData, newWidth, newHeight, newMipCount)); int dataLength = (int)new FileInfo(savePath).Length - 128; uncompressedVFX.AddRange(br.ReadBytes(dataLength)); } else { FlexibleMessageBox.Show("Incorrect file type \nExpected: " + Info.TextureTypes[texData.Type] + " Given: " + Info.TextureTypes[textureType], "Texture format error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(0); } } headerData.AddRange(BitConverter.GetBytes(128)); headerData.AddRange(BitConverter.GetBytes(2)); headerData.AddRange(BitConverter.GetBytes(uncompressedVFX.Count)); int dataOffset = 0; int totalCompSize = 0; int uncompressedLength = uncompressedVFX.Count; int partCount = (int)Math.Ceiling(uncompressedLength / 16000f); headerData.AddRange(BitConverter.GetBytes(partCount)); int remainder = uncompressedLength; using (BinaryReader br = new BinaryReader(new MemoryStream(uncompressedVFX.ToArray()))) { br.BaseStream.Seek(0, SeekOrigin.Begin); for (int i = 1; i <= partCount; i++) { if (i == partCount) { var compData = Compressor(br.ReadBytes(remainder)); int padding = 128 - ((compData.Length + 16) % 128); dataBlocks.AddRange(BitConverter.GetBytes(16)); dataBlocks.AddRange(BitConverter.GetBytes(0)); dataBlocks.AddRange(BitConverter.GetBytes(compData.Length)); dataBlocks.AddRange(BitConverter.GetBytes(remainder)); dataBlocks.AddRange(compData); dataBlocks.AddRange(new byte[padding]); headerData.AddRange(BitConverter.GetBytes(dataOffset)); headerData.AddRange(BitConverter.GetBytes((short)((compData.Length + 16) + padding))); headerData.AddRange(BitConverter.GetBytes((short)remainder)); totalCompSize = dataOffset + ((compData.Length + 16) + padding); } else { var compData = Compressor(br.ReadBytes(16000)); int padding = 128 - ((compData.Length + 16) % 128); dataBlocks.AddRange(BitConverter.GetBytes(16)); dataBlocks.AddRange(BitConverter.GetBytes(0)); dataBlocks.AddRange(BitConverter.GetBytes(compData.Length)); dataBlocks.AddRange(BitConverter.GetBytes(16000)); dataBlocks.AddRange(compData); dataBlocks.AddRange(new byte[padding]); headerData.AddRange(BitConverter.GetBytes(dataOffset)); headerData.AddRange(BitConverter.GetBytes((short)((compData.Length + 16) + padding))); headerData.AddRange(BitConverter.GetBytes((short)16000)); dataOffset += ((compData.Length + 16) + padding); remainder -= 16000; } } } headerData.InsertRange(12, BitConverter.GetBytes(totalCompSize / 128)); headerData.InsertRange(16, BitConverter.GetBytes(totalCompSize / 128)); int headerPadding = 128 - headerData.Count; headerData.AddRange(new byte[headerPadding]); newVFX.AddRange(headerData); newVFX.AddRange(dataBlocks); newOffset = WriteToDat(newVFX, modEntry, inModList, internalFilePath, category, itemName, lineNum, texData.TEXDatName); } return(newOffset); }
/// <summary> /// Gets the texture data and displays it for the currently selected item given a specified race, part, type(if applicable), and map /// </summary> private void MapComboBoxChanged() { if (saveClone != null) { //saveClone.UnlockBits(cloneLock); saveClone.Dispose(); } Bitmap colorBmp = null; int offset = 0; bool isVFX = false; bool isUI = false; if (selectedMap.Name.Equals(Strings.Normal)) { fullPath = mtrlData.NormalPath; offset = mtrlData.NormalOffset; FullPathString = fullPath; } else if (selectedMap.Name.Equals(Strings.Specular)) { fullPath = mtrlData.SpecularPath; offset = mtrlData.SpecularOffset; FullPathString = fullPath; } else if (selectedMap.Name.Equals(Strings.Diffuse)) { fullPath = mtrlData.DiffusePath; offset = mtrlData.DiffuseOffset; FullPathString = fullPath; } else if (selectedMap.Name.Equals(Strings.Mask) || selectedMap.Name.Equals(Strings.Skin)) { if (selectedItem.ItemName.Equals(Strings.Face_Paint) || selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { string part; if (selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { if (!SelectedPart.Name.Contains("stigma")) { part = selectedPart.Name.PadLeft(3, '0'); } else { part = SelectedPart.Name; } } else { part = selectedPart.Name; } fullPath = String.Format(mtrlData.MaskPath, part); offset = MTRL.GetDecalOffset(selectedItem.ItemName, selectedPart.Name); } else { fullPath = mtrlData.MaskPath; offset = mtrlData.MaskOffset; } FullPathString = fullPath; } else if (selectedMap.Name.Equals(Strings.ColorSet)) { colorBmp = TEX.TextureToBitmap(mtrlData.ColorData, 9312, 4, 16); fullPath = mtrlData.MTRLPath; FullPathString = fullPath; } else if (SelectedMap.Name.Contains("Icon")) { if (SelectedMap.Name.Contains("HQ")) { fullPath = mtrlData.UIHQPath; offset = mtrlData.UIHQOffset; } else { fullPath = mtrlData.UIPath; offset = mtrlData.UIOffset; } FullPathString = fullPath; isUI = true; } else if (selectedItem.ItemCategory.Equals(Strings.Maps)) { if (selectedMap.Name.Contains("HighRes Map")) { fullPath = string.Format(mtrlData.UIPath, "_m"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("LowRes Map")) { fullPath = string.Format(mtrlData.UIPath, "_s"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("PoI")) { fullPath = string.Format(mtrlData.UIPath, "d"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("HighRes Mask")) { fullPath = string.Format(mtrlData.UIPath, "m_m"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("LowRes Mask")) { fullPath = string.Format(mtrlData.UIPath, "m_s"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } FullPathString = fullPath; isUI = true; } else if (selectedItem.ItemCategory.Equals("HUD") || selectedItem.ItemCategory.Equals("LoadingImage")) { fullPath = mtrlData.UIPath; offset = mtrlData.UIOffset; FullPathString = fullPath; isUI = true; } else { fullPath = SelectedMap.ID; var VFXFolder = fullPath.Substring(0, fullPath.LastIndexOf("/")); var VFXFile = fullPath.Substring(fullPath.LastIndexOf("/") + 1); offset = Helper.GetDataOffset(FFCRC.GetHash(VFXFolder), FFCRC.GetHash(VFXFile), Strings.ItemsDat); FullPathString = fullPath; isVFX = true; } string line; JsonEntry modEntry = null; bool inModList = false; try { using (StreamReader sr = new StreamReader(Properties.Settings.Default.Modlist_Directory)) { while ((line = sr.ReadLine()) != null) { modEntry = JsonConvert.DeserializeObject <JsonEntry>(line); if (modEntry.fullPath.Equals(fullPath)) { inModList = true; break; } } } } catch (Exception ex) { MessageBox.Show("[TVM] Error Accessing .modlist File \n" + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } if (inModList) { var currOffset = Helper.GetDataOffset(FFCRC.GetHash(modEntry.fullPath.Substring(0, modEntry.fullPath.LastIndexOf("/"))), FFCRC.GetHash(Path.GetFileName(modEntry.fullPath)), modEntry.datFile); if (currOffset == modEntry.modOffset) { ActiveToggle = "Disable"; } else if (currOffset == modEntry.originalOffset) { ActiveToggle = "Enable"; } else { ActiveToggle = "Error"; } ActiveEnabled = true; } else { ActiveEnabled = false; ActiveToggle = "Enable/Disable"; } if (offset == 0) { TextureType = "Type: 16.16.16.16f ABGR\nMipMaps: None"; TextureDimensions = "(4 x 16)"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(colorBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); alphaBitmap.Freeze(); var removeAlphaBitmap = SetAlpha(colorBmp, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); noAlphaBitmap.Freeze(); colorBmp.Dispose(); removeAlphaBitmap.Dispose(); } else { if (!isVFX) { if (!isUI) { texData = TEX.GetTex(offset, Strings.ItemsDat); } else { texData = TEX.GetTex(offset, Strings.UIDat); } } else { texData = TEX.GetVFX(offset, Strings.ItemsDat); } string mipMaps = "Yes (" + texData.MipCount + ")"; if (texData.MipCount < 1) { mipMaps = "None"; } TextureType = "Type: " + texData.TypeString + "\nMipMaps: " + mipMaps; TextureDimensions = "(" + texData.Width + " x " + texData.Height + ")"; var clonerect = new Rectangle(0, 0, texData.Width, texData.Height); saveClone = texData.BMP.Clone(new Rectangle(0, 0, texData.Width, texData.Height), PixelFormat.Format32bppArgb); alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(texData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); alphaBitmap.Freeze(); if (!isUI) { var removeAlphaBitmap = SetAlpha(texData.BMP, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); noAlphaBitmap.Freeze(); removeAlphaBitmap.Dispose(); } } try { ImageEffect = new ColorChannels() { Channel = new System.Windows.Media.Media3D.Point4D(1.0f, 1.0f, 1.0f, 0.0f) }; } catch (Exception ex) { Debug.WriteLine(ex.StackTrace); } if (!isUI) { ImageSource = noAlphaBitmap; SetColorChannelFilter(imageEffect); ChannelsEnabled = true; } else { ImageSource = alphaBitmap; SetColorChannelFilter(imageEffect); ChannelsEnabled = true; } SaveEnabled = true; texData.Dispose(); string dxPath = Path.GetFileNameWithoutExtension(fullPath); string savePath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem.ItemName + "/" + dxPath + ".dds"; if (selectedCategory.Equals("UI")) { savePath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem.ItemCategory + "/" + dxPath + ".dds"; } if (File.Exists(savePath)) { ImportEnabled = true; } else { ImportEnabled = false; } string folderPath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem.ItemName; if (selectedCategory.Equals("UI")) { folderPath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem.ItemCategory; } if (Directory.Exists(folderPath)) { OpenEnabled = true; } else { OpenEnabled = false; } }
public void SaveAllDDS() { foreach (var m in MapComboBox) { int offset = 0; if (m.Name.Equals(Strings.Normal)) { fullPath = mtrlData.NormalPath; offset = mtrlData.NormalOffset; } else if (m.Name.Equals(Strings.Specular)) { fullPath = mtrlData.SpecularPath; offset = mtrlData.SpecularOffset; } else if (m.Name.Equals(Strings.Diffuse)) { fullPath = mtrlData.DiffusePath; offset = mtrlData.DiffuseOffset; } else if (m.Name.Equals(Strings.Mask) || m.Name.Equals(Strings.Skin)) { if (selectedItem.ItemName.Equals(Strings.Face_Paint) || selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { string part; if (selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { if (!SelectedPart.Name.Contains("stigma")) { part = selectedPart.Name.PadLeft(3, '0'); } else { part = SelectedPart.Name; } } else { part = selectedPart.Name; } fullPath = String.Format(mtrlData.MaskPath, part); offset = MTRL.GetDecalOffset(selectedItem.ItemName, selectedPart.Name); } else { fullPath = mtrlData.MaskPath; offset = mtrlData.MaskOffset; } } else if (m.Name.Equals(Strings.ColorSet)) { fullPath = mtrlData.MTRLPath; } else if (m.Name.Contains("Icon")) { if (m.Name.Contains("HQ")) { fullPath = mtrlData.UIHQPath; offset = mtrlData.UIHQOffset; } else { fullPath = mtrlData.UIPath; offset = mtrlData.UIOffset; } } else if (selectedItem.ItemCategory.Equals(Strings.Maps)) { if (selectedMap.Name.Contains("HighRes Map")) { fullPath = string.Format(mtrlData.UIPath, "_m"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("LowRes Map")) { fullPath = string.Format(mtrlData.UIPath, "_s"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("PoI")) { fullPath = string.Format(mtrlData.UIPath, "d"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("HighRes Mask")) { fullPath = string.Format(mtrlData.UIPath, "m_m"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } else if (selectedMap.Name.Contains("LowRes Mask")) { fullPath = string.Format(mtrlData.UIPath, "m_s"); offset = mtrlData.UIOffset = int.Parse(selectedMap.ID); } } else if (selectedItem.ItemCategory.Equals("HUD")) { fullPath = mtrlData.UIPath; offset = mtrlData.UIOffset; } else { fullPath = SelectedMap.ID; var VFXFolder = fullPath.Substring(0, fullPath.LastIndexOf("/")); var VFXFile = fullPath.Substring(fullPath.LastIndexOf("/") + 1); offset = Helper.GetDataOffset(FFCRC.GetHash(VFXFolder), FFCRC.GetHash(VFXFile), Strings.ItemsDat); } if (offset != 0) { if (m.ID.Contains("vfx")) { texData = TEX.GetVFX(offset, Strings.ItemsDat); } else { if (selectedCategory.Equals("UI")) { texData = TEX.GetTex(offset, Strings.UIDat); } else { texData = TEX.GetTex(offset, Strings.ItemsDat); } } } SaveTex.SaveDDS(selectedCategory, selectedItem.ItemName, fullPath, m.Name, mtrlData, texData, selectedItem.ItemCategory); } }
/// <summary> /// Updates the displayed image /// </summary> /// <remarks> /// This is called when an image has either been imported or enabled/disabled /// </remarks> /// <param name="offset">The new offset for the image.</param> /// <param name="isColor">Is the image being udpated a color set.</param> public void UpdateImage(int offset, bool isColor) { try { if (isColor) { var colorBMP = MTRL.GetColorBitmap(offset); TextureType = "Type: 16.16.16.16f ABGR\nMipMaps: 0"; TextureDimensions = "(4 x 16)"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(colorBMP.Item1.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); alphaBitmap.Freeze(); var removeAlphaBitmap = SetAlpha(colorBMP.Item1, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); noAlphaBitmap.Freeze(); mtrlData.ColorData = colorBMP.Item2; colorBMP.Item1.Dispose(); removeAlphaBitmap.Dispose(); } else { if (SelectedMap.ID.Contains("vfx")) { texData = TEX.GetVFX(offset, Strings.ItemsDat); } else { if (selectedCategory.Equals("UI")) { texData = TEX.GetTex(offset, Strings.UIDat); } else { texData = TEX.GetTex(offset, Strings.ItemsDat); } } string mipMaps = "Yes (" + texData.MipCount + ")"; if (texData.MipCount < 1) { mipMaps = "None"; } TextureType = "Type: " + texData.TypeString + "\nMipMaps: " + mipMaps; TextureDimensions = "(" + texData.Width + " x " + texData.Height + ")"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(texData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); var removeAlphaBitmap = SetAlpha(texData.BMP, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); texData.Dispose(); removeAlphaBitmap.Dispose(); } if (AlphaChecked) { ImageSource = alphaBitmap; } else { ImageSource = noAlphaBitmap; } } catch (Exception e) { MessageBox.Show("[TVM] There was an error updating the image.\n" + e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// Creates the bitmap data for the model /// </summary> /// <remarks> /// Because the original textures use channel packing, this method gets the pixel data of each texture /// and then recombines them to create the unpacked textures to use in the 3D model. /// <see cref="http://wiki.polycount.com/wiki/ChannelPacking"/> /// </remarks> /// <param name="normalTexData">The texture data of the normal map</param> /// <param name="diffuseTexData">The texture data of the diffuse map</param> /// <param name="maskTexData">The texture data of the mask map</param> /// <param name="specularTexData">The texture data of the specular map</param> /// <param name="colorMap">The bitmap of the color map</param> /// <returns>An array of bitmaps to be used on the model</returns> public static BitmapSource[] MakeModelTextureMaps(TEXData normalTexData, TEXData diffuseTexData, TEXData maskTexData, TEXData specularTexData, MTRLData mtrlData) { int height = normalTexData.Height; int width = normalTexData.Width; int tSize = height * width; var normalBitmap = normalTexData.BMPSouceAlpha; if (diffuseTexData != null && (diffuseTexData.Height * diffuseTexData.Width) > tSize) { height = diffuseTexData.Height; width = diffuseTexData.Width; tSize = height * width; } if (maskTexData != null && (maskTexData.Height * maskTexData.Width) > tSize) { height = maskTexData.Height; width = maskTexData.Width; tSize = height * width; } if (specularTexData != null && (specularTexData.Height * specularTexData.Width) > tSize) { height = specularTexData.Height; width = specularTexData.Width; tSize = height * width; } byte[] maskPixels = null; byte[] specularPixels = null; byte[] normalPixels = null; byte[] diffusePixels = null; List <System.Drawing.Color> colorList = new List <System.Drawing.Color>(); List <System.Drawing.Color> specularList = new List <System.Drawing.Color>(); List <System.Drawing.Color> emissiveList = new List <System.Drawing.Color>(); BitmapSource[] texBitmaps = new BitmapSource[5]; if (mtrlData.ColorData != null) { BitmapSource colorMap1; using (var colorBitmap = TEX.ColorSetToBitmap(mtrlData.ColorData)) { SetAlpha(colorBitmap, 255); colorMap1 = CreateBitmapSource(colorBitmap); } int colorSetStride = colorMap1.PixelWidth * (colorMap1.Format.BitsPerPixel / 8); byte[] colorPixels = new byte[colorMap1.PixelHeight * colorSetStride]; colorMap1.CopyPixels(colorPixels, colorSetStride, 0); for (int i = 0; i < colorPixels.Length; i += 16) { int red = colorPixels[i + 2]; int green = colorPixels[i + 1]; int blue = colorPixels[i]; int alpha = colorPixels[i + 3]; colorList.Add(System.Drawing.Color.FromArgb(255, red, green, blue)); red = colorPixels[i + 6]; green = colorPixels[i + 5]; blue = colorPixels[i + 4]; alpha = colorPixels[i + 7]; specularList.Add(System.Drawing.Color.FromArgb(255, red, green, blue)); var r1 = colorPixels[i + 10]; var g1 = colorPixels[i + 9]; var b1 = colorPixels[i + 8]; var a1 = colorPixels[i + 11]; emissiveList.Add(System.Drawing.Color.FromArgb(255, r1, g1, b1)); } } else if (mtrlData.ColorData == null) { for (int i = 0; i < 1024; i += 16) { colorList.Add(System.Drawing.Color.FromArgb(255, 255, 255, 255)); specularList.Add(System.Drawing.Color.FromArgb(255, 0, 0, 0)); emissiveList.Add(System.Drawing.Color.FromArgb(255, 0, 0, 0)); } } if (maskTexData != null) { if (tSize > (maskTexData.Height * maskTexData.Width)) { var resized = CreateResizedImage(maskTexData.BMPSouceAlpha, width, height); maskPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { maskPixels = GetBytesFromBitmapSource(maskTexData.BMPSouceAlpha); } } if (diffuseTexData != null) { if (tSize > (diffuseTexData.Height * diffuseTexData.Width)) { var resized = CreateResizedImage(diffuseTexData.BMPSouceAlpha, width, height); diffusePixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { diffusePixels = GetBytesFromBitmapSource(diffuseTexData.BMPSouceAlpha); } } if (specularTexData != null) { if (tSize > (specularTexData.Height * specularTexData.Width)) { var resized = CreateResizedImage(specularTexData.BMPSouceAlpha, width, height); specularPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { specularPixels = GetBytesFromBitmapSource(specularTexData.BMPSouceAlpha); } } if (normalTexData != null) { if (tSize > (normalTexData.Height * normalTexData.Width)) { var resized = CreateResizedImage(normalTexData.BMPSouceAlpha, width, height); normalBitmap = (BitmapSource)resized; normalPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { normalPixels = GetBytesFromBitmapSource(normalTexData.BMPSouceAlpha); } } List <byte> diffuseMap = new List <byte>(); List <byte> specularMap = new List <byte>(); List <byte> emissiveMap = new List <byte>(); List <byte> alphaMap = new List <byte>(); float R = 1; float G = 1; float B = 1; float R1 = 1; float G1 = 1; float B1 = 1; for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i - 3]; if (maskTexData != null) { B = maskPixels[i - 1]; R = maskPixels[i - 1]; G = maskPixels[i - 1]; B1 = maskPixels[i - 3]; R1 = maskPixels[i - 3]; G1 = maskPixels[i - 3]; } else { if (diffusePixels != null) { B = diffusePixels[i - 3]; G = diffusePixels[i - 2]; R = diffusePixels[i - 1]; } else { B = 255; G = 255; R = 255; } if (specularPixels != null) { B1 = specularPixels[i - 2]; G1 = specularPixels[i - 2]; R1 = specularPixels[i - 2]; } else { B1 = 255; G1 = 255; R1 = 255; } } System.Drawing.Color diffuseColor; System.Drawing.Color specularColor; System.Drawing.Color emissiveColor; System.Drawing.Color alphaColor; float pixel = (normalPixels[i] / 255f) * 15f; //int colorLoc = (int)Math.Floor(pixel + 0.5f); float percent = (float)(pixel - Math.Truncate(pixel)); if (percent != 0) { var color2Loc = (int)(Math.Truncate(pixel)); var color1Loc = color2Loc + 1; var color1 = System.Drawing.Color.FromArgb(alpha, colorList[color1Loc].R, colorList[color1Loc].G, colorList[color1Loc].B); var color2 = System.Drawing.Color.FromArgb(alpha, colorList[color2Loc].R, colorList[color2Loc].G, colorList[color2Loc].B); var diffuseBlend = Blend(color1, color2, percent); color1 = System.Drawing.Color.FromArgb(255, specularList[color1Loc].R, specularList[color1Loc].G, specularList[color1Loc].B); color2 = System.Drawing.Color.FromArgb(255, specularList[color2Loc].R, specularList[color2Loc].G, specularList[color2Loc].B); var specBlend = Blend(color1, color2, percent); color1 = System.Drawing.Color.FromArgb(255, emissiveList[color1Loc].R, emissiveList[color1Loc].G, emissiveList[color1Loc].B); color2 = System.Drawing.Color.FromArgb(255, emissiveList[color2Loc].R, emissiveList[color2Loc].G, emissiveList[color2Loc].B); var emisBlend = Blend(color1, color2, percent); diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((diffuseBlend.R / 255f) * R), (int)((diffuseBlend.G / 255f) * G), (int)((diffuseBlend.B / 255f) * B)); specularColor = System.Drawing.Color.FromArgb(255, (int)((specBlend.R / 255f) * R1), (int)((specBlend.G / 255f) * G1), (int)((specBlend.B / 255f) * B1)); emissiveColor = System.Drawing.Color.FromArgb(255, emisBlend.R, emisBlend.G, emisBlend.B); } else { var colorLoc = (int)Math.Floor(pixel + 0.5f); diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((colorList[colorLoc].R / 255f) * R), (int)((colorList[colorLoc].G / 255f) * G), (int)((colorList[colorLoc].B / 255f) * B)); specularColor = System.Drawing.Color.FromArgb(255, (int)((specularList[colorLoc].R / 255f) * R1), (int)((specularList[colorLoc].G / 255f) * G1), (int)((specularList[colorLoc].B / 255f) * B1)); emissiveColor = System.Drawing.Color.FromArgb(255, emissiveList[colorLoc].R, emissiveList[colorLoc].G, emissiveList[colorLoc].B); } alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); emissiveMap.AddRange(BitConverter.GetBytes(emissiveColor.ToArgb())); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } int stride = (int)normalBitmap.Width * (32 / 8); var scale = 1; if (width >= 4096 || height >= 4096) { scale = 4; } else if (width >= 2048 || height >= 2048) { scale = 2; } var nWidth = width / scale; var nHeight = height / scale; BitmapSource bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, specularMap.ToArray(), stride); texBitmaps[1] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); //texBitmaps[2] = normalTexData.BMPSouceNoAlpha; texBitmaps[2] = (BitmapSource)CreateResizedImage(normalTexData.BMPSouceNoAlpha, nWidth, nHeight); bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, alphaMap.ToArray(), stride); texBitmaps[3] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, emissiveMap.ToArray(), stride); texBitmaps[4] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); foreach (var tb in texBitmaps) { tb.Freeze(); } return(texBitmaps); }
/// <summary> /// Gets the texture data and displays it for the currently selected item given a specified race, part, type(if applicable), and map /// </summary> private void MapComboBoxChanged() { Bitmap colorBmp = null; int offset = 0; bool isVFX = false; if (selectedMap.Name.Equals(Strings.Normal)) { fullPath = mtrlData.NormalPath; offset = mtrlData.NormalOffset; FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } else if (selectedMap.Name.Equals(Strings.Specular)) { fullPath = mtrlData.SpecularPath; offset = mtrlData.SpecularOffset; FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } else if (selectedMap.Name.Equals(Strings.Diffuse)) { fullPath = mtrlData.DiffusePath; offset = mtrlData.DiffuseOffset; FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } else if (selectedMap.Name.Equals(Strings.Mask) || selectedMap.Name.Equals(Strings.Skin)) { if (selectedItem.ItemName.Equals(Strings.Face_Paint) || selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { string part; if (selectedItem.ItemName.Equals(Strings.Equipment_Decals)) { part = selectedPart.Name.PadLeft(3, '0'); } else { part = selectedPart.Name; } fullPath = String.Format(mtrlData.MaskPath, part); offset = MTRL.GetDecalOffset(selectedItem.ItemName, selectedPart.Name); FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } else { fullPath = mtrlData.MaskPath; offset = mtrlData.MaskOffset; FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } } else if (selectedMap.Name.Equals(Strings.ColorSet)) { colorBmp = TEX.TextureToBitmap(mtrlData.ColorData, 9312, 4, 16); fullPath = mtrlData.MTRLPath; FullPathString = fullPath + " [" + FFCRC.GetHash(fullPath) + "]"; } else { fullPath = SelectedMap.ID; var VFXFolder = fullPath.Substring(0, fullPath.LastIndexOf("/")); var VFXFile = fullPath.Substring(fullPath.LastIndexOf("/") + 1); offset = Helper.GetItemOffset(FFCRC.GetHash(VFXFolder), FFCRC.GetHash(VFXFile)); FullPathString = fullPath; isVFX = true; } if (Properties.Settings.Default.Mod_List == 0) { string line; JsonEntry modEntry = null; bool inModList = false; try { using (StreamReader sr = new StreamReader(Info.modListDir)) { while ((line = sr.ReadLine()) != null) { modEntry = JsonConvert.DeserializeObject <JsonEntry>(line); if (modEntry.fullPath.Equals(fullPath)) { inModList = true; break; } } } } catch (Exception ex) { MessageBox.Show("[Main] Error Accessing .modlist File \n" + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } if (inModList) { var currOffset = Helper.GetItemOffset(FFCRC.GetHash(modEntry.fullPath.Substring(0, modEntry.fullPath.LastIndexOf("/"))), FFCRC.GetHash(Path.GetFileName(modEntry.fullPath))); if (currOffset == modEntry.modOffset) { ActiveToggle = "Disable"; } else if (currOffset == modEntry.originalOffset) { ActiveToggle = "Enable"; } else { ActiveToggle = "Error"; } ActiveEnabled = true; } else { ActiveEnabled = false; ActiveToggle = "Enable/Disable"; } } else { ActiveEnabled = false; ActiveToggle = "Enable/Disable"; } if (offset == 0) { TextureType = "A16B16G16R16F"; textureType = "A16B16G16R16F"; TextureDimensions = "(4 x 16)"; textureDimensions = "(4 x 16)"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(colorBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); var removeAlphaBitmap = SetAlpha(colorBmp, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); colorBmp.Dispose(); removeAlphaBitmap.Dispose(); } else { if (!isVFX) { texData = TEX.GetTex(offset); } else { texData = TEX.GetVFX(offset); } TextureType = texData.TypeString; TextureDimensions = "(" + texData.Width + " x " + texData.Height + ")"; alphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(texData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); var removeAlphaBitmap = SetAlpha(texData.BMP, 255); noAlphaBitmap = Imaging.CreateBitmapSourceFromHBitmap(removeAlphaBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); removeAlphaBitmap.Dispose(); } try { ImageEffect = new ColorChannels() { Channel = new System.Windows.Media.Media3D.Point4D(1.0f, 1.0f, 1.0f, 0.0f) }; } catch (Exception ex) { Debug.WriteLine(ex.StackTrace); } ImageSource = noAlphaBitmap; SetColorChannelFilter(); SaveEnabled = true; texData.Dispose(); string dxPath = Path.GetFileNameWithoutExtension(fullPath); if (File.Exists(Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem.ItemName + "/" + dxPath + ".dds")) { ImportEnabled = true; } else { ImportEnabled = false; } }
/// <summary> /// Saves the currently displayed texture map as a DDS file. /// </summary> /// <param name="selectedCategory">The items category.</param> /// <param name="selectedItem">The currently selected item.</param> /// <param name="internalFilePath">The internal file path of the texture map.</param> /// <param name="textureMap">The name of the currently selected texture map.</param> /// <param name="mtrlData">The items mtrl file data</param> /// <param name="texData">The items tex file data</param> public static void SaveDDS(string selectedCategory, string selectedItem, string internalFilePath, string textureMap, MTRLData mtrlData, TEXData texData) { string savePath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem; Directory.CreateDirectory(savePath); var fullSavePath = Path.Combine(savePath, (Path.GetFileNameWithoutExtension(internalFilePath) + ".dds")); List <byte> DDS = new List <byte>(); if (textureMap.Equals(Strings.ColorSet)) { if (mtrlData.ColorFlags != null) { var colorFlagsDir = Path.Combine(savePath, (Path.GetFileNameWithoutExtension(internalFilePath) + ".dat")); File.WriteAllBytes(colorFlagsDir, mtrlData.ColorFlags); } DDS.AddRange(CreateColorDDSHeader()); DDS.AddRange(mtrlData.ColorData); } else { DDS.AddRange(CreateDDSHeader(texData)); DDS.AddRange(texData.RawTexData); } File.WriteAllBytes(fullSavePath, DDS.ToArray()); }
/// <summary> /// Gets the model data and sets the display viewmodel /// </summary> private void MeshComboBoxChanged() { if (!is3DLoaded) { disposing = false; meshData = new List <MDLTEXData>(); for (int i = 0; i < meshList.Count; i++) { BitmapSource specularBMP = null; BitmapSource diffuseBMP = null; BitmapSource normalBMP = null; BitmapSource colorBMP = null; BitmapSource alphaBMP = null; BitmapSource maskBMP = null; TEXData specularData = null; TEXData diffuseData = null; TEXData normalData = null; TEXData maskData = null; bool isBody = false; bool isFace = false; MTRLData mtrlData = MTRL3D(i); if (selectedCategory.Equals(Strings.Character)) { if (selectedItem.ItemName.Equals(Strings.Tail) || selectedItem.ItemName.Equals(Strings.Hair)) { normalData = TEX.GetTex(mtrlData.NormalOffset); specularData = TEX.GetTex(mtrlData.SpecularOffset); if (mtrlData.DiffusePath != null) { diffuseData = TEX.GetTex(mtrlData.DiffuseOffset); } var maps = TexHelper.MakeCharacterMaps(normalData, diffuseData, null, specularData); diffuseBMP = maps[0]; specularBMP = maps[1]; normalBMP = maps[2]; alphaBMP = maps[3]; specularData.Dispose(); normalData.Dispose(); if (diffuseData != null) { diffuseData.Dispose(); } } if (selectedItem.ItemName.Equals(Strings.Body)) { normalData = TEX.GetTex(mtrlData.NormalOffset); //specularTI = TEX.GetTex(mInfo.SpecularOffset); diffuseData = TEX.GetTex(mtrlData.DiffuseOffset); isBody = true; diffuseBMP = Imaging.CreateBitmapSourceFromHBitmap(diffuseData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); normalBMP = Imaging.CreateBitmapSourceFromHBitmap(normalData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } if (selectedItem.ItemName.Equals(Strings.Face)) { normalData = TEX.GetTex(mtrlData.NormalOffset); if (materialStrings[i].Contains("_fac_")) { specularData = TEX.GetTex(mtrlData.SpecularOffset); diffuseData = TEX.GetTex(mtrlData.DiffuseOffset); var maps = TexHelper.MakeCharacterMaps(normalData, diffuseData, null, specularData); diffuseBMP = maps[0]; specularBMP = maps[1]; normalBMP = maps[2]; alphaBMP = maps[3]; isFace = true; specularData.Dispose(); diffuseData.Dispose(); } else { specularData = TEX.GetTex(mtrlData.SpecularOffset); var maps = TexHelper.MakeCharacterMaps(normalData, diffuseData, null, specularData); diffuseBMP = maps[0]; specularBMP = maps[1]; normalBMP = maps[2]; alphaBMP = maps[3]; } } } else { if (mtrlData.ColorData != null) { var colorBmp = TEX.TextureToBitmap(mtrlData.ColorData, 9312, 4, 16); colorBMP = Imaging.CreateBitmapSourceFromHBitmap(colorBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } if (mtrlData.NormalOffset != 0) { normalData = TEX.GetTex(mtrlData.NormalOffset); } if (mtrlData.MaskOffset != 0) { maskData = TEX.GetTex(mtrlData.MaskOffset); maskBMP = Imaging.CreateBitmapSourceFromHBitmap(maskData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } if (mtrlData.DiffuseOffset != 0) { diffuseData = TEX.GetTex(mtrlData.DiffuseOffset); if (mtrlData.DiffusePath.Contains("human") && !mtrlData.DiffusePath.Contains("demi")) { isBody = true; diffuseBMP = Imaging.CreateBitmapSourceFromHBitmap(diffuseData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); normalBMP = Imaging.CreateBitmapSourceFromHBitmap(normalData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } } if (mtrlData.SpecularOffset != 0) { specularData = TEX.GetTex(mtrlData.SpecularOffset); specularBMP = Imaging.CreateBitmapSourceFromHBitmap(specularData.BMP.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } if (!isBody && specularData == null) { var maps = TexHelper.MakeModelTextureMaps(normalData, diffuseData, maskData, null, colorBMP); diffuseBMP = maps[0]; specularBMP = maps[1]; normalBMP = maps[2]; alphaBMP = maps[3]; } else if (!isBody && specularData != null) { var maps = TexHelper.MakeModelTextureMaps(normalData, diffuseData, null, specularData, colorBMP); diffuseBMP = maps[0]; specularBMP = maps[1]; normalBMP = maps[2]; alphaBMP = maps[3]; } if (normalData != null) { normalData.Dispose(); } if (maskData != null) { maskData.Dispose(); } if (diffuseData != null) { diffuseData.Dispose(); } if (specularData != null) { specularData.Dispose(); } } var mData = new MDLTEXData() { Specular = specularBMP, ColorTable = colorBMP, Diffuse = diffuseBMP, Normal = normalBMP, Alpha = alphaBMP, Mask = maskBMP, IsBody = isBody, IsFace = isFace, Mesh = meshList[i] }; meshData.Add(mData); } CompositeVM = new Composite3DViewModel(meshData); is3DLoaded = true; ReflectionAmount = String.Format("{0:.##}", CompositeVM.SecondModelMaterial.SpecularShininess); try { } catch (Exception ex) { MessageBox.Show("[Main] mesh 3D Error \n" + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } else { CompositeVM.Rendering(SelectedMesh.Name); } }
/// <summary> /// Creates the bitmap data for the model /// </summary> /// <remarks> /// Because the original textures use channel packing, this method gets the pixel data of each texture /// and then recombines them to create the unpacked textures to use in the 3D model. /// <see cref="http://wiki.polycount.com/wiki/ChannelPacking"/> /// </remarks> /// <param name="normalTexData">The texture data of the normal map</param> /// <param name="diffuseTexData">The texture data of the diffuse map</param> /// <param name="maskTexData">The texture data of the mask map</param> /// <param name="specularTexData">The texture data of the specular map</param> /// <param name="colorMap">The bitmap of the color map</param> /// <returns>An array of bitmaps to be used on the model</returns> public static BitmapSource[] MakeModelTextureMaps(TEXData normalTexData, TEXData diffuseTexData, TEXData maskTexData, TEXData specularTexData, MTRLData mtrlData) { int height = normalTexData.Height; int width = normalTexData.Width; int tSize = height * width; Bitmap normalBitmap = null; if (diffuseTexData != null && (diffuseTexData.Height * diffuseTexData.Width) > tSize) { height = diffuseTexData.Height; width = diffuseTexData.Width; tSize = height * width; } if (maskTexData != null && (maskTexData.Height * maskTexData.Width) > tSize) { height = maskTexData.Height; width = maskTexData.Width; tSize = height * width; } if (specularTexData != null && (specularTexData.Height * specularTexData.Width) > tSize) { height = specularTexData.Height; width = specularTexData.Width; tSize = height * width; } byte[] maskPixels = null; byte[] specularPixels = null; byte[] normalPixels = null; byte[] diffusePixels = null; List <System.Drawing.Color> colorList = new List <System.Drawing.Color>(); List <System.Drawing.Color> specularList = new List <System.Drawing.Color>(); List <System.Drawing.Color> emissiveList = new List <System.Drawing.Color>(); BitmapSource[] texBitmaps = new BitmapSource[5]; if (mtrlData.ColorData != null) { var colorBitmap = TEX.TextureToBitmap(mtrlData.ColorData, 9312, 4, 16); var cbmp = SetAlpha(colorBitmap, 255); var colorMap1 = Imaging.CreateBitmapSourceFromHBitmap(cbmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); int colorSetStride = colorMap1.PixelWidth * (colorMap1.Format.BitsPerPixel / 8); byte[] colorPixels = new byte[colorMap1.PixelHeight * colorSetStride]; colorMap1.CopyPixels(colorPixels, colorSetStride, 0); for (int i = 0; i < colorPixels.Length; i += 16) { int red = colorPixels[i + 2]; int green = colorPixels[i + 1]; int blue = colorPixels[i]; int alpha = colorPixels[i + 3]; colorList.Add(System.Drawing.Color.FromArgb(255, red, green, blue)); red = colorPixels[i + 6]; green = colorPixels[i + 5]; blue = colorPixels[i + 4]; alpha = colorPixels[i + 7]; specularList.Add(System.Drawing.Color.FromArgb(255, red, green, blue)); var r1 = colorPixels[i + 10]; var g1 = colorPixels[i + 9]; var b1 = colorPixels[i + 8]; var a1 = colorPixels[i + 11]; emissiveList.Add(System.Drawing.Color.FromArgb(255, r1, g1, b1)); } } else if (mtrlData.ColorData == null) { for (int i = 0; i < 1024; i += 16) { colorList.Add(System.Drawing.Color.FromArgb(255, 255, 255, 255)); specularList.Add(System.Drawing.Color.FromArgb(255, 0, 0, 0)); emissiveList.Add(System.Drawing.Color.FromArgb(255, 0, 0, 0)); } } if (maskTexData != null) { if (tSize > (maskTexData.Height * maskTexData.Width)) { var maskBitmap = ResizeImage(Image.FromHbitmap(maskTexData.BMP.GetHbitmap()), width, height); var maskData = maskBitmap.LockBits(new System.Drawing.Rectangle(0, 0, maskBitmap.Width, maskBitmap.Height), ImageLockMode.ReadOnly, maskBitmap.PixelFormat); var bitmapLength = maskData.Stride * maskData.Height; maskPixels = new byte[bitmapLength]; Marshal.Copy(maskData.Scan0, maskPixels, 0, bitmapLength); maskBitmap.UnlockBits(maskData); } else { var maskData = maskTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, maskTexData.Width, maskTexData.Height), ImageLockMode.ReadOnly, maskTexData.BMP.PixelFormat); var bitmapLength = maskData.Stride * maskData.Height; maskPixels = new byte[bitmapLength]; Marshal.Copy(maskData.Scan0, maskPixels, 0, bitmapLength); maskTexData.BMP.UnlockBits(maskData); } } if (diffuseTexData != null) { if (tSize > (diffuseTexData.Height * diffuseTexData.Width)) { var diffuseBitmap = ResizeImage(Image.FromHbitmap(diffuseTexData.BMP.GetHbitmap()), width, height); var diffData = diffuseBitmap.LockBits(new System.Drawing.Rectangle(0, 0, diffuseBitmap.Width, diffuseBitmap.Height), ImageLockMode.ReadOnly, diffuseBitmap.PixelFormat); var bitmapLength = diffData.Stride * diffData.Height; diffusePixels = new byte[bitmapLength]; Marshal.Copy(diffData.Scan0, diffusePixels, 0, bitmapLength); diffuseBitmap.UnlockBits(diffData); } else { var diffData = diffuseTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, diffuseTexData.Width, diffuseTexData.Height), ImageLockMode.ReadOnly, diffuseTexData.BMP.PixelFormat); var bitmapLength = diffData.Stride * diffData.Height; diffusePixels = new byte[bitmapLength]; Marshal.Copy(diffData.Scan0, diffusePixels, 0, bitmapLength); diffuseTexData.BMP.UnlockBits(diffData); } } if (specularTexData != null) { if (tSize > (specularTexData.Height * specularTexData.Width)) { var specularBitmap = ResizeImage(Image.FromHbitmap(specularTexData.BMP.GetHbitmap()), width, height); var specData = specularBitmap.LockBits(new System.Drawing.Rectangle(0, 0, specularBitmap.Width, specularBitmap.Height), ImageLockMode.ReadOnly, specularBitmap.PixelFormat); var bitmapLength = specData.Stride * specData.Height; specularPixels = new byte[bitmapLength]; Marshal.Copy(specData.Scan0, specularPixels, 0, bitmapLength); specularBitmap.UnlockBits(specData); } else { var specData = specularTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, specularTexData.BMP.Width, specularTexData.BMP.Height), ImageLockMode.ReadOnly, specularTexData.BMP.PixelFormat); var bitmapLength = specData.Stride * specData.Height; specularPixels = new byte[bitmapLength]; Marshal.Copy(specData.Scan0, specularPixels, 0, bitmapLength); specularTexData.BMP.UnlockBits(specData); } } if (normalTexData != null) { if (tSize > (normalTexData.Height * normalTexData.Width)) { var normBitmap = ResizeImage(Image.FromHbitmap(normalTexData.BMP.GetHbitmap()), width, height); var normalData = normBitmap.LockBits(new System.Drawing.Rectangle(0, 0, normBitmap.Width, normBitmap.Height), ImageLockMode.ReadOnly, normBitmap.PixelFormat); var bitmapLength = normalData.Stride * normalData.Height; normalPixels = new byte[bitmapLength]; Marshal.Copy(normalData.Scan0, normalPixels, 0, bitmapLength); normBitmap.UnlockBits(normalData); normalBitmap = normBitmap; } else { var normalData = normalTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, normalTexData.Width, normalTexData.Height), ImageLockMode.ReadOnly, normalTexData.BMP.PixelFormat); var bitmapLength = normalData.Stride * normalData.Height; normalPixels = new byte[bitmapLength]; Marshal.Copy(normalData.Scan0, normalPixels, 0, bitmapLength); normalTexData.BMP.UnlockBits(normalData); normalBitmap = normalTexData.BMP; } } List <byte> diffuseMap = new List <byte>(); List <byte> specularMap = new List <byte>(); List <byte> emissiveMap = new List <byte>(); List <byte> alphaMap = new List <byte>(); float R = 1; float G = 1; float B = 1; float R1 = 1; float G1 = 1; float B1 = 1; for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i - 3]; if (maskTexData != null) { B = maskPixels[i - 1]; R = maskPixels[i - 1]; G = maskPixels[i - 1]; B1 = maskPixels[i - 3]; R1 = maskPixels[i - 3]; G1 = maskPixels[i - 3]; } else { if (diffusePixels != null) { B = diffusePixels[i - 3]; G = diffusePixels[i - 2]; R = diffusePixels[i - 1]; } else { B = 255; G = 255; R = 255; } if (specularPixels != null) { B1 = specularPixels[i - 2]; G1 = specularPixels[i - 2]; R1 = specularPixels[i - 2]; } else { B1 = 255; G1 = 255; R1 = 255; } } System.Drawing.Color diffuseColor; System.Drawing.Color specularColor; System.Drawing.Color emissiveColor; System.Drawing.Color alphaColor; float pixel = (normalPixels[i] / 255f) * 15f; //int colorLoc = (int)Math.Floor(pixel + 0.5f); float percent = (float)(pixel - Math.Truncate(pixel)); if (percent != 0) { var color2Loc = (int)(Math.Truncate(pixel)); var color1Loc = color2Loc + 1; var color1 = System.Drawing.Color.FromArgb(alpha, colorList[color1Loc].R, colorList[color1Loc].G, colorList[color1Loc].B); var color2 = System.Drawing.Color.FromArgb(alpha, colorList[color2Loc].R, colorList[color2Loc].G, colorList[color2Loc].B); var diffuseBlend = Blend(color1, color2, percent); color1 = System.Drawing.Color.FromArgb(255, specularList[color1Loc].R, specularList[color1Loc].G, specularList[color1Loc].B); color2 = System.Drawing.Color.FromArgb(255, specularList[color2Loc].R, specularList[color2Loc].G, specularList[color2Loc].B); var specBlend = Blend(color1, color2, percent); color1 = System.Drawing.Color.FromArgb(255, emissiveList[color1Loc].R, emissiveList[color1Loc].G, emissiveList[color1Loc].B); color2 = System.Drawing.Color.FromArgb(255, emissiveList[color2Loc].R, emissiveList[color2Loc].G, emissiveList[color2Loc].B); var emisBlend = Blend(color1, color2, percent); diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((diffuseBlend.R / 255f) * R), (int)((diffuseBlend.G / 255f) * G), (int)((diffuseBlend.B / 255f) * B)); specularColor = System.Drawing.Color.FromArgb(255, (int)((specBlend.R / 255f) * R1), (int)((specBlend.G / 255f) * G1), (int)((specBlend.B / 255f) * B1)); emissiveColor = System.Drawing.Color.FromArgb(255, emisBlend.R, emisBlend.G, emisBlend.B); } else { var colorLoc = (int)Math.Floor(pixel + 0.5f); diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((colorList[colorLoc].R / 255f) * R), (int)((colorList[colorLoc].G / 255f) * G), (int)((colorList[colorLoc].B / 255f) * B)); specularColor = System.Drawing.Color.FromArgb(255, (int)((specularList[colorLoc].R / 255f) * R1), (int)((specularList[colorLoc].G / 255f) * G1), (int)((specularList[colorLoc].B / 255f) * B1)); emissiveColor = System.Drawing.Color.FromArgb(255, emissiveList[colorLoc].R, emissiveList[colorLoc].G, emissiveList[colorLoc].B); } alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); emissiveMap.AddRange(BitConverter.GetBytes(emissiveColor.ToArgb())); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } int stride = normalBitmap.Width * (32 / 8); BitmapSource bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = bitmapSource; bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, specularMap.ToArray(), stride); texBitmaps[1] = bitmapSource; var noAlphaNormal = SetAlpha(normalBitmap, 255); texBitmaps[2] = Imaging.CreateBitmapSourceFromHBitmap(noAlphaNormal.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, alphaMap.ToArray(), stride); texBitmaps[3] = bitmapSource; bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, emissiveMap.ToArray(), stride); texBitmaps[4] = bitmapSource; if (normalTexData != null) { normalTexData.Dispose(); } if (normalBitmap != null) { normalBitmap.Dispose(); } if (diffuseTexData != null) { diffuseTexData.Dispose(); } if (maskTexData != null) { maskTexData.Dispose(); } if (specularTexData != null) { specularTexData.Dispose(); } foreach (var tb in texBitmaps) { tb.Freeze(); } return(texBitmaps); }
/// <summary> /// Creates the bitmap data for the models in the character category /// </summary> /// <remarks> /// Because the original textures use channel packing, this method gets the pixel data of each texture /// and then recombines them to create the unpacked textures to use in the 3D model. /// <see cref="http://wiki.polycount.com/wiki/ChannelPacking"/> /// </remarks> /// <param name="normalTexData">The texture data of the normal map</param> /// <param name="diffuseTexData">The texture data of the diffuse map</param> /// <param name="maskTexData">The texture data of the mask map</param> /// <param name="specularTexData">The texture data of the normal map</param> /// <returns>An array of bitmaps to be used on the model</returns> public static BitmapSource[] MakeCharacterMaps(TEXData normalTexData, TEXData diffuseTexData, TEXData maskTexData, TEXData specularTexData) { int height = normalTexData.Height; int width = normalTexData.Width; int tSize = height * width; Bitmap normalBitmap = null; if (diffuseTexData != null && (diffuseTexData.Height * diffuseTexData.Width) > tSize) { height = diffuseTexData.Height; width = diffuseTexData.Width; tSize = height * width; } if (maskTexData != null && (maskTexData.Height * maskTexData.Width) > tSize) { height = maskTexData.Height; width = maskTexData.Width; tSize = height * width; } if (specularTexData != null && (specularTexData.Height * specularTexData.Width) > tSize) { height = specularTexData.Height; width = specularTexData.Width; tSize = height * width; } byte[] maskPixels = null; byte[] specularPixels = null; byte[] normalPixels = null; byte[] diffusePixels = null; BitmapSource[] texBitmaps = new BitmapSource[4]; if (maskTexData != null) { if (tSize > (maskTexData.Height * maskTexData.Width)) { var maskBitmap = ResizeImage(Image.FromHbitmap(maskTexData.BMP.GetHbitmap()), width, height); var maskData = maskBitmap.LockBits(new System.Drawing.Rectangle(0, 0, maskBitmap.Width, maskBitmap.Height), ImageLockMode.ReadOnly, maskBitmap.PixelFormat); var bitmapLength = maskData.Stride * maskData.Height; maskPixels = new byte[bitmapLength]; Marshal.Copy(maskData.Scan0, maskPixels, 0, bitmapLength); maskBitmap.UnlockBits(maskData); } else { var maskData = maskTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, maskTexData.Width, maskTexData.Height), ImageLockMode.ReadOnly, maskTexData.BMP.PixelFormat); var bitmapLength = maskData.Stride * maskData.Height; maskPixels = new byte[bitmapLength]; Marshal.Copy(maskData.Scan0, maskPixels, 0, bitmapLength); maskTexData.BMP.UnlockBits(maskData); } } if (diffuseTexData != null) { try { if (tSize > (diffuseTexData.Height * diffuseTexData.Width)) { var diffuseBitmap = ResizeImage(Image.FromHbitmap(diffuseTexData.BMP.GetHbitmap()), width, height); var diffuseData = diffuseBitmap.LockBits(new System.Drawing.Rectangle(0, 0, diffuseBitmap.Width, diffuseBitmap.Height), ImageLockMode.ReadOnly, diffuseBitmap.PixelFormat); var bitmapLength = diffuseData.Stride * diffuseData.Height; diffusePixels = new byte[bitmapLength]; Marshal.Copy(diffuseData.Scan0, diffusePixels, 0, bitmapLength); diffuseBitmap.UnlockBits(diffuseData); } else { var diffuseData = diffuseTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, diffuseTexData.Width, diffuseTexData.Height), ImageLockMode.ReadOnly, diffuseTexData.BMP.PixelFormat); var bitmapLength = diffuseData.Stride * diffuseData.Height; diffusePixels = new byte[bitmapLength]; Marshal.Copy(diffuseData.Scan0, diffusePixels, 0, bitmapLength); diffuseTexData.BMP.UnlockBits(diffuseData); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } } if (specularTexData != null) { try { if (tSize > (specularTexData.Height * specularTexData.Width)) { var specularBitmap = ResizeImage(Image.FromHbitmap(specularTexData.BMP.GetHbitmap()), width, height); var specularData = specularBitmap.LockBits(new System.Drawing.Rectangle(0, 0, specularBitmap.Width, specularBitmap.Height), ImageLockMode.ReadOnly, specularBitmap.PixelFormat); var bitmapLength = specularData.Stride * specularData.Height; specularPixels = new byte[bitmapLength]; Marshal.Copy(specularData.Scan0, specularPixels, 0, bitmapLength); specularBitmap.UnlockBits(specularData); } else { var specularData = specularTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, specularTexData.BMP.Width, specularTexData.BMP.Height), ImageLockMode.ReadOnly, specularTexData.BMP.PixelFormat); var bitmapLength = specularData.Stride * specularData.Height; specularPixels = new byte[bitmapLength]; Marshal.Copy(specularData.Scan0, specularPixels, 0, bitmapLength); specularTexData.BMP.UnlockBits(specularData); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } } if (normalTexData != null) { if (tSize > (normalTexData.Height * normalTexData.Width)) { var normBitmap = ResizeImage(Image.FromHbitmap(normalTexData.BMP.GetHbitmap()), width, height); var normData = normBitmap.LockBits(new System.Drawing.Rectangle(0, 0, normBitmap.Width, normBitmap.Height), ImageLockMode.ReadOnly, normBitmap.PixelFormat); var bitmapLength = normData.Stride * normData.Height; normalPixels = new byte[bitmapLength]; Marshal.Copy(normData.Scan0, normalPixels, 0, bitmapLength); normBitmap.UnlockBits(normData); normalBitmap = normBitmap; } else { var normData = normalTexData.BMP.LockBits(new System.Drawing.Rectangle(0, 0, normalTexData.Width, normalTexData.Height), ImageLockMode.ReadOnly, normalTexData.BMP.PixelFormat); var bitmapLength = normData.Stride * normData.Height; normalPixels = new byte[bitmapLength]; Marshal.Copy(normData.Scan0, normalPixels, 0, bitmapLength); normalTexData.BMP.UnlockBits(normData); normalBitmap = normalTexData.BMP; } } List <byte> diffuseMap = new List <byte>(); List <byte> specularMap = new List <byte>(); List <byte> alphaMap = new List <byte>(); BitmapSource bitmapSource; System.Drawing.Color diffuseColor; System.Drawing.Color specularColor; System.Drawing.Color alphaColor; int stride = normalBitmap.Width * (32 / 8); if (diffuseTexData == null) { for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i]; diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((96f / 255f) * specularPixels[i - 1]), (int)((57f / 255f) * specularPixels[i - 1]), (int)((19f / 255f) * specularPixels[i - 1])); specularColor = System.Drawing.Color.FromArgb(255, specularPixels[i - 2], specularPixels[i - 2], specularPixels[i - 2]); alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = bitmapSource; } else { for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i - 3]; diffuseColor = System.Drawing.Color.FromArgb(alpha, diffusePixels[i - 1], diffusePixels[i - 2], diffusePixels[i - 3]); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularColor = System.Drawing.Color.FromArgb(255, specularPixels[i - 2], specularPixels[i - 2], specularPixels[i - 2]); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = bitmapSource; } bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, specularMap.ToArray(), stride); texBitmaps[1] = bitmapSource; texBitmaps[2] = Imaging.CreateBitmapSourceFromHBitmap(normalBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); bitmapSource = BitmapSource.Create(width, height, normalBitmap.HorizontalResolution, normalBitmap.VerticalResolution, PixelFormats.Bgra32, null, alphaMap.ToArray(), stride); texBitmaps[3] = bitmapSource; if (normalTexData != null) { normalTexData.Dispose(); } if (normalBitmap != null) { normalBitmap.Dispose(); } if (diffuseTexData != null) { diffuseTexData.Dispose(); } if (maskTexData != null) { maskTexData.Dispose(); } if (specularTexData != null) { specularTexData.Dispose(); } foreach (var tb in texBitmaps) { tb.Freeze(); } return(texBitmaps); }
/// <summary> /// Saves the currently displayed texture map as an image file. /// </summary> /// <param name="selectedCategory">The items category</param> /// <param name="selectedItem">The currently selected item</param> /// <param name="internalFilePath">The internal file path of the texture map</param> /// <param name="selectedBitmap">The bitmap of the texturemap currently being displayed</param> public static void SaveImage(string selectedCategory, string selectedItem, string internalFilePath, BitmapSource selectedBitmap, TEXData texData, string textureMap, string subCategory) { string savePath = ""; if (selectedCategory.Equals("UI")) { savePath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + subCategory; } else { savePath = Properties.Settings.Default.Save_Directory + "/" + selectedCategory + "/" + selectedItem; } Directory.CreateDirectory(savePath); var fullSavePath = Path.Combine(savePath, (Path.GetFileNameWithoutExtension(internalFilePath) + ".bmp")); if (textureMap.Equals(Strings.ColorSet)) { using (var fileStream = new FileStream(fullSavePath, FileMode.Create)) { BitmapEncoder encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(selectedBitmap)); encoder.Save(fileStream); } } else { using (var fileStream = new FileStream(fullSavePath, FileMode.Create)) { BitmapEncoder encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(texData.BMPSouceAlpha)); encoder.Save(fileStream); } } }
/// <summary> /// Creates the header for the compressed texture data to be imported. /// </summary> /// <param name="texData">Data for the currently displayed texture.</param> /// <param name="mipPartOffsets">List of part offsets.</param> /// <param name="mipPartCount">List containing the amount of parts per mipmap.</param> /// <param name="uncompressedLength">Length of the uncompressed texture file.</param> /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param> /// <param name="newWidth">The width of the DDS texture to be imported.</param> /// <param name="newHeight">The height of the DDS texture to be imported.</param> /// <returns>The created header data.</returns> private static List <byte> MakeType4DATHeader(TEXData texData, List <short> mipPartOffsets, List <short> mipPartCount, int uncompressedLength, int newMipCount, int newWidth, int newHeight) { List <byte> headerData = new List <byte>(); int headerSize = 24 + (newMipCount * 20) + (mipPartOffsets.Count * 2); int headerPadding = 128 - (headerSize % 128); headerData.AddRange(BitConverter.GetBytes(headerSize + headerPadding)); headerData.AddRange(BitConverter.GetBytes(4)); headerData.AddRange(BitConverter.GetBytes(uncompressedLength)); headerData.AddRange(BitConverter.GetBytes(0)); headerData.AddRange(BitConverter.GetBytes(0)); headerData.AddRange(BitConverter.GetBytes(newMipCount)); int partIndex = 0; int mipOffsetIndex = 80; int uncompMipSize = newHeight * newWidth; if (texData.Type == TextureTypes.DXT1) { uncompMipSize = (newWidth * newHeight) / 2; } else if (texData.Type == TextureTypes.DXT5 || texData.Type == TextureTypes.A8) { uncompMipSize = newWidth * newHeight; } else if (texData.Type == TextureTypes.A1R5G5B5 || texData.Type == TextureTypes.A4R4G4B4) { uncompMipSize = (newWidth * newHeight) * 2; } else { uncompMipSize = (newWidth * newHeight) * 4; } for (int i = 0; i < newMipCount; i++) { headerData.AddRange(BitConverter.GetBytes(mipOffsetIndex)); int paddedSize = 0; for (int j = 0; j < mipPartCount[i]; j++) { paddedSize = paddedSize + mipPartOffsets[j + partIndex]; } headerData.AddRange(BitConverter.GetBytes(paddedSize)); if (uncompMipSize > 16) { headerData.AddRange(BitConverter.GetBytes(uncompMipSize)); } else { headerData.AddRange(BitConverter.GetBytes(16)); } uncompMipSize = uncompMipSize / 4; headerData.AddRange(BitConverter.GetBytes(partIndex)); headerData.AddRange(BitConverter.GetBytes((int)mipPartCount[i])); partIndex = partIndex + mipPartCount[i]; mipOffsetIndex = mipOffsetIndex + paddedSize; } foreach (short part in mipPartOffsets) { headerData.AddRange(BitConverter.GetBytes(part)); } headerData.AddRange(new byte[headerPadding]); return(headerData); }
/// <summary> /// Gets the texture data of an item /// </summary> /// <param name="offset">The offset of the item</param> /// <returns>The texture data</returns> public static TEXData GetTex(int offset, string datName) { int datNum = ((offset / 8) & 0x0F) / 2; var datPath = string.Format(Info.datDir, datName, datNum); var storeOffset = offset; offset = Helper.OffsetCorrection(datNum, offset); List <byte> decompressedData = new List <byte>(); TEXData texData = new TEXData(); using (BinaryReader br = new BinaryReader(File.OpenRead(datPath))) { br.BaseStream.Seek(offset, SeekOrigin.Begin); int headerLength = br.ReadInt32(); int fileType = br.ReadInt32(); int uncompressedFileSize = br.ReadInt32(); br.ReadBytes(8); texData.MipCount = br.ReadInt32(); int endOfHeader = offset + headerLength; int mipMapInfoOffset = offset + 24; br.BaseStream.Seek(endOfHeader + 4, SeekOrigin.Begin); texData.Type = br.ReadInt32(); texData.Width = br.ReadInt16(); texData.Height = br.ReadInt16(); for (int i = 0, j = 0; i < texData.MipCount; i++) { br.BaseStream.Seek(mipMapInfoOffset + j, SeekOrigin.Begin); int offsetFromHeaderEnd = br.ReadInt32(); int mipMapLength = br.ReadInt32(); int mipMapSize = br.ReadInt32(); int mipMapStart = br.ReadInt32(); int mipMapParts = br.ReadInt32(); int mipMapPartOffset = endOfHeader + offsetFromHeaderEnd; br.BaseStream.Seek(mipMapPartOffset, SeekOrigin.Begin); br.ReadBytes(8); int compressedSize = br.ReadInt32(); int uncompressedSize = br.ReadInt32(); if (mipMapParts > 1) { byte[] compressedData = br.ReadBytes(compressedSize); byte[] decompressedPartData = new byte[uncompressedSize]; using (MemoryStream ms = new MemoryStream(compressedData)) { using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress)) { ds.Read(decompressedPartData, 0, uncompressedSize); } } decompressedData.AddRange(decompressedPartData); for (int k = 1; k < mipMapParts; k++) { byte check = br.ReadByte(); while (check != 0x10) { check = br.ReadByte(); } br.ReadBytes(7); compressedSize = br.ReadInt32(); uncompressedSize = br.ReadInt32(); if (compressedSize != 32000) { compressedData = br.ReadBytes(compressedSize); decompressedPartData = new byte[uncompressedSize]; using (MemoryStream ms = new MemoryStream(compressedData)) { using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress)) { ds.Read(decompressedPartData, 0, uncompressedSize); } } decompressedData.AddRange(decompressedPartData); } else { decompressedPartData = br.ReadBytes(uncompressedSize); decompressedData.AddRange(decompressedPartData); } } } else { if (compressedSize != 32000) { var compressedData = br.ReadBytes(compressedSize); var uncompressedData = new byte[uncompressedSize]; using (MemoryStream ms = new MemoryStream(compressedData)) { using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress)) { ds.Read(uncompressedData, 0, uncompressedSize); } } decompressedData.AddRange(uncompressedData); } else { var decompressedPartData = br.ReadBytes(uncompressedSize); decompressedData.AddRange(decompressedPartData); } } j = j + 20; } if (decompressedData.Count < uncompressedFileSize) { int difference = uncompressedFileSize - decompressedData.Count; byte[] padding = new byte[difference]; Array.Clear(padding, 0, difference); decompressedData.AddRange(padding); } } TextureToBitmap(decompressedData.ToArray(), texData); texData.TypeString = Info.TextureTypes[texData.Type]; texData.TexOffset = storeOffset; texData.TEXDatName = datName; return(texData); }
/// <summary> /// Creates the bitmap data for the models in the character category /// </summary> /// <remarks> /// Because the original textures use channel packing, this method gets the pixel data of each texture /// and then recombines them to create the unpacked textures to use in the 3D model. /// <see cref="http://wiki.polycount.com/wiki/ChannelPacking"/> /// </remarks> /// <param name="normalTexData">The texture data of the normal map</param> /// <param name="diffuseTexData">The texture data of the diffuse map</param> /// <param name="maskTexData">The texture data of the mask map</param> /// <param name="specularTexData">The texture data of the normal map</param> /// <returns>An array of bitmaps to be used on the model</returns> public static BitmapSource[] MakeCharacterMaps(TEXData normalTexData, TEXData diffuseTexData, TEXData maskTexData, TEXData specularTexData, string itemName, string path) { int height = normalTexData.Height; int width = normalTexData.Width; int tSize = height * width; var normalBitmap = normalTexData.BMPSouceAlpha; Color charaColor; if (path.Contains("/body/b")) { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Skin_Color); } else if (path.Contains("/hair/h")) { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Hair_Color); } else if (path.Contains("/face/f")) { if (path.Contains("_etc_")) { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Etc_Color); } else if (path.Contains("_iri_")) { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Iris_Color); } else { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Skin_Color); } } else if (path.Contains("tail/t")) { if (!path.Contains("c1401") && !path.Contains("c1301")) { charaColor = (Color)ColorConverter.ConvertFromString(Properties.Settings.Default.Hair_Color); } else { charaColor = Color.FromArgb(255, 255, 255, 255); } } else { charaColor = Color.FromArgb(255, 96, 57, 19); } if (diffuseTexData != null && (diffuseTexData.Height * diffuseTexData.Width) > tSize) { height = diffuseTexData.Height; width = diffuseTexData.Width; tSize = height * width; } if (maskTexData != null && (maskTexData.Height * maskTexData.Width) > tSize) { height = maskTexData.Height; width = maskTexData.Width; tSize = height * width; } if (specularTexData != null && (specularTexData.Height * specularTexData.Width) > tSize) { height = specularTexData.Height; width = specularTexData.Width; tSize = height * width; } byte[] maskPixels = null; byte[] specularPixels = null; byte[] normalPixels = null; byte[] diffusePixels = null; BitmapSource[] texBitmaps = new BitmapSource[4]; if (maskTexData != null) { if (tSize > (maskTexData.Height * maskTexData.Width)) { var resized = CreateResizedImage(maskTexData.BMPSouceAlpha, width, height); maskPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { maskPixels = GetBytesFromBitmapSource(maskTexData.BMPSouceAlpha); } } if (diffuseTexData != null) { try { if (tSize > (diffuseTexData.Height * diffuseTexData.Width)) { var resized = CreateResizedImage(diffuseTexData.BMPSouceAlpha, width, height); diffusePixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { diffusePixels = GetBytesFromBitmapSource(diffuseTexData.BMPSouceAlpha); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } } if (specularTexData != null) { try { if (tSize > (specularTexData.Height * specularTexData.Width)) { var resized = CreateResizedImage(specularTexData.BMPSouceAlpha, width, height); specularPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { specularPixels = GetBytesFromBitmapSource(specularTexData.BMPSouceAlpha); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } } if (normalTexData != null) { if (tSize > (normalTexData.Height * normalTexData.Width)) { var resized = CreateResizedImage(normalTexData.BMPSouceAlpha, width, height); normalBitmap = (BitmapSource)resized; normalPixels = GetBytesFromBitmapSource((BitmapSource)resized); } else { normalPixels = GetBytesFromBitmapSource(normalTexData.BMPSouceAlpha); } } List <byte> diffuseMap = new List <byte>(); List <byte> specularMap = new List <byte>(); List <byte> alphaMap = new List <byte>(); BitmapSource bitmapSource; System.Drawing.Color diffuseColor; System.Drawing.Color specularColor; System.Drawing.Color alphaColor; int stride = (int)normalBitmap.Width * (32 / 8); var scale = 1; if (width >= 4096 || height >= 4096) { scale = 4; } else if (width >= 2048 || height >= 2048) { scale = 2; } var nWidth = width / scale; var nHeight = height / scale; if (diffuseTexData == null) { for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i]; diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((charaColor.R / 255f) * specularPixels[i - 1]), (int)((charaColor.G / 255f) * specularPixels[i - 1]), (int)((charaColor.B / 255f) * specularPixels[i - 1])); specularColor = System.Drawing.Color.FromArgb(255, (int)(specularPixels[i - 2] * 0.1), (int)(specularPixels[i - 2] * 0.1), (int)(specularPixels[i - 2] * 0.1)); alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); } else { for (int i = 3; i < normalPixels.Length; i += 4) { int alpha = normalPixels[i - 3]; diffuseColor = System.Drawing.Color.FromArgb(alpha, (int)((charaColor.R / 255f) * diffusePixels[i - 1]), (int)((charaColor.G / 255f) * diffusePixels[i - 2]), (int)((charaColor.B / 255f) * diffusePixels[i - 3])); diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToArgb())); specularColor = System.Drawing.Color.FromArgb(255, (int)(specularPixels[i - 2] * 0.1), (int)(specularPixels[i - 2] * 0.1), (int)(specularPixels[i - 2] * 0.1)); specularMap.AddRange(BitConverter.GetBytes(specularColor.ToArgb())); alphaColor = System.Drawing.Color.FromArgb(255, alpha, alpha, alpha); alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToArgb())); } bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, diffuseMap.ToArray(), stride); texBitmaps[0] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); } bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, specularMap.ToArray(), stride); texBitmaps[1] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); texBitmaps[2] = (BitmapSource)CreateResizedImage(normalTexData.BMPSouceNoAlpha, nWidth, nHeight); bitmapSource = BitmapSource.Create(width, height, normalBitmap.DpiX, normalBitmap.DpiY, PixelFormats.Bgra32, null, alphaMap.ToArray(), stride); texBitmaps[3] = (BitmapSource)CreateResizedImage(bitmapSource, nWidth, nHeight); foreach (var tb in texBitmaps) { tb.Freeze(); } return(texBitmaps); }
/// <summary> /// Creates the DDS header for given texture data. /// <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/bb943982(v=vs.85).aspx"/> /// </summary> /// <param name="texData">The texture data.</param> /// <returns>Byte array containing DDS header</returns> public static byte[] CreateDDSHeader(TEXData texData) { uint dwPitchOrLinearSize, pfFlags, dwFourCC; List <byte> header = new List <byte>(); // DDS header magic number uint dwMagic = 0x20534444; header.AddRange(BitConverter.GetBytes(dwMagic)); // Size of structure. This member must be set to 124. uint dwSize = 124; header.AddRange(BitConverter.GetBytes(dwSize)); // Flags to indicate which members contain valid data. uint dwFlags = 528391; header.AddRange(BitConverter.GetBytes(dwFlags)); // Surface height (in pixels). uint dwHeight = (uint)texData.Height; header.AddRange(BitConverter.GetBytes(dwHeight)); // Surface width (in pixels). uint dwWidth = (uint)texData.Width; header.AddRange(BitConverter.GetBytes(dwWidth)); // The pitch or number of bytes per scan line in an uncompressed texture; the total number of bytes in the top level texture for a compressed texture. if (texData.Type == 9312) { dwPitchOrLinearSize = 512; } else if (texData.Type == 5200) { dwPitchOrLinearSize = (uint)((dwHeight * dwWidth) * 4); } else if (texData.Type == 13344) { dwPitchOrLinearSize = (uint)((dwHeight * dwWidth) / 2); } else { dwPitchOrLinearSize = (uint)(dwHeight * dwWidth); } header.AddRange(BitConverter.GetBytes(dwPitchOrLinearSize)); // Depth of a volume texture (in pixels), otherwise unused. uint dwDepth = 0; header.AddRange(BitConverter.GetBytes(dwDepth)); // Number of mipmap levels, otherwise unused. uint dwMipMapCount = (uint)texData.MipCount; header.AddRange(BitConverter.GetBytes(dwMipMapCount)); // Unused. byte[] dwReserved1 = new byte[44]; Array.Clear(dwReserved1, 0, 44); header.AddRange(dwReserved1); // DDS_PIXELFORMAT start // Structure size; set to 32 (bytes). uint pfSize = 32; header.AddRange(BitConverter.GetBytes(pfSize)); // Values which indicate what type of data is in the surface. if (texData.Type == 5200) { pfFlags = 65; } else { pfFlags = 4; } header.AddRange(BitConverter.GetBytes(pfFlags)); // Four-character codes for specifying compressed or custom formats. if (texData.Type == 13344) { dwFourCC = 0x31545844; } else if (texData.Type == 13361) { dwFourCC = 0x35545844; } else if (texData.Type == 13360) { dwFourCC = 0x33545844; } else if (texData.Type == 9312) { dwFourCC = 0x71; } else if (texData.Type == 5200) { dwFourCC = 0; } else { return(null); } header.AddRange(BitConverter.GetBytes(dwFourCC)); if (texData.Type == 5200) { // Number of bits in an RGB (possibly including alpha) format. uint dwRGBBitCount = 32; header.AddRange(BitConverter.GetBytes(dwRGBBitCount)); // Red (or lumiannce or Y) mask for reading color data. uint dwRBitMask = 16711680; header.AddRange(BitConverter.GetBytes(dwRBitMask)); // Green (or U) mask for reading color data. uint dwGBitMask = 65280; header.AddRange(BitConverter.GetBytes(dwGBitMask)); // Blue (or V) mask for reading color data. uint dwBBitMask = 255; header.AddRange(BitConverter.GetBytes(dwBBitMask)); // Alpha mask for reading alpha data. uint dwABitMask = 4278190080; header.AddRange(BitConverter.GetBytes(dwABitMask)); // DDS_PIXELFORMAT End // Specifies the complexity of the surfaces stored. uint dwCaps = 4096; header.AddRange(BitConverter.GetBytes(dwCaps)); // dwCaps2, dwCaps3, dwCaps4, dwReserved2. // Unused. byte[] blank1 = new byte[16]; header.AddRange(blank1); } else { // dwRGBBitCount, dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask, dwCaps, dwCaps2, dwCaps3, dwCaps4, dwReserved2. // Unused. byte[] blank1 = new byte[40]; header.AddRange(blank1); } return(header.ToArray()); }
/// <summary> /// Imports the items texture into a dat file /// </summary> /// <param name="texData">Data for the currently displayed texture</param> /// <param name="category">The items category</param> /// <param name="itemName">The items name</param> /// <param name="internalFilePath">The internal file path of the texture map</param> /// <returns>The offset in which the data was placed</returns> public static int ImportTexture(TEXData texData, string category, string itemName, string internalFilePath) { int textureType, lineNum = 0, offset = 0; bool inModList = false; JsonEntry modEntry = null; string dxPath = Path.GetFileNameWithoutExtension(internalFilePath); var savePath = Properties.Settings.Default.Save_Directory + "/" + category + "/" + itemName + "/" + dxPath + ".dds"; if (File.Exists(savePath)) { if (Properties.Settings.Default.Mod_List == 0) { try { using (StreamReader sr = new StreamReader(Info.modListDir)) { string line; while ((line = sr.ReadLine()) != null) { modEntry = JsonConvert.DeserializeObject <JsonEntry>(line); if (modEntry.fullPath.Equals(internalFilePath)) { inModList = true; break; } lineNum++; } } } catch (Exception ex) { MessageBox.Show("[Main] Error Accessing .modlist File \n" + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } using (BinaryReader br = new BinaryReader(File.OpenRead(savePath))) { br.BaseStream.Seek(12, SeekOrigin.Begin); var newHeight = br.ReadInt32(); var newWidth = br.ReadInt32(); br.ReadBytes(8); var newMipCount = br.ReadInt32(); br.BaseStream.Seek(84, SeekOrigin.Begin); textureType = Info.DDSType[br.ReadInt32()]; if (textureType == texData.Type) { List <byte> newTEX = new List <byte>(); int uncompressedLength = (int)new FileInfo(savePath).Length - 128; var DDSInfo = ReadDDS(br, texData, newWidth, newHeight, newMipCount); newTEX.AddRange(MakeType4DATHeader(texData, DDSInfo.Item2, DDSInfo.Item3, uncompressedLength, newMipCount, newWidth, newHeight)); newTEX.AddRange(MakeTextureInfoHeader(texData, newWidth, newHeight, newMipCount)); newTEX.AddRange(DDSInfo.Item1); offset = WriteToDat(newTEX, modEntry, inModList, internalFilePath, category, itemName, lineNum); } else { MessageBox.Show("Incorrect file type \nExpected: " + Info.TextureTypes[texData.Type] + " Given: " + Info.TextureTypes[textureType], "Texture format error", MessageBoxButton.OK, MessageBoxImage.Error); } } } else { MessageBox.Show("Could not find file \n" + savePath, "File read Error", MessageBoxButton.OK, MessageBoxImage.Error); } return(offset); }