private void AttachJoint(PartsModel partInfo, IRenderableFile actorRender) { var modelPart = actorRender.Renderer.Models[0]; foreach (ModelAsset model in ModelFile.Renderer.Models) { var bone = model.ModelData.Skeleton.SearchBone(partInfo.JointName); if (bone != null) { //Setup local transform var localPosition = new OpenTK.Vector3( partInfo.LocalTranslate.X, partInfo.LocalTranslate.Y, partInfo.LocalTranslate.Z); var localRotation = STMath.FromEulerAngles(new OpenTK.Vector3( partInfo.LocalRotate.X, partInfo.LocalRotate.Y, partInfo.LocalRotate.Z) * STMath.Deg2Rad); var localScale = new OpenTK.Vector3( partInfo.LocalScale.X, partInfo.LocalScale.Y, partInfo.LocalScale.Z); modelPart.ModelData.Skeleton.LocalTransform = OpenTK.Matrix4.CreateScale(localScale) * OpenTK.Matrix4.CreateFromQuaternion(localRotation) * OpenTK.Matrix4.CreateTranslation(localPosition); //Attach bone children bone.AttachSkeleton(modelPart.ModelData.Skeleton); model.ModelData.Skeleton.Update(); break; } } }
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(); } }
static void ParseRotationTrack(FileReader reader, Header header, Track track, AnimationGroup group) { switch (track.OpCode) { case 0x0F: //4 Singles Frame Count { for (int f = 0; f < header.FrameCount; f++) { float frame = f; float[] quat = reader.ReadSingles(4); Quaternion quaternion = new Quaternion(quat[0], quat[1], quat[2], quat[3]); group.RotateX.AddKey(frame, quaternion.X); group.RotateY.AddKey(frame, quaternion.Y); group.RotateZ.AddKey(frame, quaternion.Z); group.RotateW.AddKey(frame, quaternion.W); } } break; case 0x13: //4 Singles Custom Count { uint count = reader.ReadUInt32(); for (int f = 0; f < count; f++) { float frame = f; float[] quat = reader.ReadSingles(4); group.RotateX.AddKey(frame, quat[0]); group.RotateY.AddKey(frame, quat[1]); group.RotateZ.AddKey(frame, quat[2]); group.RotateW.AddKey(frame, quat[3]); } } break; case 0x15: //4 Singles Constant { float[] quat = reader.ReadSingles(4); group.RotateX.AddKey(0, quat[0]); group.RotateY.AddKey(0, quat[1]); group.RotateZ.AddKey(0, quat[2]); group.RotateW.AddKey(0, quat[3]); } break; case 0x16: //Short Quat Constant { //Todo this gives weird results. short[] quat = reader.ReadInt16s(4); /* group.RotateX.AddKey(0, quat[0] / 0x7FFF); * group.RotateY.AddKey(0, quat[1] / 0x7FFF); * group.RotateZ.AddKey(0, quat[2] / 0x7FFF); * group.RotateW.AddKey(0, quat[3] / 0x7FFF);*/ Console.WriteLine($"track {track.OpCode} Unknown {track.Unknown} {string.Join(",", quat)}"); } break; case 0x17: //Short X Axis Angle { var euler = new Vector3(reader.ReadInt16() / 180.0f, 0, 0) * STMath.Deg2Rad; var quat = STMath.FromEulerAngles(euler); group.RotateX.AddKey(0, quat.X); group.RotateY.AddKey(0, quat.Y); group.RotateZ.AddKey(0, quat.Z); group.RotateW.AddKey(0, quat.W); } break; case 0x18: //Short Y Axis Angle (Degrees) Frame Count { for (int f = 0; f < header.FrameCount; f++) { float frame = f; var euler = new Vector3(0, reader.ReadInt16() / 180.0f, 0) * STMath.Deg2Rad; var quat = STMath.FromEulerAngles(euler); group.RotateX.AddKey(frame, quat.X); group.RotateY.AddKey(frame, quat.Y); group.RotateZ.AddKey(frame, quat.Z); group.RotateW.AddKey(frame, quat.W); } } break; case 0x19: //Short Z Axis Angle (Degrees) Frame Count { for (int f = 0; f < header.FrameCount; f++) { float frame = f; var euler = new Vector3(0, 0, reader.ReadInt16() / 180.0f) * STMath.Deg2Rad; var quat = STMath.FromEulerAngles(euler); group.RotateX.AddKey(frame, quat.X); group.RotateY.AddKey(frame, quat.Y); group.RotateZ.AddKey(frame, quat.Z); group.RotateW.AddKey(frame, quat.W); } } break; //Todo these give weird results. /* case 0x1A: //Consta * { * ushort flag = reader.ReadUInt16(); * short[] angles = reader.ReadInt16s(2); * ushort[] param = reader.ReadUInt16s(2); * * var euler = new Vector3(reader.ReadInt16() / 180.0f, 0, 0) * STMath.Deg2Rad; * var quat = STMath.FromEulerAngles(euler); * group.RotateX.AddKey(0, quat.X); * group.RotateY.AddKey(0, quat.Y); * group.RotateZ.AddKey(0, quat.Z); * group.RotateW.AddKey(0, quat.W); * } * break; * case 0x1B: * { * ushort flag = reader.ReadUInt16(); * // short[] quat = reader.ReadInt16s(4); * * var euler = new Vector3(0, reader.ReadInt16() / 180.0f, 0) * STMath.Deg2Rad; * var quat = STMath.FromEulerAngles(euler); * group.RotateX.AddKey(0, quat.X); * group.RotateY.AddKey(0, quat.Y); * group.RotateZ.AddKey(0, quat.Z); * group.RotateW.AddKey(0, quat.W); * } * break; * case 0x1C: * { * ushort flag = reader.ReadUInt16(); * // short[] quat = reader.ReadInt16s(4); * * var euler = new Vector3(0, 0, reader.ReadInt16() / 180.0f) * STMath.Deg2Rad; * var quat = STMath.FromEulerAngles(euler); * group.RotateX.AddKey(0, quat.X); * group.RotateY.AddKey(0, quat.Y); * group.RotateZ.AddKey(0, quat.Z); * group.RotateW.AddKey(0, quat.W); * } * break;*/ default: Console.WriteLine($"Unknown Op Code! Track {track.Index} Type {track.Type} OpCode {track.OpCode}"); break; } }