mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-23 13:03:15 +00:00
371 lines
15 KiB
C#
371 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Toolbox.Library;
|
|
using Toolbox.Library.Rendering;
|
|
using System.Windows.Forms;
|
|
using OpenTK;
|
|
|
|
namespace FirstPlugin
|
|
{
|
|
public class CsvModel : IFileFormat
|
|
{
|
|
public FileType FileType { get; set; } = FileType.Spreadsheet;
|
|
|
|
public bool CanSave { get; set; }
|
|
public string[] Description { get; set; } = new string[] { "CSV Model" };
|
|
public string[] Extension { get; set; } = new string[] { "*.csv" };
|
|
public string FileName { get; set; }
|
|
public string FilePath { get; set; }
|
|
public IFileInfo IFileInfo { get; set; }
|
|
|
|
public bool Identify(System.IO.Stream stream)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public Type[] Types
|
|
{
|
|
get
|
|
{
|
|
List<Type> types = new List<Type>();
|
|
return types.ToArray();
|
|
}
|
|
}
|
|
|
|
public List<STGenericObject> objects = new List<STGenericObject>();
|
|
|
|
public class Model
|
|
{
|
|
public string Name { get; set; }
|
|
public int UVChannelCount { get; set; }
|
|
public DataType type;
|
|
public DataSubType subType;
|
|
|
|
public List<string[]> bones = new List<string[]>();
|
|
public List<float[]> weights = new List<float[]>();
|
|
}
|
|
public enum DataType : int
|
|
{
|
|
vertex = 1,
|
|
faces = 2,
|
|
bones = 3,
|
|
}
|
|
public enum DataSubType : int
|
|
{
|
|
position = 0,
|
|
normals = 1,
|
|
colors = 2,
|
|
uv0 = 3,
|
|
uv1 = 4,
|
|
uv2 = 5,
|
|
uv3 = 6,
|
|
}
|
|
|
|
float X, Y, Z, W;
|
|
public void Load(System.IO.Stream stream)
|
|
{
|
|
LoadFile(stream);
|
|
}
|
|
public void LoadFile(Stream stream, bool IsModel = false)
|
|
{
|
|
if (!IsModel)
|
|
{
|
|
MessageBox.Show("Not valid model csv");
|
|
return;
|
|
}
|
|
|
|
string line = null;
|
|
|
|
List<Model> models = new List<Model>();
|
|
|
|
TextReader csv = new StreamReader(stream);
|
|
Model model = new Model();
|
|
STGenericObject STobj = new STGenericObject();
|
|
Vertex vtx = new Vertex();
|
|
STGenericObject.LOD_Mesh lod = new STGenericObject.LOD_Mesh();
|
|
int Index = 0;
|
|
int ww = 0;
|
|
while (true)
|
|
{
|
|
line = csv.ReadLine();
|
|
if (line != null)
|
|
{
|
|
if (line.StartsWith("Obj Name"))
|
|
{
|
|
model = new Model();
|
|
STobj = new STGenericObject();
|
|
model.Name = line.Split(':')[1].Replace("\n", "");
|
|
model.subType = DataSubType.position;
|
|
models.Add(model);
|
|
|
|
STobj.ObjectName = model.Name;
|
|
lod = new STGenericObject.LOD_Mesh();
|
|
lod.IndexFormat = STIndexFormat.UInt16;
|
|
lod.PrimitiveType = STPolygonType.Triangle;
|
|
STobj.lodMeshes.Add(lod);
|
|
STobj.VertexBufferIndex = Index;
|
|
objects.Add(STobj);
|
|
Index++;
|
|
}
|
|
else if (line.StartsWith("tex_Array:"))
|
|
{
|
|
|
|
}
|
|
else if (line.StartsWith("Bone_Suport"))
|
|
{
|
|
|
|
}
|
|
else if (line.StartsWith("Color_Suport"))
|
|
{
|
|
|
|
}
|
|
else if (line.StartsWith("UV_Num:"))
|
|
{
|
|
int uvCount;
|
|
int.TryParse(line.Split(':')[1].Replace("\n", ""), out uvCount);
|
|
model.UVChannelCount = uvCount;
|
|
}
|
|
else if (line.StartsWith("vert_Array"))
|
|
{
|
|
model.type = DataType.vertex;
|
|
}
|
|
else if (line.StartsWith("face_Array"))
|
|
{
|
|
model.type = DataType.faces;
|
|
}
|
|
else if (line.StartsWith("bone_Array"))
|
|
{
|
|
model.type = DataType.bones;
|
|
}
|
|
else
|
|
{
|
|
string[] values = line.Replace("\n", "").Replace("\r", "").Split(',');
|
|
|
|
if (model.type == DataType.vertex)
|
|
{
|
|
switch (model.subType)
|
|
{
|
|
case DataSubType.position:
|
|
vtx = new Vertex();
|
|
STobj.vertices.Add(vtx);
|
|
|
|
STobj.HasPos = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
float.TryParse(values[2], out Z);
|
|
vtx.pos = new Vector3(X, Y, Z);
|
|
model.subType = DataSubType.normals;
|
|
break;
|
|
case DataSubType.normals:
|
|
STobj.HasNrm = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
float.TryParse(values[2], out Z);
|
|
vtx.nrm = new Vector3(X, Y, Z);
|
|
model.subType = DataSubType.colors;
|
|
break;
|
|
case DataSubType.colors:
|
|
STobj.HasVertColors = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
float.TryParse(values[2], out Z);
|
|
float.TryParse(values[3], out W);
|
|
vtx.col = new Vector4(X / 255, Y / 255, Z / 255, 1);
|
|
model.subType = DataSubType.uv0;
|
|
break;
|
|
case DataSubType.uv0:
|
|
STobj.HasUv0 = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
vtx.uv0 = new Vector2(X, 1 - Y);
|
|
if (model.UVChannelCount == 1)
|
|
model.subType = DataSubType.position;
|
|
else
|
|
model.subType = DataSubType.uv1;
|
|
break;
|
|
case DataSubType.uv1:
|
|
STobj.HasUv1 = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
vtx.uv1 = new Vector2(X, 1 - Y);
|
|
if (model.UVChannelCount == 2)
|
|
model.subType = DataSubType.position;
|
|
else
|
|
model.subType = DataSubType.uv2;
|
|
break;
|
|
case DataSubType.uv2:
|
|
STobj.HasUv2 = true;
|
|
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
vtx.uv2 = new Vector2(X, 1 - Y);
|
|
if (model.UVChannelCount == 3)
|
|
model.subType = DataSubType.position;
|
|
else
|
|
model.subType = DataSubType.uv3;
|
|
break;
|
|
case DataSubType.uv3:
|
|
float.TryParse(values[0], out X);
|
|
float.TryParse(values[1], out Y);
|
|
model.subType = DataSubType.position;
|
|
break;
|
|
}
|
|
}
|
|
if (model.type == DataType.faces)
|
|
{
|
|
int face;
|
|
foreach (string v in values)
|
|
{
|
|
var cleaned = v.Replace(".0", string.Empty);
|
|
int.TryParse(cleaned, out face);
|
|
lod.faces.Add(face-1);
|
|
}
|
|
}
|
|
if (model.type == DataType.bones)
|
|
{
|
|
STobj.HasWeights = true;
|
|
STobj.HasIndices = true;
|
|
|
|
Array.Resize(ref values, values.Length - 1);
|
|
|
|
List<string> bones = new List<string>();
|
|
List<float> weights = new List<float>();
|
|
|
|
int bbs = 0;
|
|
foreach (string obj in values)
|
|
{
|
|
if (bbs == 0)
|
|
{
|
|
bones.Add(obj);
|
|
bbs += 1;
|
|
}
|
|
else
|
|
{
|
|
float.TryParse(obj, out X);
|
|
weights.Add(X);
|
|
bbs = 0;
|
|
}
|
|
}
|
|
|
|
STobj.bones.Add(bones.ToArray());
|
|
STobj.weightsT.Add(weights.ToArray());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (objects[0].weightsT.Count > 0 && objects[0].weightsT.Count != objects[0].vertices.Count)
|
|
throw new Exception("Incorrect vertex amount");
|
|
|
|
foreach (STGenericObject obj in objects)
|
|
{
|
|
obj.lodMeshes[0].GenerateSubMesh();
|
|
for (int v = 0; v < obj.vertices.Count; v++)
|
|
{
|
|
foreach (string bn in obj.bones[v])
|
|
obj.vertices[v].boneNames.Add(bn);
|
|
|
|
//Produce identical results for the weight output as BFRES_Vertex.py
|
|
//This should prevent encoding back and exploding
|
|
float MaxWeight = 1.0f;
|
|
int i = 0;
|
|
foreach (float f in obj.weightsT[v])
|
|
{
|
|
float weight = f;
|
|
if (i + 1 == obj.weightsT.Count)
|
|
weight = MaxWeight;
|
|
|
|
if (weight >= MaxWeight)
|
|
{
|
|
weight = MaxWeight;
|
|
MaxWeight = 0;
|
|
}
|
|
else
|
|
MaxWeight -= weight;
|
|
|
|
obj.vertices[v].boneWeights.Add(weight);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
int vID = 0;
|
|
foreach (Vertex v in obj.vertices)
|
|
{
|
|
if (v.boneNames.Count == 1)
|
|
Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]}");
|
|
if (v.boneNames.Count == 2)
|
|
Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}");
|
|
if (v.boneNames.Count == 3)
|
|
Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}");
|
|
if (v.boneNames.Count == 4)
|
|
Console.WriteLine($"{vID} {v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}");
|
|
|
|
vID++;
|
|
}
|
|
}
|
|
|
|
csv.Close();
|
|
csv = null;
|
|
}
|
|
public void Unload()
|
|
{
|
|
|
|
}
|
|
public byte[] Save()
|
|
{
|
|
MemoryStream mem = new MemoryStream();
|
|
|
|
using (System.IO.StreamWriter file = new System.IO.StreamWriter(mem))
|
|
{
|
|
foreach (STGenericObject obj in objects)
|
|
{
|
|
file.WriteLine($"Obj Name:" + obj.ObjectName);
|
|
file.WriteLine($"Bone_Suport");
|
|
file.WriteLine($"UV_Num:1");
|
|
file.WriteLine($"vert_Array");
|
|
|
|
foreach (Vertex v in obj.vertices)
|
|
{
|
|
file.WriteLine($"{v.pos.X},{v.pos.Y},{v.pos.Z}");
|
|
file.WriteLine($"{v.nrm.X},{v.nrm.Y},{v.nrm.Z}");
|
|
file.WriteLine($"{v.col.X * 255},{v.col.Y * 255},{v.col.Z * 255},{v.col.W * 255}");
|
|
file.WriteLine($"{v.uv0.X},{v.uv0.Y}");
|
|
// file.WriteLine($"{v.uv1.X},{v.uv1.Y}");
|
|
}
|
|
file.WriteLine($"face_Array");
|
|
for (int f = 0; f < obj.faces.Count / 3; f++)
|
|
{
|
|
file.WriteLine($"{obj.faces[f] + 1},{obj.faces[f++] + 1},{obj.faces[f++] + 1}");
|
|
}
|
|
file.WriteLine($"bone_Array");
|
|
foreach (Vertex v in obj.vertices)
|
|
{
|
|
if (v.boneNames.Count == 1)
|
|
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]}");
|
|
if (v.boneNames.Count == 2)
|
|
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}");
|
|
if (v.boneNames.Count == 3)
|
|
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}");
|
|
if (v.boneNames.Count == 4)
|
|
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}");
|
|
}
|
|
}
|
|
file.Close();
|
|
}
|
|
|
|
|
|
return mem.ToArray();
|
|
}
|
|
}
|
|
}
|