/// <summary> /// Compares the given anim's joints with the joints provided by the user returns true if the anim contains atleast one /// </summary> private bool ReadSEanimForJoint(SEAnim anim) { if (anim.Bones.Count < 1) { return(false); } else { if (Joints.Count < 2) { for (int i = 0; i < anim.Bones.Count; i++) { if (anim.Bones.ElementAt(i).CompareTo(Joints.ElementAt(0)) == 0) { return(true); } } } else { for (int j = 0; j < Joints.Count; j++) { for (int y = 0; y < anim.Bones.Count; y++) { if (anim.Bones.ElementAt(y).CompareTo(Joints.ElementAt(j)) == 0) { return(true); } } } } } return(false); }
private static void ConvertAnimation(Stream animStream, string path, bool convertAnims, FindLogic.Combo.AnimationInfoNew animationInfo) { teAnimation parsedAnimation = new teAnimation(animStream, true); string animationDirectory = Path.Combine(path, "Animations", parsedAnimation.Header.Priority.ToString()); if (convertAnims) { SEAnim seAnim = new SEAnim(parsedAnimation); string animOutput = Path.Combine(animationDirectory, animationInfo.GetNameIndex() + "." + seAnim.Extension); CreateDirectoryFromFile(animOutput); using (Stream fileStream = new FileStream(animOutput, FileMode.Create)) { seAnim.Write(fileStream); } } else { string rawAnimOutput = Path.Combine(animationDirectory, $"{animationInfo.GetNameIndex()}.{teResourceGUID.Type(animationInfo.GUID):X3}"); CreateDirectoryFromFile(rawAnimOutput); using (Stream fileStream = new FileStream(rawAnimOutput, FileMode.Create)) { animStream.CopyTo(fileStream); } } }
private SMDFile() { Bones = new List <SEModelBone>(); Meshes = new List <SEModelMesh>(); Materials = new List <SEModelMaterial>(); Animation = new SEAnim { AnimType = AnimationType.Absolute }; Namespaces = new List <string>(); }
public static void TestAnimation() { using (Stream stream = OpenFile(0xA000000000042D9)) { // ANCR_base_3p_ohHai_POTG teAnimation animation = new teAnimation(stream); SEAnim seAnim = new SEAnim(animation); using (Stream file = File.OpenWrite($"test.{seAnim.Extension}")) { seAnim.Write(file); } } }
public static void SaveAnimation(string FileName, Animation anim, STSkeleton skeleton) { anim.SetFrame(anim.FrameCount - 1); //from last frame for (int f = 0; f < anim.FrameCount; ++f) //go through each frame with nextFrame { anim.NextFrame(skeleton); } anim.NextFrame(skeleton); //go on first frame SEAnim seAnim = new SEAnim(); seAnim.Looping = anim.CanLoop; seAnim.AnimType = AnimationType.Absolute; //Reset active animation to 0 anim.SetFrame(0); for (int frame = 0; frame < anim.FrameCount; frame++) { anim.NextFrame(skeleton, false, true); foreach (Animation.KeyNode boneAnim in anim.Bones) { if (boneAnim.HasKeyedFrames(frame)) { STBone bone = skeleton.GetBone(boneAnim.Text); if (bone == null) { continue; } Vector3 position = bone.GetPosition(); Quaternion rotation = bone.GetRotation(); Vector3 scale = bone.GetScale(); seAnim.AddTranslationKey(boneAnim.Text, frame, position.X, position.Y, position.Z); seAnim.AddRotationKey(boneAnim.Text, frame, rotation.X, rotation.Y, rotation.Z, rotation.W); seAnim.AddScaleKey(boneAnim.Text, frame, scale.X, scale.Y, scale.Z); } } } seAnim.Write(FileName); }
public static void ExportIOAnimation(string FileName, IOAnimation animData) { SEAnim seOut = new SEAnim(); //init new SEAnim foreach (IOAnimNode node in animData.Nodes) //iterate through each node { for (int i = 0; i < animData.FrameCount; i++) { OpenTK.Vector3 pos = node.GetPosition(i, OpenTK.Vector3.Zero); OpenTK.Quaternion rot = node.GetQuaternionRotation(i, new OpenTK.Quaternion(0, 0, 0, 0)); OpenTK.Vector3 sca = node.GetScaling(i, OpenTK.Vector3.Zero); seOut.AddTranslationKey(node.Name, i, pos.X, pos.Y, pos.Z); seOut.AddRotationKey(node.Name, i, rot.X, rot.Y, rot.Z, rot.W); seOut.AddScaleKey(node.Name, i, sca.X, sca.Y, sca.Z); } } seOut.Write(FileName); //write it! }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { SEAnim seOut = new SEAnim(); //init new SEAnim foreach (var node in animation.TransformNodes) //iterate through each node { for (int i = 0; i < animation.FrameCount; i++) { SBBone temp = new SBBone(); temp.Transform = node.GetTransformAt(i, skeleton); seOut.AddTranslationKey(node.Name, i, temp.X, temp.Y, temp.Z); seOut.AddRotationKey(node.Name, i, temp.RotationQuaternion.X, temp.RotationQuaternion.Y, temp.RotationQuaternion.Z, temp.RotationQuaternion.W); seOut.AddScaleKey(node.Name, i, temp.SX, temp.SY, temp.SZ); } } seOut.Write(FileName); //write it! }
static void CheckAnimName(string animName, Boolean patchAnim = false) { string hashName = string.Format("{0:x}", HashUtil.Hash(animName)); string hashFilePath = greyhoundExportFolder + "\\xanims\\xanim_" + hashName + ".seanim"; if (File.Exists(hashFilePath)) { Console.WriteLine("Found asset: {0:x}", animName.PadRight(40) + hashName); File.AppendAllText(greyhoundExportFolder + "\\AnimsFound.txt", hashName + "," + animName + Environment.NewLine); string destFileName = greyhoundExportFolder + "\\xanims\\" + animName + ".seanim"; File.Copy(hashFilePath, destFileName, true); if (patchAnim) { SEAnim seAnim = SEAnim.Read(destFileName); seAnim.AnimType = AnimationType.Absolute; seAnim.AnimationBoneModifiers["tag_weapon"] = AnimationType.Relative; seAnim.AnimationBoneModifiers["tag_weapon_le"] = AnimationType.Relative; seAnim.Write(destFileName, false); } } }
public static void SaveAnimation(string FileName, Animation anim, STSkeleton skeleton) { SEAnim seAnim = new SEAnim(); //Reset active animation to 0 anim.SetFrame(0); for (int frame = 0; frame < anim.FrameCount; frame++) { anim.NextFrame(skeleton); //Reset it when it reaches the total frame count if (anim.Frame >= anim.FrameCount) { anim.Frame = 0; } foreach (Animation.KeyNode boneAnim in anim.Bones) { STBone bone = skeleton.GetBone(boneAnim.Text); if (bone == null) { continue; } Vector3 position = bone.GetPosition(); Quaternion rotation = bone.GetRotation(); Vector3 scale = bone.GetScale(); seAnim.AddTranslationKey(boneAnim.Text, frame, position.X, position.Y, position.Z); seAnim.AddRotationKey(boneAnim.Text, frame, rotation.X, rotation.Y, rotation.Z, rotation.W); seAnim.AddScaleKey(boneAnim.Text, frame, scale.X, scale.Y, scale.Z); } //Add frames to the playing animation anim.Frame += 1f; } seAnim.Write(FileName); }
private static void ConvertAnimation(Stream animStream, string path, bool convertAnims, FindLogic.Combo.AnimationAsset animationInfo, bool scaleAnims) { var parsedAnimation = default(teAnimation); var priority = 100; try { parsedAnimation = new teAnimation(animStream, true); priority = parsedAnimation.Header.Priority; } catch (Exception) { Logger.Error("Combo", $"Unable to parse animation {animationInfo.GetName()}"); } string animationDirectory = Path.Combine(path, "Animations", priority.ToString()); if (convertAnims && parsedAnimation != null) { SEAnim seAnim = new SEAnim(parsedAnimation, scaleAnims); string animOutput = Path.Combine(animationDirectory, animationInfo.GetNameIndex() + "." + seAnim.Extension); CreateDirectoryFromFile(animOutput); using (Stream fileStream = new FileStream(animOutput, FileMode.Create)) { seAnim.Write(fileStream); } } else { animStream.Position = 0; string rawAnimOutput = Path.Combine(animationDirectory, $"{animationInfo.GetNameIndex()}.{teResourceGUID.Type(animationInfo.m_GUID):X3}"); CreateDirectoryFromFile(rawAnimOutput); using (Stream fileStream = new FileStream(rawAnimOutput, FileMode.Create)) { animStream.CopyTo(fileStream); } } }
public static void Save(STSkeletonAnimation anim, string FileName) { STSkeleton skeleton = anim.GetActiveSkeleton(); SEAnim seAnim = new SEAnim(); seAnim.Looping = anim.Loop; seAnim.AnimType = AnimationType.Absolute; anim.SetFrame(0); for (int frame = 0; frame < anim.FrameCount; frame++) { anim.SetFrame(frame); anim.NextFrame(); foreach (STAnimGroup boneAnim in anim.AnimGroups) { if (boneAnim.GetTracks().Any(x => x.HasKeys)) { STBone bone = skeleton.GetBone(boneAnim.Name); if (bone == null) { continue; } Vector3 position = bone.GetPosition(); Quaternion rotation = bone.GetRotation(); Vector3 scale = bone.GetScale(); seAnim.AddTranslationKey(boneAnim.Name, frame, position.X, position.Y, position.Z); seAnim.AddRotationKey(boneAnim.Name, frame, rotation.X, rotation.Y, rotation.Z, rotation.W); seAnim.AddScaleKey(boneAnim.Name, frame, scale.X, scale.Y, scale.Z); } } } seAnim.Write(FileName); }
/// <summary> /// Goes through each anim bone and compares it to the joints specified by user /// </summary> private void DoAnimScan() { for (int i = 0; i < file_paths.Count; i++) { outputTextbox.Invoke(new Action(() => outputTextbox.AppendText("Reading " + System.IO.Path.GetFileNameWithoutExtension(file_paths.ElementAt(i)) + " .... \n"))); bool isCorrectAnim = ReadSEanimForJoint(SEAnim.Read(file_paths.ElementAt(i))); if (isCorrectAnim) { if (!System.IO.Directory.Exists(ExportDirectory)) { System.IO.Directory.CreateDirectory(ExportDirectory); } System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(ExportDirectory); System.IO.File.Move(@file_paths.ElementAt(i), ExportDirectory + System.IO.Path.GetFileName(file_paths.ElementAt(i))); file_paths.RemoveAt(i); //Remove the anim , then lower I to make sure to get the last element animList.Invoke(new Action(() => animList.Items.RemoveAt(i--))); //Add file name to the UI list } progressBar.Invoke(new Action(() => progressBar.Increment(1))); //Increments the progress bar to inform the user how long till it's done } System.Windows.Forms.MessageBox.Show("Scan has been completed, anims can be found in \"SEanimations\" "); ScanInProgress = false; }
public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { SEAnim seOut = new SEAnim(); //init new SEAnim foreach (var node in animation.TransformNodes) //iterate through each node { for (int i = 0; i < animation.FrameCount; i++) { SBBone temp = new SBBone(); temp.Transform = node.Transform.GetValue(i); OpenTK.Vector3 pos = temp.Translation; OpenTK.Quaternion rot = temp.RotationQuaternion; OpenTK.Vector3 sca = temp.Scale; seOut.AddTranslationKey(node.Name, i, pos.X, pos.Y, pos.Z); seOut.AddRotationKey(node.Name, i, rot.X, rot.Y, rot.Z, rot.W); seOut.AddScaleKey(node.Name, i, sca.X, sca.Y, sca.Z); } } seOut.Write(FileName); //write it! }
public static void Decode(string fileName) { // Get the right export folder and names string OutputName = Path.GetDirectoryName(fileName) + "\\" + Path.GetFileNameWithoutExtension(fileName); string ModelName = Path.GetFileNameWithoutExtension(fileName).Replace("-", "_").Replace("#", ""); // Make a new stream reader using (BinaryReader reader = new BinaryReader(new FileStream(fileName, FileMode.Open))) { // Make sure we are parsing a animation file string Magic = reader.ReadFixedString(4); if (Magic != "ANIM") { Console.WriteLine(String.Format("File Magic \"{0}\" does not match IS's \"ANIM\"", Magic)); return; } // Get anim type int AnimType = reader.ReadInt32(); if (AnimType == 10 || AnimType == 8) { // Skip unknown bytes reader.ReadBytes(4); // Get base info of the animation int BoneCount = reader.ReadInt32(); int FrameCount = reader.ReadInt32(); // Make a new SEAnim to export SEAnim AnimFile = new SEAnim(); // Put the base info in the animation AnimFile.BoneCount = BoneCount; AnimFile.AnimType = AnimationType.Additive; AnimFile.FrameCount = FrameCount; // Skip unknown bytes reader.ReadBytes(4); // Go through all the frames for (int i = 0; i < FrameCount; i++) { // Skip 4 bytes for now // Animtype 8 -> frame count // Animtype 10 -> frame byte length reader.ReadBytes(4); // Go through all bone data for (int j = 0; j < BoneCount; j++) { // Get offset to the next joint data long StreamPos = reader.BaseStream.Position + 20; // Read the joint rotation data float BoneDirX = reader.ReadInt16() / 32768.0f; float BoneDirZ = reader.ReadInt16() / 32768.0f; float BoneDirY = reader.ReadInt16() / 32768.0f; float BoneDirW = reader.ReadInt16() / 32768.0f; // Put it in a quaternion object Quaternion BoneDirection = new Quaternion(BoneDirX, BoneDirY, BoneDirZ, BoneDirW); // Add the rotation of the joint to the anim AnimFile.AddRotationKey("tag_is_model_" + j, i, BoneDirection.X, BoneDirection.Y, BoneDirection.Z, BoneDirection.W); // Read joint position data float bonePosX = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); float bonePosZ = System.BitConverter.ToSingle(reader.ReadBytes(4), 0); float bonePosY = System.BitConverter.ToSingle(reader.ReadBytes(4), 0) * -1; // Add the position of the joint to the anim AnimFile.AddTranslationKey("tag_is_model_" + j, i, bonePosX, bonePosY, bonePosZ); // Go to the next joint data reader.Seek(StreamPos, SeekOrigin.Begin); } } // Write the SEAnim file AnimFile.Write(OutputName + ".seanim"); // Get the length of the Es file name int EsFileNameLength = reader.ReadInt32(); // Only read it if it got an actual name if (EsFileNameLength != 0) { // Read the name string EsFileName = Path.GetFileName(reader.ReadFixedString(EsFileNameLength)); // Make a stream reader using (BinaryReader ESreader = new BinaryReader(new FileStream(EsFileName, FileMode.Open))) { // Make sure were reading an ES file if (ESreader.ReadFixedString(4) != "ESES") { Console.WriteLine("File Magic does not match IS's \"ESES\""); return; } // Get the ES type int ESType = ESreader.ReadInt32(); int skipInfo = ESreader.ReadInt32(); } } } } }
public static Animation Read(string FileName, STSkeleton skeleton) { Animation anim = new Animation(); var seanim = SEAnim.Read(FileName); anim.FrameCount = seanim.FrameCount; anim.CanLoop = seanim.Looping; foreach (var bone in seanim.Bones) { STBone genericBone = skeleton.GetBone(bone); if (genericBone != null) { var boneAnim = new Animation.KeyNode(bone); boneAnim.RotType = Animation.RotationType.EULER; boneAnim.UseSegmentScaleCompensate = false; anim.Bones.Add(boneAnim); float PositionX = 0; float PositionY = 0; float PositionZ = 0; float RotationX = 0; float RotationY = 0; float RotationZ = 0; float ScaleX = 0; float ScaleY = 0; float ScaleZ = 0; if (seanim.AnimType == AnimationType.Relative) { PositionX = genericBone.position[0]; PositionY = genericBone.position[1]; PositionZ = genericBone.position[2]; RotationX = genericBone.rotation[0]; RotationY = genericBone.rotation[1]; RotationZ = genericBone.rotation[2]; ScaleX = genericBone.scale[0]; ScaleY = genericBone.scale[1]; ScaleZ = genericBone.scale[2]; } System.Console.WriteLine(bone); if (seanim.AnimationPositionKeys.ContainsKey(bone)) { var translationKeys = seanim.AnimationPositionKeys[bone]; foreach (SEAnimFrame animFrame in translationKeys) { System.Console.WriteLine(animFrame.Frame + " T " + ((SELib.Utilities.Vector3)animFrame.Data).X); System.Console.WriteLine(animFrame.Frame + " T " + ((SELib.Utilities.Vector3)animFrame.Data).Y); System.Console.WriteLine(animFrame.Frame + " T " + ((SELib.Utilities.Vector3)animFrame.Data).Z); boneAnim.XPOS.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).X + PositionX, Frame = animFrame.Frame, }); boneAnim.YPOS.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).Y + PositionY, Frame = animFrame.Frame, }); boneAnim.ZPOS.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).Z + PositionZ, Frame = animFrame.Frame, }); } } if (seanim.AnimationRotationKeys.ContainsKey(bone)) { var rotationnKeys = seanim.AnimationRotationKeys[bone]; foreach (SEAnimFrame animFrame in rotationnKeys) { var quat = ((SELib.Utilities.Quaternion)animFrame.Data); var euler = STMath.ToEulerAngles(quat.X, quat.Y, quat.Z, quat.W); System.Console.WriteLine(animFrame.Frame + " R " + euler.X); System.Console.WriteLine(animFrame.Frame + " R " + euler.Y); System.Console.WriteLine(animFrame.Frame + " R " + euler.Z); boneAnim.XROT.Keys.Add(new Animation.KeyFrame() { Value = euler.X + RotationX, Frame = animFrame.Frame, }); boneAnim.YROT.Keys.Add(new Animation.KeyFrame() { Value = euler.Y + RotationY, Frame = animFrame.Frame, }); boneAnim.ZROT.Keys.Add(new Animation.KeyFrame() { Value = euler.Z + RotationZ, Frame = animFrame.Frame, }); } } if (seanim.AnimationScaleKeys.ContainsKey(bone)) { var scaleKeys = seanim.AnimationScaleKeys[bone]; foreach (SEAnimFrame animFrame in scaleKeys) { System.Console.WriteLine(animFrame.Frame + " S " + ((SELib.Utilities.Vector3)animFrame.Data).X); System.Console.WriteLine(animFrame.Frame + " S " + ((SELib.Utilities.Vector3)animFrame.Data).Y); System.Console.WriteLine(animFrame.Frame + " S " + ((SELib.Utilities.Vector3)animFrame.Data).Z); boneAnim.XSCA.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).X + ScaleX, Frame = animFrame.Frame, }); boneAnim.YSCA.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).Y + ScaleY, Frame = animFrame.Frame, }); boneAnim.ZSCA.Keys.Add(new Animation.KeyFrame() { Value = (float)((SELib.Utilities.Vector3)animFrame.Data).Z + ScaleZ, Frame = animFrame.Frame, }); } } else { boneAnim.XSCA.Keys.Add(new Animation.KeyFrame() { Value = 1, Frame = 0, }); boneAnim.YSCA.Keys.Add(new Animation.KeyFrame() { Value = 1, Frame = 0, }); boneAnim.ZSCA.Keys.Add(new Animation.KeyFrame() { Value = 1, Frame = 0, }); } } } return(anim); }
public static void SaveAnimation(string FileName, Animation anim, STSkeleton skeleton) { anim.SetFrame(anim.FrameCount - 1); //from last frame for (int f = 0; f < anim.FrameCount; ++f) //go through each frame with nextFrame { anim.NextFrame(skeleton); } anim.NextFrame(skeleton); //go on first frame foreach (STBone b in skeleton.getBoneTreeOrder()) { if (anim.HasBone(b.Text)) { Animation.KeyNode n = anim.GetBone(b.Text); if (n.XPOS.HasAnimation()) { WriteKey(n.XPOS); } if (n.YPOS.HasAnimation()) { WriteKey(n.YPOS); } if (n.ZPOS.HasAnimation()) { WriteKey(n.ZPOS); } if (n.XROT.HasAnimation()) { WriteKey(n.XROT); } if (n.YROT.HasAnimation()) { WriteKey(n.YROT); } if (n.ZROT.HasAnimation()) { WriteKey(n.ZROT); } if (n.XSCA.HasAnimation()) { WriteKey(n.XSCA); } if (n.YSCA.HasAnimation()) { WriteKey(n.YSCA); } if (n.ZSCA.HasAnimation()) { WriteKey(n.ZSCA); } } } SEAnim seAnim = new SEAnim(); seAnim.Looping = anim.CanLoop; seAnim.AnimType = AnimationType.Absolute; //Reset active animation to 0 anim.SetFrame(0); for (int frame = 0; frame < anim.FrameCount; frame++) { anim.NextFrame(skeleton, false, true); foreach (Animation.KeyNode boneAnim in anim.Bones) { if (boneAnim.HasKeyedFrames(frame)) { STBone bone = skeleton.GetBone(boneAnim.Text); if (bone == null) { continue; } Vector3 position = bone.GetPosition(); Quaternion rotation = bone.GetRotation(); Vector3 scale = bone.GetScale(); //Exporting at specific keys doesn't work atm //Todo bool IsTranlationKeyed = (boneAnim.XPOS.GetKeyFrame(frame).IsKeyed || boneAnim.YPOS.GetKeyFrame(frame).IsKeyed || boneAnim.ZPOS.GetKeyFrame(frame).IsKeyed); bool IsRotationKeyed = (boneAnim.XROT.GetKeyFrame(frame).IsKeyed || boneAnim.YROT.GetKeyFrame(frame).IsKeyed || boneAnim.ZROT.GetKeyFrame(frame).IsKeyed); bool IsScaleKeyed = (boneAnim.XSCA.GetKeyFrame(frame).IsKeyed || boneAnim.YSCA.GetKeyFrame(frame).IsKeyed || boneAnim.ZSCA.GetKeyFrame(frame).IsKeyed); seAnim.AddTranslationKey(boneAnim.Text, frame, position.X, position.Y, position.Z); seAnim.AddRotationKey(boneAnim.Text, frame, rotation.X, rotation.Y, rotation.Z, rotation.W); seAnim.AddScaleKey(boneAnim.Text, frame, scale.X, scale.Y, scale.Z); } } } seAnim.Write(FileName); }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="skeleton"></param> /// <returns></returns> public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SEAnim anim = SEAnim.Read(FileName); var sbAnim = new SBAnimation(); sbAnim.FrameCount = anim.FrameCount; sbAnim.Name = anim.DeltaTagName; Dictionary <string, SBTransformAnimation> nameToAnim = new Dictionary <string, SBTransformAnimation>(); foreach (var v in anim.AnimationPositionKeys) { if (!nameToAnim.ContainsKey(v.Key)) { SBTransformAnimation an = new SBTransformAnimation(); an.Name = v.Key; nameToAnim.Add(v.Key, an); sbAnim.TransformNodes.Add(an); } var a = nameToAnim[v.Key]; foreach (var k in v.Value) { if (k.Data is SELib.Utilities.Vector2 vc) { a.AddKey(k.Frame, (float)vc.X, SBTrackType.TranslateX, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc.Y, SBTrackType.TranslateY, InterpolationType.Linear); } if (k.Data is SELib.Utilities.Vector3 vc3) { a.AddKey(k.Frame, (float)vc3.X, SBTrackType.TranslateX, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc3.Y, SBTrackType.TranslateY, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc3.Z, SBTrackType.TranslateZ, InterpolationType.Linear); } } } foreach (var v in anim.AnimationRotationKeys) { if (!nameToAnim.ContainsKey(v.Key)) { SBTransformAnimation an = new SBTransformAnimation(); an.Name = v.Key; nameToAnim.Add(v.Key, an); sbAnim.TransformNodes.Add(an); } var a = nameToAnim[v.Key]; foreach (var k in v.Value) { if (k.Data is SELib.Utilities.Quaternion q) { var euler = Tools.CrossMath.ToEulerAngles(new OpenTK.Quaternion((float)q.X, (float)q.Y, (float)q.Z, (float)q.W).Inverted()); a.AddKey(k.Frame, (float)q.X, SBTrackType.RotateX, InterpolationType.Linear); a.AddKey(k.Frame, (float)q.Y, SBTrackType.RotateY, InterpolationType.Linear); a.AddKey(k.Frame, (float)q.Z, SBTrackType.RotateZ, InterpolationType.Linear); a.AddKey(k.Frame, (float)q.W, SBTrackType.RotateW, InterpolationType.Linear); } if (k.Data is SELib.Utilities.Vector3 vc) { a.AddKey(k.Frame, (float)vc.X, SBTrackType.RotateX, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc.Y, SBTrackType.RotateY, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc.Z, SBTrackType.RotateZ, InterpolationType.Linear); } } } foreach (var v in anim.AnimationScaleKeys) { if (!nameToAnim.ContainsKey(v.Key)) { SBTransformAnimation an = new SBTransformAnimation(); an.Name = v.Key; nameToAnim.Add(v.Key, an); sbAnim.TransformNodes.Add(an); } var a = nameToAnim[v.Key]; foreach (var k in v.Value) { if (k.Data is SELib.Utilities.Vector3 vc3) { a.AddKey(k.Frame, (float)vc3.X, SBTrackType.ScaleX, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc3.Y, SBTrackType.ScaleY, InterpolationType.Linear); a.AddKey(k.Frame, (float)vc3.Z, SBTrackType.ScaleZ, InterpolationType.Linear); } } } return(sbAnim); }
/// <summary> /// Print the log to the file /// </summary> /// <param name="File">The file to debug</param> /// <param name="FileOutput">The output log file</param> private static void DebugLOGSEAnim(string File, string FileOutput) { // Load the anim var anim = SEAnim.Read(File); // Load bones var bones = anim.Bones; // Log Console.WriteLine(" Writing log to file..."); // Prepare output using (StreamWriter writeFile = new StreamWriter(FileOutput)) { // Log writeFile.WriteLine("-- SEAnim Debugger Utility --"); writeFile.WriteLine(""); // Output initial info writeFile.WriteLine(" Header:"); // Header data { writeFile.WriteLine(" - Frame count: " + anim.FrameCount); writeFile.WriteLine(" - Frame rate: " + anim.FrameRate); writeFile.WriteLine(" - Animation type: " + anim.AnimType.ToString()); writeFile.WriteLine(" - Bone count: " + anim.BoneCount); writeFile.WriteLine(" - Notetrack count: " + anim.NotificationCount); writeFile.WriteLine(" - Modifiers count: " + anim.AnimationBoneModifiers.Count); // Check for delta if (anim.AnimType == AnimationType.Delta) { // Delta bone must be the first one writeFile.WriteLine(" - Delta tag \"" + anim.DeltaTagName + "\""); } } // Separate and prepare keys by bone writeFile.WriteLine("\n Frames:"); // Output keys foreach (string Bone in anim.Bones) { // Bone header writeFile.WriteLine(" - Bone \"" + Bone + "\" data:"); // Translation header writeFile.Write(" - Translations ["); // Check for translation keys if (anim.AnimationPositionKeys.ContainsKey(Bone)) { // Output translation keys var translationKeys = anim.AnimationPositionKeys[Bone]; // Count writeFile.WriteLine(translationKeys.Count + "]"); // Output values foreach (SEAnimFrame frame in translationKeys) { // Output the vector writeFile.WriteLine(" [" + frame.Frame + "] {0} {1} {2}", ((Vector3)frame.Data).X, ((Vector3)frame.Data).Y, ((Vector3)frame.Data).Z); } } else { // Had no keys writeFile.WriteLine("0]"); } // Rotation header writeFile.Write(" - Rotations ["); // Check for rotation keys if (anim.AnimationRotationKeys.ContainsKey(Bone)) { // Output rotation keys var rotKeys = anim.AnimationRotationKeys[Bone]; // Count writeFile.WriteLine(rotKeys.Count + "]"); // Output values foreach (SEAnimFrame frame in rotKeys) { // Output the quat writeFile.WriteLine(" [" + frame.Frame + "] {0} {1} {2} {3}", ((Quaternion)frame.Data).X, ((Quaternion)frame.Data).Y, ((Quaternion)frame.Data).Z, ((Quaternion)frame.Data).W); } } else { // Had no keys writeFile.WriteLine("0]"); } // Scales header writeFile.Write(" - Scales ["); // Check for scale keys if (anim.AnimationScaleKeys.ContainsKey(Bone)) { // Output scale keys var scaleKeys = anim.AnimationScaleKeys[Bone]; // Count writeFile.WriteLine(scaleKeys.Count + "]"); // Output values foreach (SEAnimFrame frame in scaleKeys) { // Output the vector writeFile.WriteLine(" [" + frame.Frame + "] {0} {1} {2}", ((Vector3)frame.Data).X, ((Vector3)frame.Data).Y, ((Vector3)frame.Data).Z); } } else { // Had no keys writeFile.WriteLine("0]"); } } // Separate and prepare notes writeFile.WriteLine("\n Notifications:"); // Output notetracks foreach (KeyValuePair <string, List <SEAnimFrame> > Notetrack in anim.AnimationNotetracks) { // Note header writeFile.WriteLine(" - Note \"" + Notetrack.Key + "\" data:"); // Loop and output keys foreach (SEAnimFrame frame in Notetrack.Value) { // Log it writeFile.WriteLine(" [" + frame.Frame + "] plays"); } } } }
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 LTBFile Read(FileInfo info) { var bFlip = info.Name.StartsWith("PV"); var ltbFile = new LTBFile(); var br = new ExtendedBinaryReader(info.OpenRead()); #region Header var header = br.ReadUInt16(); if (header > 20) { br.Close(); var lzmaStream = new LzmaDecodeStream(info.OpenRead()); var ms = new MemoryStream(); lzmaStream.CopyTo(ms); if (ms.Length == 0) { Console.WriteLine($"{info.Name} is not a vaild LTB file."); return(null); } br = new ExtendedBinaryReader(ms); br.Skip(0, true); } // Skip header br.Skip(0x14, true); uint version = br.ReadUInt32(); uint nKeyFrame = br.ReadUInt32(); uint nAnim = br.ReadUInt32(); uint numBones = br.ReadUInt32(); uint nPieces = br.ReadUInt32(); uint nChildModels = br.ReadUInt32(); uint nTris = br.ReadUInt32(); uint nVerts = br.ReadUInt32(); uint nVertexWeights = br.ReadUInt32(); uint nLODs = br.ReadUInt32(); uint nSockets = br.ReadUInt32(); uint nWeightSets = br.ReadUInt32(); uint nStrings = br.ReadUInt32(); uint StringLengths = br.ReadUInt32(); uint VertAnimDataSize = br.ReadUInt32(); uint nAnimData = br.ReadUInt32(); string cmdString = br.ReadStringWithUInt16Length(); float globalRadius = br.ReadSingle(); uint iNumEnabledOBBs = br.ReadUInt32(); if (iNumEnabledOBBs != 0) { throw new Exception("LTB with OBB infomations are not supported"); } uint numMesh = br.ReadUInt32(); #endregion var romanisation = new McCuneReischauerRomanisation { PreserveNonKoreanText = true }; #region Mesh nodes for (int i = 0; i < numMesh; i++) { string meshName = br.ReadStringWithUInt16Length(ltbEncode); meshName = romanisation.RomaniseText(meshName); foreach (var kvp in replaceDictionary) { meshName = meshName.Replace(kvp.Key, kvp.Value); } meshName = meshName.ToLower(); uint numLod = br.ReadUInt32(); Console.WriteLine($"{meshName} - {numLod} Lods"); meshName = meshName.ToLower(); br.Skip((int)numLod * 4 + 8); int materialIndex = -1; if (!ltbFile.Materials.Any(material => material.Name == meshName)) { ltbFile.Materials.Add(new SEModelMaterial { Name = "mtl_" + meshName, MaterialData = new SEModelSimpleMaterial { DiffuseMap = meshName + ".png" } }); materialIndex = ltbFile.Materials.Count - 1; } else { materialIndex = ltbFile.Materials.FindIndex(mtl => mtl.Name == meshName); } for (int iLod = 0; iLod < numLod; iLod++) { var mesh = new SEModelMesh(); mesh.AddMaterialIndex(materialIndex); var nNumTex = br.ReadUInt32(); const int MAX_PIECE_TEXTURES = 4; for (int iTex = 0; iTex < MAX_PIECE_TEXTURES; iTex++) { // Texture index br.ReadUInt32(); } var renderStyle = br.ReadUInt32(); var nRenderPriority = br.ReadByte(); var lodType = (PieceType)br.ReadUInt32(); var lodSize = br.ReadUInt32(); if (lodSize != 0) { uint numVerts = br.ReadUInt32(); uint numTris = br.ReadUInt32(); uint iMaxBonesPerTri = br.ReadUInt32(); uint iMaxBonesPerVert = br.ReadUInt32(); Console.WriteLine($" Lod {iLod}: \n Vertex count: {numVerts}\n Triangle count: {numTris}"); bool bReIndexBones = false, bUseMatrixPalettes = false; if (lodType == PieceType.SkelMesh) { bReIndexBones = br.ReadBoolean(); } DataType[] streamData = { (DataType)br.ReadUInt32(), (DataType)br.ReadUInt32(), (DataType)br.ReadUInt32(), (DataType)br.ReadUInt32() }; uint rigidBone = uint.MaxValue; if (lodType == PieceType.RigidMesh) { rigidBone = br.ReadUInt32(); } else if (lodType == PieceType.SkelMesh) { bUseMatrixPalettes = br.ReadBoolean(); } else { throw new Exception("Unsupported lod type"); } if (bUseMatrixPalettes) { uint iMinBone = br.ReadUInt32(); uint iMaxBone = br.ReadUInt32(); } var boneMap = new List <uint>(); if (bReIndexBones) { uint reindexBoneMapSize = br.ReadUInt32(); for (int iMap = 0; iMap < reindexBoneMapSize; iMap++) { boneMap.Add(br.ReadUInt32()); } } for (int iStream = 0; iStream < 4; ++iStream) { if (!streamData[iStream].HasFlag(DataType.Position)) { continue; } for (int iVert = 0; iVert < numVerts; iVert++) { var v = new SEModelVertex(); if (streamData[iStream].HasFlag(DataType.Position)) { v.Position = new Vector3 { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle(), }; if (bFlip) { v.Position.X *= -1; } if (rigidBone == uint.MaxValue) { var weightSum = 0.0f; var maxWeight = bUseMatrixPalettes ? iMaxBonesPerVert : iMaxBonesPerTri; for (int iWeight = 0; iWeight < maxWeight - 1; iWeight++) { var weight = br.ReadSingle(); if (weight > 1) { throw new Exception("wtf"); } weightSum += weight; v.Weights.Add(new SEModelWeight { BoneIndex = uint.MaxValue, BoneWeight = weight }); } if (1.0f - weightSum > float.Epsilon) { v.Weights.Add(new SEModelWeight { BoneIndex = uint.MaxValue, BoneWeight = 1.0f - weightSum }); } if (bUseMatrixPalettes) { for (int iWeight = 0; iWeight < 4; iWeight++) { var boneIndex = br.ReadByte(); if (bReIndexBones) { boneIndex = (byte)boneMap[boneIndex]; } if (v.Weights.Count > iWeight) { v.Weights[iWeight].BoneIndex = boneIndex; } } } } else { if (rigidBone >= numBones || rigidBone < 0) { throw new Exception("wtf"); } v.Weights.Add(new SEModelWeight { BoneIndex = rigidBone, BoneWeight = 1.0f }); } } if (streamData[iStream].HasFlag(DataType.Normal)) { v.VertexNormal = new Vector3 { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle(), }; if (bFlip) { v.VertexNormal.X *= -1; } } if (streamData[iStream].HasFlag(DataType.Color)) { br.Skip(4); } if (streamData[iStream].HasFlag(DataType.UVSets1)) { v.UVSets.Add(new Vector2 { X = br.ReadSingle(), Y = br.ReadSingle() }); if (v.UVSets[0].X > 1.0f) { v.UVSets[0].X -= 1.0f; } } if (streamData[iStream].HasFlag(DataType.UVSets2)) { br.Skip(8); } if (streamData[iStream].HasFlag(DataType.UVSets3)) { br.Skip(8); } if (streamData[iStream].HasFlag(DataType.UVSets4)) { br.Skip(8); } if (streamData[iStream].HasFlag(DataType.BasisVectors)) { br.Skip(24); } if (v.Position == null || v.WeightCount == 0) { throw new Exception("wtf"); } mesh.AddVertex(v); } } for (uint iTriangle = 0; iTriangle < numTris; iTriangle++) { mesh.AddFace(br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16()); } if (lodType == PieceType.SkelMesh && !bUseMatrixPalettes) { var boneComboCount = br.ReadUInt32(); for (int iCombo = 0; iCombo < boneComboCount; iCombo++) { int m_BoneIndex_Start = br.ReadUInt16(); int m_BoneIndex_End = m_BoneIndex_Start + br.ReadUInt16(); Console.WriteLine($" Weight Combo: {m_BoneIndex_Start} to {m_BoneIndex_End}"); var bones = br.ReadBytes(4); uint m_iIndexIndex = br.ReadUInt32(); for (int iVertex = m_BoneIndex_Start; iVertex < m_BoneIndex_End; iVertex++) { for (int iBone = 0; iBone < 4 && bones[iBone] != 0xFF; iBone++) { if (mesh.Verticies[iVertex].Weights.Count <= iBone) { break; } mesh.Verticies[iVertex].Weights[iBone].BoneIndex = bones[iBone]; } } } } ltbFile.Meshes.Add(mesh); br.Skip(br.ReadByte()); } } } #endregion #region Bones uint[] boneTree = new uint[numBones]; for (int i = 0; i < numBones; i++) { var boneName = br.ReadStringWithUInt16Length(); var boneId = br.ReadByte(); var num2 = br.ReadUInt16(); Matrix4x4 transformMatrix = new Matrix4x4(); for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { transformMatrix[j, k] = br.ReadSingle(); } } boneTree[i] = br.ReadUInt32(); var bone = new SEModelBone { BoneName = boneName.Replace('.', '_').Replace('-', '_').Replace(' ', '_'), GlobalRotation = new Quaternion(transformMatrix), GlobalPosition = new Vector3(transformMatrix) }; if (bFlip) { bone.GlobalPosition.X *= -1; bone.GlobalRotation.Y *= -1; bone.GlobalRotation.Z *= -1; } // rotate root bone; if (boneId == 0) { bone.GlobalRotation *= globalRotation; } ltbFile.Bones[boneId] = bone; } uint[] nSubbone = new uint[numBones]; nSubbone[0] = boneTree[0]; ltbFile.Bones[0].BoneParent = -1; // Build bone tree for (byte i = 1; i < numBones; i++) { nSubbone[i] = boneTree[i]; for (int j = i - 1; j >= 0; j--) { if (nSubbone[j] > 0) { nSubbone[j]--; ltbFile.Bones[i].BoneParent = j; break; } } } #endregion #region Random stuff Console.WriteLine("\nInternal filenames:"); var childModelCount = br.ReadUInt32(); for (int i = 0; i < childModelCount; i++) { Console.WriteLine(br.ReadStringWithUInt16Length()); br.Skip((int)br.ReadUInt32() * 4); } br.Skip(4); #endregion #region Animations if (nAnim > 0) { var animationCount = br.ReadUInt32(); Console.WriteLine($"\nAnimation count: {animationCount}\n"); for (int i = 0; i < animationCount; i++) { var seanim = new SEAnim(); var dim = new Vector3 { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle(), }; var animName = br.ReadStringWithUInt16Length(); Console.Write(animName); var compressionType = (AnimCompressionType)br.ReadUInt32(); var interpolationMS = br.ReadUInt32(); var keyFrameCount = br.ReadUInt32(); Console.WriteLine($" has {keyFrameCount} keyframes"); for (int iKeyFrame = 0; iKeyFrame < keyFrameCount; iKeyFrame++) { var time = br.ReadUInt32(); var animString = br.ReadStringWithUInt16Length(); if (!string.IsNullOrEmpty(animString)) { seanim.AddNoteTrack(animString, iKeyFrame); } } for (byte iBone = 0; iBone < numBones; iBone++) { if (compressionType != AnimCompressionType.None) { uint pFrames = br.ReadUInt32(); for (int iKeyFrame = 0; iKeyFrame < pFrames; iKeyFrame++) { var v = new Vector3(br.ReadInt16() / 16.0, br.ReadInt16() / 16.0, br.ReadInt16() / 16.0); if (bFlip) { v.X *= -1; } seanim.AddTranslationKey(ltbFile.Bones[iBone].BoneName, iKeyFrame, v.X, v.Y, v.Z); } uint rFrames = br.ReadUInt32(); for (int iKeyFrame = 0; iKeyFrame < rFrames; iKeyFrame++) { var q = new Quaternion(br.ReadInt16() / 16.0, -br.ReadInt16() / 16.0, -br.ReadInt16() / 16.0, br.ReadInt16() / 16.0); if (bFlip) { q.Y *= -1; q.Z *= -1; } // rotate root bone; if (iBone == 0) { q *= globalRotation; } seanim.AddRotationKey(ltbFile.Bones[iBone].BoneName, iKeyFrame, q.X, q.Y, q.Z, q.W); } } else if (compressionType == AnimCompressionType.None) { bool isVertexAnim = br.ReadBoolean(); if (isVertexAnim) { throw new Exception("Vertex animation not supported!"); } else { for (int iKeyFrame = 0; iKeyFrame < keyFrameCount; iKeyFrame++) { var v = new Vector3(-br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); seanim.AddTranslationKey(ltbFile.Bones[iBone].BoneName, iKeyFrame, v.X, v.Y, v.Z); } for (int iKeyFrame = 0; iKeyFrame < keyFrameCount; iKeyFrame++) { var q = new Quaternion(br.ReadSingle(), -br.ReadSingle(), -br.ReadSingle(), br.ReadSingle()); // rotate root bone; if (iBone == 0) { q *= globalRotation; } seanim.AddRotationKey(ltbFile.Bones[iBone].BoneName, iKeyFrame, q.X, q.Y, q.Z, q.W); } } } } ltbFile.Animations.Add(animName + ".seanim", seanim); } } #endregion return(ltbFile); }
public void FromSeanim(string FileName) { SEAnim anim = SEAnim.Read(FileName); if (GetResFileU() != null) { SkeletalAnimU = new ResU.SkeletalAnim(); SkeletalAnimU.FrameCount = anim.FrameCount; SkeletalAnimU.FlagsScale = ResU.SkeletalAnimFlagsScale.Maya; SkeletalAnimU.FlagsRotate = ResU.SkeletalAnimFlagsRotate.EulerXYZ; SkeletalAnimU.Loop = anim.Looping; SkeletalAnimU.Name = System.IO.Path.GetFileNameWithoutExtension(FileName); SkeletalAnimU.Path = ""; } else { SkeletalAnim = new SkeletalAnim(); SkeletalAnim.FrameCount = anim.FrameCount; SkeletalAnim.FlagsScale = SkeletalAnimFlagsScale.Maya; SkeletalAnim.FlagsRotate = SkeletalAnimFlagsRotate.EulerXYZ; SkeletalAnim.Loop = anim.Looping; SkeletalAnim.Name = System.IO.Path.GetFileNameWithoutExtension(FileName); SkeletalAnim.Path = ""; } for (int i = 0; i < anim.Bones.Count; i++) { if (GetResFileU() != null) { var BoneAnimU = new ResU.BoneAnim(); BoneAnimU.Name = anim.Bones[i]; SkeletalAnimU.BoneAnims.Add(BoneAnimU); SkeletalAnimU.BindIndices[i] = ushort.MaxValue; bool IsRoot = false; if (!IsRoot) { BoneAnimU.ApplyIdentity = false; BoneAnimU.ApplyRotateTranslateZero = false; BoneAnimU.ApplyRotateZero = false; BoneAnimU.ApplyScaleOne = true; BoneAnimU.ApplyScaleVolumeOne = true; BoneAnimU.ApplyScaleUniform = true; BoneAnimU.ApplySegmentScaleCompensate = true; BoneAnimU.ApplyTranslateZero = false; } else { BoneAnimU.ApplyIdentity = true; BoneAnimU.ApplyRotateTranslateZero = true; BoneAnimU.ApplyRotateZero = true; BoneAnimU.ApplyScaleOne = true; BoneAnimU.ApplyScaleVolumeOne = true; BoneAnimU.ApplyScaleUniform = true; BoneAnimU.ApplySegmentScaleCompensate = false; BoneAnimU.ApplyTranslateZero = true; } } else { var BoneAnim = new BoneAnim(); BoneAnim.Name = anim.Bones[i]; SkeletalAnim.BoneAnims.Add(BoneAnim); SkeletalAnim.BindIndices[i] = ushort.MaxValue; //Set base data and curves var baseData = new BoneAnimData(); if (anim.AnimationPositionKeys.ContainsKey(anim.Bones[i]) && anim.AnimationPositionKeys[anim.Bones[i]].Count > 0) { BoneAnim.FlagsBase |= BoneAnimFlagsBase.Translate; var keys = anim.AnimationPositionKeys[anim.Bones[i]]; var data = (SELib.Utilities.Vector3)keys[0].Data; baseData.Translate = new Syroot.Maths.Vector3F((float)data.X, (float)data.Y, (float)data.Z); if (keys.Count > 1) { AnimCurve curve = new AnimCurve(); BoneAnim.Curves.Add(curve); CreateCurveData(curve, keys); } } if (anim.AnimationRotationKeys.ContainsKey(anim.Bones[i]) && anim.AnimationRotationKeys[anim.Bones[i]].Count > 0) { BoneAnim.FlagsBase |= BoneAnimFlagsBase.Rotate; var keys = anim.AnimationPositionKeys[anim.Bones[i]]; var data = (SELib.Utilities.Quaternion)keys[0].Data; baseData.Rotate = new Syroot.Maths.Vector4F((float)data.X, (float)data.Y, (float)data.Z, (float)data.W); if (keys.Count > 1) { AnimCurve curve = new AnimCurve(); BoneAnim.Curves.Add(curve); CreateCurveData(curve, keys); } } if (anim.AnimationScaleKeys.ContainsKey(anim.Bones[i]) && anim.AnimationScaleKeys[anim.Bones[i]].Count > 0) { BoneAnim.FlagsBase |= BoneAnimFlagsBase.Scale; var keys = anim.AnimationPositionKeys[anim.Bones[i]]; var data = (SELib.Utilities.Vector3)keys[0].Data; baseData.Scale = new Syroot.Maths.Vector3F((float)data.X, (float)data.Y, (float)data.Z); if (keys.Count > 1) { AnimCurve curve = new AnimCurve(); BoneAnim.Curves.Add(curve); CreateCurveData(curve, keys); } } //Set transforms bool IsRoot = false; if (!IsRoot) { BoneAnim.ApplyIdentity = false; BoneAnim.ApplyRotateTranslateZero = false; BoneAnim.ApplyRotateZero = false; BoneAnim.ApplyScaleOne = true; BoneAnim.ApplyScaleVolumeOne = true; BoneAnim.ApplyScaleUniform = true; BoneAnim.ApplySegmentScaleCompensate = true; BoneAnim.ApplyTranslateZero = false; } else { BoneAnim.ApplyIdentity = true; BoneAnim.ApplyRotateTranslateZero = true; BoneAnim.ApplyRotateZero = true; BoneAnim.ApplyScaleOne = true; BoneAnim.ApplyScaleVolumeOne = true; BoneAnim.ApplyScaleUniform = true; BoneAnim.ApplySegmentScaleCompensate = false; BoneAnim.ApplyTranslateZero = true; } } } for (int frame = 0; frame < anim.FrameCount; frame++) { } }