More additions and fixes.

Added GMX rendering (note explodes atm)
Fixed mario tennis aces/ultra compression (now uses external dll from Simon)
Fixed a bug where file sizes for IArchives (TMPK and ME01) would not adjust on save. casuing corrupted file data.
This commit is contained in:
KillzXGaming 2019-07-05 14:45:16 -04:00
parent d157fa4c84
commit ab80051646
22 changed files with 734 additions and 322 deletions

Binary file not shown.

View file

@ -129,7 +129,10 @@ namespace FirstPlugin
writer.Write(Alignment);
writer.Write(new uint[files.Count]); //Save space for offsets
for (int i = 0; i < files.Count; i++)
{
files[i].SaveFileFormat();
writer.Write(files[i].FileData.Length);
}
for (int i = 0; i < files.Count; i++)
{
@ -155,7 +158,6 @@ namespace FirstPlugin
{
Offsets[i] = (uint)(writer.Position - DataStart);
files[i].SaveFileFormat();
writer.Write(files[i].FileData);
Align(writer, (int)Alignment);
}

View file

@ -103,6 +103,8 @@ namespace FirstPlugin
writer.Write(0);
for (int i = 0; i < files.Count; i++)
{
files[i].SaveFileFormat();
files[i]._posHeader = writer.Position;
writer.Write(uint.MaxValue);
writer.Write(uint.MaxValue);
@ -119,7 +121,6 @@ namespace FirstPlugin
SetAlignment(writer, files[i].FileName);
writer.WriteUint32Offset(files[i]._posHeader + 4);
files[i].SaveFileFormat();
writer.Write(files[i].FileData);
}
writer.Close();

View file

@ -8,6 +8,7 @@ using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Rendering;
using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
@ -39,19 +40,103 @@ namespace FirstPlugin
}
}
Viewport viewport
{
get
{
var editor = LibraryGUI.Instance.GetObjectEditor();
return editor.GetViewport();
}
set
{
var editor = LibraryGUI.Instance.GetObjectEditor();
editor.LoadViewport(value);
}
}
bool DrawablesLoaded = false;
public override void OnClick(TreeView treeView)
{
if (Runtime.UseOpenGL)
{
if (viewport == null)
{
viewport = new Viewport(ObjectEditor.GetDrawableContainers());
viewport.Dock = DockStyle.Fill;
}
if (!DrawablesLoaded)
{
ObjectEditor.AddContainer(DrawableContainer);
DrawablesLoaded = true;
}
viewport.ReloadDrawables(DrawableContainer);
LibraryGUI.Instance.LoadEditor(viewport);
viewport.Text = Text;
}
}
public Header GMXHeader;
public GMX_Renderer Renderer;
public DrawableContainer DrawableContainer = new DrawableContainer();
public void Load(System.IO.Stream stream)
{
CanSave = true;
//Set renderer
Renderer = new GMX_Renderer();
DrawableContainer.Name = FileName;
DrawableContainer.Drawables.Add(Renderer);
//Read file
GMXHeader = new Header();
GMXHeader.Read(new FileReader(stream));
for (int i = 0; i < GMXHeader.Meshes.Count; i++)
{
var node = new TreeNode($"Mesh ({i})");
node.Tag = GMXHeader.Meshes[i];
Nodes.Add(node);
var renderedMesh = new GenericRenderedObject();
renderedMesh.Text = $"Mesh ({i})";
renderedMesh.ImageKey = "mesh";
renderedMesh.SelectedImageKey = "mesh";
renderedMesh.Checked = true;
if (GMXHeader.Meshes[i].VertexGroup != null)
{
renderedMesh.vertices = GMXHeader.Meshes[i].VertexGroup.Vertices;
}
if (GMXHeader.Meshes[i].IndexGroup != null)
{
renderedMesh.lodMeshes = new List<STGenericObject.LOD_Mesh>();
var msh = new STGenericObject.LOD_Mesh();
msh.PrimitiveType = STPolygonType.Triangle;
msh.FirstVertex = 0;
/* int VertexID = 0;
for (int f = 0; f < GMXHeader.Meshes[i].VertexCount; f+= 3)
{
msh.faces.AddRange(new List<int>() { VertexID + 2, VertexID + 1, VertexID });
VertexID++;
}*/
for (int f = 0; f < GMXHeader.Meshes[i].IndexGroup.Indices.Length / 3; f++)
{
ushort face0 = GMXHeader.Meshes[i].IndexGroup.Indices[f + 0];
ushort face1 = GMXHeader.Meshes[i].IndexGroup.Indices[f + 1];
ushort face2 = GMXHeader.Meshes[i].IndexGroup.Indices[f + 2];
msh.faces.AddRange(new List<int>() { face2, face1, face0, });
}
renderedMesh.lodMeshes.Add(msh);
}
renderedMesh.Tag = GMXHeader.Meshes[i];
Nodes.Add(renderedMesh);
Renderer.Meshes.Add(renderedMesh);
}
}
public void Unload()
@ -99,7 +184,7 @@ namespace FirstPlugin
break;
case "INDX":
INDX indexGrp = new INDX();
indexGrp.Read(reader);
indexGrp.Read(reader, GetLastMesh());
GetLastMesh().IndexGroup = indexGrp;
break;
case "VMAP":
@ -140,6 +225,7 @@ namespace FirstPlugin
PADX padding = new PADX();
Console.WriteLine("Saving GMX");
writer.WriteSignature("GMX2");
writer.Write(HeaderSize);
for (int i = 0; i < Meshes.Count; i++)
@ -171,6 +257,8 @@ namespace FirstPlugin
}
writer.WriteSignature("ENDX");
writer.Write(8); //Last section size
writer.Close();
writer.Dispose();
}
public class VERT
@ -194,6 +282,35 @@ namespace FirstPlugin
Vertices.Add(vert);
}
}
else if (mesh.VertexSize == 12)
{
for (int v = 0; v < mesh.VertexCount; v++)
{
Vertex vert = new Vertex();
vert.pos = reader.ReadVec3();
Vertices.Add(vert);
}
}
else if (mesh.VertexSize == 20)
{
for (int v = 0; v < mesh.VertexCount; v++)
{
Vertex vert = new Vertex();
vert.pos = reader.ReadVec3();
vert.uv0 = reader.ReadVec2();
Vertices.Add(vert);
}
}
else if (mesh.VertexSize == 24)
{
for (int v = 0; v < mesh.VertexCount; v++)
{
Vertex vert = new Vertex();
vert.pos = reader.ReadVec3();
vert.nrm = reader.ReadVec3();
Vertices.Add(vert);
}
}
else if (mesh.VertexSize == 36)
{
for (int v = 0; v < mesh.VertexCount; v++)
@ -205,7 +322,6 @@ namespace FirstPlugin
vert.uv0 = reader.ReadVec2();
Vertices.Add(vert);
Unknowns.Add(Unknown);
Console.WriteLine($"Unknown {Unknown}");
}
}
else
@ -287,14 +403,13 @@ namespace FirstPlugin
{
public ushort[] Indices;
public void Read(FileReader reader)
public void Read(FileReader reader, MESH mesh)
{
reader.ReadSignature(4, "INDX");
uint SectionSize = reader.ReadUInt32();
uint FaceCount = (SectionSize - 8) / sizeof(ushort);
Indices = new ushort[FaceCount];
for (int i = 0; i < FaceCount; i++)
Indices = new ushort[mesh.FaceCount];
for (int i = 0; i < mesh.FaceCount; i++)
{
Indices[i] = reader.ReadUInt16();
}
@ -331,7 +446,7 @@ namespace FirstPlugin
writer.WriteSignature("VMAP");
writer.Write(Indices.Length * sizeof(ushort) + 8);
for (int i = 0; i < Indices.Length; i++)
writer.Write(Indices[i]);
writer.Write(Indices[i]);
}
}

View file

@ -95,7 +95,7 @@ namespace FirstPlugin
}
Skeleton.bones.AddRange(((STSkeleton)model.DrawableContainer.Drawables[0]).bones);
Objects.AddRange(((Renderer)model.DrawableContainer.Drawables[1]).Meshes);
Objects.AddRange(((GenericModelRenderer)model.DrawableContainer.Drawables[1]).Meshes);
model.Unload();
}
@ -173,20 +173,20 @@ namespace FirstPlugin
var model = new STGenericModel();
model.Materials = Materials;
model.Objects = ((Renderer)DrawableContainer.Drawables[1]).Meshes;
model.Objects = ((GenericModelRenderer)DrawableContainer.Drawables[1]).Meshes;
assimp.SaveFromModel(model, FileName, new List<STGenericTexture>(), ((STSkeleton)DrawableContainer.Drawables[0]));
}
public void Unload()
{
foreach (var mesh in ((Renderer)DrawableContainer.Drawables[1]).Meshes)
foreach (var mesh in ((GenericModelRenderer)DrawableContainer.Drawables[1]).Meshes)
{
mesh.vertices.Clear();
mesh.faces.Clear();
mesh.display = new int[0];
}
((Renderer)DrawableContainer.Drawables[1]).Meshes.Clear();
((GenericModelRenderer)DrawableContainer.Drawables[1]).Meshes.Clear();
DrawableContainer.Drawables.Clear();
DrawableContainer = null;
@ -202,302 +202,6 @@ namespace FirstPlugin
return null;
}
public struct DisplayVertex
{
// Used for rendering.
public Vector3 pos;
public Vector3 nrm;
public Vector3 tan;
public Vector2 uv;
public Vector4 col;
public Vector4 node;
public Vector4 weight;
public Vector2 uv2;
public Vector2 uv3;
public static int Size = 4 * (3 + 3 + 3 + 2 + 4 + 4 + 4 + 2 + 2);
}
public class MeshWrapper : STGenericObject
{
public int[] display;
public int DisplayId;
public List<DisplayVertex> CreateDisplayVertices()
{
display = lodMeshes[DisplayLODIndex].getDisplayFace().ToArray();
List<DisplayVertex> displayVertList = new List<DisplayVertex>();
if (lodMeshes[DisplayLODIndex].faces.Count <= 3)
return displayVertList;
foreach (Vertex v in vertices)
{
DisplayVertex displayVert = new DisplayVertex()
{
pos = v.pos,
nrm = v.nrm,
tan = v.tan.Xyz,
col = v.col,
uv = v.uv0,
uv2 = v.uv1,
uv3 = v.uv2,
node = new Vector4(
v.boneIds.Count > 0 ? v.boneIds[0] : -1,
v.boneIds.Count > 1 ? v.boneIds[1] : -1,
v.boneIds.Count > 2 ? v.boneIds[2] : -1,
v.boneIds.Count > 3 ? v.boneIds[3] : -1),
weight = new Vector4(
v.boneWeights.Count > 0 ? v.boneWeights[0] : 0,
v.boneWeights.Count > 1 ? v.boneWeights[1] : 0,
v.boneWeights.Count > 2 ? v.boneWeights[2] : 0,
v.boneWeights.Count > 3 ? v.boneWeights[3] : 0),
};
displayVertList.Add(displayVert);
/* Console.WriteLine($"---------------------------------------------------------------------------------------");
Console.WriteLine($"Position {displayVert.pos.X} {displayVert.pos.Y} {displayVert.pos.Z}");
Console.WriteLine($"Normal {displayVert.nrm.X} {displayVert.nrm.Y} {displayVert.nrm.Z}");
Console.WriteLine($"Tanget {displayVert.tan.X} {displayVert.tan.Y} {displayVert.tan.Z}");
Console.WriteLine($"Color {displayVert.col.X} {displayVert.col.Y} {displayVert.col.Z} {displayVert.col.W}");
Console.WriteLine($"UV Layer 1 {displayVert.uv.X} {displayVert.uv.Y}");
Console.WriteLine($"UV Layer 2 {displayVert.uv2.X} {displayVert.uv2.Y}");
Console.WriteLine($"UV Layer 3 {displayVert.uv3.X} {displayVert.uv3.Y}");
Console.WriteLine($"Bone Index {displayVert.node.X} {displayVert.node.Y} {displayVert.node.Z} {displayVert.node.W}");
Console.WriteLine($"Weights {displayVert.weight.X} {displayVert.weight.Y} {displayVert.weight.Z} {displayVert.weight.W}");
Console.WriteLine($"---------------------------------------------------------------------------------------");*/
}
return displayVertList;
}
}
public class Renderer : AbstractGlDrawable
{
public Vector3 Max = new Vector3(0);
public Vector3 Min = new Vector3(0);
public List<ushort> SelectedTypes = new List<ushort>();
public Vector3 position = new Vector3(0, 0, 0);
protected bool Selected = false;
protected bool Hovered = false;
// public override bool IsSelected() => Selected;
// public override bool IsSelected(int partIndex) => Selected;
public bool IsHovered() => Selected;
// gl buffer objects
int vbo_position;
int ibo_elements;
public List<MeshWrapper> Meshes = new List<MeshWrapper>();
private void GenerateBuffers()
{
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out ibo_elements);
}
public void Destroy()
{
GL.DeleteBuffer(vbo_position);
GL.DeleteBuffer(ibo_elements);
}
public void UpdateVertexData()
{
if (!Runtime.OpenTKInitialized)
return;
DisplayVertex[] Vertices;
int[] Faces;
int poffset = 0;
int voffset = 0;
List<DisplayVertex> Vs = new List<DisplayVertex>();
List<int> Ds = new List<int>();
foreach (var m in Meshes)
{
m.Offset = poffset * 4;
List<DisplayVertex> pv = m.CreateDisplayVertices();
Vs.AddRange(pv);
for (int i = 0; i < m.lodMeshes[m.DisplayLODIndex].displayFaceSize; i++)
{
Ds.Add(m.display[i] + voffset);
}
poffset += m.lodMeshes[m.DisplayLODIndex].displayFaceSize;
voffset += pv.Count;
}
// Binds
Vertices = Vs.ToArray();
Faces = Ds.ToArray();
// Bind only once!
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<DisplayVertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * DisplayVertex.Size), Vertices, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw);
LibraryGUI.Instance.UpdateViewport();
}
public ShaderProgram defaultShaderProgram;
public override void Prepare(GL_ControlModern control)
{
string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "MKAGPDX") + "\\MKAGPDX_Model.frag";
string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "MKAGPDX") + "\\MKAGPDX_Model.vert";
var defaultFrag = new FragmentShader(File.ReadAllText(pathFrag));
var defaultVert = new VertexShader(File.ReadAllText(pathVert));
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert, control);
}
public override void Prepare(GL_ControlLegacy control)
{
}
private void CheckBuffers()
{
if (!Runtime.OpenTKInitialized)
return;
bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0;
if (!buffersWereInitialized)
{
GenerateBuffers();
UpdateVertexData();
}
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
CheckBuffers();
if (!Runtime.OpenTKInitialized)
return;
}
public override void Draw(GL_ControlModern control, Pass pass)
{
CheckBuffers();
if (!Runtime.OpenTKInitialized)
return;
control.CurrentShader = defaultShaderProgram;
SetRenderSettings(defaultShaderProgram);
Matrix4 camMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix;
GL.Disable(EnableCap.CullFace);
GL.Uniform3(defaultShaderProgram["difLightDirection"], Vector3.TransformNormal(new Vector3(0f, 0f, -1f), camMat.Inverted()).Normalized());
GL.Uniform3(defaultShaderProgram["difLightColor"], new Vector3(1));
GL.Uniform3(defaultShaderProgram["ambLightColor"], new Vector3(1));
defaultShaderProgram.EnableVertexAttributes();
foreach (var mdl in Meshes)
{
DrawModel(mdl, defaultShaderProgram);
}
defaultShaderProgram.DisableVertexAttributes();
GL.UseProgram(0);
GL.Disable(EnableCap.DepthTest);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
}
private void SetRenderSettings(ShaderProgram shader)
{
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
GL.Uniform1(defaultShaderProgram["renderType"], (int)Runtime.viewportShading);
}
private void DrawModel(MeshWrapper m, ShaderProgram shader, bool drawSelection = false)
{
if (m.lodMeshes[m.DisplayLODIndex].faces.Count <= 3)
return;
SetVertexAttributes(m, shader);
if (m.Checked)
{
if ((m.IsSelected))
{
DrawModelSelection(m, shader);
}
else
{
if (Runtime.RenderModelWireframe)
{
DrawModelWireframe(m, shader);
}
if (Runtime.RenderModels)
{
GL.DrawElements(PrimitiveType.Triangles, m.lodMeshes[m.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, m.Offset);
}
}
}
}
private static void DrawModelSelection(MeshWrapper p, ShaderProgram shader)
{
//This part needs to be reworked for proper outline. Currently would make model disappear
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.Enable(EnableCap.StencilTest);
// use vertex color for wireframe color
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.5f);
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
GL.Enable(EnableCap.DepthTest);
}
private void SetVertexAttributes(MeshWrapper m, ShaderProgram shader)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 0); //+12
GL.VertexAttribPointer(shader.GetAttribute("vNormal"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 12); //+12
GL.VertexAttribPointer(shader.GetAttribute("vTangent"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 24); //+12
GL.VertexAttribPointer(shader.GetAttribute("vUV0"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 36); //+8
GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 44); //+16
GL.VertexAttribIPointer(shader.GetAttribute("vBone"), 4, VertexAttribIntegerType.Int, DisplayVertex.Size, new IntPtr(60)); //+16
GL.VertexAttribPointer(shader.GetAttribute("vWeight"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 76);//+16
GL.VertexAttribPointer(shader.GetAttribute("vUV1"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 92);//+8
GL.VertexAttribPointer(shader.GetAttribute("vUV2"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 100);//+8
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
}
private static void DrawModelWireframe(MeshWrapper p, ShaderProgram shader)
{
// use vertex color for wireframe color
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.5f);
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
}
}
Viewport viewport
{
get
@ -550,12 +254,12 @@ namespace FirstPlugin
public List<Node> LowerNodes = new List<Node>();
public STSkeleton Skeleton { get; set; }
Renderer DrawableRenderer { get; set; }
GenericModelRenderer DrawableRenderer { get; set; }
public void Read(FileReader reader, MKAGPDX_Model root)
{
Skeleton = new STSkeleton();
DrawableRenderer = new Renderer();
DrawableRenderer = new GenericModelRenderer();
root.DrawableContainer.Drawables.Add(Skeleton);
root.DrawableContainer.Drawables.Add(DrawableRenderer);
@ -720,13 +424,13 @@ namespace FirstPlugin
}
else if (Node.IsMesh)
{
MeshWrapper meshNode = new MeshWrapper();
GenericRenderedObject meshNode = new GenericRenderedObject();
meshNode.ImageKey = "mesh";
meshNode.SelectedImageKey = "mesh";
int i = 0;
meshNode.lodMeshes = new List<MeshWrapper.LOD_Mesh>();
var msh = new MeshWrapper.LOD_Mesh();
meshNode.lodMeshes = new List<GenericRenderedObject.LOD_Mesh>();
var msh = new GenericRenderedObject.LOD_Mesh();
msh.PrimitiveType = STPolygonType.Triangle;
msh.FirstVertex = 0;
msh.faces = Node.SubMeshes[0].Faces;
@ -738,12 +442,12 @@ namespace FirstPlugin
{
if (i > 0)
{
MeshWrapper subMeshNode = new MeshWrapper();
GenericRenderedObject subMeshNode = new GenericRenderedObject();
subMeshNode.ImageKey = "mesh";
subMeshNode.SelectedImageKey = "mesh";
subMeshNode.lodMeshes = new List<MeshWrapper.LOD_Mesh>();
var submsh = new MeshWrapper.LOD_Mesh();
subMeshNode.lodMeshes = new List<GenericRenderedObject.LOD_Mesh>();
var submsh = new GenericRenderedObject.LOD_Mesh();
submsh.PrimitiveType = STPolygonType.Triangle;
submsh.FirstVertex = 0;
submsh.faces = subMesh.Faces;

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library.Rendering;
namespace FirstPlugin
{
public class GMX_Renderer : GenericModelRenderer
{
}
}

View file

@ -265,6 +265,7 @@
<Compile Include="FileFormats\XLINK\XLINK.cs" />
<Compile Include="GL\BCRES_Render.cs" />
<Compile Include="GL\GFBMDL_Render.cs" />
<Compile Include="GL\GMX_Renderer.cs" />
<Compile Include="GL\Helpers\DepthGLControl.cs" />
<Compile Include="GL\ShaderData\AglShaderOdyssey.cs" />
<Compile Include="GL\ShaderData\AglShaderTurbo.cs" />

View file

@ -145,13 +145,18 @@ namespace Switch_Toolbox.Library.IO
//Mario Tennis Aces Custom compression
public class MTA_CUSTOM
{
[DllImport("Lib/LibTennis.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void DecompressBuffer(IntPtr output, IntPtr input, uint len);
public unsafe byte[] Decompress(byte[] input, uint decompressedLength)
{
fixed (byte* outputPtr = new byte[decompressedLength])
{
fixed (byte* inputPtr = input)
{
Decompress(outputPtr, inputPtr, decompressedLength);
DecompressBuffer((IntPtr)outputPtr, (IntPtr)inputPtr, decompressedLength);
// Decompress(outputPtr, inputPtr, decompressedLength);
}
byte[] decomp = new byte[decompressedLength];

View file

@ -29,6 +29,11 @@ namespace Switch_Toolbox.Library
}
public virtual STGenericMaterial GetMaterial()
{
return new STGenericMaterial();
}
public List<STGenericPolygonGroup> PolygonGroups = new List<STGenericPolygonGroup>();
public bool HasPos;

View file

@ -194,6 +194,29 @@ namespace Switch_Toolbox.Library.IO
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Yaz0, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".cbtex")
{
fileReader.Position = 0;
byte compType = fileReader.ReadByte();
if (compType == 0x50)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
fileReader.Seek(4, System.IO.SeekOrigin.Begin);
uint decompSize = fileReader.ReadUInt32();
uint compSize = (uint)fileReader.BaseStream.Length - 8;
var comp = new STLibraryCompression.MTA_CUSTOM();
data = comp.Decompress(data, decompSize);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.MarioTennisCustom, DecompressedFileSize, CompressedFileSize);
}
fileReader.Position = 0;
}
if (Path.GetExtension(FileName) == ".lz")
{
if (data == null)

View file

@ -144,7 +144,7 @@ namespace Switch_Toolbox.Library
public void SaveFileFormat()
{
if (FileFormat != null && FileFormat.CanSave)
_fileData = FileFormat.Save();
FileData = FileFormat.Save();
}
[Browsable(false)]

View file

@ -15,5 +15,6 @@ namespace Switch_Toolbox.Library
Lz4,
Lz4f,
Zstb,
MarioTennisCustom,
}
}

View file

@ -0,0 +1,448 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace Switch_Toolbox.Library.Rendering
{
public class GenericModelRenderer : AbstractGlDrawable
{
public List<GenericRenderedObject> Meshes = new List<GenericRenderedObject>();
public STSkeleton Skeleton = new STSkeleton();
public Matrix4 ModelTransform = Matrix4.Identity;
// gl buffer objects
int vbo_position;
int ibo_elements;
private void GenerateBuffers()
{
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out ibo_elements);
UpdateVertexData();
UpdateTextureMaps();
}
public void Destroy()
{
GL.DeleteBuffer(vbo_position);
GL.DeleteBuffer(ibo_elements);
}
public void UpdateVertexData()
{
if (!Runtime.OpenTKInitialized)
return;
GenericRenderedObject.DisplayVertex[] Vertices;
int[] Faces;
int poffset = 0;
int voffset = 0;
List<GenericRenderedObject.DisplayVertex> Vs = new List<GenericRenderedObject.DisplayVertex>();
List<int> Ds = new List<int>();
foreach (GenericRenderedObject shape in Meshes)
{
List<GenericRenderedObject.DisplayVertex> pv = shape.CreateDisplayVertices();
Vs.AddRange(pv);
int GroupOffset = 0;
int groupIndex = 0;
if (shape.PolygonGroups.Count > 0)
{
foreach (var group in shape.PolygonGroups)
{
group.Offset = poffset * 4;
for (int i = 0; i < group.displayFaceSize; i++)
{
Ds.Add(shape.display[GroupOffset + i] + voffset);
}
poffset += group.displayFaceSize;
GroupOffset += group.displayFaceSize;
}
voffset += pv.Count;
}
else if (shape.lodMeshes.Count > 0)
{
shape.Offset = poffset * 4;
for (int i = 0; i < shape.lodMeshes[shape.DisplayLODIndex].displayFaceSize; i++)
{
Ds.Add(shape.display[i] + voffset);
}
poffset += shape.lodMeshes[shape.DisplayLODIndex].displayFaceSize;
voffset += pv.Count;
}
}
// Binds
Vertices = Vs.ToArray();
Faces = Ds.ToArray();
// Bind only once!
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<GenericRenderedObject.DisplayVertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * GenericRenderedObject.DisplayVertex.Size), Vertices, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw);
LibraryGUI.Instance.UpdateViewport();
}
public void UpdateTextureMaps()
{
if (!Runtime.OpenTKInitialized)
return;
LibraryGUI.Instance.UpdateViewport();
}
public ShaderProgram defaultShaderProgram;
public override void Prepare(GL_ControlModern control)
{
string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "GFBModel.frag");
string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "GFBModel.vert");
string pathUtiltyFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Utility") + "\\Utility.frag";
string pathPbrUtiltyFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Utility") + "\\PbrUtility.frag";
var defaultFrag = new FragmentShader(File.ReadAllText(pathFrag));
var defaultVert = new VertexShader(File.ReadAllText(pathVert));
var utiltyFrag = new FragmentShader(System.IO.File.ReadAllText(pathUtiltyFrag));
var pbrUtiltyFrag = new FragmentShader(System.IO.File.ReadAllText(pathPbrUtiltyFrag));
defaultShaderProgram = new ShaderProgram(new Shader[]
{ utiltyFrag, pbrUtiltyFrag, defaultVert, defaultFrag }, control);
}
public override void Prepare(GL_ControlLegacy control)
{
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
if (!Runtime.OpenTKInitialized)
return;
}
public override void Draw(GL_ControlModern control, Pass pass)
{
if (!Runtime.OpenTKInitialized || pass == Pass.TRANSPARENT)
return;
bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0;
if (!buffersWereInitialized)
GenerateBuffers();
ShaderProgram shader = defaultShaderProgram;
control.CurrentShader = shader;
control.UpdateModelMatrix(Matrix4.CreateScale(Runtime.previewScale) * ModelTransform);
Matrix4 camMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix;
Matrix4 invertedCamera = Matrix4.Identity;
if (invertedCamera.Determinant != 0)
invertedCamera = camMat.Inverted();
Vector3 lightDirection = new Vector3(0f, 0f, -1f);
shader.SetVector3("difLightDirection", Vector3.TransformNormal(lightDirection, invertedCamera).Normalized());
// GL.Enable(EnableCap.AlphaTest);
// GL.AlphaFunc(AlphaFunction.Gequal, 0.1f);
SetRenderSettings(shader);
DrawModels(shader, control);
GL.UseProgram(0);
GL.Disable(EnableCap.DepthTest);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
}
private static void SetBoneUniforms(GLControl control, ShaderProgram shader, STSkeleton Skeleton, STGenericObject mesh)
{
int i = 0;
foreach (var bone in Skeleton.bones)
{
Matrix4 transform = bone.invert * bone.Transform;
GL.UniformMatrix4(GL.GetUniformLocation(shader.programs[control], String.Format("bones[{0}]", i++)), false, ref transform);
}
/* foreach (var FaceGroup in fshp.Shape.FaceGroups)
{
if (FaceGroup.BoneIndexList == null)
continue;
for (int i = 0; i < FaceGroup.BoneIndexList.Length; i++)
{
GL.Uniform1(GL.GetUniformLocation(shader.programs[control], String.Format("boneIds[{0}]", i)), FaceGroup.BoneIndexList[i]);
Matrix4 transform = fmdl.Skeleton.Renderable.bones[(int)FaceGroup.BoneIndexList[i]].invert * fmdl.Skeleton.Renderable.bones[(int)FaceGroup.BoneIndexList[i]].Transform;
GL.UniformMatrix4(GL.GetUniformLocation(shader.programs[control], String.Format("bones[{0}]", i)), false, ref transform);
}
}*/
}
private void SetUniformBlocks(STGenericMaterial mat, ShaderProgram shader, STGenericObject m)
{
}
private static void SetUniforms(STGenericMaterial mat, ShaderProgram shader, STGenericObject m)
{
}
private static void SetUniformData(STGenericMaterial mat, ShaderProgram shader, string propertyName)
{
}
private static void LoadDebugTextureMaps(ShaderProgram shader)
{
GL.ActiveTexture(TextureUnit.Texture0 + 1);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.defaultTex.RenderableTex.TexID);
GL.Uniform1(shader["debugOption"], 2);
GL.ActiveTexture(TextureUnit.Texture11);
GL.Uniform1(shader["weightRamp1"], 11);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.BoneWeightGradient.Id);
GL.ActiveTexture(TextureUnit.Texture12);
GL.Uniform1(shader["weightRamp2"], 12);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.BoneWeightGradient2.Id);
GL.ActiveTexture(TextureUnit.Texture10);
GL.Uniform1(shader["UVTestPattern"], 10);
GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);
}
private static void SetTextureUniforms(STGenericMaterial mat, STGenericObject m, ShaderProgram shader)
{
SetDefaultTextureAttributes(mat, shader);
LoadDebugTextureMaps(shader);
shader.SetInt("RedChannel", 0);
shader.SetInt("GreenChannel", 1);
shader.SetInt("BlueChannel", 2);
shader.SetInt("AlphaChannel", 3);
LoadPBRMaps(shader);
foreach (STGenericMatTexture matex in mat.TextureMaps)
{
if (matex.Type == STGenericMatTexture.TextureType.Diffuse)
{
shader.SetBoolToInt("HasDiffuse", true);
TextureUniform(shader, mat, true, "DiffuseMap", matex);
}
}
}
private static void LoadPBRMaps(ShaderProgram shader)
{
GL.ActiveTexture(TextureUnit.Texture0 + 26);
RenderTools.specularPbr.Bind();
shader.SetInt("specularIbl", 26);
// GL.GenerateMipmap(GenerateMipmapTarget.TextureCubeMap);
// PBR IBL
GL.ActiveTexture(TextureUnit.Texture0 + 25);
RenderTools.diffusePbr.Bind();
shader.SetInt("irradianceMap", 25);
GL.ActiveTexture(TextureUnit.Texture0 + 27);
RenderTools.brdfPbr.Bind();
shader.SetInt("brdfLUT", 27);
}
private static void TextureUniform(ShaderProgram shader, STGenericMaterial mat, bool hasTex, string name, STGenericMatTexture mattex)
{
if (mattex.textureState == STGenericMatTexture.TextureState.Binded)
return;
// Bind the texture and create the uniform if the material has the right textures.
if (hasTex)
{
GL.Uniform1(shader[name], BindTexture(mattex, shader));
}
}
public static 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 bntx in TextureContainers)
{
if (TextureContainers.ContainsKey(activeTex))
{
BindGLTexture(bntx, tex, shader, activeTex);
return tex.textureUnit + 1;
}
}*/
return tex.textureUnit + 1;
}
private static void BindGLTexture(STGenericMatTexture tex, ShaderProgram shader, STGenericTexture texture)
{
if (tex.Type == STGenericMatTexture.TextureType.Diffuse)
{
shader.SetInt("RedChannel", (int)texture.RedChannel);
shader.SetInt("GreenChannel", (int)texture.GreenChannel);
shader.SetInt("BlueChannel", (int)texture.BlueChannel);
shader.SetInt("AlphaChannel", (int)texture.AlphaChannel);
}
// GL.ActiveTexture(TextureUnit.Texture0 + texid);
GL.BindTexture(TextureTarget.Texture2D, texture.RenderableTex.TexID);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)STGenericMatTexture.wrapmode[tex.wrapModeS]);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)STGenericMatTexture.wrapmode[tex.wrapModeT]);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)STGenericMatTexture.minfilter[tex.minFilter]);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)STGenericMatTexture.magfilter[tex.magFilter]);
GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)ExtTextureFilterAnisotropic.TextureMaxAnisotropyExt, 0.0f);
}
private static void SetDefaultTextureAttributes(STGenericMaterial mat, ShaderProgram shader)
{
}
private void SetRenderSettings(ShaderProgram shader)
{
shader.SetInt("renderType", (int)Runtime.viewportShading);
shader.SetInt("selectedBoneIndex", Runtime.SelectedBoneIndex);
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
}
private void DrawModels(ShaderProgram shader, GL_ControlModern control)
{
shader.EnableVertexAttributes();
foreach (STGenericObject shp in Meshes)
{
if (shp.Checked)
DrawModel(control, Skeleton, shp.GetMaterial(), shp, shader);
}
shader.DisableVertexAttributes();
}
private void SetVertexAttributes(STGenericObject m, ShaderProgram shader)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 0); //+12
GL.VertexAttribPointer(shader.GetAttribute("vNormal"), 3, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 12); //+12
GL.VertexAttribPointer(shader.GetAttribute("vTangent"), 3, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 24); //+12
GL.VertexAttribPointer(shader.GetAttribute("vUV0"), 2, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 36); //+8
GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 44); //+16
GL.VertexAttribIPointer(shader.GetAttribute("vBone"), 4, VertexAttribIntegerType.Int, GenericRenderedObject.DisplayVertex.Size, new IntPtr(60)); //+16
GL.VertexAttribPointer(shader.GetAttribute("vWeight"), 4, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 76);//+16
GL.VertexAttribPointer(shader.GetAttribute("vUV1"), 2, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 92);//+8
GL.VertexAttribPointer(shader.GetAttribute("vUV2"), 2, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 100);//+8
GL.VertexAttribPointer(shader.GetAttribute("vBinormal"), 3, VertexAttribPointerType.Float, false, GenericRenderedObject.DisplayVertex.Size, 108); //+12
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
}
private void DrawModel(GLControl control, STSkeleton Skeleton, STGenericMaterial Material, STGenericObject m, ShaderProgram shader)
{
if (m.PolygonGroups.Count > 0)
{
foreach (var group in m.PolygonGroups)
{
if (group.faces.Count <= 3)
return;
SetUniforms(Material, shader, m);
SetUniformBlocks(Material, shader, m);
SetBoneUniforms(control, shader, Skeleton, m);
SetVertexAttributes(m, shader);
SetTextureUniforms(Material, m, shader);
if (m.IsSelected)
{
DrawModelSelection(group, shader);
}
else
{
if (Runtime.RenderModels)
{
GL.DrawElements(PrimitiveType.Triangles, group.displayFaceSize, DrawElementsType.UnsignedInt, group.Offset);
}
}
}
}
else
{
if (m.lodMeshes.Count <= 0 || m.lodMeshes[m.DisplayLODIndex].faces.Count <= 3)
return;
SetUniforms(Material, shader, m);
SetUniformBlocks(Material, shader, m);
SetBoneUniforms(control, shader, Skeleton, m);
SetVertexAttributes(m, shader);
SetTextureUniforms(Material, m, shader);
if (m.IsSelected)
{
DrawModelSelection(m, shader);
}
else
{
if (Runtime.RenderModels)
{
GL.DrawElements(PrimitiveType.Triangles, m.lodMeshes[m.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, m.Offset);
}
}
}
}
private static void DrawModelSelection(STGenericObject p, ShaderProgram shader)
{
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.3f);
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
}
private static void DrawModelSelection(STGenericPolygonGroup p, ShaderProgram shader)
{
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.3f);
GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
}
}
}

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
namespace Switch_Toolbox.Library.Rendering
{
public class GenericRenderedObject : STGenericObject
{
public int[] display;
public int DisplayId;
public struct DisplayVertex
{
// Used for rendering.
public Vector3 pos;
public Vector3 nrm;
public Vector3 tan;
public Vector2 uv;
public Vector4 col;
public Vector4 node;
public Vector4 weight;
public Vector2 uv2;
public Vector2 uv3;
public Vector3 binorm;
public static int Size = 4 * (3 + 3 + 3 + 2 + 4 + 4 + 4 + 2 + 2 + 3);
}
public virtual List<DisplayVertex> CreateDisplayVertices()
{
display = new int[0];
if (PolygonGroups.Count > 0)
{
List<int> Faces = new List<int>();
foreach (var group in PolygonGroups)
Faces.AddRange(group.GetDisplayFace());
display = Faces.ToArray();
}
if (lodMeshes.Count > 0)
{
display = lodMeshes[DisplayLODIndex].getDisplayFace().ToArray();
}
List<DisplayVertex> displayVertList = new List<DisplayVertex>();
if (display.Length <= 3)
return displayVertList;
foreach (Vertex v in vertices)
{
DisplayVertex displayVert = new DisplayVertex()
{
pos = v.pos,
nrm = v.nrm,
tan = v.tan.Xyz,
binorm = v.bitan.Xyz,
col = v.col,
uv = v.uv0,
uv2 = v.uv1,
uv3 = v.uv2,
node = new Vector4(
v.boneIds.Count > 0 ? v.boneIds[0] : -1,
v.boneIds.Count > 1 ? v.boneIds[1] : -1,
v.boneIds.Count > 2 ? v.boneIds[2] : -1,
v.boneIds.Count > 3 ? v.boneIds[3] : -1),
weight = new Vector4(
v.boneWeights.Count > 0 ? v.boneWeights[0] : 0,
v.boneWeights.Count > 1 ? v.boneWeights[1] : 0,
v.boneWeights.Count > 2 ? v.boneWeights[2] : 0,
v.boneWeights.Count > 3 ? v.boneWeights[3] : 0),
};
displayVertList.Add(displayVert);
}
return displayVertList;
}
}
}

View file

@ -214,6 +214,8 @@
<Compile Include="Compression\STLibraryCompression.cs" />
<Compile Include="Compression\ZCMP.cs" />
<Compile Include="Config.cs" />
<Compile Include="Rendering\GenericModelRenderer\GenericModelRenderer.cs" />
<Compile Include="Rendering\GenericModelRenderer\GenericRenderedObject.cs" />
<Compile Include="Security\Cryptography\crc32.cs" />
<Compile Include="DrawableContainer.cs" />
<Compile Include="FileFormats\3DS\ETC1.cs" />

BIN
Toolbox/Lib/LibTennis.dll Normal file

Binary file not shown.

View file

@ -386,6 +386,9 @@
<Content Include="Lib\LibHac.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\LibTennis.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\Licenses\Assimp COPYRIGHT.txt" />
<Content Include="Lib\Licenses\ImageBox COPYRIGHT.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>