Fix loading 3ds bflim

This commit is contained in:
KillzXGaming 2019-07-27 21:05:12 -04:00
parent f599ea9b41
commit 2da0d605fe
12 changed files with 260 additions and 135 deletions

Binary file not shown.

View file

@ -83,7 +83,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
DrawableContainer.Name = FileName;
Renderer = new LM2_Renderer();
DrawableContainer.Drawables.Add(Renderer);
Text = FileName;
using (var reader = new FileReader(stream))
@ -181,6 +181,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
currentTexture.Read(textureReader);
currentTexture.Text = $"Texture {ImageHeaderIndex}";
textureFolder.Nodes.Add(currentTexture);
Renderer.TextureList.Add(currentTexture);
ImageHeaderIndex++;
}
@ -218,6 +219,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
currentModel.Meshes.Add(mesh);
}
}
currentModel.ModelInfo.Read(new FileReader(currentModel.ModelInfo.Data), currentModel.Meshes);
break;
case SubDataType.ModelTransform:
using (var transformReader = new FileReader(chunkEntry.FileData))

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Toolbox.Library;
namespace FirstPlugin.LuigisMansion.DarkMoon
{
public class LM2_Material : STGenericMaterial
{
}
}

View file

@ -121,6 +121,8 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
RenderableMeshWrapper genericObj = new RenderableMeshWrapper();
genericObj.Mesh = mesh;
genericObj.Text = $"Mesh {i}";
genericObj.SetMaterial(mesh.Material);
Nodes.Add(genericObj);
DataDictionary.Renderer.Meshes.Add(genericObj);
@ -247,6 +249,8 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
genericObj.TransformPosition(new Vector3(0), new Vector3(-90, 0, 0), new Vector3(1));
}
}
genericObj.RemoveDuplicateVertices();
}
}
}
@ -282,12 +286,80 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public class LM2_ModelInfo
{
public byte[] Data;
public void Read(FileReader reader, List<LM2_Mesh> Meshes)
{
// This is very dumb. Just look and try to find the mesh hash and get the texture after
int pos = 0;
while (!reader.EndOfStream && reader.Position < reader.BaseStream.Length - 5)
{
reader.Position = pos++;
uint HashIDCheck = reader.ReadUInt32();
for (int i = 0; i < Meshes.Count; i++)
{
if (Meshes[i].HashID == HashIDCheck)
{
uint TextureHashID = reader.ReadUInt32();
Meshes[i].Material = new LM2_Material();
var texUnit = 1;
Meshes[i].Material.TextureMaps.Add(new STGenericMatTexture()
{
textureUnit = texUnit++,
Type = STGenericMatTexture.TextureType.Diffuse,
Name = TextureHashID.ToString("x"),
});
}
}
}
/*
for (int i = 0; i < Meshes.Count; i++)
{
//This section keeps varing so just search for mesh hash id and get texture hash after it
uint Unknown = reader.ReadUInt32(); //A81E313F
reader.Seek(40);
//Not sure what this is. Not a transform as the UVs seem fine as is
float[] Unknown2 = reader.ReadSingles(5); //0.5, 1, 0.5,0.5, 1
reader.Seek(4); //Padding
uint MeshHashID = reader.ReadUInt32();
uint TextureHashID = reader.ReadUInt32();
uint UnknownHashID = reader.ReadUInt32(); //Material hash??
//Go through each mesh and find a matching hash
for (int m = 0; m < Meshes.Count; m++)
{
if (Meshes[m].HashID == MeshHashID)
{
}
};
if (i != Meshes.Count - 1)
reader.Seek(4); //padding on all but last entry
}*/
}
}
public class RenderableMeshWrapper : GenericRenderedObject
{
public LM2_Mesh Mesh { get; set; }
LM2_Material material;
public override STGenericMaterial GetMaterial()
{
return material;
}
public void SetMaterial(LM2_Material mat)
{
material = mat;
}
public override void OnClick(TreeView treeView)
{
STPropertyGrid editor = (STPropertyGrid)LibraryGUI.GetActiveContent(typeof(STPropertyGrid));
@ -382,10 +454,14 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public ushort Unknown7 { get; private set; } //Always 256?
public uint HashID { get; private set; }
public LM2_Material Material { get; set; }
public Matrix4 Transform { get; set; } = Matrix4.Identity;
public void Read(FileReader reader)
{
Material = new LM2_Material();
IndexStartOffset = reader.ReadUInt32();
IndexCount = reader.ReadUInt16();
IndexFormat = reader.ReadEnum<IndexFormat>(true);

View file

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Threading.Tasks;
using System.ComponentModel;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Forms;
@ -72,6 +72,32 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public byte[] ImageData { get; set; }
private POWEProperties properties;
public class POWEProperties
{
[Browsable(false)]
public uint ID { get; set; }
public string HashID
{
get
{
return ID.ToString("x");
}
}
[ReadOnly(true)]
public uint Width { get; set; }
[ReadOnly(true)]
public uint Height { get; set; }
[ReadOnly(true)]
public byte NumMips { get; set; }
[ReadOnly(true)]
public TEX_FORMAT Format { get; set; }
}
public void Read(FileReader reader)
{
//Magic and ID not pointed to for sub entries so just skip them for now
@ -98,8 +124,17 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
Parameters = new ImageParameters();
Parameters.FlipY = true;
properties = new POWEProperties();
properties.ID = ID2;
properties.Width = Width;
properties.Height = Height;
properties.NumMips = numMips;
properties.Format = Format;
}
public override void OnClick(TreeView treeview)
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
@ -111,7 +146,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
LibraryGUI.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadProperties(this.GenericProperties);
editor.LoadProperties(properties);
editor.LoadImage(this);
}

View file

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
@ -44,33 +44,6 @@ namespace FirstPlugin
}
}
public static BFLIMFormat ConvertFormatGenericToBflim(TEX_FORMAT Format)
{
switch (Format)
{
case TEX_FORMAT.A8_UNORM: return BFLIMFormat.L8_UNORM;
case TEX_FORMAT.R8G8_UNORM: return BFLIMFormat.LA8;
case TEX_FORMAT.R8G8_SNORM: return BFLIMFormat.LA8;
case TEX_FORMAT.B5G6R5_UNORM: return BFLIMFormat.RGB565;
case TEX_FORMAT.B5G5R5A1_UNORM: return BFLIMFormat.RGB5A1;
case TEX_FORMAT.R8G8B8A8_UNORM: return BFLIMFormat.RGBA8;
case TEX_FORMAT.R8G8B8A8_UNORM_SRGB: return BFLIMFormat.RGBA8_SRGB;
case TEX_FORMAT.R10G10B10A2_UNORM: return BFLIMFormat.RGB10A2_UNORM;
case TEX_FORMAT.B4G4R4A4_UNORM: return BFLIMFormat.RGBA4;
case TEX_FORMAT.BC1_UNORM: return BFLIMFormat.BC1_UNORM;
case TEX_FORMAT.BC1_UNORM_SRGB: return BFLIMFormat.BC1_SRGB;
case TEX_FORMAT.BC2_UNORM: return BFLIMFormat.BC2_UNORM;
case TEX_FORMAT.BC2_UNORM_SRGB: return BFLIMFormat.BC2_SRGB;
case TEX_FORMAT.BC3_UNORM: return BFLIMFormat.BC3_UNORM;
case TEX_FORMAT.BC3_UNORM_SRGB: return BFLIMFormat.BC3_SRGB;
case TEX_FORMAT.BC4_UNORM: return BFLIMFormat.BC4A_UNORM;
case TEX_FORMAT.BC4_SNORM: return BFLIMFormat.BC4L_UNORM;
case TEX_FORMAT.BC5_UNORM: return BFLIMFormat.BC5_UNORM;
default:
throw new Exception("Unsupported format " + Format);
}
}
public override bool CanEdit { get; set; } = true;
public bool CanSave { get; set; }
@ -114,7 +87,7 @@ namespace FirstPlugin
prop.TileMode = image.TileMode;
prop.Swizzle = image.Swizzle;
ImageEditorBase form = new ImageEditorBase();
form = new ImageEditorBase();
form.Text = Text;
form.Dock = DockStyle.Fill;
form.AddFileContextEvent("Save", Save);
@ -299,11 +272,11 @@ namespace FirstPlugin
bflim.Text = ftex.texture.Name;
bflim.image = new Image();
bflim.image.Swizzle = (byte)ftex.texture.Swizzle;
bflim.image.BflimFormat = BFLIM.ConvertFormatGenericToBflim(ftex.Format);
bflim.image.BflimFormat = FormatsWiiU.FirstOrDefault(x => x.Value == ftex.Format).Key;
bflim.image.Height = (ushort)ftex.texture.Height;
bflim.image.Width = (ushort)ftex.texture.Width;
bflim.Format = BFLIM.GetFormat(bflim.image.BflimFormat);
bflim.Format = FormatsWiiU[bflim.image.BflimFormat];
bflim.Width = bflim.image.Width;
bflim.Height = bflim.image.Height;
@ -340,11 +313,11 @@ namespace FirstPlugin
if (ftex.texture != null)
{
image.Swizzle = (byte)ftex.texture.Swizzle;
image.BflimFormat = ConvertFormatGenericToBflim(ftex.Format);
image.BflimFormat = FormatsWiiU.FirstOrDefault(x => x.Value == ftex.Format).Key;
image.Height = (ushort)ftex.texture.Height;
image.Width = (ushort)ftex.texture.Width;
Format = GetFormat(image.BflimFormat);
Format = FormatsWiiU[image.BflimFormat];
Width = image.Width;
Height = image.Height;
@ -444,10 +417,17 @@ namespace FirstPlugin
header = new Header();
header.Read(reader);
bool Is3DS = reader.ByteOrder == Syroot.BinaryData.ByteOrder.LittleEndian;
reader.Seek(header.HeaderSize + FileSize - 0x28, SeekOrigin.Begin);
image = new Image();
image = new Image(Is3DS);
image.Read(reader);
Format = GetFormat(image.BflimFormat);
if (Is3DS)
Format = Formats3DS[image.BflimFormat];
else
Format = FormatsWiiU[image.BflimFormat];
Width = image.Width;
Height = image.Height;
@ -485,82 +465,59 @@ namespace FirstPlugin
}
}
public static TEX_FORMAT GetFormat(BFLIMFormat format)
public static Dictionary<byte, TEX_FORMAT> Formats3DS = new Dictionary<byte, TEX_FORMAT>()
{
switch (format)
{
case BFLIMFormat.L8_UNORM:
case BFLIMFormat.A8:
return TEX_FORMAT.A8_UNORM;
case BFLIMFormat.LA4:
return TEX_FORMAT.B4G4R4A4_UNORM;
case BFLIMFormat.LA8:
case BFLIMFormat.HILO8:
return TEX_FORMAT.R8G8_UNORM;
case BFLIMFormat.RGB565:
return TEX_FORMAT.B5G6R5_UNORM;
case BFLIMFormat.RGBX8:
case BFLIMFormat.RGBA8:
return TEX_FORMAT.R8G8B8A8_UNORM;
case BFLIMFormat.RGBA8_SRGB:
return TEX_FORMAT.R8G8B8A8_UNORM_SRGB;
case BFLIMFormat.RGB10A2_UNORM:
return TEX_FORMAT.R10G10B10A2_UNORM;
case BFLIMFormat.RGB5A1:
return TEX_FORMAT.B5G5R5A1_UNORM;
case BFLIMFormat.RGBA4:
return TEX_FORMAT.B4G4R4A4_UNORM;
case BFLIMFormat.BC1_UNORM:
return TEX_FORMAT.BC1_UNORM;
case BFLIMFormat.BC1_SRGB:
return TEX_FORMAT.BC1_UNORM_SRGB;
case BFLIMFormat.BC2_UNORM:
return TEX_FORMAT.BC2_UNORM_SRGB;
case BFLIMFormat.BC3_UNORM:
return TEX_FORMAT.BC3_UNORM;
case BFLIMFormat.BC3_SRGB:
return TEX_FORMAT.BC3_UNORM_SRGB;
case BFLIMFormat.BC4L_UNORM:
case BFLIMFormat.BC4A_UNORM:
return TEX_FORMAT.BC4_UNORM;
case BFLIMFormat.BC5_UNORM:
return TEX_FORMAT.BC5_UNORM;
case BFLIMFormat.RGB565_Indirect_UNORM:
return TEX_FORMAT.B5G6R5_UNORM;
default:
throw new Exception("Unsupported format " + format);
}
}
[0] = TEX_FORMAT.L8,
[1] = TEX_FORMAT.A8_UNORM,
[2] = TEX_FORMAT.A4,
[3] = TEX_FORMAT.LA8,
[4] = TEX_FORMAT.HIL08,
[5] = TEX_FORMAT.B5G6R5_UNORM,
[6] = TEX_FORMAT.R8G8B8A8_UNORM,
[7] = TEX_FORMAT.B5G5R5A1_UNORM,
[8] = TEX_FORMAT.B4G4R4A4_UNORM,
[9] = TEX_FORMAT.R8G8B8A8_UNORM,
[10] = TEX_FORMAT.ETC1_UNORM,
[11] = TEX_FORMAT.ETC1_A4,
[12] = TEX_FORMAT.BC1_UNORM,
[13] = TEX_FORMAT.BC2_UNORM,
[14] = TEX_FORMAT.BC3_UNORM,
[15] = TEX_FORMAT.BC4_UNORM, //BC4L_UNORM
[16] = TEX_FORMAT.BC4_UNORM, //BC4A_UNORM
[17] = TEX_FORMAT.BC5_UNORM,
[18] = TEX_FORMAT.L4,
[19] = TEX_FORMAT.A4,
};
public enum BFLIMFormat : byte
public static Dictionary<byte, TEX_FORMAT> FormatsWiiU = new Dictionary<byte, TEX_FORMAT>()
{
L8_UNORM,
A8,
LA4,
LA8,
HILO8,
RGB565,
RGBX8,
RGB5A1,
RGBA4,
RGBA8,
ETC1,
ETC1A4,
BC1_UNORM,
BC2_UNORM,
BC3_UNORM,
BC4L_UNORM,
BC4A_UNORM,
BC5_UNORM,
L4_UNORM,
A4_UNORM,
RGBA8_SRGB,
BC1_SRGB,
BC2_SRGB,
BC3_SRGB,
RGB10A2_UNORM,
RGB565_Indirect_UNORM,
}
[0] = TEX_FORMAT.L8,
[1] = TEX_FORMAT.A8_UNORM,
[2] = TEX_FORMAT.A4,
[3] = TEX_FORMAT.LA8,
[4] = TEX_FORMAT.R8G8_UNORM, //HILO8
[5] = TEX_FORMAT.B5G6R5_UNORM,
[6] = TEX_FORMAT.R8G8B8A8_UNORM,
[7] = TEX_FORMAT.B5G5R5A1_UNORM,
[8] = TEX_FORMAT.B4G4R4A4_UNORM,
[9] = TEX_FORMAT.R8G8B8A8_UNORM,
[10] = TEX_FORMAT.ETC1_UNORM,
[11] = TEX_FORMAT.ETC1_A4,
[12] = TEX_FORMAT.BC1_UNORM,
[13] = TEX_FORMAT.BC2_UNORM,
[14] = TEX_FORMAT.BC3_UNORM,
[15] = TEX_FORMAT.BC4_UNORM, //BC4L_UNORM
[16] = TEX_FORMAT.BC4_UNORM, //BC4A_UNORM
[17] = TEX_FORMAT.BC5_UNORM,
[18] = TEX_FORMAT.L4,
[19] = TEX_FORMAT.A4,
[20] = TEX_FORMAT.R8G8B8A8_UNORM,
[21] = TEX_FORMAT.BC1_UNORM_SRGB,
[22] = TEX_FORMAT.BC2_UNORM_SRGB,
[23] = TEX_FORMAT.BC3_UNORM_SRGB,
[24] = TEX_FORMAT.R10G10B10A2_UNORM,
[25] = TEX_FORMAT.R5G5B5_UNORM,
};
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
@ -589,7 +546,7 @@ namespace FirstPlugin
);
image.Swizzle = (byte)surface.swizzle;
image.BflimFormat = ConvertFormatGenericToBflim(Format);
image.BflimFormat = FormatsWiiU.FirstOrDefault(x => x.Value == Format).Key;
image.Height = (ushort)surface.height;
image.Width = (ushort)surface.width;
@ -612,26 +569,34 @@ namespace FirstPlugin
{
uint bpp = GetBytesPerPixel(Format);
GX2.GX2Surface surf = new GX2.GX2Surface();
surf.bpp = bpp;
surf.height = image.Height;
surf.width = image.Width;
surf.aa = (uint)GX2.GX2AAMode.GX2_AA_MODE_1X;
surf.alignment = image.Alignment;
surf.depth = 1;
surf.dim = (uint)GX2.GX2SurfaceDimension.DIM_2D;
surf.format = (uint)FTEX.ConvertToGx2Format(Format);
surf.use = (uint)GX2.GX2SurfaceUse.USE_COLOR_BUFFER;
surf.pitch = 0;
surf.data = ImageData;
surf.numMips = 1;
surf.mipOffset = new uint[0];
surf.mipData = ImageData;
surf.tileMode = (uint)GX2.GX2TileMode.MODE_2D_TILED_THIN1;
surf.swizzle = image.Swizzle;
surf.numArray = 1;
if (image.Is3DS)
{
PlatformSwizzle = PlatformSwizzle.Platform_3DS;
return ImageData;
}
else
{
GX2.GX2Surface surf = new GX2.GX2Surface();
surf.bpp = bpp;
surf.height = image.Height;
surf.width = image.Width;
surf.aa = (uint)GX2.GX2AAMode.GX2_AA_MODE_1X;
surf.alignment = image.Alignment;
surf.depth = 1;
surf.dim = (uint)GX2.GX2SurfaceDimension.DIM_2D;
surf.format = (uint)FTEX.ConvertToGx2Format(Format);
surf.use = (uint)GX2.GX2SurfaceUse.USE_COLOR_BUFFER;
surf.pitch = 0;
surf.data = ImageData;
surf.numMips = 1;
surf.mipOffset = new uint[0];
surf.mipData = ImageData;
surf.tileMode = (uint)GX2.GX2TileMode.MODE_2D_TILED_THIN1;
surf.swizzle = image.Swizzle;
surf.numArray = 1;
return GX2.Decode(surf, ArrayLevel, MipLevel);
return GX2.Decode(surf, ArrayLevel, MipLevel);
}
}
public void Unload()
@ -706,9 +671,15 @@ namespace FirstPlugin
public ushort Width;
public ushort Height;
public ushort Alignment;
public BFLIMFormat BflimFormat;
public byte BflimFormat;
public byte Flags;
public bool Is3DS = false;
public Image(bool is3DS)
{
Is3DS = is3DS;
}
public Image()
{
@ -748,7 +719,7 @@ namespace FirstPlugin
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
Alignment = reader.ReadUInt16();
BflimFormat = reader.ReadEnum<BFLIMFormat>(true);
BflimFormat = reader.ReadByte();
Flags = reader.ReadByte();
}
@ -759,7 +730,7 @@ namespace FirstPlugin
writer.Write(Width);
writer.Write(Height);
writer.Write(Alignment);
writer.Write(BflimFormat, true);
writer.Write(BflimFormat);
writer.Write(Flags);
}
}

View file

@ -205,6 +205,7 @@
<Compile Include="FileFormats\Archives\APAK.cs" />
<Compile Include="FileFormats\Archives\ARC.cs" />
<Compile Include="FileFormats\Archives\GFA.cs" />
<Compile Include="FileFormats\Archives\LM2\LM2_Material.cs" />
<Compile Include="FileFormats\HyruleWarriors\GITextureContainer.cs" />
<Compile Include="FileFormats\HyruleWarriors\HWBinGzResource.cs" />
<Compile Include="FileFormats\Archives\IGA_PAK.cs" />

View file

@ -8,14 +8,36 @@ using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Toolbox.Library;
namespace FirstPlugin.LuigisMansion.DarkMoon
{
public class LM2_Renderer : GenericModelRenderer
{
public List<TexturePOWE> TextureList = new List<TexturePOWE>();
public override void OnRender(GLControl control)
{
}
public override int BindTexture(STGenericMatTexture tex, ShaderProgram shader)
{
GL.ActiveTexture(TextureUnit.Texture0 + tex.textureUnit + 1);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.defaultTex.RenderableTex.TexID);
string activeTex = tex.Name;
foreach (var texture in TextureList)
{
if (texture.ID2.ToString("x") == tex.Name)
{
BindGLTexture(tex, shader, texture);
return tex.textureUnit + 1;
}
}
return tex.textureUnit + 1;
}
}
}

View file

@ -196,13 +196,16 @@ namespace Toolbox.Library
}
}
public void RemoveDuplicateVertices()
{
}
public void FlipUvsVertical()
{
foreach (Vertex v in vertices)
{
v.uv0 = new Vector2(v.uv0.X, 1 - v.uv0.Y);
}
}
public void FlipUvsHorizontal()
{

View file

@ -377,6 +377,7 @@ namespace Toolbox.Library.Rendering
shader.SetInt("selectedBoneIndex", Runtime.SelectedBoneIndex);
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
shader.SetInt("uvChannel", (int)Runtime.uvChannel);
}
public virtual void DrawModels(ShaderProgram shader, GL_ControlModern control)