private void ImportAnimation(Assimp.Node node, GameObject go, Quaternion cumulRotation) { Assimp.Animation animation = scene.Animations[0]; if ((GlobalState.Animation.fps / (float)animation.TicksPerSecond) * animation.DurationInTicks > GlobalState.Animation.EndFrame) { GlobalState.Animation.EndFrame = Mathf.CeilToInt(GlobalState.Animation.fps / (float)animation.TicksPerSecond * (float)animation.DurationInTicks) + 1; } Assimp.NodeAnimationChannel nodeChannel = animation.NodeAnimationChannels.Find(x => x.NodeName == node.Name); if (nodeChannel == null) { nodeChannel = animation.NodeAnimationChannels.Find(x => x.NodeName.Split('_')[0] == node.Name); } if (null != nodeChannel) { if (nodeChannel.PositionKeyCount < 2 && nodeChannel.RotationKeyCount < 2) { return; } AnimationSet animationSet = new AnimationSet(go); animationSet.ComputeCache(); if (nodeChannel.PositionKeyCount > 1 || nodeChannel.RotationKeyCount == nodeChannel.PositionKeyCount) { foreach (Assimp.VectorKey vectorKey in nodeChannel.PositionKeys) { int frame = Mathf.CeilToInt((float)vectorKey.Time * GlobalState.Animation.fps / (float)animation.TicksPerSecond) + 1; animationSet.curves[AnimatableProperty.PositionX].AddKey(new AnimationKey(frame, vectorKey.Value.X, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.PositionY].AddKey(new AnimationKey(frame, vectorKey.Value.Y, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.PositionZ].AddKey(new AnimationKey(frame, vectorKey.Value.Z, Interpolation.Bezier)); } } foreach (Assimp.VectorKey vectorKey in nodeChannel.ScalingKeys) { int frame = Mathf.CeilToInt((float)vectorKey.Time * GlobalState.Animation.fps / (float)animation.TicksPerSecond) + 1; animationSet.curves[AnimatableProperty.ScaleX].AddKey(new AnimationKey(frame, vectorKey.Value.X, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.ScaleY].AddKey(new AnimationKey(frame, vectorKey.Value.Y, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.ScaleZ].AddKey(new AnimationKey(frame, vectorKey.Value.Z, Interpolation.Bezier)); } Vector3 previousRotation = Vector3.zero; foreach (Assimp.QuaternionKey quaternionKey in nodeChannel.RotationKeys) { int frame = Mathf.RoundToInt((float)quaternionKey.Time * GlobalState.Animation.fps / (float)animation.TicksPerSecond) + 1; Quaternion uQuaternion = new Quaternion(quaternionKey.Value.X, quaternionKey.Value.Y, quaternionKey.Value.Z, quaternionKey.Value.W); uQuaternion = cumulRotation * uQuaternion * Quaternion.Inverse(cumulRotation); Vector3 eulerValue = uQuaternion.eulerAngles; eulerValue.x = previousRotation.x + Mathf.DeltaAngle(previousRotation.x, eulerValue.x); eulerValue.y = previousRotation.y + Mathf.DeltaAngle(previousRotation.y, eulerValue.y); eulerValue.z = previousRotation.z + Mathf.DeltaAngle(previousRotation.z, eulerValue.z); animationSet.curves[AnimatableProperty.RotationX].AddKey(new AnimationKey(frame, eulerValue.x, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.RotationY].AddKey(new AnimationKey(frame, eulerValue.y, Interpolation.Bezier)); animationSet.curves[AnimatableProperty.RotationZ].AddKey(new AnimationKey(frame, eulerValue.z, Interpolation.Bezier)); previousRotation = eulerValue; } GlobalState.Animation.SetObjectAnimations(go, animationSet); } }
private Track GenerateTrack(Assimp.NodeAnimationChannel channel, Bone bone) { Track track = new Track(); track.Translation = GenerateTranslationTrack(channel.PositionKeys, bone); track.Rotation = GenerateRotationTrack(channel.RotationKeys, bone); track.Scale = GenerateScaleTrack(channel.ScalingKeys, bone); return(track); }
public static int FindPosition(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { for (int i = 0; i < nodeAnim.PositionKeyCount - 1; i++) { if (animationTime < (float)nodeAnim.PositionKeys[i + 1].Time) { return(i); } } return(0); }
public Assimp.Animation assimpExport(ref Assimp.Scene scn) { Assimp.Animation asAnim = new Assimp.Animation(); asAnim.Name = Anim; //Make sure keyframe data is loaded from the files if (!loaded) { fetchAnimMetaData(); loaded = true; } asAnim.TicksPerSecond = 60; asAnim.DurationInTicks = animMeta.FrameCount; float time_interval = 1.0f / (float)asAnim.TicksPerSecond; //Add Node-Bone Channels for (int i = 0; i < animMeta.NodeCount; i++) { string name = animMeta.NodeData[i].Node; Assimp.NodeAnimationChannel mChannel = new Assimp.NodeAnimationChannel(); mChannel.NodeName = name; //mChannel.PostState = Assimp.AnimationBehaviour.Linear; //mChannel.PreState = Assimp.AnimationBehaviour.Linear; //Export Keyframe Data for (int j = 0; j < animMeta.FrameCount; j++) { //Position Assimp.VectorKey vk = new Assimp.VectorKey(j * time_interval, MathUtils.convertVector(animMeta.anim_positions[name][j])); mChannel.PositionKeys.Add(vk); //Rotation Assimp.QuaternionKey qk = new Assimp.QuaternionKey(j * time_interval, MathUtils.convertQuaternion(animMeta.anim_rotations[name][j])); mChannel.RotationKeys.Add(qk); //Scale Assimp.VectorKey sk = new Assimp.VectorKey(j * time_interval, MathUtils.convertVector(animMeta.anim_scales[name][j])); mChannel.ScalingKeys.Add(sk); } asAnim.NodeAnimationChannels.Add(mChannel); } return(asAnim); }
private static uint FindPosition(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { for (uint i = 0; i < nodeAnim.PositionKeyCount - 1; i++) { if (animationTime < (float)nodeAnim.PositionKeys[i + 1].Time) { return(i); } } //assert(0); return(0); }
private static Assimp.NodeAnimationChannel FineNodeAnim(Assimp.Animation animation, string nodeName) { Assimp.NodeAnimationChannel channel = null; for (int i = 0; i < animation.NodeAnimationChannelCount; i++) { var nodeAnim = animation.NodeAnimationChannels[i]; if (nodeAnim.NodeName == nodeName) { channel = nodeAnim; break; } } return(channel); }
private static uint FindScaling(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { //assert(pNodeAnim->mNumScalingKeys > 0); for (uint i = 0; i < nodeAnim.ScalingKeyCount - 1; i++) { if (animationTime < (float)nodeAnim.ScalingKeys[i + 1].Time) { return(i); } } //assert(0); return(0); }
public static int FindRotation(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { //assert(pNodeAnim->mNumRotationKeys > 0); for (int i = 0; i < nodeAnim.RotationKeyCount - 1; i++) { if (animationTime < (float)nodeAnim.RotationKeys[i + 1].Time) { return(i); } } //assert(0); return(0); }
public static Assimp.Vector3D CalcInterpolatedScaling(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { if (nodeAnim.ScalingKeyCount == 1) { return(nodeAnim.ScalingKeys[0].Value); } Assimp.Vector3D result; int index = FindScaling(animationTime, nodeAnim); int nextIndex = (index + 1); float deltaTime = (float)(nodeAnim.ScalingKeys[nextIndex].Time - nodeAnim.ScalingKeys[index].Time); float factor = (animationTime - (float)nodeAnim.ScalingKeys[index].Time) / deltaTime; Assimp.Vector3D start = nodeAnim.ScalingKeys[index].Value; Assimp.Vector3D end = nodeAnim.ScalingKeys[nextIndex].Value; Assimp.Vector3D delta = end - start; result = start + factor * delta; return(result); }
private static Assimp.Vector3D CalcInterpolatedScaling(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { Assimp.Vector3D Out; if (nodeAnim.ScalingKeyCount == 1) { Out = nodeAnim.ScalingKeys[0].Value; return(Out); } uint ScalingIndex = FindScaling(animationTime, nodeAnim); uint NextScalingIndex = (ScalingIndex + 1); //assert(NextScalingIndex < nodeAnim->mNumScalingKeys); float DeltaTime = (float)(nodeAnim.ScalingKeys[NextScalingIndex].Time - nodeAnim.ScalingKeys[ScalingIndex].Time); float Factor = (animationTime - (float)nodeAnim.ScalingKeys[ScalingIndex].Time) / DeltaTime; //assert(Factor >= 0.0f && Factor <= 1.0f); Assimp.Vector3D Start = nodeAnim.ScalingKeys[ScalingIndex].Value; Assimp.Vector3D End = nodeAnim.ScalingKeys[NextScalingIndex].Value; Assimp.Vector3D Delta = End - Start; Out = Start + Factor * Delta; return(Out); }
private static Assimp.Vector3D CalcInterpolatedPosition(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { Assimp.Vector3D result; if (nodeAnim.PositionKeyCount == 1) { result = nodeAnim.PositionKeys[0].Value; return(result); } uint index = FindPosition(animationTime, nodeAnim); uint nextIndex = (index + 1); //assert(NextPositionIndex < nodeAnim->mNumPositionKeys); float deltaTime = (float)(nodeAnim.PositionKeys[nextIndex].Time - nodeAnim.PositionKeys[index].Time); float factor = (animationTime - (float)nodeAnim.PositionKeys[index].Time) / deltaTime; //assert(Factor >= 0.0f && Factor <= 1.0f); Assimp.Vector3D start = nodeAnim.PositionKeys[index].Value; Assimp.Vector3D end = nodeAnim.PositionKeys[nextIndex].Value; Assimp.Vector3D delta = end - start; result = start + factor * delta; return(result); }
private static void ReadNodeHeirarchy(float animationTime, Assimp.Node node, Assimp.Animation animation, mat4 parentTransform, AllBoneInfos allBones) { string nodeName = node.Name; mat4 nodeTransform = node.Transform.ToMat4(); Assimp.NodeAnimationChannel nodeAnim = FineNodeAnim(animation, nodeName); if (nodeAnim != null) { mat4 mat = mat4.identity(); // Interpolate scaling and generate scaling transformation matrix Assimp.Vector3D Scaling = CalcInterpolatedScaling(animationTime, nodeAnim); mat4 ScalingM = glm.scale(mat, new vec3(Scaling.X, Scaling.Y, Scaling.Z)); // Interpolate rotation and generate rotation transformation matrix Assimp.Quaternion RotationQ = CalcInterpolatedRotation(animationTime, nodeAnim); mat4 RotationM = new Assimp.Matrix4x4(RotationQ.GetMatrix()).ToMat4(); // Interpolate translation and generate translation transformation matrix Assimp.Vector3D Translation = CalcInterpolatedPosition(animationTime, nodeAnim); mat4 TranslationM = glm.translate(mat4.identity(), new vec3(Translation.X, Translation.Y, Translation.Z)); // Combine the above transformations nodeTransform = TranslationM * RotationM * ScalingM; } mat4 transform = parentTransform * nodeTransform; if (allBones.nameIndexDict.ContainsKey(nodeName)) { uint BoneIndex = allBones.nameIndexDict[nodeName]; allBones.boneInfos[BoneIndex].finalTransformation = transform; } for (int i = 0; i < node.ChildCount; i++) { ReadNodeHeirarchy(animationTime, node.Children[i], animation, transform, allBones); } }
public BCK(Assimp.Animation src_anim, List <Rigging.Bone> bone_list) { Name = src_anim.Name; LoopMode = LoopMode.Loop; RotationFrac = 0; Duration = (short)(src_anim.DurationInTicks * 30.0f); Tracks = new Track[bone_list.Count]; for (int i = 0; i < bone_list.Count; i++) { Assimp.NodeAnimationChannel node = src_anim.NodeAnimationChannels.Find(x => x.NodeName == bone_list[i].Name); if (node == null) { Tracks[i] = Track.Identity(bone_list[i].TransformationMatrix, Duration); } else { Tracks[i] = GenerateTrack(node, bone_list[i]); } } }
public static Assimp.Scene ToAssimpScene(RwAnimationNode animation, RwFrameListNode frameList) { var aiScene = new Assimp.Scene(); // RootNode var rootFrame = frameList[0]; var aiRootNode = new Assimp.Node("RootNode", null); aiRootNode.Transform = new Assimp.Matrix4x4(rootFrame.Transform.M11, rootFrame.Transform.M21, rootFrame.Transform.M31, rootFrame.Transform.M41, rootFrame.Transform.M12, rootFrame.Transform.M22, rootFrame.Transform.M32, rootFrame.Transform.M42, rootFrame.Transform.M13, rootFrame.Transform.M23, rootFrame.Transform.M33, rootFrame.Transform.M43, rootFrame.Transform.M14, rootFrame.Transform.M24, rootFrame.Transform.M34, rootFrame.Transform.M44); aiScene.RootNode = aiRootNode; for (int i = 1; i < frameList.Count; i++) { var frame = frameList[i]; var frameName = "_" + frame.HAnimFrameExtensionNode.NameId; Assimp.Node aiParentNode = null; if (frame.Parent != null) { string parentName = "RootNode"; if (frame.Parent.HasHAnimExtension) { parentName = "_" + frame.Parent.HAnimFrameExtensionNode.NameId; } aiParentNode = aiRootNode.FindNode(parentName); } var aiNode = new Assimp.Node(frameName, aiParentNode); aiNode.Transform = new Assimp.Matrix4x4(frame.Transform.M11, frame.Transform.M21, frame.Transform.M31, frame.Transform.M41, frame.Transform.M12, frame.Transform.M22, frame.Transform.M32, frame.Transform.M42, frame.Transform.M13, frame.Transform.M23, frame.Transform.M33, frame.Transform.M43, frame.Transform.M14, frame.Transform.M24, frame.Transform.M34, frame.Transform.M44); aiParentNode.Children.Add(aiNode); } var aiAnimation = new Assimp.Animation(); aiAnimation.TicksPerSecond = FPS; aiAnimation.DurationInTicks = animation.Duration * FPS; aiAnimation.Name = "Take 01"; aiScene.Animations.Add(aiAnimation); var keyFrameToNodeAnimationChannel = new Dictionary <RwKeyFrame, Assimp.NodeAnimationChannel>(); for (var i = 0; i < frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes.Count; i++) { var hierarchyNode = frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes[i]; var keyFrame = animation.KeyFrames[i]; // Create channel var aiNodeAnimationChannel = new Assimp.NodeAnimationChannel(); aiNodeAnimationChannel.NodeName = "_" + hierarchyNode.NodeId; aiNodeAnimationChannel.PostState = Assimp.AnimationBehaviour.Default; aiNodeAnimationChannel.PreState = Assimp.AnimationBehaviour.Default; aiNodeAnimationChannel.PositionKeys.Add(new Assimp.VectorKey(0, new Assimp.Vector3D(keyFrame.Translation.X, keyFrame.Translation.Y, keyFrame.Translation.Z))); aiNodeAnimationChannel.RotationKeys.Add(new Assimp.QuaternionKey(0, new Assimp.Quaternion(keyFrame.Rotation.X, keyFrame.Rotation.Y, keyFrame.Rotation.Z, keyFrame.Rotation.W))); aiNodeAnimationChannel.ScalingKeys.Add(new Assimp.VectorKey(0, new Assimp.Vector3D(1, 1, 1))); aiNodeAnimationChannel.ScalingKeys.Add(new Assimp.VectorKey(Math.Round(animation.Duration * FPS), new Assimp.Vector3D(1, 1, 1))); keyFrameToNodeAnimationChannel[keyFrame] = aiNodeAnimationChannel; aiAnimation.NodeAnimationChannels.Add(aiNodeAnimationChannel); } for (int i = frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes.Count; i < animation.KeyFrames.Count; i++) { var keyFrame = animation.KeyFrames[i]; // Add keys var aiNodeAnimationChannel = keyFrameToNodeAnimationChannel[keyFrame.Previous]; aiNodeAnimationChannel.PositionKeys.Add(new Assimp.VectorKey(keyFrame.Time * FPS, new Assimp.Vector3D(keyFrame.Translation.X, keyFrame.Translation.Y, keyFrame.Translation.Z))); aiNodeAnimationChannel.RotationKeys.Add(new Assimp.QuaternionKey(keyFrame.Time * FPS, new Assimp.Quaternion(keyFrame.Rotation.X, keyFrame.Rotation.Y, keyFrame.Rotation.Z, keyFrame.Rotation.W))); keyFrameToNodeAnimationChannel[keyFrame] = aiNodeAnimationChannel; } return(aiScene); }
private static Assimp.Quaternion CalcInterpolatedRotation(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { Assimp.Quaternion result; // we need at least two values to interpolate... if (nodeAnim.RotationKeyCount == 1) { result = nodeAnim.RotationKeys[0].Value; return(result); } uint index = FindRotation(animationTime, nodeAnim); uint nextIndex = (index + 1); //assert(NextRotationIndex < nodeAnim.RotationKeyCount); float deltaTime = (float)(nodeAnim.RotationKeys[nextIndex].Time - nodeAnim.RotationKeys[index].Time); float factor = (animationTime - (float)nodeAnim.RotationKeys[index].Time) / deltaTime; //assert(Factor >= 0.0f && Factor <= 1.0f); Assimp.Quaternion start = nodeAnim.RotationKeys[index].Value; Assimp.Quaternion end = nodeAnim.RotationKeys[nextIndex].Value; result = Interpolate(start, end, factor); result.Normalize(); return(result); }
public override void Export(Model model, Motion motion, string filepath, Config config) { var aiScene = AssimpModelExporter.Instance.ConvertToScene(model, new AssimpModelExporter.Config()); var aiAnimation = new Assimp.Animation { DurationInTicks = motion.Duration, TicksPerSecond = 30 }; var aiChannelLookup = new Dictionary <int, Assimp.NodeAnimationChannel>(); for (var i = 0; i < model.Nodes.Count; i++) { var node = model.Nodes[i]; aiAnimation.NodeAnimationChannels.Add(aiChannelLookup[i] = new Assimp.NodeAnimationChannel() { NodeName = node.Name.Replace(" ", "_"), }); } var aiChannelLookupRev = new Dictionary <Assimp.NodeAnimationChannel, int>(); foreach (var lookup in aiChannelLookup) { aiChannelLookupRev[lookup.Value] = lookup.Key; } foreach (var controller in motion.Controllers) { if (!aiChannelLookup.TryGetValue(controller.NodeIndex, out var aiChannel)) { throw new InvalidOperationException(); } switch (controller.Type) { case ControllerType.Position: foreach (var key in controller.Keys) { switch (key) { case Vector3Key positionKey: aiChannel.PositionKeys.RemoveAll(x => x.Time == positionKey.Time); aiChannel.PositionKeys.Add(new Assimp.VectorKey(positionKey.Time, positionKey.Value.ToAssimp())); break; } } break; case ControllerType.Type1: break; case ControllerType.Scale: foreach (var key in controller.Keys) { switch (key) { case Vector3Key scaleKey: aiChannel.ScalingKeys.RemoveAll(x => x.Time == scaleKey.Time); aiChannel.ScalingKeys.Add(new Assimp.VectorKey(scaleKey.Time, scaleKey.Value.ToAssimp())); break; } } break; case ControllerType.Rotation: foreach (var key in controller.Keys) { switch (key) { case QuaternionKey rotationKey: aiChannel.RotationKeys.RemoveAll(x => x.Time == rotationKey.Time); aiChannel.RotationKeys.Add(new Assimp.QuaternionKey(rotationKey.Time, Quaternion.Inverse(rotationKey.Value).ToAssimp())); break; } } break; case ControllerType.Morph: break; case ControllerType.Type5: break; case ControllerType.Type8: break; } } foreach (var aiChannel in aiAnimation.NodeAnimationChannels) { if (aiChannel.PositionKeys.Count == 0 || aiChannel.PositionKeys[0].Time != 0) { aiChannel.PositionKeys.Insert(0, new Assimp.VectorKey(0, model.Nodes[aiChannelLookupRev[aiChannel]].Position.ToAssimp())); } if (aiChannel.RotationKeys.Count == 0 || aiChannel.RotationKeys[0].Time != 0) { var rotation = model.Nodes[aiChannelLookupRev[aiChannel]].Rotation; aiChannel.RotationKeys.Insert(0, new Assimp.QuaternionKey(0, Quaternion.Inverse(Quaternion.CreateFromRotationMatrix((Matrix4x4.CreateRotationX(rotation.X) * Matrix4x4.CreateRotationY(rotation.Y) * Matrix4x4.CreateRotationZ(rotation.Z)))).ToAssimp())); } if (aiChannel.ScalingKeys.Count == 0 || aiChannel.ScalingKeys[0].Time != 0) { aiChannel.ScalingKeys.Insert(0, new Assimp.VectorKey(0, model.Nodes[aiChannelLookupRev[aiChannel]].Scale.ToAssimp())); } var keyCount = Math.Max(1, Math.Max(aiChannel.PositionKeyCount, Math.Max(aiChannel.RotationKeyCount, aiChannel.ScalingKeyCount))); if (aiChannel.PositionKeyCount < keyCount) { var lastKey = aiChannel.PositionKeyCount == 0 ? new Assimp.VectorKey(-1, model.Nodes[aiChannelLookupRev[aiChannel]].Position.ToAssimp()) : aiChannel.PositionKeys[aiChannel.PositionKeyCount - 1]; while (aiChannel.PositionKeyCount < keyCount) { lastKey.Time++; if (lastKey.Time > aiAnimation.DurationInTicks) { break; } aiChannel.PositionKeys.Add(lastKey); } } if (aiChannel.RotationKeyCount < keyCount) { var rotation = model.Nodes[aiChannelLookupRev[aiChannel]].Rotation; var lastKey = aiChannel.RotationKeyCount == 0 ? new Assimp.QuaternionKey(-1, Quaternion.Inverse(Quaternion.CreateFromRotationMatrix((Matrix4x4.CreateRotationX(rotation.X) * Matrix4x4.CreateRotationY(rotation.Y) * Matrix4x4.CreateRotationZ(rotation.Z)))).ToAssimp()) : aiChannel.RotationKeys[aiChannel.RotationKeyCount - 1]; while (aiChannel.RotationKeyCount < keyCount) { lastKey.Time++; if (lastKey.Time > aiAnimation.DurationInTicks) { break; } aiChannel.RotationKeys.Add(lastKey); } } if (aiChannel.ScalingKeyCount < keyCount) { var lastKey = aiChannel.ScalingKeyCount == 0 ? new Assimp.VectorKey(-1, model.Nodes[aiChannelLookupRev[aiChannel]].Scale.ToAssimp()) : aiChannel.ScalingKeys[aiChannel.ScalingKeyCount - 1]; while (aiChannel.ScalingKeyCount < keyCount) { lastKey.Time++; if (lastKey.Time > aiAnimation.DurationInTicks) { break; } aiChannel.ScalingKeys.Add(lastKey); } } } aiScene.Animations.Add(aiAnimation); //aiScene.ExportColladaFile( filepath ); using (var aiContext = new Assimp.AssimpContext()) aiContext.ExportFile(aiScene, filepath, "collada", Assimp.PostProcessSteps.FlipUVs); }
public static Assimp.Quaternion CalcInterpolatedRotation(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { if (nodeAnim.RotationKeyCount == 1) { return(nodeAnim.RotationKeys[0].Value); } Assimp.Quaternion result; int index = FindRotation(animationTime, nodeAnim); int nextIndex = (index + 1); float deltaTime = (float)(nodeAnim.RotationKeys[nextIndex].Time - nodeAnim.RotationKeys[index].Time); float factor = (animationTime - (float)nodeAnim.RotationKeys[index].Time) / deltaTime; Assimp.Quaternion start = nodeAnim.RotationKeys[index].Value; Assimp.Quaternion end = nodeAnim.RotationKeys[nextIndex].Value; result = Interpolate(start, end, factor); result.Normalize(); return(result); }
private static Assimp.Quaternion CalcInterpolatedRotation(float animationTime, Assimp.NodeAnimationChannel nodeAnim) { Assimp.Quaternion Out; // we need at least two values to interpolate... if (nodeAnim.RotationKeyCount == 1) { Out = nodeAnim.RotationKeys[0].Value; return(Out); } uint RotationIndex = FindRotation(animationTime, nodeAnim); uint NextRotationIndex = (RotationIndex + 1); //assert(NextRotationIndex < nodeAnim.RotationKeyCount); float DeltaTime = (float)(nodeAnim.RotationKeys[NextRotationIndex].Time - nodeAnim.RotationKeys[RotationIndex].Time); float Factor = (animationTime - (float)nodeAnim.RotationKeys[RotationIndex].Time) / DeltaTime; //assert(Factor >= 0.0f && Factor <= 1.0f); Assimp.Quaternion StartRotationQ = nodeAnim.RotationKeys[RotationIndex].Value; Assimp.Quaternion EndRotationQ = nodeAnim.RotationKeys[NextRotationIndex].Value; Out = Interpolate(StartRotationQ, EndRotationQ, Factor); Out.Normalize(); return(Out); }