/// <summary> /// /// </summary> public static void ImportTextures(HSD_JOBJ jobj) { var folder = Tools.FileIO.OpenFolder(); if (!string.IsNullOrEmpty(folder)) { // get all tobjs Dictionary <int, HSD_TOBJ> hashToImage = new Dictionary <int, HSD_TOBJ>(); // load all textures from file foreach (var tf in System.IO.Directory.GetFiles(folder)) { if (tf.ToLower().EndsWith(".png")) { var fn = System.IO.Path.GetFileNameWithoutExtension(tf); if (fn.Length >= 8 && int.TryParse(fn.Substring(0, 8), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int hash) && TOBJConverter.FormatFromString(fn, out HSDRaw.GX.GXTexFmt texFmt, out HSDRaw.GX.GXTlutFmt tlutFmt)) { hashToImage.Add(hash, TOBJConverter.ImportTOBJFromFile(tf, texFmt, tlutFmt)); } } } // get all tobjs foreach (var j in jobj.BreathFirstList) { if (j.Dobj != null) { foreach (var dobj in j.Dobj.List) { if (dobj.Mobj != null && dobj.Mobj.Textures != null) { foreach (var tobj in dobj.Mobj.Textures.List) { // generate hashes and export textures and formatting var hash = ComputeHash(tobj.GetDecodedImageData()); if (hashToImage.ContainsKey(hash)) { var imgClone = HSDAccessor.DeepClone <HSD_TOBJ>(hashToImage[hash]); tobj.ImageData = imgClone.ImageData; tobj.TlutData = imgClone.TlutData; } } } } } } } }
/// <summary> /// /// </summary> /// <param name="objFileStream"></param> /// <returns></returns> public static HSD_TOBJ GenerateEmblemIconImage(EmblemModel model) { // normalize range foreach (var ve in model.v) { ve[0] = ((ve[0] - model.xRange.X) / Math.Abs(model.xRange.Y - model.xRange.X)) * model.aspectX; ve[2] = (1 - (ve[2] - model.yRange.X) / Math.Abs(model.xRange.Y - model.yRange.X)) * model.aspectY; } using (Bitmap b = new Bitmap(80, 64)) { var brushback = new SolidBrush(Color.Black); var brush = new SolidBrush(Color.White); int icoWidth = 64, icoHeight = 64; if (model.aspectX < 1) { icoWidth = b.Height; icoHeight = b.Height; } if (model.aspectY < 1) { icoWidth = b.Width; icoHeight = b.Width; } icoWidth -= icoWidth / 9; icoHeight -= icoHeight / 9; int xoff = b.Width / 2 - icoWidth / 2; int yoff = b.Height / 2 + icoHeight / 2; using (Graphics g = Graphics.FromImage(b)) { g.FillRectangle(brushback, 0, 0, b.Width, b.Height); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; GraphicsPath path = new GraphicsPath(); foreach (var ve in model.f) { path.AddPolygon(new PointF[] { new PointF(xoff + model.v[ve[0] - 1][0] * icoWidth, yoff - model.v[ve[0] - 1][2] * icoHeight), new PointF(xoff + model.v[ve[1] - 1][0] * icoWidth, yoff - model.v[ve[1] - 1][2] * icoHeight), new PointF(xoff + model.v[ve[2] - 1][0] * icoWidth, yoff - model.v[ve[2] - 1][2] * icoHeight) }); } g.FillPath(brush, path); } return(TOBJConverter.BitmapToTOBJ(b, HSDRaw.GX.GXTexFmt.I4, HSDRaw.GX.GXTlutFmt.IA8)); } }
/// <summary> /// Import TOBJ from PNG file /// </summary> /// <returns></returns> public static HSD_TOBJ ImportTOBJFromFile() { var TOBJ = new HSD_TOBJ() { MagFilter = GXTexFilter.GX_LINEAR, Flags = TOBJ_FLAGS.COORD_UV | TOBJ_FLAGS.LIGHTMAP_DIFFUSE | TOBJ_FLAGS.COLORMAP_MODULATE | TOBJ_FLAGS.ALPHAMAP_MODULATE, HScale = 1, WScale = 1, WrapS = GXWrapMode.CLAMP, WrapT = GXWrapMode.CLAMP, SX = 1, SY = 1, SZ = 1, GXTexGenSrc = 4, Blending = 1 }; var f = Tools.FileIO.OpenFile(ApplicationSettings.ImageFileFilter); if (f != null) { using (TextureImportDialog settings = new TextureImportDialog()) { if (FormatFromString(f, out GXTexFmt fmt, out GXTlutFmt pal)) { settings.PaletteFormat = pal; settings.TextureFormat = fmt; } if (settings.ShowDialog() == DialogResult.OK) { using (Bitmap bmp = new Bitmap(f)) { settings.ApplySettings(bmp); TOBJConverter.InjectBitmap(bmp, TOBJ, settings.TextureFormat, settings.PaletteFormat); return(TOBJ); } } } } return(null); }
/// <summary> /// /// </summary> public static void ExportTextures(HSD_JOBJ jobj) { var folder = Tools.FileIO.OpenFolder(); if (!string.IsNullOrEmpty(folder)) { HashSet <int> textures = new HashSet <int>(); // get all tobjs foreach (var j in jobj.BreathFirstList) { if (j.Dobj != null) { foreach (var dobj in j.Dobj.List) { if (dobj.Mobj != null && dobj.Mobj.Textures != null) { foreach (var tobj in dobj.Mobj.Textures.List) { // generate hashes and export textures and formatting var hash = ComputeHash(tobj.GetDecodedImageData()); if (!textures.Contains(hash)) { using (var bmp = TOBJConverter.ToBitmap(tobj)) bmp.Save(System.IO.Path.Combine(folder, TOBJConverter.FormatName(hash.ToString("X8"), tobj) + ".png")); textures.Add(hash); } } } } } } } }
/// <summary> /// /// </summary> /// <param name="settings"></param> /// <param name="material"></param> /// <returns></returns> private HSD_MOBJ GenerateMaterial(IOMaterial material) { // create blank mobj var Mobj = new HSD_MOBJ(); Mobj.Material = new HSD_Material() { AMB_A = 0xFF, AMB_R = 0x7F, AMB_G = 0x7F, AMB_B = 0x7F, DiffuseColor = System.Drawing.Color.White, SpecularColor = System.Drawing.Color.White, Shininess = 50, Alpha = 1 }; // detect and set flags if (Settings.ImportVertexColor) { Mobj.RenderFlags |= RENDER_MODE.VERTEX; } if (Settings.EnableDiffuse) { Mobj.RenderFlags |= RENDER_MODE.DIFFUSE; } if (Settings.EnableConstant) { Mobj.RenderFlags |= RENDER_MODE.CONSTANT; } // Properties if (material != null && Settings.ImportMaterialInfo) { Mobj.Material.Shininess = material.Shininess; Mobj.Material.Alpha = material.Alpha; Mobj.Material.AMB_R = (byte)(material.AmbientColor.X * 255); Mobj.Material.AMB_G = (byte)(material.AmbientColor.Y * 255); Mobj.Material.AMB_B = (byte)(material.AmbientColor.Z * 255); Mobj.Material.AMB_A = (byte)(material.AmbientColor.W * 255); Mobj.Material.DIF_R = (byte)(material.DiffuseColor.X * 255); Mobj.Material.DIF_G = (byte)(material.DiffuseColor.Y * 255); Mobj.Material.DIF_B = (byte)(material.DiffuseColor.Z * 255); Mobj.Material.DIF_A = (byte)(material.DiffuseColor.W * 255); Mobj.Material.SPC_R = (byte)(material.SpecularColor.X * 255); Mobj.Material.SPC_G = (byte)(material.SpecularColor.Y * 255); Mobj.Material.SPC_B = (byte)(material.SpecularColor.Z * 255); Mobj.Material.SPC_A = (byte)(material.SpecularColor.W * 255); } // Textures if (material != null && Settings.ImportTexture) { if (material.DiffuseMap != null && !string.IsNullOrEmpty(material.DiffuseMap.FilePath)) { var texturePath = material.DiffuseMap.FilePath; if (texturePath.Contains("file://")) { texturePath = texturePath.Replace("file://", ""); } if (File.Exists(Path.Combine(_cache.FolderPath, texturePath))) { texturePath = Path.Combine(_cache.FolderPath, texturePath); } if (File.Exists(material.DiffuseMap.FilePath)) { texturePath = material.DiffuseMap.FilePath; } if (File.Exists(texturePath + ".png")) { texturePath = texturePath + ".png"; } var mobjPath = Path.Combine(Path.GetDirectoryName(texturePath), Path.GetFileNameWithoutExtension(texturePath)) + ".mobj"; if (Settings.ImportMOBJ && File.Exists(mobjPath)) { var dat = new HSDRaw.HSDRawFile(mobjPath); Mobj._s = dat.Roots[0].Data._s; return(Mobj); } else /// special mobj loading if (Path.GetExtension(texturePath).ToLower() == ".mobj") { var dat = new HSDRaw.HSDRawFile(texturePath); Mobj._s = dat.Roots[0].Data._s; return(Mobj); } else if (File.Exists(texturePath) && (texturePath.ToLower().EndsWith(".png") || texturePath.ToLower().EndsWith(".bmp"))) { Mobj.RenderFlags |= RENDER_MODE.TEX0; var tobj = TOBJConverter.ImportTOBJFromFile(texturePath, Settings.TextureFormat, Settings.PaletteFormat); tobj.Flags = TOBJ_FLAGS.LIGHTMAP_DIFFUSE | TOBJ_FLAGS.COORD_UV | TOBJ_FLAGS.COLORMAP_MODULATE; tobj.GXTexGenSrc = 4; tobj.TexMapID = GXTexMapID.GX_TEXMAP0; tobj.WrapS = ToGXWrapMode(material.DiffuseMap.WrapS); tobj.WrapT = ToGXWrapMode(material.DiffuseMap.WrapT); if (TOBJConverter.IsTransparent(tobj)) { _cache.HasXLU = true; Mobj.RenderFlags |= RENDER_MODE.XLU; tobj.Flags |= TOBJ_FLAGS.ALPHAMAP_MODULATE; } Mobj.Textures = tobj; } } } return(Mobj); }
/// <summary> /// /// </summary> /// <param name="settings"></param> /// <param name="material"></param> /// <returns></returns> private static HSD_MOBJ GenerateMaterial(ProcessingCache cache, ModelImportSettings settings, Material material) { var Mobj = new HSD_MOBJ(); Mobj.Material = new HSD_Material(); Mobj.Material.AmbientColorRGBA = 0x7F7F7FFF; Mobj.Material.DiffuseColorRGBA = 0xFFFFFFFF; Mobj.Material.SpecularColorRGBA = 0xFFFFFFFF; Mobj.Material.Shininess = 1; Mobj.Material.Alpha = 1; Mobj.RenderFlags = RENDER_MODE.ALPHA_COMPAT | RENDER_MODE.DIFFSE_VTX; // Properties if (settings.ImportMaterialInfo) { if (material.HasShininess) { Mobj.Material.Shininess = material.Shininess; } if (material.HasColorAmbient) { Mobj.Material.AMB_A = ColorFloatToByte(material.ColorAmbient.A); Mobj.Material.AMB_R = ColorFloatToByte(material.ColorAmbient.R); Mobj.Material.AMB_G = ColorFloatToByte(material.ColorAmbient.G); Mobj.Material.AMB_B = ColorFloatToByte(material.ColorAmbient.B); } if (material.HasColorDiffuse) { Mobj.Material.DIF_A = ColorFloatToByte(material.ColorDiffuse.A); Mobj.Material.DIF_R = ColorFloatToByte(material.ColorDiffuse.R); Mobj.Material.DIF_G = ColorFloatToByte(material.ColorDiffuse.G); Mobj.Material.DIF_B = ColorFloatToByte(material.ColorDiffuse.B); } if (material.HasColorSpecular) { Mobj.Material.SPC_A = ColorFloatToByte(material.ColorSpecular.A); Mobj.Material.SPC_R = ColorFloatToByte(material.ColorSpecular.R); Mobj.Material.SPC_G = ColorFloatToByte(material.ColorSpecular.G); Mobj.Material.SPC_B = ColorFloatToByte(material.ColorSpecular.B); } } // Textures if (settings.ImportTexture) { if (material.HasTextureDiffuse) { var texturePath = Path.Combine(cache.FolderPath, material.TextureDiffuse.FilePath); if (File.Exists(material.TextureDiffuse.FilePath)) { texturePath = material.TextureDiffuse.FilePath; } /// special mobj loading if (Path.GetExtension(texturePath).ToLower() == ".mobj") { var dat = new HSDRaw.HSDRawFile(texturePath); Mobj._s = dat.Roots[0].Data._s; return(Mobj); } else if (File.Exists(texturePath)) { Mobj.RenderFlags |= RENDER_MODE.TEX0; var tobj = TOBJConverter.ImportTOBJFromFile(texturePath, settings.TextureFormat, settings.PaletteFormat); tobj.Flags = TOBJ_FLAGS.LIGHTMAP_DIFFUSE | TOBJ_FLAGS.COORD_UV; if (settings.ShadingType == ShadingType.VertexColor || settings.ShadingType == ShadingType.Material) { tobj.Flags |= TOBJ_FLAGS.COLORMAP_MODULATE; } else { tobj.Flags |= TOBJ_FLAGS.COLORMAP_REPLACE; } tobj.GXTexGenSrc = 4; tobj.TexMapID = GXTexMapID.GX_TEXMAP0; tobj.WrapS = ToGXWrapMode(material.TextureDiffuse.WrapModeU); tobj.WrapT = ToGXWrapMode(material.TextureDiffuse.WrapModeV); Mobj.Textures = tobj; } } } return(Mobj); }
/// <summary> /// /// </summary> private void WriteDOBJNodes(ModelExportSettings settings) { var jIndex = 0; foreach (var j in Jobjs) { var dIndex = 0; if (j.Dobj != null) { foreach (var dobj in j.Dobj.List) { Node dobjNode = new Node(); dobjNode.Name = $"JOBJ_{jIndex}_DOBJ_{dIndex}"; if (dobj.Pobj != null) { var pindex = 0; foreach (var pobj in dobj.Pobj.List) { dobjNode.MeshIndices.Add(Scene.Meshes.Count); var mesh = ProcessPOBJ(pobj, j, pobj.SingleBoundJOBJ); mesh.Name = dobjNode.Name + "_POBJ_" + pindex++; mesh.MaterialIndex = Scene.MaterialCount; Scene.Meshes.Add(mesh); } } // process and export textures Material m = new Material(); m.Name = $"JOBJ_{jIndex}_DOBJ_{dIndex}_MOBJ_{dIndex}"; m.Shininess = dobj.Mobj.Material.Shininess; m.Opacity = dobj.Mobj.Material.Alpha; if (dobj.Mobj.Textures != null) { foreach (var t in dobj.Mobj.Textures.List) { if (t.ImageData != null && t.ImageData.ImageData != null && !imageToName.ContainsKey(t.ImageData.ImageData)) { var name = $"TOBJ_{imageToName.Count}"; using (Bitmap img = TOBJConverter.ToBitmap(t)) img.Save(settings.Directory + name + ".png"); imageToName.Add(t.ImageData.ImageData, name); } } var dif = new TextureSlot(); dif.TextureType = TextureType.Diffuse; dif.UVIndex = 0; dif.FilePath = imageToName[dobj.Mobj.Textures.ImageData.ImageData]; m.TextureDiffuse = dif; } Scene.Materials.Add(m); RootNode.Children.Add(dobjNode); dIndex++; } } jIndex++; } }