/// <summary> /// Generates a baked skeleton based on the first frame of the animation. /// </summary> /// <returns></returns> public STSkeleton CreateBakedSkeleton(int skeletonIndex) { var skel = Skeletons.FirstOrDefault(); if (skeletonIndex < Skeletons.Count) { skel = Skeletons[skeletonIndex]; } if (skel == null) { return(new STSkeleton()); } var target = Animations[0]; STSkeleton skeleton = new STSkeleton(); for (int i = 0; i < skel.GlobalIndexList.Count; i++) { var boneAnim = target.BoneGroups[i]; float posX = boneAnim.TranslateX.GetBaseValue(); float posY = boneAnim.TranslateY.GetBaseValue(); float posZ = boneAnim.TranslateZ.GetBaseValue(); float rotX = boneAnim.RotateX.GetBaseValue(); float rotY = boneAnim.RotateY.GetBaseValue(); float rotZ = boneAnim.RotateZ.GetBaseValue(); float scaleX = boneAnim.ScaleX.GetBaseValue(true); float scaleY = boneAnim.ScaleY.GetBaseValue(true); float scaleZ = boneAnim.ScaleZ.GetBaseValue(true); STBone bone = new STBone(skeleton); bone.ParentIndex = skel.GlobalIndexList[i].ParentIndex; bone.Name = $"Bone{i}"; //Multiply by 1024 (hardcoded scale value) bone.Position = new Vector3(posX, posY, posZ) * 1024.0f; bone.EulerRotation = new Vector3(rotX, rotY, rotZ); bone.Scale = new Vector3(scaleX, scaleY, scaleZ); skeleton.Bones.Add(bone); } skeleton.Reset(); skeleton.Update(); return(skeleton); }
private void PlaySkeletalAnim(HSFMotionAnimation anim) { STSkeleton skeleton = Renderer.Scene.Models[0].Skeleton; foreach (var container in Runtime.ModelContainers) { var skel = container.SearchActiveSkeleton(); if (skel != null) { skeleton = skel; } } Console.WriteLine($"skeleton {skeleton != null}"); if (skeleton == null) { return; } if (anim.Frame == 0) { skeleton.Reset(); } bool Updated = false; // no need to update skeleton of animations that didn't change foreach (AnimationNode node in anim.AnimGroups) { var b = skeleton.SearchBone(node.Name); if (b == null) { continue; } Updated = true; Vector3 position = b.Position; Vector3 scale = b.Scale; Quaternion rotation = b.Rotation; if (node.TranslateX.HasKeys) { position.X = node.TranslateX.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.TranslateY.HasKeys) { position.Y = node.TranslateY.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.TranslateZ.HasKeys) { position.Z = node.TranslateZ.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.ScaleX.HasKeys) { scale.X = node.ScaleX.GetFrameValue(anim.Frame); } if (node.ScaleY.HasKeys) { scale.Y = node.ScaleY.GetFrameValue(anim.Frame); } if (node.ScaleZ.HasKeys) { scale.Z = node.ScaleZ.GetFrameValue(anim.Frame); } if (node.RotationX.HasKeys || node.RotationY.HasKeys || node.RotationZ.HasKeys) { float x = node.RotationX.HasKeys ? MathHelper.DegreesToRadians(node.RotationX.GetFrameValue(anim.Frame)) : b.EulerRotation.X; float y = node.RotationY.HasKeys ? MathHelper.DegreesToRadians(node.RotationY.GetFrameValue(anim.Frame)) : b.EulerRotation.Y; float z = node.RotationZ.HasKeys ? MathHelper.DegreesToRadians(node.RotationZ.GetFrameValue(anim.Frame)) : b.EulerRotation.Z; rotation = STMath.FromEulerAngles(new Vector3(x, y, z)); } b.AnimationController.Position = position; b.AnimationController.Scale = scale; b.AnimationController.Rotation = rotation; } if (Updated) { skeleton.Update(); } }
private void LoadSkeleton() { ObjectTreeNode skeletonFolder = new ObjectTreeNode("Skeleton"); this.AddChild(skeletonFolder); for (int i = 0; i < Header.ObjectCount; i++) { var info = Header.ObjectData.Objects[i]; var name = Header.ObjectData.ObjectNames[i]; if (name == string.Empty) { name = $"Object_{i}"; } //Add a dummy bone. Some bone data is set at runtime and uses large random values if (info.ChildrenCount > Header.ObjectCount) { Skeleton.Bones.Add(new HSFBoneWrapper(info, Skeleton) { Name = name, ParentIndex = -1, Position = new Vector3(), Scale = Vector3.One, EulerRotation = new Vector3(), }); } else { Skeleton.Bones.Add(new HSFBoneWrapper(info, Skeleton) { Name = name, ParentIndex = -1, Position = new OpenTK.Vector3( info.BaseTransform.Translate.X, info.BaseTransform.Translate.Y, info.BaseTransform.Translate.Z) * HSF_Renderer.PreviewScale, EulerRotation = new OpenTK.Vector3( MathHelper.DegreesToRadians(info.BaseTransform.Rotate.X), MathHelper.DegreesToRadians(info.BaseTransform.Rotate.Y), MathHelper.DegreesToRadians(info.BaseTransform.Rotate.Z)), Scale = new OpenTK.Vector3( info.BaseTransform.Scale.X == 0 ? 1 : info.BaseTransform.Scale.X, info.BaseTransform.Scale.Y == 0 ? 1 : info.BaseTransform.Scale.Y, info.BaseTransform.Scale.Z == 0 ? 1 : info.BaseTransform.Scale.Z), }); } } for (int i = 0; i < Header.ObjectCount; i++) { if (Header.ObjectData.Objects[i].ChildrenCount > Header.ObjectCount) { Skeleton.Bones[i].ParentIndex = -1; } else { Skeleton.Bones[i].ParentIndex = Header.ObjectData.Objects[i].ParentIndex; } } var boneNodes = Skeleton.CreateBoneTree(); foreach (var bone in boneNodes) { skeletonFolder.AddChild(bone); } Skeleton.PreviewScale = 0.05f; Skeleton.Reset(); Skeleton.Update(); }