/// <summary> /// Defines the texture from a bitmap. /// All texture levels will be generated until the texture size is no longer divisible by two. /// </summary> /// <param name="format">The format to encode the new texture as.</param> /// <param name="intFormat">The type of interpolation to use</param> /// <param name="bmp">The bitmap that will define the texture.</param> public void DefineTextureFromBitmap(GxTextureFormat format, GxInterpolationFormat intFormat, int numMipmaps, Bitmap bmp) { if (!SupportedTextureFormats.Contains(format)) { throw new ArgumentOutOfRangeException("format", "Unsupported format."); } if (bmp == null) { throw new ArgumentNullException("bmp"); } // Define all possible texture levels until the size // of the texture can no longer be divided by two int currentWidth = bmp.Width, currentHeight = bmp.Height; for (int mipmapLevel = 0; mipmapLevel < numMipmaps; mipmapLevel++) { if (mipmapLevel == 0) { DefineMainLevelFromBitmap(format, intFormat, bmp); } else { DefineLevelDataFromBitmap(mipmapLevel, intFormat, DownscaleBitmap(mipmapLevel, intFormat, bmp)); } if ((currentWidth % 2) != 0 || (currentHeight % 2) != 0) { break; } currentWidth /= 2; currentHeight /= 2; } }
/// <summary>Define the main level of the texture from the given properties.</summary> public void DefineMainLevel(GxTextureFormat newFormat, int newWidth, int newHeight, int newImageStride, byte[] newImageData) { if (SupportedTextureFormats.Contains(newFormat)) { throw new ArgumentOutOfRangeException("newFormat", "Unsupported format."); } if (newWidth <= 0) { throw new ArgumentOutOfRangeException("newWidth"); } if (newHeight <= 0) { throw new ArgumentOutOfRangeException("newHeight"); } if (newImageStride < 0) { throw new ArgumentOutOfRangeException("newImageStride"); } if (newImageStride < newWidth * 4) { throw new ArgumentOutOfRangeException("newImageStride", "Stride is too small to contain a row of data."); } if (newImageData == null) { throw new ArgumentNullException("newImageData"); } format = newFormat; width = newWidth; height = newHeight; encodedLevelData = new List <byte[]>(); DefineLevelData(0, newImageStride, newImageData); }
/// <summary>Get the codec associated to the given texture format.</summary> /// <param name="palFmt">The texture format.</param> /// <returns>The codec associated to the given texture format.</returns> public static GxTextureFormatCodec GetCodec(GxTextureFormat palFmt) { switch (palFmt) { case GxTextureFormat.I4: return(new GxTextureFormatCodecI4()); case GxTextureFormat.I8: return(new GxTextureFormatCodecI8()); case GxTextureFormat.IA4: return(new GxTextureFormatCodecIA4()); case GxTextureFormat.IA8: return(new GxTextureFormatCodecIA8()); case GxTextureFormat.RGB565: return(new GxTextureFormatCodecRGB565()); case GxTextureFormat.RGB5A3: return(new GxTextureFormatCodecRGB5A3()); case GxTextureFormat.RGBA8: return(new GxTextureFormatCodecRGBA8()); case GxTextureFormat.CI4: return(new GxTextureFormatCodecCI4()); case GxTextureFormat.CI8: return(new GxTextureFormatCodecCI8()); case GxTextureFormat.CI14X2: return(new GxTextureFormatCodecCI14X2()); case GxTextureFormat.CMPR: return(new GxTextureFormatCodecCMPR()); default: throw new ArgumentOutOfRangeException("palFmt"); } }
/// <summary>Define the texture as a texture with no texture levels.</summary> /// <param name="newFormatRaw">See definition of the FormatRaw property.</param> public void DefineEmptyTexture(int newFormatRaw) { formatRaw = newFormatRaw; format = (GxTextureFormat)0; width = 0; height = 0; encodedLevelData = new List <byte[]>(); }
public GeneratedTextureHeader(GxTextureFormat textureFormat, int textureCount, int textureWidth, int textureHeight, int textureMipmapCount) { this.textureFormat = textureFormat; this.textureCount = textureCount; this.textureWidth = textureWidth; this.textureHeight = textureHeight; this.textureMipmapCount = textureMipmapCount; }
public void WriteTexture(BinaryWriter writer, Texture2D texture, GxTextureFormat format) { // Decide whether to use name as format or link each texture to a SO // Name only is nice because it means no linkage with SO // SO is nice because there need not be copies of textures to export // The only data needed from TEXDescriptor // - format throw new System.NotImplementedException(); }
/// <summary> /// Defines a texture and the respective mipmap levels of the texture from the respective files, starting from level 1. /// /// </summary> /// <param name="format">The format to encode the new texture as.</param> /// <param name="intFormat">The type of interpolation to use.</param> /// <param name="path">The path to the level 1 bitmap.</param> public void DefineAllLevelsFromFiles(GxTextureFormat format, GxInterpolationFormat intFormat, String path) { int currentMipmapLevel = 1; // Iterates until no more mipmap levels exist. while (File.Exists(path)) { DefineLevelDataFromBitmap(currentMipmapLevel, intFormat, new Bitmap(path)); currentMipmapLevel++; // Gets the path to the next mipmap. path = Regex.Replace(path, @"\d{1,}(?=\..{3,4}$)", currentMipmapLevel.ToString()); } }
/// <summary> /// Defines the texture from a bitmap. /// All texture levels will be generated (if the provided bitmap is not specified as level 0) until the texture size is no longer divisible by two. /// </summary> /// <param name="format">The format to encode the new texture as.</param> /// <param name="intFormat">The type of interpolation to use</param> /// <param name="bmp">The bitmap that will define the texture.</param> /// <param name="path">The path to the bitmap file.</param> public void DefineTextureFromBitmap(GxTextureFormat format, GxInterpolationFormat intFormat, int numMipmaps, Bitmap bmp, String path = "") { if (!SupportedTextureFormats.Contains(format)) { throw new ArgumentOutOfRangeException("format", "Unsupported format."); } if (bmp == null) { throw new ArgumentNullException("bmp"); } // If the filename ends in '_0.???(?)' or ' 0.???(?)', import them from the respective files, otherwise, generate them. if (Regex.IsMatch(path, @"(_| )0(?=\..{3,4}$)")) { DefineMainLevelFromBitmap(format, intFormat, bmp); // Gets the path to the potential level 1 mipmap of the texture. path = Regex.Replace(path, @"\d{1,}(?=\..{3,4}$)", "1"); DefineAllLevelsFromFiles(format, intFormat, path); } else { // Define all possible texture levels until the size // of the texture can no longer be divided by two int currentWidth = bmp.Width, currentHeight = bmp.Height; for (int mipmapLevel = 0; mipmapLevel < numMipmaps; mipmapLevel++) { if (mipmapLevel == 0) { DefineMainLevelFromBitmap(format, intFormat, bmp); } else { DefineLevelDataFromBitmap(mipmapLevel, intFormat, DownscaleBitmap(mipmapLevel, intFormat, bmp)); } if ((currentWidth % 2) != 0 || (currentHeight % 2) != 0) { break; } currentWidth /= 2; currentHeight /= 2; } } }
public AddTextureHeader(IEnumerable <GxTextureFormat> availableFormats, GxTextureFormat defaultFormat, String fileName, int fileSize) { this.fileSize = fileSize; if (availableFormats == null) { throw new ArgumentNullException("availableFormats"); } if (!availableFormats.Contains(defaultFormat)) { throw new ArgumentOutOfRangeException("defaultFormat", "Default format not in list of available formats."); } InitializeComponent(); // Populate the format combobox from the available formats cmbFormat.ValueMember = "Key"; cmbFormat.DisplayMember = "Value"; cmbFormat.DataSource = new BindingSource(availableFormats .Select(g => new { Key = g, Value = string.Format("{0} ({1})", g, EnumUtils.GetEnumDescription(g)) }).ToArray(), null); // Select the default format given cmbFormat.SelectedValue = defaultFormat; // Obtains dimensions from filename Match defaultValues = new Regex(@"(\d+)x(\d+)").Match(fileName); // Automatically fills in dimensions if they exist if (defaultValues.Groups[1].Value != null || defaultValues.Groups[2].Value != null) { texX.Text = defaultValues.Groups[1].Value; texY.Text = defaultValues.Groups[2].Value; } // Otherwise, they are set to zero else { texX.Text = "0"; texY.Text = "0"; } // Most headerless TPLs seem to only have one mipmap level texMipmapCount.Text = "1"; // Obtains texture count from filesize updateTextureCount(); }
/// <summary>Define the main level of the texture from the given bitmap.</summary> public void DefineMainLevelFromBitmap(GxTextureFormat newFormat, GxInterpolationFormat intFormat, Bitmap bmp) { if (!SupportedTextureFormats.Contains(newFormat)) { throw new ArgumentOutOfRangeException("newFormat", "Unsupported format."); } if (bmp == null) { throw new ArgumentNullException("bmp"); } format = newFormat; width = bmp.Width; height = bmp.Height; encodedLevelData = new List <byte[]>(); DefineLevelDataFromBitmap(0, intFormat, bmp); }
/// <summary> /// Reads a texture with the specified characteristics from a binary stream. /// </summary> internal void LoadTextureData(EndianBinaryReader input, GxGame game, GxTextureFormat format, int width, int height, int levelCount) { if (!SupportedTextureFormats.Contains(format)) { throw new InvalidTplFileException("Unsupported texture format."); } this.format = format; this.width = width; this.height = height; for (int level = 0; level < levelCount; level++) { byte[] levelData = new byte[CalculateSizeOfLevel(level)]; input.Read(levelData, 0, CalculateSizeOfLevel(level, (game == GxGame.FZeroGX))); if (game == GxGame.SuperMonkeyBallDX) { if (format == GxTextureFormat.CMPR) { // Swap pallete byte order for (int i = 0; i < levelData.Length; i += 8) { byte temp = levelData[i]; levelData[i] = levelData[i + 1]; levelData[i + 1] = temp; temp = levelData[i + 2]; levelData[i + 2] = levelData[i + 3]; levelData[i + 3] = temp; } } } encodedLevelData.Add(levelData); } }
/// <summary> /// Create a TPL texture file from the specified model. /// </summary> /// <param name="model">The model to create the TPL file from.</param> /// <param name="textureIndexMapping">The correspondence between textures images in the model and the generated TPL texture indices.</param> public Tpl(ObjMtlModel model, GxInterpolationFormat intFormat, int numMipmaps, out Dictionary <Bitmap, int> textureIndexMapping) { if (model == null) { throw new ArgumentNullException("model"); } // Gather all material definitions in the model IEnumerable <ObjMtlMaterial> allMaterials = model.Objects .SelectMany(o => o.Value.Meshes).Select(m => m.Material); Dictionary <Bitmap, int> textureIndexMappingInt = new Dictionary <Bitmap, int>(); foreach (ObjMtlMaterial mat in allMaterials) { // Create and add texture for diffuse map if (mat.DiffuseTextureMap != null && !textureIndexMappingInt.ContainsKey(mat.DiffuseTextureMap)) { int textureIndex = Count; Match materialPreset = Regex.Match(mat.Name, @"(?<=TEX_)[^\]]*"); GxTextureFormat format = GxTextureFormat.CMPR; if (materialPreset.Success) { switch (materialPreset.Value) { case "RGB5A3": format = GxTextureFormat.RGB5A3; break; case "RGB565": format = GxTextureFormat.RGB565; break; case "RGBA8": format = GxTextureFormat.RGBA8; break; case "I4": format = GxTextureFormat.I4; break; case "I8": format = GxTextureFormat.I8; break; case "IA4": format = GxTextureFormat.IA4; break; default: break; } } TplTexture texture = new TplTexture(format, intFormat, numMipmaps, mat.DiffuseTextureMap); Add(texture); textureIndexMappingInt.Add(mat.DiffuseTextureMap, textureIndex); } } // Replace the 'out' variable at the end so it does not get // modified if an exception textureIndexMapping = textureIndexMappingInt; }
/// <summary> /// Create a new texture from the given bitmap. /// </summary> /// <param name="intFormat">The type of interpolation to use</param> /// <param name="bmp">The bitmap to build the texture from.</param> public TplTexture(GxTextureFormat format, GxInterpolationFormat intFormat, int numMipmaps, Bitmap bmp) { DefineTextureFromBitmap(format, intFormat, numMipmaps, bmp); }
/// <summary> /// Create a new GxTextureFormat picker dialog. /// </summary> /// <param name="availableFormats">The choices to make available to the user.</param> /// <param name="defaultFormat">The default format to be selected by the picker.</param> public GxTextureFormatPickerDialog(IEnumerable <GxTextureFormat> availableFormats, GxTextureFormat defaultFormat) { if (availableFormats == null) { throw new ArgumentNullException("availableFormats"); } if (!availableFormats.Contains(defaultFormat)) { throw new ArgumentOutOfRangeException("defaultFormat", "Default format not in list of available formats."); } InitializeComponent(); // Populate the format combobox from the available formats cmbFormat.ValueMember = "Key"; cmbFormat.DisplayMember = "Value"; cmbFormat.DataSource = new BindingSource(availableFormats .Select(g => new { Key = g, Value = string.Format("{0} ({1})", g, EnumUtils.GetEnumDescription(g)) }).ToArray(), null); // Select the default format given cmbFormat.SelectedValue = defaultFormat; }
private void btnImportTextureLevel_Click(object sender, EventArgs e) { // Extract the TextureReference structure to get the selected texture TextureReference textureData = (TextureReference)treeTextures.SelectedNode.Tag; TplTexture tex = tpl[textureData.TextureIdx]; // Request image filename if (ofdTextureImportPath.ShowDialog() != DialogResult.OK) { return; } // Load image Bitmap bmp; try { bmp = new Bitmap(ofdTextureImportPath.FileName); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error loading image.", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (textureData.TextureLevel == -1) // Replacing whole texture { // Ask the user to select the format to import GxTextureFormatPickerDialog formatPickerDlg = new GxTextureFormatPickerDialog( TplTexture.SupportedTextureFormats, tex.Format); if (formatPickerDlg.ShowDialog() != DialogResult.OK) { return; } GxTextureFormat newFmt = formatPickerDlg.SelectedFormat; // Redefine the entire texture from the bitmap tex.DefineTextureFromBitmap(newFmt, GetSelectedMipmap(), GetNumMipmaps(), bmp); TextureHasChanged(textureData.TextureIdx); UpdateTextureTree(); treeTextures.SelectedNode = treeTextures.Nodes.Cast <TreeNode>() .Where(tn => ((TextureReference)tn.Tag).TextureIdx == textureData.TextureIdx).First(); } else // Replacing single level { if (bmp.Width != tex.WidthOfLevel(textureData.TextureLevel) || bmp.Height != tex.HeightOfLevel(textureData.TextureLevel)) { MessageBox.Show("The selected image has an invalid size to replace this level.\n" + "If you wish to replace the entire texture, select the node coresponding to the texture.", "Invalid image size", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Replace just the selected level from the bitmap tex.DefineLevelDataFromBitmap(textureData.TextureLevel, GetSelectedMipmap(), bmp); TextureHasChanged(textureData.TextureIdx); } }
private void cmbFormat_SelectedIndexChanged(object sender, EventArgs e) { currentFormat = (GxTextureFormat)cmbFormat.SelectedValue; updateTextureCount(); }