public SEModel ToSEModel() { var semdl = new SEModel(); foreach (var bone in from x in Bones orderby x.Key ascending select x.Value) { semdl.AddBone(bone.BoneName, bone.BoneParent, bone.GlobalPosition, bone.GlobalRotation, bone.LocalPosition, bone.LocalRotation, bone.Scale); } foreach (var material in Materials) { semdl.AddMaterial(material); } foreach (var mesh in Meshes) { semdl.AddMesh(mesh); } foreach (var mesh in semdl.Meshes) { foreach (var v in mesh.Verticies) { var weightLeft = 1.0f; var maxWeight = 0.0f; var maxWeightIdx = 0u; for (int i = (int)v.WeightCount - 1; i >= 0; i--) { if (v.Weights[i].BoneWeight == 0 || v.Weights[i].BoneIndex >= 0xFF) { //Console.WriteLine($"Removed SB Weight at vertex {mesh.Verticies.IndexOf(v)} on mesh {ltbFile.Meshes.IndexOf(mesh)}"); v.Weights.RemoveAt(i); } else { weightLeft -= v.Weights[i].BoneWeight; if (v.Weights[i].BoneWeight > maxWeight) { maxWeight = v.Weights[i].BoneWeight; maxWeightIdx = v.Weights[i].BoneIndex; } } } if (weightLeft != 0.0f) { v.Weights.Find(weight => weight.BoneIndex == maxWeightIdx).BoneWeight += weightLeft; } } } semdl.GenerateLocalPositions(true, true); return(semdl); }
public void Init() { _seModel = new SEModel(new Entity.SEEntityList(_seList)); _seView.StopSound(); }
private static Model LoadSEModel(string filePath) { var model = new Model(Path.GetFileNameWithoutExtension(filePath)); var input = SEModel.Read(filePath); Printer.WriteLine("LOADER", string.Format("Loading {0}", model.Name)); foreach (var bone in input.Bones) { model.Bones.Add(new Model.Bone( bone.BoneName, bone.BoneParent, new Vector3( (float)bone.LocalPosition.X, (float)bone.LocalPosition.Y, (float)bone.LocalPosition.Z), new Quaternion( (float)bone.LocalRotation.X, (float)bone.LocalRotation.Y, (float)bone.LocalRotation.Z, (float)bone.LocalRotation.W), new Vector3( (float)bone.GlobalPosition.X, (float)bone.GlobalPosition.Y, (float)bone.GlobalPosition.Z), new Quaternion( (float)bone.GlobalRotation.X, (float)bone.GlobalRotation.Y, (float)bone.GlobalRotation.Z, (float)bone.GlobalRotation.W))); } foreach (var semesh in input.Meshes) { var mesh = new Model.Mesh((int)semesh.VertexCount, (int)semesh.FaceCount); foreach (var mtl in semesh.MaterialReferenceIndicies) { mesh.MaterialIndices.Add(mtl); } foreach (var severtex in semesh.Verticies) { var vertex = new Model.Vertex( new Vector3((float)severtex.Position.X, (float)severtex.Position.Y, (float)severtex.Position.Z), new Vector3((float)severtex.VertexNormal.X, (float)severtex.VertexNormal.Y, (float)severtex.VertexNormal.Z)); foreach (var uv in severtex.UVSets) { vertex.UVs.Add(new Vector2((float)uv.X, (float)uv.Y)); } foreach (var weight in severtex.Weights) { vertex.Weights.Add(new Model.Vertex.Weight() { BoneIndex = (int)weight.BoneIndex, Influence = weight.BoneWeight }); } vertex.Color = new Vector4( severtex.VertexColor.R / 255.0f, severtex.VertexColor.G / 255.0f, severtex.VertexColor.B / 255.0f, severtex.VertexColor.A / 255.0f); mesh.Vertices.Add(vertex); } foreach (var face in semesh.Faces) { mesh.Faces.Add(new Model.Face((int)face.FaceIndex1, (int)face.FaceIndex2, (int)face.FaceIndex3)); } model.Meshes.Add(mesh); } foreach (var material in input.Materials) { model.Materials.Add(new Model.Material(material.Name)); } Printer.WriteLine("LOADER", string.Format("Loaded {0}", model.Name)); return(model); }
static void ProcessFile(FileInfo fileInfo, string prefix) { taskQuene.Enqueue(async() => { var ext = fileInfo.Extension.ToLower(); if (ext == ".semodel") { var dir = "converted_files/"; if (prefix != "") { dir += $"{fileInfo.FullName.Replace(prefix, "").Replace(fileInfo.Name, "")}/"; } if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var semodel = SEModel.Read(fileInfo.OpenRead()); var smd = semodel.ToSMD(); File.WriteAllText($"{dir}{fileInfo.Name.Replace(fileInfo.Extension, "")}.smd", smd); } else if (ext == ".smd") { Console.WriteLine("Converting SMD..."); var dir = "converted_files/"; if (prefix != "") { dir += $"{fileInfo.FullName.Replace(prefix, "").Replace(fileInfo.Name, "")}/"; } if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var smd = SMDFile.Load(fileInfo); if (smd.IsAnimation) { smd.ToSEAnim().Write(File.OpenWrite($"{dir}{fileInfo.Name.Replace(fileInfo.Extension, "")}.seanim"), false); } else { smd.ToSEModel().Write(File.OpenWrite($"{dir}{fileInfo.Name.Replace(fileInfo.Extension, "")}.semodel")); } } else if (ext == ".ltb") { Console.WriteLine($"{fileInfo.Name}"); var ltb = LTBFile.Read(fileInfo); if (ltb != null) { if (!Directory.Exists($"converted_files/{fileInfo.FullName.Replace(prefix, "")}/anims/")) { Directory.CreateDirectory($"converted_files/{fileInfo.FullName.Replace(prefix, "")}/anims/"); } var semodel = ltb.ToSEModel(); foreach (var anim in ltb.Animations) { anim.Value.Write(File.OpenWrite($"converted_files/{fileInfo.FullName.Replace(prefix, "")}/anims/{anim.Key}"), false); } semodel.Write(File.OpenWrite($"converted_files/{fileInfo.FullName.Replace(prefix, "")}/{fileInfo.Name.Replace(fileInfo.Extension, ".semodel")}")); } } else if (ext == ".dtx") { if (!Directory.Exists($"converted_files/_images/{fileInfo.Directory.FullName.Replace(prefix, "")}")) { Directory.CreateDirectory($"converted_files/_images/{fileInfo.Directory.FullName.Replace(prefix, "")}"); } var dtxFile = await DTXFile.Load(fileInfo); dtxFile.Save(File.OpenWrite($"converted_files/_images/{fileInfo.FullName.Replace(fileInfo.Extension, ".png").Replace(prefix, "")}")); } else if (ext == ".dat") { var datFile = new DATFileV85(new SELib.Utilities.ExtendedBinaryReader(fileInfo.OpenRead())); } else if (ext == ".ogg") { var br = new BinaryReader(fileInfo.OpenRead()); uint rate = 0; ulong length = 0; br.BaseStream.Seek(-4, SeekOrigin.End); while (length == 0) { if (Encoding.ASCII.GetString(br.ReadBytes(4)) == "OggS") { br.BaseStream.Seek(2, SeekOrigin.Current); length = br.ReadUInt64(); } br.BaseStream.Seek(-5, SeekOrigin.Current); } br.BaseStream.Seek(0, SeekOrigin.Begin); while (rate == 0) { if (Encoding.ASCII.GetString(br.ReadBytes(6)) == "vorbis") { br.BaseStream.Seek(5, SeekOrigin.Current); rate = br.ReadUInt32(); } br.BaseStream.Seek(-5, SeekOrigin.Current); } Console.WriteLine($"{fileInfo.Name} has {length} Samples, Sample rate {rate}, time is {length / (float)rate} sec"); } else { Console.WriteLine($"{fileInfo.Name} - Unsupported format!"); } }); }
static void Main(string[] args) { // SELib Unit Test Console.Title = "SELib Unit Tests"; Console.WriteLine("SELib Unit Tests\n"); Console.WriteLine("- SEAnims\n"); #region SEAnim { // Log Console.Write("-- Test 1 "); // Make it var anim = new SEAnim(); // Add some keys anim.AddTranslationKey("shoulder", 0, 0, 0, 0); anim.AddTranslationKey("shoulder", 5, 1, 1, 1); anim.AddTranslationKey("shoulder", 10, 10, 10, 10); anim.AddTranslationKey("shoulder", 30, 20, 20, 20); anim.AddTranslationKey("shoulder", 40, 30, 30, 30); // Save it anim.Write("test1.seanim"); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 2 "); // Make it var anim = new SEAnim(); // Add some keys anim.AddTranslationKey("shoulder", 0, 0, 0, 0); anim.AddTranslationKey("shoulder", 5, 1, 1, 1); anim.AddTranslationKey("shoulder", 10, 10, 10, 10); anim.AddTranslationKey("shoulder", 30, 20, 20, 20); anim.AddTranslationKey("shoulder", 40, 30, 30, 30); // Add some scale anim.AddScaleKey("shoulder", 0, 1, 1, 1); anim.AddScaleKey("shoulder", 50, 3, 3, 3); // Save it anim.Write("test2.seanim"); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 3 "); // Make it var anim = new SEAnim(); // Add some keys anim.AddTranslationKey("shoulder", 0, 0, 0, 0); anim.AddTranslationKey("shoulder", 5, 1, 1, 1); anim.AddTranslationKey("shoulder", 10, 10, 10, 10); anim.AddTranslationKey("shoulder", 30, 20, 20, 20); anim.AddTranslationKey("shoulder", 40, 30, 30, 30); // Add some scale anim.AddScaleKey("shoulder", 0, 1, 1, 1); anim.AddScaleKey("shoulder", 50, 3, 3, 3); // Add some note anim.AddNoteTrack("hello_world", 3); anim.AddNoteTrack("bye", 50); // Save it anim.Write("test3.seanim"); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 4 "); // Make it var anim = new SEAnim(); // Add some keys anim.AddTranslationKey("shoulder", 0, 0, 0, 0); anim.AddTranslationKey("shoulder", 5, 1, 1, 1); anim.AddTranslationKey("shoulder", 10, 10, 10, 10); anim.AddTranslationKey("shoulder", 30, 20, 20, 20); anim.AddTranslationKey("shoulder", 40, 30, 30, 30); // Add some scale anim.AddScaleKey("shoulder", 0, 1, 1, 1); anim.AddScaleKey("shoulder", 50, 3, 3, 3); // Add some note anim.AddNoteTrack("hello_world", 3); anim.AddNoteTrack("bye", 50); // Save it (Really, we don't need doubles!!) anim.Write("test4.seanim", true); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 5 "); // Make it var anim = new SEAnim(); // Add some keys anim.AddTranslationKey("shoulder", 0, 0, 0, 0); anim.AddTranslationKey("shoulder", 5, 1, 1, 1); anim.AddTranslationKey("shoulder", 10, 10, 10, 10); anim.AddTranslationKey("shoulder", 30, 20, 20, 20); anim.AddTranslationKey("shoulder", 40, 30, 30, 30); // Add some scale anim.AddScaleKey("shoulder", 0, 1, 1, 1); anim.AddScaleKey("shoulder", 50, 3, 3, 3); // Add some rot anim.AddRotationKey("shoulder", 0, 0, 0, 0, 1); anim.AddRotationKey("shoulder", 50, 0.3, 0.2, 0.5, 1); // Random quat for test // Add some note anim.AddNoteTrack("hello_world", 3); anim.AddNoteTrack("bye", 50); // Save it anim.Write("test5.seanim"); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 6 "); // Read from test 5 var anim = SEAnim.Read("test5.seanim"); // Check data System.Diagnostics.Debug.Assert(anim.AnimationNotetracks.Count == 2); System.Diagnostics.Debug.Assert(anim.AnimationPositionKeys.Count == 1); System.Diagnostics.Debug.Assert(anim.AnimationRotationKeys.Count == 1); System.Diagnostics.Debug.Assert(anim.AnimationScaleKeys.Count == 1); System.Diagnostics.Debug.Assert(anim.BoneCount == 1); System.Diagnostics.Debug.Assert(anim.FrameCount == 51); System.Diagnostics.Debug.Assert(anim.FrameRate == 30.0); // Version System.Diagnostics.Debug.Assert(anim.APIVersion == "v1.0.1"); // Check functions System.Diagnostics.Debug.Assert(anim.RenameBone("shoulder", "shoulder") == false); System.Diagnostics.Debug.Assert(anim.RenameBone("shoulder", "new_shoulder") == true); // Done Console.WriteLine("DONE!"); } #endregion Console.WriteLine("\n- SEModels\n"); #region SEModel { // Log Console.Write("-- Test 1 "); // Make it var model = new SEModel(); // Add some bones model.AddBone("bone_0001", -1, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0002", 0, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0003", 0, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0004", 2, Vector3.Zero, Quaternion.Identity, new Vector3(22, 22, 22), Quaternion.Identity, Vector3.One); // Save it model.Write("test1.semodel"); // Done Console.WriteLine("DONE!"); } { // Log Console.Write("-- Test 2 "); // Make it var model = new SEModel(); // Allow globals too model.ModelBoneSupport = ModelBoneSupportTypes.SupportsBoth; // Add some bones model.AddBone("bone_0001", -1, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0002", 0, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0003", 0, Vector3.Zero, Quaternion.Identity, Vector3.Zero, Quaternion.Identity, Vector3.One); model.AddBone("bone_0004", 2, Vector3.Zero, Quaternion.Identity, new Vector3(22, 22, 22), Quaternion.Identity, Vector3.One); // Save it model.Write("test2.semodel"); // Done Console.WriteLine("DONE!"); } #endregion // Pause Console.Write("\nPress any key to continue..."); Console.ReadKey(); }
public static string ToSMD(this SEModel semodel) { var buffer = new StringBuilder(); buffer.AppendLine("// Converted by SEFormat Convertor"); buffer.AppendLine("version 1"); #region Bones buffer.AppendLine("nodes"); for (int i = 0; i < semodel.BoneCount; i++) { buffer.AppendLine($" {i} \"{semodel.Bones[i].BoneName}\" {semodel.Bones[i].BoneParent}"); } buffer.AppendLine("end"); #endregion #region Bone transforms buffer.AppendLine("skeleton"); { buffer.AppendLine(" time 0"); for (int i = 0; i < semodel.BoneCount; i++) { var bone = semodel.Bones[i]; var eularAngle = bone.LocalRotation.ToEulerAngles(); buffer.AppendLine($" {i} {bone.LocalPosition.X:F6} {bone.LocalPosition.Y:F6} {bone.LocalPosition.Z:F6} {eularAngle.X:F6} {eularAngle.Y:F6} {eularAngle.Z:F6}"); } } buffer.AppendLine("end"); #endregion #region Triangles buffer.AppendLine("triangles"); foreach (var mesh in semodel.Meshes) { var mtlName = semodel.Materials[mesh.MaterialReferenceIndicies[0]].Name; foreach (var face in mesh.Faces) { buffer.AppendLine(mtlName); SEModelVertex[] verts = { mesh.Verticies[(int)face.FaceIndex1], mesh.Verticies[(int)face.FaceIndex2], mesh.Verticies[(int)face.FaceIndex3] }; foreach (var vert in verts) { buffer.Append($" {vert.Weights[0].BoneIndex} {vert.Position.X:F6} {vert.Position.Y:F6} {vert.Position.Z:F6} {vert.VertexNormal.X:F6} {vert.VertexNormal.Y:F6} {vert.VertexNormal.Z:F6} {vert.UVSets[0].X:F6} {vert.UVSets[0].X:F6}"); if (vert.WeightCount > 1) { buffer.Append(vert.WeightCount - 1); for (int i = 1; i < vert.WeightCount; i++) { buffer.Append($" {vert.Weights[i].BoneIndex} {vert.Weights[i].BoneWeight:F6}"); } } buffer.AppendLine(); } } } buffer.AppendLine("end"); #endregion return(buffer.ToString()); }