protected override FbxAnimStack GenerateFbx() { HavokAnimationData anim = Souls.dsAnimation; IDictionary <int, FrameData> frameDatas = ExtractAnimationData(anim); var animStack = FbxAnimStack.Create(Scene, anim.Name + "_AnimStack"); animStack.SetLocalTimeSpan(new FbxTimeSpan(FbxTime.FromFrame(0), FbxTime.FromFrame(anim.FrameCount))); FbxAnimLayer animLayer = FbxAnimLayer.Create(animStack, "Layer0"); animStack.AddMember(animLayer); IDictionary <int, AnimExportHelper> boneHelpers = new Dictionary <int, AnimExportHelper>(); foreach (DsBoneData boneData in Souls.skeleton.boneDatas) { boneData.exportData.FbxNode.LclTranslation.GetCurveNode(animLayer, true); boneData.exportData.FbxNode.LclRotation.GetCurveNode(animLayer, true); boneData.exportData.FbxNode.LclScaling.GetCurveNode(animLayer, true); boneHelpers.Add(boneData.exportData.SoulsData.HkxBoneIndex, new AnimExportHelper( animLayer, boneData.exportData.FbxNode.LclTranslation, boneData.exportData.FbxNode.LclRotation, boneData.exportData.FbxNode.LclScaling ) ); } foreach (var frameData in frameDatas) { FbxTime time = FbxTime.FromFrame(frameData.Key); foreach (var boneData in frameData.Value.boneDatas) { int hkxBoneIndex = boneData.hkxBoneIndex; var newBlendableTransform = boneData.transform; AnimExportHelper animExportHelper = boneHelpers[hkxBoneIndex]; var euler = new Quaternion(newBlendableTransform.Rotation.X, newBlendableTransform.Rotation.Y, newBlendableTransform.Rotation.Z, newBlendableTransform.Rotation.W).QuaternionToEuler(); animExportHelper.translation.AddPoint(time, newBlendableTransform.Translation); animExportHelper.rotation.AddPoint(time, euler); animExportHelper.scale.AddPoint(time, newBlendableTransform.Scale); } } foreach (AnimExportHelper helper in boneHelpers.Values) { helper.translation.Finish(); helper.rotation.Finish(); helper.scale.Finish(); } return(null); }
public static void ExportToFile(HavokAnimationData anim, string filePath, string assimpFileFormatStr) { var scene = ExportToScene(anim); using (var x = new AssimpContext()) { x.ExportFile(scene, filePath, assimpFileFormatStr); } }
protected NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton skeleton, NewAnimationContainer container) { this.data = data; ParentContainer = container; Skeleton = skeleton; lock (_lock_boneMatrixStuff) { blendableTransforms = new NewBlendableTransform[skeleton.HkxSkeleton.Count]; } RotMatrixAtStartOfAnim = ParentContainer.MODEL.CurrentRootMotionRotation; }
public NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton_HKX skeleton, NewAnimationContainer container) { this.data = data; ParentContainer = container; Skeleton = skeleton; lock (_lock_boneMatrixStuff) { blendableTransforms = new NewBlendableTransform[skeleton.HkxSkeleton.Count]; } RootMotion = new RootMotionDataPlayer(data.RootMotion); }
protected NewHavokAnimation(HavokAnimationData data, NewAnimSkeleton skeleton, NewAnimationContainer container) { this.data = data; ParentContainer = container; Skeleton = skeleton; lock (_lock_boneMatrixStuff) { blendableTransforms = new List <NewBlendableTransform>(); for (int i = 0; i < skeleton.HkxSkeleton.Count; i++) { blendableTransforms.Add(NewBlendableTransform.Identity); } } RotMatrixAtStartOfAnim = ParentContainer.MODEL.CurrentRootMotionRotation; }
private Matrix4x4 GetMatrix(int hkxBoneIndex, float frameIndex) { HavokAnimationData anim = Souls.dsAnimation; NewBlendableTransform newBlendableTransform = anim.GetBlendableTransformOnFrame(hkxBoneIndex, frameIndex); var currentTransformMatrix = newBlendableTransform.GetMatrix(); int parentIndex = Souls.dsAnimation.hkaSkeleton.ParentIndices[hkxBoneIndex].data; if (parentIndex >= 0) { currentTransformMatrix *= GetMatrix(parentIndex, frameIndex); } else { //var rootMotion = rootMotionCache.GetRootMotionOnFrame((int)frameIndex); //currentTransformMatrix *= Microsoft.Xna.Framework.Matrix.CreateRotationY(rootMotion.W); //currentTransformMatrix *= Microsoft.Xna.Framework.Matrix.CreateTranslation(rootMotion.X, rootMotion.Y, rootMotion.Z); } return(currentTransformMatrix); }
private IDictionary <int, FrameData> ExtractAnimationData(HavokAnimationData anim) { IDictionary <int, FrameData> frameDatas = new Dictionary <int, FrameData>(); try { for (int frameIndex = 0; frameIndex < Souls.dsAnimation.FrameCount; ++frameIndex) { var frameBoneDatas = new List <FrameData.FrameBoneData>(); FrameData data = new FrameData() { boneDatas = frameBoneDatas, frameIndex = frameIndex }; Func <DsBoneData, Matrix4x4> calculateTransform = bone => { if (bone.parent == null) { return(Matrix4x4.Identity); } var calculatedMatrix = GetMatrix(bone.exportData.SoulsData.HkxBoneIndex, frameIndex); var hackPreMatrix = Matrix4x4.CreateRotationZ((float)(-Math.PI / 2)); // * Matrix4x4.CreateRotationY((float)(-Math.PI / 2)); ; // Microsoft.Xna.Framework.Matrix.CreateScale(-1, 1, 1); var hackPostMatrix = Matrix4x4.Identity; // Matrix4x4.CreateScale(-1, 1, 1); // Matrix4x4.CreateScale(-1,1,1); // * Matrix4x4.CreateRotationY((float)(Math.PI)); // Matrix4x4.CreateScale(1, 1, -1); var transformedMatrix = hackPreMatrix * calculatedMatrix * hackPostMatrix; var btr = new NewBlendableTransform(transformedMatrix); btr.Translation.Z = -btr.Translation.Z; btr.Rotation.X = -btr.Rotation.X; btr.Rotation.Y = -btr.Rotation.Y; return(btr.GetMatrix()); }; foreach (var bone in Souls.skeleton.boneDatas) { var boneData111 = new FrameData.FrameBoneData() { hkxBoneIndex = bone.exportData.SoulsData.HkxBoneIndex }; var calculatedMatrix = calculateTransform(bone); var hackNewBlendableMatrix = calculatedMatrix; if (bone.parent != null) { Matrix4x4 parentMatrix = calculateTransform(bone.parent); if (Matrix4x4.Invert(parentMatrix, out var inverted)) { hackNewBlendableMatrix *= inverted; } else { throw new Exception(); } } else { Func <Matrix4x4> getRefMatrix = () => { if (Souls.animRefFrame == null) { return(Matrix4x4.Identity); } return(Matrix4x4.CreateWorld(Vector3.Zero, Souls.animRefFrame.Forward.ToVector3(), Souls.animRefFrame.Up.ToVector3())); }; var refMatrix = Matrix4x4.Identity; // getRefMatrix(); Matrix4x4 additionalPostTransformation = refMatrix; // this is a root bone if (anim.RootMotion != null) { var rootMotion = anim.RootMotion.ExtractRootMotion(0, anim.Duration * (((float)frameIndex / anim.FrameCount))); rootMotion.positionChange.Z = -rootMotion.positionChange.Z; Matrix4x4 rootMotionTransformation = Matrix4x4.CreateRotationY(rootMotion.directionChange) * Matrix4x4.CreateTranslation(rootMotion.positionChange); additionalPostTransformation *= rootMotionTransformation; } hackNewBlendableMatrix *= additionalPostTransformation; } var newBlendableTransform = new NewBlendableTransform(hackNewBlendableMatrix); int hkxBoneIndex = bone.exportData.SoulsData.HkxBoneIndex; boneData111.hkxBoneIndex = hkxBoneIndex; boneData111.transform = newBlendableTransform; frameBoneDatas.Add(boneData111); } frameDatas.Add(frameIndex, data); } return(frameDatas); } catch (Exception ex) { throw new AnimationExportException("An exception occured while exporting animations!", ex); } }
public static Scene ExportToScene(HavokAnimationData anim) { var scene = new Scene(); scene.RootNode = new Node("scene_root"); scene.RootNode.Metadata["FrameRate"] = new Metadata.Entry(MetaDataType.Int32, 14); scene.RootNode.Metadata["TimeSpanStart"] = new Metadata.Entry(MetaDataType.UInt64, (ulong)0); scene.RootNode.Metadata["TimeSpanStop"] = new Metadata.Entry(MetaDataType.UInt64, (ulong)0); scene.RootNode.Metadata["CustomFrameRate"] = new Metadata.Entry(MetaDataType.Float, 1f / anim.FrameDuration); scene.RootNode.Metadata["FrontAxisSign"] = new Metadata.Entry(MetaDataType.Int32, -1); scene.RootNode.Metadata["OriginalUnitScaleFactor"] = new Metadata.Entry(MetaDataType.Int32, 100); scene.RootNode.Metadata["UnitScaleFactor"] = new Metadata.Entry(MetaDataType.Int32, 100); var a = new Assimp.Animation(); a.DurationInTicks = anim.Duration * 30; a.TicksPerSecond = 30; a.Name = anim.Name; List <Node> animTrackNodes = new List <Node>(); for (int i = 0; i < anim.TransformTrackIndexToHkxBoneMap.Length; i++) { int boneIndex = anim.TransformTrackIndexToHkxBoneMap[i]; if (boneIndex < 0 || boneIndex > anim.hkaSkeleton.Bones.Capacity) { continue; } string trackName = anim.hkaSkeleton.Bones[boneIndex].Name.GetString(); var animTrack = new NodeAnimationChannel(); animTrack.NodeName = trackName; for (int f = 0; f < anim.FrameCount; f++) { var t = anim.GetTransformOnFrame(i, f, enableLooping: false); animTrack.PositionKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(t.Translation.X * -100, t.Translation.Y * 100, t.Translation.Z * 100))); animTrack.ScalingKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(t.Scale.X, t.Scale.Y, t.Scale.Z))); var q = t.Rotation; //q.X *= -1; //q.Y *= -1; //q.Z *= -1; //q.W *= -1; q = SapMath.MirrorQuat(q); //q.X *= -1; //q.Y *= -1; //q.Z *= -1; //q.W *= -1; animTrack.RotationKeys.Add(new QuaternionKey(1.0 * f * anim.FrameDuration, new Quaternion(q.W, q.X, q.Y, q.Z))); } a.NodeAnimationChannels.Add(animTrack); var fakeNode = new Node(trackName); animTrackNodes.Add(fakeNode); } List <Node> topLevelTrackNodes = new List <Node>(); for (int i = 0; i < animTrackNodes.Count; i++) { var hkxBoneIndex = anim.TransformTrackIndexToHkxBoneMap[i]; var parentBoneIndex = anim.hkaSkeleton.ParentIndices[hkxBoneIndex].data; if (parentBoneIndex >= 0) { var parentTrackIndex = anim.HkxBoneIndexToTransformTrackMap[parentBoneIndex]; if (parentTrackIndex >= 0) { animTrackNodes[parentTrackIndex].Children.Add(animTrackNodes[i]); } } else { topLevelTrackNodes.Add(animTrackNodes[i]); } } var actualRootNode = new Node("root"); if (anim.RootMotion != null) { var animTrack = new NodeAnimationChannel(); animTrack.NodeName = actualRootNode.Name; for (int f = 0; f < anim.FrameCount; f++) { var rootMotionOnFrame = anim.RootMotion.GetSampleClamped(f * anim.FrameDuration); animTrack.PositionKeys.Add(new VectorKey(1.0 * f * anim.FrameDuration, new Vector3D(rootMotionOnFrame.X * -100, rootMotionOnFrame.Y * 100, rootMotionOnFrame.Z * 100))); var q = NQuaternion.CreateFromRotationMatrix(NMatrix.CreateRotationY(rootMotionOnFrame.W)); animTrack.RotationKeys.Add(new QuaternionKey(1.0 * f * anim.FrameDuration, new Quaternion(q.W, q.X, q.Y, q.Z))); } a.NodeAnimationChannels.Add(animTrack); } foreach (var t in topLevelTrackNodes) { actualRootNode.Children.Add(t); } scene.RootNode.Children.Add(actualRootNode); scene.Animations.Add(a); return(scene); }