public void assimpExport(ref Assimp.Scene scn) { foreach (AnimData ad in Animations) { Assimp.Animation anim = ad.assimpExport(ref scn); scn.Animations.Add(anim); } }
public Animation(Assimp.Animation animation, Bone[] bones) { // We need to repair the string the assimp wrapper gives us var cutoffIndex = animation.Name.LastIndexOf('|') + 1; mName = animation.Name.Substring(cutoffIndex); mDuration = (float)animation.DurationInTicks; mTickPerSecond = (float)animation.TicksPerSecond; mBoneKeys = new BoneKey[bones.Length]; for (var i = 0; i < animation.NodeAnimationChannelCount; i++) { // We want one additional key to store the bind pose var positionKeys = animation.NodeAnimationChannels[i].PositionKeyCount + 1; var rotationKeys = animation.NodeAnimationChannels[i].RotationKeyCount + 1; var scaleKeys = animation.NodeAnimationChannels[i].ScalingKeyCount + 1; var keyFrames = new BoneKeyFrames(positionKeys, rotationKeys, scaleKeys); // Copy the position keys for (var j = 0; j < positionKeys - 1; j++) { var position = animation.NodeAnimationChannels[i].PositionKeys[j].Value; keyFrames.mPositionKeys[j].mPosition = new Vector3(position.X, position.Y, position.Z); keyFrames.mPositionKeys[j].mTime = (float)animation.NodeAnimationChannels[i].PositionKeys[j].Time; } // Copy the position keys for (var j = 0; j < rotationKeys - 1; j++) { var quaternion = animation.NodeAnimationChannels[i].RotationKeys[j].Value; keyFrames.mRotationKeys[j].mRotation = new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W); keyFrames.mRotationKeys[j].mTime = (float)animation.NodeAnimationChannels[i].RotationKeys[j].Time; } // Copy the scale keys for (var j = 0; j < scaleKeys - 1; j++) { var scale = animation.NodeAnimationChannels[i].ScalingKeys[j].Value; keyFrames.mScaleKeys[j].mScale = new Vector3(scale.X, scale.Y, scale.Z); keyFrames.mScaleKeys[j].mTime = (float)animation.NodeAnimationChannels[i].ScalingKeys[j].Time; } // Find the bone corresponding to the NodeChannel var index = Array.FindIndex(bones, ele => ele.mName == animation.NodeAnimationChannels[i].NodeName); // Set the binding pose keyFrames.mPositionKeys[positionKeys - 1].mPosition = bones[index].mTransformation.Translation; keyFrames.mRotationKeys[rotationKeys - 1].mRotation = bones[index].mTransformation.Rotation; keyFrames.mScaleKeys[scaleKeys - 1].mScale = bones[index].mTransformation.Scale; mBoneKeys[index].mKeyFrames = keyFrames; mBoneKeys[index].mHasKeyFrames = true; } }
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); } }
public AnimEvaluator(Assimp.Animation anim) { LastTime = 0.0f; TicksPerSecond = anim.TicksPerSecond > 0.0f ? (float)anim.TicksPerSecond : 920.0f; Duration = (float)anim.DurationInTicks; Name = anim.Name; Channels = new List <AnimChannel>(); foreach (Assimp.NodeAnimationChannel channel in anim.NodeAnimationChannels) { AnimChannel nac = new AnimChannel(); List <VectorKey> pk = new List <VectorKey>(); List <QuatKey> rk = new List <QuatKey>(); List <VectorKey> sk = new List <VectorKey>(); foreach (Assimp.VectorKey k in channel.PositionKeys) { VectorKey npk = new VectorKey { Time = k.Time, Value = new OpenTK.Vector3(k.Value.X, k.Value.Y, k.Value.Z) }; pk.Add(npk); } foreach (Assimp.QuaternionKey k in channel.RotationKeys) { QuatKey nrk = new QuatKey { Time = k.Time, Value = new OpenTK.Quaternion(k.Value.X, k.Value.Y, k.Value.Z, k.Value.W) }; rk.Add(nrk); } foreach (Assimp.VectorKey s in channel.ScalingKeys) { VectorKey nsk = new VectorKey { Time = s.Time, Value = new OpenTK.Vector3(s.Value.X, s.Value.Y, s.Value.Z) }; sk.Add(nsk); } nac.Name = channel.NodeName; nac.PositionKeys = pk; nac.RotationKeys = rk; nac.ScalingKeys = sk; Channels.Add(nac); } LastPositions = Enumerable.Repeat(new MutableTuple <int, int, int>(0, 0, 0), anim.NodeAnimationChannelCount).ToList(); Transforms = new List <List <OpenTK.Matrix4> >(); PlayAnimationForward = true; }
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 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 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); }
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 Animation(Assimp.Animation assimpAnimation) { isInitialized = true; timer = new DispatcherTimer(); this.assimpAnimation = assimpAnimation; }