private void ReadMaterialAnimations(Anim animFile, AnimGroup animGroup, SBAnimation animation) { var decoder = new SsbhAnimTrackDecoder(animFile); foreach (AnimNode animNode in animGroup.Nodes) { foreach (AnimTrack track in animNode.Tracks) { SBMaterialAnimation matAnim = new SBMaterialAnimation() { MaterialName = animNode.Name, AttributeName = track.Name }; object[] MaterialAnim = decoder.ReadTrack(track); // only get vectors for now if (MaterialAnim == null || MaterialAnim.Length == 0 || MaterialAnim[0] == null || MaterialAnim[0].GetType() != typeof(AnimTrackCustomVector4)) { continue; } animation.MaterialNodes.Add(matAnim); for (int i = 0; i < MaterialAnim.Length; i++) { var vec = (AnimTrackCustomVector4)MaterialAnim[i]; matAnim.Keys.AddKey(i, new Vector4(vec.X, vec.Y, vec.Z, vec.W)); } } } }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> private void ExportAnimJoint(string FileName, SBAnimation animation, SBSkeleton skeleton) { HSDRawFile file = new HSDRawFile(); HSDRootNode root = new HSDRootNode(); if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = System.IO.Path.GetFileNameWithoutExtension(FileName); } if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = animation.Name; } root.Name = HSDSettings.RootName; if (root.Name == null) { System.Windows.Forms.MessageBox.Show($"Warning, the root name does not end with \"_figatree\"\n{root.Name}"); } file.Roots.Add(root); var joint = new HSD_AnimJoint(); EncodeAnimJoint(skeleton.Bones[0], joint, animation); root.Data = joint; file.Save(FileName); }
private void ReadVisibilityAnimations(Anim animFile, AnimGroup animGroup, SBAnimation animation) { var decoder = new SsbhAnimTrackDecoder(animFile); foreach (AnimNode animNode in animGroup.Nodes) { SBVisibilityAnimation visAnim = new SBVisibilityAnimation() { MeshName = animNode.Name }; foreach (AnimTrack track in animNode.Tracks) { if (track.Name.Equals("Visibility")) { object[] Visibility = decoder.ReadTrack(track); for (int i = 0; i < Visibility.Length; i++) { visAnim.Visibility.AddKey(i, (bool)Visibility[i]); } } } animation.VisibilityNodes.Add(visAnim); } }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SBAnimation anim = new SBAnimation(); SsbhFile File; if (Ssbh.TryParseSsbhFile(FileName, out File)) { if (File is Anim animation) { anim.Name = animation.Name; anim.FrameCount = animation.FinalFrameIndex + 1; foreach (var group in animation.Animations) { if (group.Type == AnimType.Visibility) { ReadVisibilityAnimations(animation, group, anim); } if (group.Type == AnimType.Transform) { ReadTransformAnimations(animation, group, anim); } if (group.Type == AnimType.Material) { ReadMaterialAnimations(animation, group, anim); } } } } return(anim); }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SBAnimation anim = new SBAnimation(); ISSBH_File File; if (SSBH.TryParseSSBHFile(FileName, out File)) { if (File is ANIM animation) { anim.Name = animation.Name; anim.FrameCount = animation.FrameCount; foreach (var group in animation.Animations) { if (group.Type == ANIM_TYPE.Visibilty) { ReadVisibilityAnimations(animation, group, anim); } if (group.Type == ANIM_TYPE.Transform) { ReadTransformAnimations(animation, group, anim); } if (group.Type == ANIM_TYPE.Material) { ReadMaterialAnimations(animation, group, anim); } } } } return(anim); }
private void ReadTransformAnimations(ANIM animFile, AnimGroup animGroup, SBAnimation animation) { var decoder = new SSBHAnimTrackDecoder(animFile); foreach (AnimNode animNode in animGroup.Nodes) { SBTransformAnimation tfrmAnim = new SBTransformAnimation() { Name = animNode.Name }; foreach (AnimTrack track in animNode.Tracks) { object[] Transform = decoder.ReadTrack(track); if (track.Name.Equals("Transform")) { for (int i = 0; i < Transform.Length; i++) { AnimTrackTransform t = (AnimTrackTransform)Transform[i]; tfrmAnim.Transform.Keys.Add(new SBAnimKey <Matrix4>() { Frame = i, Value = GetMatrix((AnimTrackTransform)Transform[i]), }); } } } animation.TransformNodes.Add(tfrmAnim); } }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { if (HSDSettings.FigaTree) { ExportFigaTree(FileName, animation, skeleton); } else { ExportAnimJoint(FileName, animation, skeleton); } }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { IO_MayaANIM anim = new IO_MayaANIM(); anim.Open(FileName); var animation = new SBAnimation(); animation.Name = Path.GetFileNameWithoutExtension(FileName); animation.FrameCount = anim.header.endTime - 1; foreach (var node in anim.Bones) { SBTransformAnimation a = new SBTransformAnimation(); a.Name = node.name; animation.TransformNodes.Add(a); foreach (var att in node.atts) { if (!trackTypeConversion.ContainsKey(att.type)) { continue; } SBTransformTrack track = new SBTransformTrack(trackTypeConversion[att.type]); a.Tracks.Add(track); foreach (var key in att.keys) { InterpolationType itype = InterpolationType.Linear; float intan = 0; float outtan = 0; if (key.intan == "fixed") { itype = InterpolationType.Hermite; intan = key.t1; } if (key.outtan == "fixed") { itype = InterpolationType.Hermite; outtan = key.t2; } track.AddKey(key.input - header.startTime, GetOutputValue(anim, att, key.output), itype, intan , outtan); } } } return(animation); }
public static void ExportIOAnimationAsANIM(string fname, SBAnimation animation, SBSkeleton Skeleton, bool ordinal = false) { IO_MayaANIM anim = new IO_MayaANIM(); anim.header.endTime = animation.FrameCount + 1; // get bone order List <SBBone> BonesInOrder = getBoneTreeOrder(Skeleton); if (ordinal) { BonesInOrder = BonesInOrder.OrderBy(f => f.Name, StringComparer.Ordinal).ToList(); } foreach (SBBone b in BonesInOrder) { AnimBone animBone = new AnimBone() { name = b.Name }; anim.Bones.Add(animBone); // Add Tracks SBTransformAnimation node = null; foreach (var animNode in animation.TransformNodes) { if (animNode.Name.Equals(b.Name)) { node = animNode; break; } } if (node == null) { continue; } AddAnimData(animBone, node.Transform, ControlType.translate, TrackType.translateX); AddAnimData(animBone, node.Transform, ControlType.translate, TrackType.translateY); AddAnimData(animBone, node.Transform, ControlType.translate, TrackType.translateZ); AddAnimData(animBone, node.Transform, ControlType.rotate, TrackType.rotateX); AddAnimData(animBone, node.Transform, ControlType.rotate, TrackType.rotateY); AddAnimData(animBone, node.Transform, ControlType.rotate, TrackType.rotateZ); AddAnimData(animBone, node.Transform, ControlType.scale, TrackType.scaleX); AddAnimData(animBone, node.Transform, ControlType.scale, TrackType.scaleY); AddAnimData(animBone, node.Transform, ControlType.scale, TrackType.scaleZ); } anim.Save(fname); }
private void ReadTransformAnimations(Anim animFile, AnimGroup animGroup, SBAnimation animation) { var decoder = new SsbhAnimTrackDecoder(animFile); foreach (AnimNode animNode in animGroup.Nodes) { SBTransformAnimation tfrmAnim = new SBTransformAnimation() { Name = animNode.Name }; SBTransformTrack X = new SBTransformTrack(SBTrackType.TranslateX); SBTransformTrack Y = new SBTransformTrack(SBTrackType.TranslateY); SBTransformTrack Z = new SBTransformTrack(SBTrackType.TranslateZ); SBTransformTrack RX = new SBTransformTrack(SBTrackType.RotateX); SBTransformTrack RY = new SBTransformTrack(SBTrackType.RotateY); SBTransformTrack RZ = new SBTransformTrack(SBTrackType.RotateZ); SBTransformTrack SX = new SBTransformTrack(SBTrackType.ScaleX); SBTransformTrack SY = new SBTransformTrack(SBTrackType.ScaleY); SBTransformTrack SZ = new SBTransformTrack(SBTrackType.ScaleZ); SBTransformTrack CompensateScale = new SBTransformTrack(SBTrackType.CompensateScale); tfrmAnim.Tracks.AddRange(new SBTransformTrack[] { X, Y, Z, RX, RY, RZ, SX, SY, SZ, CompensateScale }); foreach (AnimTrack track in animNode.Tracks) { object[] Transform = decoder.ReadTrack(track); if (track.Name.Equals("Transform")) { for (int i = 0; i < Transform.Length; i++) { AnimTrackTransform t = (AnimTrackTransform)Transform[i]; SBBone transform = new SBBone(); transform.Transform = GetMatrix((AnimTrackTransform)Transform[i]); X.AddKey(i, transform.X); Y.AddKey(i, transform.Y); Z.AddKey(i, transform.Z); RX.AddKey(i, transform.RX); RY.AddKey(i, transform.RY); RZ.AddKey(i, transform.RZ); SX.AddKey(i, transform.SX); SY.AddKey(i, transform.SY); SZ.AddKey(i, transform.SZ); CompensateScale.AddKey(i, t.CompensateScale); } } } animation.TransformNodes.Add(tfrmAnim); } }
public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { SMD file = new SMD(); var bonelist = new List <SBBone>(skeleton.Bones); foreach (var bone in bonelist) { file.nodes.Add(new SMDNode() { Name = bone.Name, ID = bonelist.IndexOf(bone), ParentID = bonelist.IndexOf(bone.Parent) }); } for (int i = 0; i < animation.FrameCount; i++) { var group = new SMDSkeletonFrame(); group.time = i; file.skeleton.Add(group); foreach (var bone in bonelist) { bool found = false; foreach (var animbone in animation.TransformNodes) { if (animbone.Name.Equals(bone.Name)) { var tempBone = new SBBone(); tempBone.Transform = animbone.GetTransformAt(i, skeleton); group.skeletons.Add(new SMDSkeleton() { BoneID = bonelist.IndexOf(bone), Position = tempBone.Translation, Rotation = tempBone.RotationEuler }); found = true; break; } } if (!found) { group.skeletons.Add(new SMDSkeleton() { BoneID = bonelist.IndexOf(bone), Position = bone.Translation, Rotation = bone.RotationEuler }); } } } file.Save(FileName); }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SMD smd = new SMD(); smd.Open(FileName); SBAnimation animation = new SBAnimation(); animation.Name = Path.GetFileNameWithoutExtension(FileName); Dictionary <int, SBTransformAnimation> idToAnim = new Dictionary <int, SBTransformAnimation>(); foreach (var node in smd.nodes) { var nodeAnim = new SBTransformAnimation() { Name = node.Name }; idToAnim.Add(node.ID, nodeAnim); animation.TransformNodes.Add(nodeAnim); } var frameCount = 0; foreach (var v in smd.skeleton) { frameCount = Math.Max(v.time, frameCount); foreach (var node in v.skeletons) { var animNode = idToAnim[node.BoneID]; animNode.AddKey(v.time, node.Position.X, SBTrackType.TranslateX); animNode.AddKey(v.time, node.Position.Y, SBTrackType.TranslateY); animNode.AddKey(v.time, node.Position.Z, SBTrackType.TranslateZ); animNode.AddKey(v.time, node.Rotation.X, SBTrackType.RotateX); animNode.AddKey(v.time, node.Rotation.Y, SBTrackType.RotateY); animNode.AddKey(v.time, node.Rotation.Z, SBTrackType.RotateZ); } } animation.FrameCount = frameCount; return(animation); }
/// <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! }
public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { using (StreamWriter w = new StreamWriter(new FileStream(FileName, FileMode.Create))) { w.WriteLine("#SBAnimation Version 1"); w.WriteLine($"FrameCount {animation.FrameCount}"); foreach (var visNode in animation.VisibilityNodes) { w.WriteLine($"visibility {visNode.MeshName}"); w.WriteLine("{"); bool prev = false; foreach (var key in visNode.Visibility.Keys) { if (key.Frame == 0 || prev != key.Value) { w.WriteLine($"{key.Frame} : {key.Value}"); } prev = key.Value; } w.WriteLine("}"); } foreach (var matNode in animation.MaterialNodes) { w.WriteLine($"material {matNode.MaterialName} {matNode.AttributeName}"); w.WriteLine("{"); Vector4 prev = Vector4.Zero; foreach (var key in matNode.Keys.Keys) { if (key.Frame == 0 || prev != key.Value) { w.WriteLine($"{key.Frame} : {key.Value.ToString()}"); } prev = key.Value; } w.WriteLine("}"); } } }
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 void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { // The final frame index is one less than the number of frames. // Empty animations have a final frame index of 1, so clamp to 1. int finalFrameIndex = Math.Max((int)animation.FrameCount - 1, 1); SsbhAnimTrackEncoder encoder = new SsbhAnimTrackEncoder(finalFrameIndex); encoder.CompressVector4 = ExportSettings.CompressVector4; encoder.SetCompressionLevel(ExportSettings.CompressionLevel); var animNodes = animation.TransformNodes.OrderBy(e => e.Name, StringComparer.Ordinal); foreach (var node in animNodes) { if (node.Name.StartsWith("H_") || node.Name.EndsWith("_null")) // skip helper bones and null swing bones { continue; } List <object> transforms = new List <object>(); for (int i = 0; i < animation.FrameCount; i++) { transforms.Add(MatrixToTransform(node.GetTransformAt(i, skeleton))); } encoder.AddTrack(node.Name, "Transform", AnimType.Transform, transforms); } var visNodes = animation.VisibilityNodes.OrderBy(e => e.MeshName, StringComparer.Ordinal); foreach (var node in visNodes) { List <object> visibilities = new List <object>(); bool AllSame = true; bool first = node.Visibility.GetValue(0); for (int i = 0; i < animation.FrameCount; i++) { visibilities.Add(node.Visibility.GetValue(i)); if (AllSame && node.Visibility.GetValue(i) != first) { AllSame = false; } } if (AllSame) { visibilities.Clear(); visibilities.Add(first); } encoder.AddTrack(node.MeshName, "Visibility", AnimType.Visibility, visibilities); } var matNodes = animation.MaterialNodes.OrderBy(e => e.MaterialName, StringComparer.Ordinal); foreach (var mat in matNodes) { var list = new List <object>(); bool AllSame = true; Vector4 first = mat.Keys.GetValue(0); for (int i = 0; i < animation.FrameCount; i++) { var value = mat.Keys.GetValue(i); list.Add(new AnimTrackCustomVector4(value.X, value.Y, value.Z, value.W)); if (AllSame && mat.Keys.GetValue(i) != first) { AllSame = false; } } if (AllSame) { list.Clear(); list.Add(new AnimTrackCustomVector4(first.X, first.Y, first.Z, first.W)); } encoder.AddTrack(mat.MaterialName, mat.AttributeName, AnimType.Material, list); } try { encoder.Save(FileName); } catch (Exception) { System.Windows.Forms.MessageBox.Show("Error creating Anim file: try using a larger compression level"); } }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SBAnimation anim = new SBAnimation(); HSDRawFile f = new HSDRawFile(FileName); foreach (var root in f.Roots) { if (root == null || root.Data == null) { continue; } anim.Name = root.Name; if (root.Data is HSD_AnimJoint joint) { var joints = joint.BreathFirstList; int nodeIndex = -1; foreach (var j in joints) { nodeIndex++; if (j.AOBJ == null || j.AOBJ.FObjDesc == null) { continue; } SBConsole.WriteLine(nodeIndex + " " + j.Flags.ToString("X8") + " " + j.AOBJ.Flags.ToString()); SBTransformAnimation a = new SBTransformAnimation(); if (nodeIndex < skeleton.Bones.Length) { a.Name = skeleton.Bones[nodeIndex].Name; } else { a.Name = "JOBJ_" + nodeIndex; } anim.TransformNodes.Add(a); anim.FrameCount = Math.Max(anim.FrameCount, j.AOBJ.EndFrame); foreach (var fobj in j.AOBJ.FObjDesc.List) { a.Tracks.Add(DecodeFOBJ(fobj.ToFOBJ())); } } } if (root.Data is HSD_FigaTree tree) { anim.FrameCount = tree.FrameCount; int nodeIndex = 0; foreach (var node in tree.Nodes) { SBTransformAnimation a = new SBTransformAnimation(); a.Name = skeleton.Bones[nodeIndex++].Name; anim.TransformNodes.Add(a); foreach (var att in node.Tracks) { if (att.FOBJ == null) { continue; } a.Tracks.Add(DecodeFOBJ(att.FOBJ)); } } } if (root.Data is HSD_MatAnimJoint matjoint) { var joints = matjoint.BreathFirstList; anim.FrameCount = 0; int nodeIndex = -1; foreach (var j in joints) { if (j.MaterialAnimation == null) { continue; } var matAnims = j.MaterialAnimation.List; foreach (var manim in matAnims) { nodeIndex++; var aobj = manim.AnimationObject; if (aobj != null) { anim.FrameCount = Math.Max(anim.FrameCount, aobj.EndFrame); } var texanim = manim.TextureAnimation; if (texanim == null) { continue; } var texAOBJ = texanim.AnimationObject; if (texAOBJ == null || texAOBJ.FObjDesc == null) { continue; } anim.FrameCount = Math.Max(anim.FrameCount, texAOBJ.EndFrame); //TODO: tex anim is a list if (texanim != null) { SBTextureAnimation textureAnim = new SBTextureAnimation(); anim.TextureNodes.Add(textureAnim); textureAnim.MeshName = "DOBJ_" + nodeIndex; textureAnim.TextureAttibute = texanim.GXTexMapID.ToString(); textureAnim.Keys = DecodeFOBJ(texAOBJ.FObjDesc.ToFOBJ()).Keys; for (int i = 0; i < texanim.ImageCount; i++) { HSD_TOBJ tobj = new HSD_TOBJ(); tobj.ImageData = texanim.ImageBuffers.Array[i].Data; if (texanim.TlutCount > i) { tobj.TlutData = texanim.TlutBuffers.Array[i].Data; } var surface = new SBSurface(); surface.Arrays.Add(new MipArray() { Mipmaps = new List <byte[]>() { tobj.GetDecodedImageData() } }); surface.Width = tobj.ImageData.Width; surface.Height = tobj.ImageData.Height; surface.PixelFormat = PixelFormat.Bgra; surface.PixelType = PixelType.UnsignedByte; surface.InternalFormat = InternalFormat.Rgba; textureAnim.Surfaces.Add(surface); } } } } SBConsole.WriteLine(nodeIndex); } } return(anim); }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> private void ExportFigaTree(string FileName, SBAnimation animation, SBSkeleton skeleton) { HSDRawFile file = new HSDRawFile(); HSDRootNode root = new HSDRootNode(); if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = System.IO.Path.GetFileNameWithoutExtension(FileName); } if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = animation.Name; } root.Name = HSDSettings.RootName; if (root.Name == null || !root.Name.EndsWith("_figatree")) { System.Windows.Forms.MessageBox.Show($"Warning, the root name does not end with \"_figatree\"\n{root.Name}"); } file.Roots.Add(root); var nodes = new List <FigaTreeNode>(); int boneIndex = -1; foreach (var skelnode in skeleton.Bones) { FigaTreeNode animNode = new FigaTreeNode(); nodes.Add(animNode); boneIndex++; // skip trans n and rotn tracks if (boneIndex == 0) { continue; } var node = animation.TransformNodes.Find(e => e.Name == skelnode.Name); if (node == null) { continue; } foreach (var track in node.Tracks) { HSD_Track animTrack = new HSD_Track(); animTrack.FOBJ = EncodeFOBJ(track); animTrack.DataLength = (short)animTrack.FOBJ.Buffer.Length; animNode.Tracks.Add(animTrack); } } HSD_FigaTree tree = new HSD_FigaTree(); tree.FrameCount = animation.FrameCount; tree.Type = 1; tree.Nodes = nodes; root.Data = tree; file.Save(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> /// /// </summary> /// <param name="animation"></param> /// <param name="outputPath"></param> /// <param name="skeleton"></param> /// <param name="animType"></param> public static void ConvertAnim(SBAnimation animation, string outputPath, SBSkeleton skeleton, IExportableAnimation animType) { animType.ExportSBAnimation(outputPath, animation, skeleton); }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { var jointTable = GetJointTable(Settings.JVCPath).ToList(); Anim a = new Anim(); a.EndTime = animation.FrameCount / Settings.FrameScale; a.PlaySpeed = 0.01f; a.Joints.Add(new Joint() { BoneID = -1, Flag3 = 0x40, MaxTime = a.EndTime, }); List <double> AllKeys = new List <double>(); foreach (var v in animation.TransformNodes) { if (skeleton[v.Name] == null) { continue; } var sb = skeleton[v.Name]; if (sb == null) { continue; } var index = (short)jointTable.IndexOf((short)skeleton.IndexOfBone(sb)); Console.WriteLine(v.Name + " " + index); if (index == -1) { continue; } Joint Position = null; Joint Rotation = null; Joint Scale = null; if (v.HasTranslation) { Position = new Joint(); var j = Position; j.Flag1 = 0x02; j.Flag2 = 0x02; j.Flag3 = 0x21; j.BoneID = index; j.MaxTime = a.EndTime; } if (v.HasRotation) { Rotation = new Joint(); var j = Rotation; j.Flag1 = 0x02; j.Flag2 = 0x02; j.Flag3 = 0x28; j.BoneID = index; j.MaxTime = a.EndTime; } if (v.HasScale) { Scale = new Joint(); var j = Scale; j.Flag1 = 0x02; j.Flag2 = 0x02; j.Flag3 = 0x22; j.BoneID = index; j.MaxTime = a.EndTime; } // gather baked nodes List <Vector3> Positions = new List <Vector3>(); List <Vector4> Rotations = new List <Vector4>(); List <Vector3> Scales = new List <Vector3>(); for (int i = 0; i <= animation.FrameCount; i++) { var t = v.GetTransformAt(i, skeleton); if (v.HasTranslation) { Positions.Add(t.ExtractTranslation() - sb.Translation); } if (v.HasScale) { Positions.Add(t.ExtractScale() - sb.Scale); } if (v.HasRotation) { var quat = (t.ExtractRotation().Inverted() * sb.RotationQuaternion).Inverted(); var inv = new Quaternion(quat.X, 0, 0, quat.W).Normalized().Inverted(); var dir = Vector3.TransformNormal(Vector3.UnitX, Matrix4.CreateFromQuaternion(quat * inv)); var angle = Tools.CrossMath.ToEulerAngles(inv).X * 180 / (float)Math.PI; Rotations.Add(new Vector4(dir, angle)); } } // now we convert the bake nodes into linear tracks in the new time scale range if (Positions.Count > 0) { var X = SimplifyLines(Positions.Select(e => e.X)); var Y = SimplifyLines(Positions.Select(e => e.Y)); var Z = SimplifyLines(Positions.Select(e => e.Z)); var frames = X.Select(e => e.Item1).Union(Y.Select(e => e.Item1).Union(Z.Select(e => e.Item1))).ToList(); frames.Sort(); if (frames[frames.Count - 1] != animation.FrameCount) { frames.Add(animation.FrameCount); } AllKeys = AllKeys.Union(frames).ToList(); foreach (var f in frames) { Position.Keys.Add(new Key() { Time = (float)f / Settings.FrameScale, X = Positions[(int)f].X, Y = Positions[(int)f].Y, Z = Positions[(int)f].Z, W = 0 }); } } if (Rotations.Count > 0) { var X = SimplifyLines(Rotations.Select(e => e.X)); var Y = SimplifyLines(Rotations.Select(e => e.Y)); var Z = SimplifyLines(Rotations.Select(e => e.Z)); var W = SimplifyLines(Rotations.Select(e => e.W)); var frames = X.Select(e => e.Item1).Union(Y.Select(e => e.Item1).Union(Z.Select(e => e.Item1))).Union(W.Select(e => e.Item1)).ToList(); frames.Sort(); if (frames[frames.Count - 1] != animation.FrameCount) { frames.Add(animation.FrameCount); } AllKeys = AllKeys.Union(frames).ToList(); foreach (var f in frames) { Rotation.Keys.Add(new Key() { Time = (float)f / Settings.FrameScale, X = Rotations[(int)f].X, Y = Rotations[(int)f].Y, Z = Rotations[(int)f].Z, W = Rotations[(int)f].W, }); } } if (Position != null) { a.Joints.Add(Position); } if (Rotation != null) { a.Joints.Add(Rotation); } if (Scale != null) { a.Joints.Add(Scale); } } AllKeys.Sort(); foreach (var v in AllKeys) { a.Joints[0].Keys.Add(new Key() { Time = (float)v / Settings.FrameScale }); } a.Save(FileName); }
public SBAnimAttachment(SBAnimation animation) { this.animation = animation; }
/// <summary> /// /// </summary> /// <param name="bone"></param> /// <param name="joint"></param> /// <param name="animation"></param> private void EncodeAnimJoint(SBBone bone, HSD_AnimJoint joint, SBAnimation animation) { var node = animation.TransformNodes.Find(e => e.Name == bone.Name); if (node != null) { // encode tracks joint.Flags = 1; joint.AOBJ = new HSD_AOBJ(); joint.AOBJ.EndFrame = animation.FrameCount; joint.AOBJ.Flags = AOBJ_Flags.ANIM_LOOP; if (!HSDSettings.LoopAnimation) { joint.AOBJ.Flags = AOBJ_Flags.FIRST_PLAY; } if (node.Tracks.Count == 0) { joint.AOBJ.Flags = AOBJ_Flags.NO_ANIM; } var prev = new HSD_FOBJDesc(); foreach (var track in node.Tracks) { var fobjdesc = new HSD_FOBJDesc(); fobjdesc.FromFOBJ(EncodeFOBJ(track)); fobjdesc.DataLength = fobjdesc.ToFOBJ().Buffer.Length; if (joint.AOBJ.FObjDesc == null) { joint.AOBJ.FObjDesc = fobjdesc; } else { prev.Next = fobjdesc; } prev = fobjdesc; } } // continue adding children var prevChild = new HSD_AnimJoint(); foreach (var c in bone.Children) { HSD_AnimJoint child = new HSD_AnimJoint(); EncodeAnimJoint(c, child, animation); if (joint.Child == null) { joint.Child = child; } else { prevChild.Next = child; } prevChild = child; } }
public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { ExportIOAnimationAsANIM(FileName, animation, skeleton); }
public static void ExportIOAnimationAsANIM(string fname, SBAnimation animation, SBSkeleton Skeleton) { IO_MayaANIM anim = new IO_MayaANIM(); anim.header.endTime = animation.FrameCount + 1; if (!MayaSettings.UseRadians) { anim.header.angularUnit = "deg"; } // get bone order List <SBBone> BonesInOrder = getBoneTreeOrder(Skeleton); if (MayaSettings.Maya2015) { BonesInOrder = BonesInOrder.OrderBy(f => f.Name, StringComparer.Ordinal).ToList(); } if (MayaSettings.RemoveRedundantFrames) { animation.Optimize(); } foreach (SBBone b in BonesInOrder) { AnimBone animBone = new AnimBone() { name = b.Name }; anim.Bones.Add(animBone); // Add Tracks SBTransformAnimation node = null; foreach (var animNode in animation.TransformNodes) { if (animNode.Name.Equals(b.Name)) { node = animNode; break; } } if (node == null) { continue; } //TODO: bake scale for compensate scale... foreach (var track in node.Tracks) { switch (track.Type) { case SBTrackType.TranslateX: AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateX); break; case SBTrackType.TranslateY: AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateY); break; case SBTrackType.TranslateZ: AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateZ); break; case SBTrackType.RotateX: AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateX); break; case SBTrackType.RotateY: AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateY); break; case SBTrackType.RotateZ: AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateZ); break; case SBTrackType.ScaleX: AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleX); break; case SBTrackType.ScaleY: AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleY); break; case SBTrackType.ScaleZ: AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleZ); break; } } } anim.Save(fname); }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton) { using (StreamWriter file = new StreamWriter(FileName)) Write(file, animation, skeleton); }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton) { SBAnimation anim = new SBAnimation(); using (StreamReader r = new StreamReader(new FileStream(FileName, FileMode.Open))) { if (r.ReadLine() != "#SBAnimation Version 1") { return(anim); } while (!r.EndOfStream) { var line = r.ReadLine(); var args = line.Trim().Split(' '); switch (args[0]) { case "comment": break; case "FrameCount": anim.FrameCount = int.Parse(args[1]); break; case "visibility": SBVisibilityAnimation visAnim = new SBVisibilityAnimation(); visAnim.MeshName = args[1]; var visLien = r.ReadLine(); if (visLien == "{") { visLien = r.ReadLine(); while (!r.EndOfStream && visLien != "}") { visLien = visLien.Replace(" ", ""); var frame = visLien.Substring(0, visLien.IndexOf(":")).Trim(); var value = visLien.Substring(visLien.IndexOf(":") + 1, visLien.Length - (visLien.IndexOf(":") + 1)).Trim(); visAnim.Visibility.AddKey(float.Parse(frame), bool.Parse(value)); visLien = r.ReadLine(); } } anim.VisibilityNodes.Add(visAnim); break; case "bone": if (args[1].Contains(".anim")) { IO_MayaANIM manim = new IO_MayaANIM(); var bones = manim.ImportSBAnimation(Path.GetDirectoryName(FileName) + "/" + args[1], skeleton); anim.TransformNodes.AddRange(bones.TransformNodes); } break; case "material": SBMaterialAnimation matAnim = new SBMaterialAnimation(); matAnim.MaterialName = args[1]; matAnim.AttributeName = args[2]; var matLien = r.ReadLine(); if (matLien == "{") { matLien = r.ReadLine(); while (!r.EndOfStream && matLien != "}") { matLien = matLien.Replace(" ", ""); var frame = matLien.Substring(0, matLien.IndexOf(":")).Trim(); var value = matLien.Substring(matLien.IndexOf(":") + 1, matLien.Length - (matLien.IndexOf(":") + 1)).Trim(); var vector = value.Replace(")", "").Replace("(", "").Split(','); if (vector.Length != 4) { continue; } matAnim.Keys.AddKey(float.Parse(frame), new Vector4(float.Parse(vector[0]), float.Parse(vector[1]), float.Parse(vector[2]), float.Parse(vector[3]))); matLien = r.ReadLine(); } } anim.MaterialNodes.Add(matAnim); break; } } } return(anim); }
public void Write(StreamWriter file, SBAnimation animation, SBSkeleton skeleton) { List <Bone> roots = CreateRoots(skeleton.Roots.ToList()); file.WriteLine("HIERARCHY"); foreach (var root in roots) { Vector3 offset = Vector3.TransformPosition(Vector3.Zero, root.head.WorldTransform); file.WriteLine("ROOT " + root.name); file.WriteLine("{"); file.WriteLine("\tOFFSET " + offset.X + " " + offset.Y + " " + offset.Z); file.WriteLine("\tCHANNELS 6 Xposition Yposition Zposition Zrotation Yrotation Xrotation"); foreach (var child in root.children) { WriteChildBone(file, child, "\t"); } file.WriteLine("}"); } int nFrames = !Settings.SkeletonOnly ? (int)animation.FrameCount : 1; file.WriteLine("MOTION"); file.WriteLine("Frames: " + nFrames); file.WriteLine("Frame Time: .0083333"); if (Settings.SkeletonOnly) { String line = ""; for (int i = 0; i < roots.Count; i++) { Bone root = roots[i]; Vector3 offset = Vector3.TransformPosition(Vector3.Zero, root.head.WorldTransform); line += offset.X + " " + offset.Y + " " + offset.Z + " 0 0 0"; if (root.children.Count > 0) { line += " " + AnimateSkeletonOnly(root.children); } if (i < roots.Count - 1) { line += " "; } } file.WriteLine(line); return; } Dictionary <String, SBTransformAnimation> transformNodes = new Dictionary <string, SBTransformAnimation>(); foreach (var v in animation.TransformNodes) { transformNodes[v.Name] = v; } for (int frame = 0; frame < nFrames; frame++) { String line = ""; UpdateSBSkeleton(skeleton, transformNodes, frame); for (int i = 0; i < roots.Count; i++) { Bone root = roots[i]; Vector3 pos = root.offset; line += pos.X + " " + pos.Y + " " + pos.Z + " 0 0 0"; foreach (var child in root.children) { line += " " + Animate(child); } if (i < roots.Count - 1) { line += " "; } } file.WriteLine(line); } }
public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton, string jvcPath) { var sbAnim = new SBAnimation(); var jointTable = GetJointTable(jvcPath); var anim = new Anim(); using (BinaryReaderExt r = new BinaryReaderExt(new FileStream(FileName, FileMode.Open))) anim.Parse(r); float scale = Settings.FrameScale; sbAnim.FrameCount = (float)(scale * anim.EndTime); foreach (var j in anim.Joints) { if (j.BoneID == -1) { continue; } if (j.BoneID >= jointTable.Length || jointTable[j.BoneID] == -1 || jointTable[j.BoneID] >= skeleton.Bones.Length) { continue; } var bone = skeleton.Bones[jointTable[j.BoneID]]; SBTransformAnimation node = sbAnim.TransformNodes.Find(e => e.Name == bone.Name); if (node == null) { node = new SBTransformAnimation(); node.Name = bone.Name; sbAnim.TransformNodes.Add(node); } //Console.WriteLine(bone.Name); if (j.Flag3 == 0x21) { foreach (var k in j.Keys) { //Console.WriteLine($"\t{k.Time} {k.X} {k.Y} {k.Z} {k.W}"); node.AddKey((float)Math.Ceiling(k.Time * scale), bone.X + k.X, SBTrackType.TranslateX); node.AddKey((float)Math.Ceiling(k.Time * scale), bone.Y + k.Y, SBTrackType.TranslateY); node.AddKey((float)Math.Ceiling(k.Time * scale), bone.Z + k.Z, SBTrackType.TranslateZ); } } else if (j.Flag3 == 0x28) { var eul0 = ToQuat(bone.RotationQuaternion, j.Keys[0].W, new Vector3(j.Keys[0].X, j.Keys[0].Y, j.Keys[0].Z)); node.AddKey(0, eul0.X, SBTrackType.RotateX, InterpolationType.Step); node.AddKey(0, eul0.Y, SBTrackType.RotateY, InterpolationType.Step); node.AddKey(0, eul0.Z, SBTrackType.RotateZ, InterpolationType.Step); node.AddKey(0, eul0.W, SBTrackType.RotateW, InterpolationType.Step); foreach (var k in j.Keys) { var eul = ToQuat(bone.RotationQuaternion, k.W, new Vector3(k.X, k.Y, k.Z)); node.AddKey((float)Math.Ceiling(k.Time * scale), eul.X, SBTrackType.RotateX); node.AddKey((float)Math.Ceiling(k.Time * scale), eul.Y, SBTrackType.RotateY); node.AddKey((float)Math.Ceiling(k.Time * scale), eul.Z, SBTrackType.RotateZ); node.AddKey((float)Math.Ceiling(k.Time * scale), eul.W, SBTrackType.RotateW); } } else { SBConsole.WriteLine("Unknown MOT Track Type " + j.Flag3.ToString("X")); } } sbAnim.ConvertRotationKeysToEuler(); return(sbAnim); }