mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-30 00:10:36 +00:00
c78251aab3
Update primative type for meshes. This will allow custom primative types for rendering. Add strikers and punch out wii model/texture support (older formats of LM2/LM3). Add LM2 Arcade model support (updated format of MKAGPDX) Add support for LM2/LM3 pck audio archives. Add support for LM2 message/localization data.
238 lines
9.3 KiB
C#
238 lines
9.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SELib;
|
|
using Toolbox.Library.Rendering;
|
|
using OpenTK;
|
|
|
|
namespace Toolbox.Library
|
|
{
|
|
public class SEModel
|
|
{
|
|
public List<STGenericObject> objects = new List<STGenericObject>();
|
|
public List<STGenericMaterial> materials = new List<STGenericMaterial>();
|
|
public STSkeleton skeleton;
|
|
|
|
public static void Save(string FileName, List<STGenericObject> Meshes, List<STGenericMaterial> Materials, List<STBone> bones)
|
|
{
|
|
SELib.SEModel seModel = new SELib.SEModel();
|
|
|
|
for (int i = 0; i < Meshes.Count; i++)
|
|
seModel.AddMesh(SaveMesh(Meshes[i]));
|
|
|
|
for (int i = 0; i < Materials.Count; i++)
|
|
seModel.AddMaterial(SaveMaterial(Materials[i]));
|
|
|
|
// for (int i = 0; i < bones.Count; i++)
|
|
// seModel.AddBone(SaveBone(bones[i]));
|
|
}
|
|
|
|
private static SELib.SEModelMesh SaveMesh(STGenericObject mesh)
|
|
{
|
|
var seMesh = new SELib.SEModelMesh();
|
|
|
|
var MeshLevel = mesh.lodMeshes[mesh.DisplayLODIndex];
|
|
for (int i = 0; i < MeshLevel.faces.Count; i++)
|
|
{
|
|
seMesh.AddFace((uint)MeshLevel.faces[i], (uint)MeshLevel.faces[i++], (uint)MeshLevel.faces[i++]);
|
|
}
|
|
return seMesh;
|
|
}
|
|
|
|
private static SELib.SEModelMaterial SaveMaterial(STGenericMaterial material)
|
|
{
|
|
var seMaterial = new SELib.SEModelMaterial();
|
|
return seMaterial;
|
|
}
|
|
|
|
private static SELib.SEModelBone SaveBone(STBone bone)
|
|
{
|
|
var seBone = new SELib.SEModelBone();
|
|
return seBone;
|
|
}
|
|
|
|
public void CreateGenericModel(string FileName)
|
|
{
|
|
skeleton = new STSkeleton();
|
|
|
|
var seModel = SELib.SEModel.Read(FileName);
|
|
for (int i = 0; i < seModel.MeshCount; i++)
|
|
objects.Add(CreateGenericObject(seModel, seModel.Meshes[i]));
|
|
|
|
for (int i = 0; i < seModel.MaterialCount; i++)
|
|
materials.Add(CreateGenericMaterial(seModel, seModel.Materials[i]));
|
|
|
|
for (int i = 0; i < seModel.BoneCount; i++)
|
|
skeleton.bones.Add(CreateGenericBone(seModel, seModel.Bones[i]));
|
|
|
|
}
|
|
|
|
public STBone CreateGenericBone(SELib.SEModel seModel, SELib.SEModelBone seBone)
|
|
{
|
|
STBone bone = new STBone(skeleton);
|
|
bone.Text = seBone.BoneName;
|
|
bone.parentIndex = seBone.BoneParent;
|
|
bone.RotationType = STBone.BoneRotationType.Euler;
|
|
|
|
Vector3 rotEular = ToEular(seBone.LocalRotation);
|
|
|
|
bone.position = new float[] { (float)seBone.LocalPosition.X, (float)seBone.LocalPosition.Y, (float)seBone.LocalPosition.Z };
|
|
bone.scale = new float[] { (float)seBone.Scale.X, (float)seBone.Scale.Y, (float)seBone.Scale.Z };
|
|
bone.rotation = new float[] { rotEular.X, rotEular.Y, rotEular.Z, 0 };
|
|
|
|
return bone;
|
|
}
|
|
|
|
public STGenericMaterial CreateGenericMaterial(SELib.SEModel seModel, SELib.SEModelMaterial seMaterial)
|
|
{
|
|
STGenericMaterial material = new STGenericMaterial();
|
|
material.Text = seMaterial.Name;
|
|
if (seMaterial.MaterialData is SEModelSimpleMaterial)
|
|
{
|
|
if (((SEModelSimpleMaterial)seMaterial.MaterialData).DiffuseMap != string.Empty)
|
|
{
|
|
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).DiffuseMap;
|
|
material.TextureMaps.Add(new STGenericMatTexture()
|
|
{
|
|
Name = TextureName,
|
|
Type = STGenericMatTexture.TextureType.Diffuse
|
|
});
|
|
}
|
|
if (((SEModelSimpleMaterial)seMaterial.MaterialData).NormalMap != string.Empty)
|
|
{
|
|
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).NormalMap;
|
|
material.TextureMaps.Add(new STGenericMatTexture()
|
|
{
|
|
Name = TextureName,
|
|
Type = STGenericMatTexture.TextureType.Normal
|
|
});
|
|
}
|
|
if (((SEModelSimpleMaterial)seMaterial.MaterialData).SpecularMap != string.Empty)
|
|
{
|
|
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).SpecularMap;
|
|
material.TextureMaps.Add(new STGenericMatTexture()
|
|
{
|
|
Name = TextureName,
|
|
Type = STGenericMatTexture.TextureType.Specular
|
|
});
|
|
}
|
|
}
|
|
return material;
|
|
}
|
|
|
|
public STGenericObject CreateGenericObject(SELib.SEModel seModel, SELib.SEModelMesh seMesh)
|
|
{
|
|
int Index = seModel.Meshes.IndexOf(seMesh);
|
|
|
|
STGenericObject mesh = new STGenericObject();
|
|
mesh.ObjectName = $"Mesh_{Index}";
|
|
if (seMesh.MaterialReferenceIndicies.Count > 0)
|
|
mesh.MaterialIndex = seMesh.MaterialReferenceIndicies[0];
|
|
|
|
mesh.HasPos = true;
|
|
for (int v = 0; v < seMesh.VertexCount; v++)
|
|
{
|
|
if (seMesh.Verticies[v].UVSets.Count > 0)
|
|
mesh.HasUv0 = true;
|
|
if (seMesh.Verticies[v].Weights.Count > 0)
|
|
{
|
|
mesh.HasIndices = true;
|
|
for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++)
|
|
{
|
|
if (seMesh.Verticies[v].Weights[w].BoneWeight != 0)
|
|
mesh.HasWeights = true;
|
|
}
|
|
}
|
|
if (seMesh.Verticies[v].VertexColor != SELib.Utilities.Color.White)
|
|
mesh.HasVertColors = true;
|
|
if (seMesh.Verticies[v].VertexNormal != SELib.Utilities.Vector3.Zero)
|
|
mesh.HasNrm = true;
|
|
|
|
Vertex vertex = new Vertex();
|
|
mesh.vertices.Add(vertex);
|
|
|
|
vertex.pos = ToTKVector3(seMesh.Verticies[v].Position);
|
|
vertex.nrm = ToTKVector3(seMesh.Verticies[v].VertexNormal);
|
|
vertex.col = ToTKVector4(seMesh.Verticies[v].VertexColor);
|
|
|
|
for (int u = 0; u < seMesh.Verticies[v].UVSetCount; u++)
|
|
{
|
|
if (u == 0)
|
|
vertex.uv0 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
|
|
if (u == 1)
|
|
vertex.uv1 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
|
|
if (u == 2)
|
|
vertex.uv2 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
|
|
}
|
|
|
|
for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++)
|
|
{
|
|
//Get the bone name from the index. Indices for formats get set after the importer
|
|
string BoneName = seModel.Bones[(int)seMesh.Verticies[v].Weights[w].BoneIndex].BoneName;
|
|
float BoneWeight = seMesh.Verticies[v].Weights[w].BoneWeight;
|
|
|
|
vertex.boneNames.Add(BoneName);
|
|
vertex.boneWeights.Add(BoneWeight);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
mesh.lodMeshes = new List<STGenericObject.LOD_Mesh>();
|
|
var lodMesh = new STGenericObject.LOD_Mesh();
|
|
lodMesh.PrimativeType = STPrimativeType.Triangles;
|
|
mesh.lodMeshes.Add(lodMesh);
|
|
for (int f = 0; f < seMesh.FaceCount; f++)
|
|
{
|
|
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex1);
|
|
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex2);
|
|
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex3);
|
|
}
|
|
|
|
return mesh;
|
|
}
|
|
|
|
private Vector2 ToTKVector2(SELib.Utilities.Vector2 value) {
|
|
return new Vector2((float)value.X, (float)value.Y);
|
|
}
|
|
|
|
private Vector3 ToTKVector3(SELib.Utilities.Vector3 value) {
|
|
return new Vector3((float)value.X, (float)value.Y, (float)value.Z);
|
|
}
|
|
|
|
private Vector4 ToTKVector4(SELib.Utilities.Color value) {
|
|
return new Vector4((float)(value.R / 255),
|
|
(float)(value.G / 255),
|
|
(float)(value.B / 255),
|
|
(float)(value.A / 255));
|
|
}
|
|
|
|
private static Vector3 ToEular(SELib.Utilities.Quaternion selibQuat)
|
|
{
|
|
OpenTK.Quaternion q = new Quaternion((float)selibQuat.X, (float)selibQuat.Y, (float)selibQuat.Z, (float)selibQuat.W);
|
|
Matrix4 mat = Matrix4.CreateFromQuaternion(q);
|
|
float x, y, z;
|
|
y = (float)Math.Asin(Clamp(mat.M13, -1, 1));
|
|
|
|
if (Math.Abs(mat.M13) < 0.99999)
|
|
{
|
|
x = (float)Math.Atan2(-mat.M23, mat.M33);
|
|
z = (float)Math.Atan2(-mat.M12, mat.M11);
|
|
}
|
|
else
|
|
{
|
|
x = (float)Math.Atan2(mat.M32, mat.M22);
|
|
z = 0;
|
|
}
|
|
return new Vector3(x, y, z) * -1;
|
|
}
|
|
private static float Clamp(float v, float min, float max)
|
|
{
|
|
if (v < min) return min;
|
|
if (v > max) return max;
|
|
return v;
|
|
}
|
|
}
|
|
}
|