public Animations.Animation CreateGenericAnimation(Assimp.Animation animation) { Animations.Animation STanim = new Animations.Animation(); STanim.Text = animation.Name; STanim.FrameCount = (int)animation.DurationInTicks; //Load node animations if (animation.HasNodeAnimations) { var _channels = new NodeAnimationChannel[animation.NodeAnimationChannelCount]; for (int i = 0; i < _channels.Length; i++) { _channels[i] = new NodeAnimationChannel(); } } //Load mesh animations if (animation.HasMeshAnimations) { var _meshChannels = new MeshAnimationChannel[animation.MeshAnimationChannelCount]; for (int i = 0; i < _meshChannels.Length; i++) { _meshChannels[i] = new MeshAnimationChannel(); } } return(STanim); }
public static Animation CopyAnimationInto(Animation animSource, Animation animTarget) { foreach (NodeAnimationChannel animChan in animSource.NodeAnimationChannels) { NodeAnimationChannel copyChannel = new NodeAnimationChannel(); copyChannel.NodeName = animChan.NodeName; copyChannel.PostState = animChan.PostState; copyChannel.PreState = animChan.PreState; //copyChannel.ScalingKeys = animChan.ScalingKeys.Add(animChan.) animChan.ScalingKeys.ForEach((item) => { copyChannel.ScalingKeys.Add(new VectorKey(item.Time, item.Value)); }); animChan.RotationKeys.ForEach((item) => { copyChannel.RotationKeys.Add(new QuaternionKey(item.Time, item.Value)); }); animChan.PositionKeys.ForEach((item) => { copyChannel.PositionKeys.Add(new VectorKey(item.Time, item.Value)); }); animTarget.NodeAnimationChannels.Add(copyChannel); } return animTarget; }
/// <summary> /// Add a new frame Animation channel /// </summary> private void AddNewFrame(Hand hand, Animation anim) { NodeAnimationChannel nodeChannelHand = AssimpUtil.FindNodeAnim(anim, GetNodeHandName(hand.Id.ToString())); var assimpNodeAnimHand = VectorToNode(hand.PalmPosition, anim.DurationInTicks); nodeChannelHand.PositionKeys.Add(assimpNodeAnimHand.Item1); nodeChannelHand.RotationKeys.Add(assimpNodeAnimHand.Item2); foreach (Finger finger in hand.Fingers) { Leap.Bone bone; foreach (Leap.Bone.BoneType boneType in (Leap.Bone.BoneType[])Enum.GetValues(typeof(Leap.Bone.BoneType))) { bone = finger.Bone(boneType); //Fetch the NodeAnim corresponding to the Bone NodeAnimationChannel nodeChannel = AssimpUtil.FindNodeAnim(anim, GetNodeBoneName(finger.Type.ToString(), boneType.ToString(), hand)); var assimpNodeAnim = VectorToNode(bone.NextJoint - bone.PrevJoint, anim.DurationInTicks); //BoneToNode(bone); nodeChannel.PositionKeys.Add(assimpNodeAnim.Item1); nodeChannel.RotationKeys.Add(assimpNodeAnim.Item2); } } }
/// <summary> /// Converts an <see cref="AssimpAnimation"/> to a <see cref="DomainAnimation"/>. /// </summary> /// <param name="animation">The <see cref="AssimpAnimation"/> to convert.</param> /// <returns>The resulting <see cref="DomainAnimation"/>.</returns> private static DomainAnimation ConvertToDomainAnimation(AssimpAnimation animation) { var ticksPerSecond = animation.TicksPerSecond; if (ticksPerSecond <= 0.0) { ticksPerSecond = 30.0; } var durationInSeconds = animation.DurationInTicks / ticksPerSecond; var channels = new List <DomainChannel>(); foreach (var channel in animation.NodeAnimationChannels) { var rotationKeyFrames = channel.RotationKeys .Select(rk => GetDomainQuaternionKeyFrame(rk, ticksPerSecond)) .ToArray(); var offsetKeyFrames = channel.PositionKeys .Select(ok => GetDomainVector3KeyFrame(ok, ticksPerSecond)) .ToArray(); var scaleKeyFrames = channel.ScalingKeys .Select(sk => GetDomainVector3KeyFrame(sk, ticksPerSecond)) .ToArray(); channels.Add(new DomainChannel(channel.NodeName, new ReadOnlyCollection <DomainQuaternionKeyFrame>(rotationKeyFrames), new ReadOnlyCollection <DomainVector3KeyFrame>(offsetKeyFrames), new ReadOnlyCollection <DomainVector3KeyFrame>(scaleKeyFrames))); } return(new DomainAnimation(animation.Name, new ReadOnlyCollection <DomainChannel>(channels.ToArray()), durationInSeconds)); }
/// <summary> /// Because there is no copy constructor inside Assimp.Net /// we decided to implemented or own copy method for animation. /// NB: This is a partial copy because we only copy what we are interested by /// </summary> /// <param name="anim"></param> /// <returns></returns> public static Animation DuplicateAnimation(Animation anim) { Animation newAnim = new Animation(); newAnim.DurationInTicks = anim.DurationInTicks; newAnim.Name = anim.Name; newAnim.TicksPerSecond = anim.TicksPerSecond; return CopyAnimationInto(anim, newAnim); }
public AnimEvaluator(Animation animation, double ticksPerSecond) { _animation = animation; _ticksPerSecond = ticksPerSecond; _lastPositions = new T3[_animation.NodeAnimationChannelCount]; _currentTransforms = new Matrix4[_animation.NodeAnimationChannelCount]; }
/// <summary> /// Creates an Assimp.Animation by copying the given source Assimp.Animation content.<br /> /// </summary> /// <param name="rootNode"></param> /// <param name="sourceAnimation">The source Assimp.Animation to copy.</param> /// <returns></returns> private static Assimp.Animation CreateAssimpAnimation(Node rootNode, Assimp.Animation sourceAnimation) { Assimp.Animation animation = new Assimp.Animation(); animation.DurationInTicks = sourceAnimation.DurationInTicks; animation.Name = sourceAnimation.Name; animation.TicksPerSecond = sourceAnimation.TicksPerSecond; CreateNodeAnimationChannels(animation, sourceAnimation.NodeAnimationChannels, rootNode); return animation; }
/// <summary> /// Generate weights and skeleton Nodes from an assimp skeleton Node. /// However pinocchio does not looks to be very good with /// that Method. /// It takes a /// </summary> /// <param name="modelPath">The original model Path</param> /// <param name="scene"></param> /// <param name="skeletalAnim"></param> /// <param name="rootSkeletalAnim"></param> public void AutomaticRiggingFromSkeleton(string modelPath, Scene scene, Animation skeletalAnim, Node rootSkeletalAnim) { string skelPathFile = Path.Combine(Path.Combine(projectPath, PINOCCHIO_TMP_DIR_INPUT), "skeleton.out"); ExportToPinocchioFormat(projectPath, skeletalAnim, rootSkeletalAnim, 0); LaunchPinocchioBinary(modelPath, skelPathFile); //Import Data that pinocchio did generated //There is a problem here since we dont have a way to associate AssimpNodes and Bones in the attachement.out for now() BuildBones(scene.Meshes[0], rootSkeletalAnim); BuildBonesWeight(scene); }
public AnimationSDX(Assimp.Animation animation) { FramePerSecond = (float)(animation.TicksPerSecond > 24 ? animation.TicksPerSecond : 25); FrameDuration = 1000 / FramePerSecond; foreach (var n in animation.NodeAnimationChannels) { frames.Add(n.NodeName, GetFrames(n).ToArray()); } DurationInTicks = frames.Values.Max(x => x.Length); DurationInMiliseconds = DurationInTicks * FrameDuration; }
private static string FormatAnimationName(Animation anim) { var dur = anim.DurationInTicks; if (anim.TicksPerSecond > 1e-10) { dur /= anim.TicksPerSecond; } else { dur /= SceneAnimator.DefaultTicksPerSecond; } string text = string.Format("{0} ({1}s)", anim.Name, dur.ToString("0.000")); return text; }
private static List <Assimp.Animation> PAMtoFBXAnim(Pmo pmo, Pam pam) { List <Assimp.Animation> animationList = new List <Assimp.Animation>(); for (int i = 0; i < pam.header.AnimationCount; i++) { Assimp.Animation anim = new Assimp.Animation(); anim.Name = pam.animList[i].AnimEntry.AnimationName; anim.DurationInTicks = pam.animList[i].AnimHeader.FrameCount; anim.TicksPerSecond = pam.animList[i].AnimHeader.Framerate; //anim.MeshAnimationChannels[0].MeshKeys.Add(new MeshKey(anim.DurationInTicks / 2, new Vector3D(0, 0, 100))); for (int b = 0; b < pam.animList[i].AnimHeader.BoneCount; b++) { Pam.BoneChannel chann = pam.animList[i].BoneChannels[b]; anim.NodeAnimationChannels.Add(new NodeAnimationChannel()); anim.NodeAnimationChannels[b].NodeName = pmo.boneList[b].JointName; ChannelData dat = GetChannelKeyframes(chann, anim.DurationInTicks); //AddTranslationAtKeyframe(anim.NodeAnimationChannels[b].PositionKeys, 0, new Vector3D(), anim.TicksPerSecond); // Position /*if(dat.transData != null) * { * foreach (ChannelTranslationData trans in dat.transData) * { * AddTranslationAtKeyframe(anim.NodeAnimationChannels[b].PositionKeys, trans.keyframeID, trans.Translation, anim.TicksPerSecond); * } * }*/ /*if (dat.rotData != null) * { * // Rotation * foreach (ChannelRotationData trans in dat.rotData) * { * AddRotationAtKeyframe(anim.NodeAnimationChannels[b].RotationKeys, trans.keyframeID, trans.Rotation, anim.TicksPerSecond); * } * }*/ } animationList.Add(anim); } return(animationList); }
private AnimationContent CreateAnimation(Assimp.Animation aiAnimation) { var animation = new AnimationContent { Name = FixupAnimationName(aiAnimation.Name), Duration = TimeSpan.FromSeconds(aiAnimation.DurationInTicks / aiAnimation.TicksPerSecond) }; foreach (var aiChannel in aiAnimation.NodeAnimationChannels) { var channel = new AnimationChannel(); // We can have different numbers of keyframes for each, so find the max index. var keyCount = Math.Max(aiChannel.PositionKeyCount, Math.Max(aiChannel.RotationKeyCount, aiChannel.ScalingKeyCount)); // Get all unique keyframe times var times = aiChannel.PositionKeys.Select(k => k.Time) .Union(aiChannel.RotationKeys.Select(k => k.Time)) .Union(aiChannel.ScalingKeys.Select(k => k.Time)) .Distinct().ToList(); // The rest of this loop is almost certainly wrong. Don't trust it. // There's some magical combination, ordering, or transposition we have // to figure out to translate FBX->Assimp->XNA. // Possibilities: matrix offset transform, missing a base transform, an extra base transform, etc. var toBoneSpace = _objectToBone.ContainsKey(aiChannel.NodeName) ? _objectToBone[aiChannel.NodeName] * _skeletonRoot.Transform : _skeletonRoot.Transform; foreach (var aiKeyTime in times) { var time = TimeSpan.FromSeconds(aiKeyTime / aiAnimation.TicksPerSecond); var translation = Matrix4x4.FromTranslation(aiChannel.PositionKeys.FirstOrDefault(k => k.Time == aiKeyTime).Value); var rotation = new Matrix4x4(aiChannel.RotationKeys.FirstOrDefault(k => k.Time == aiKeyTime).Value.GetMatrix()); var scale = Matrix4x4.FromScaling(aiChannel.ScalingKeys.FirstOrDefault(k => k.Time == aiKeyTime).Value); var nodeTransform = translation * rotation * scale; var xform = toBoneSpace * nodeTransform * _globalInverseXform; channel.Add(new AnimationKeyframe(time, ToXna(xform))); } animation.Channels.Add(aiChannel.NodeName, channel); } return(animation); }
public AnimEvaluator(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<AnimationChannel>(); foreach (var channel in anim.NodeAnimationChannels) { var c = new AnimationChannel { Name = channel.NodeName, PositionKeys = channel.PositionKeys.ToList(), RotationKeys = channel.RotationKeys.ToList(), ScalingKeys = channel.ScalingKeys.ToList() }; Channels.Add(c); } LastPositions = Enumerable.Repeat(new MutableTuple<int, int, int>(0, 0, 0), anim.NodeAnimationChannelCount).ToList(); Transforms = new List<List<Matrix>>(); PlayAnimationForward = true; }
private ErrorCode AddAnimationsToScene(Scene scene) { if (animations == null || animations.Count == 0) { return(ErrorCode.Succeed); } for (int i = 0; i < animations.Count; ++i) { var ani = new Animation { Name = string.IsNullOrEmpty(animations[i].Name) ? $"Animation_{i}" : animations[i].Name, TicksPerSecond = DefaultTicksPerSecond, DurationInTicks = (animations[i].EndTime - animations[i].StartTime) * DefaultTicksPerSecond }; foreach (var f in animations[i].NodeAnimationCollection) { if (f.Node == null || string.IsNullOrEmpty(f.Node.Name)) { logger.LogWarning("Node Animation NodeName is empty. AnimationName:{}", ani.Name); continue; } var ch = new NodeAnimationChannel { NodeName = f.Node.Name }; foreach (var kf in f.KeyFrames) { var t = kf.Time * DefaultTicksPerSecond; ch.PositionKeys.Add(new VectorKey(t, kf.Translation.ToAssimpVector3D())); ch.ScalingKeys.Add(new VectorKey(t, kf.Scale.ToAssimpVector3D())); ch.RotationKeys.Add(new QuaternionKey(t, kf.Rotation.ToAssimpQuaternion())); } ani.NodeAnimationChannels.Add(ch); } scene.Animations.Add(ani); } return(ErrorCode.Succeed); }
public cAnimEvaluator(Animation pAnim) { mLastTime = 0.0f; TicksPerSecond = (float)(pAnim.TicksPerSecond != 0.0f ? pAnim.TicksPerSecond : 100.0f); Duration = (float)(pAnim.DurationInTicks); Name = pAnim.Name; //OUTPUT_DEBUG_MSG("Creating Animation named: "<<Name); //Channels.resize(pAnim.MeshAnimationChannelCount); for(int a = 0; a < pAnim.NodeAnimationChannelCount; a++) { Channels[a].Name = pAnim.NodeAnimationChannels[a].NodeName; for(int i = 0; i < pAnim.NodeAnimationChannels[a].PositionKeyCount; i++) Channels[a].mPositionKeys.Add(pAnim.NodeAnimationChannels[a].PositionKeys[i]); for(int j = 0; j < pAnim.NodeAnimationChannels[a].RotationKeyCount; j++) Channels[a].mRotationKeys.Add(pAnim.NodeAnimationChannels[a].RotationKeys[j]); for(int k = 0; k < pAnim.NodeAnimationChannels[a].ScalingKeyCount; k++) Channels[a].mScalingKeys.Add(pAnim.NodeAnimationChannels[a].ScalingKeys[k]); } //mLastPositions.resize( pAnim->mNumChannels, std::make_tuple( 0, 0, 0)); //OUTPUT_DEBUG_MSG("Finished Creating Animation named: "<<Name); }
public static void ExcludeNodeAnimation(Animation anim, string nodeAnimName) { NodeAnimationChannel nodeAnim = anim.NodeAnimationChannels.Find(item => item.NodeName == nodeAnimName); anim.NodeAnimationChannels.Remove(nodeAnim); }
/// <summary> /// Imports an FBX animation, storing the transformations that apply to each bone at each time. /// </summary> /// <param name="name"> /// The name of the animation. /// </param> /// <param name="assimpAnimation"> /// The AssImp animation to apply to the scene. /// </param> /// <returns> /// The <see cref="IAnimation"/> representing the imported animation. /// </returns> private IAnimation ImportAnimation(string name, Assimp.Animation assimpAnimation) { var translation = new Dictionary <string, IDictionary <double, Vector3> >(); var rotation = new Dictionary <string, IDictionary <double, Quaternion> >(); var scale = new Dictionary <string, IDictionary <double, Vector3> >(); foreach (var animChannel in assimpAnimation.NodeAnimationChannels) { if (animChannel.HasPositionKeys) { if (!translation.ContainsKey(animChannel.NodeName)) { translation[animChannel.NodeName] = new Dictionary <double, Vector3>(); } foreach (var positionKey in animChannel.PositionKeys) { var vector = new Vector3(positionKey.Value.X, positionKey.Value.Y, positionKey.Value.Z); translation[animChannel.NodeName].Add(positionKey.Time, vector); } } if (animChannel.HasRotationKeys) { if (!rotation.ContainsKey(animChannel.NodeName)) { rotation[animChannel.NodeName] = new Dictionary <double, Quaternion>(); } foreach (var rotationKey in animChannel.RotationKeys) { var quaternion = new Quaternion( rotationKey.Value.X, rotationKey.Value.Y, rotationKey.Value.Z, rotationKey.Value.W); rotation[animChannel.NodeName].Add(rotationKey.Time, quaternion); } } if (animChannel.HasScalingKeys) { if (!scale.ContainsKey(animChannel.NodeName)) { scale[animChannel.NodeName] = new Dictionary <double, Vector3>(); } foreach (var scaleKey in animChannel.ScalingKeys) { var vector = new Vector3(scaleKey.Value.X, scaleKey.Value.Y, scaleKey.Value.Z); scale[animChannel.NodeName].Add(scaleKey.Time, vector); } } } return(new Animation( name, assimpAnimation.TicksPerSecond, assimpAnimation.DurationInTicks, translation, rotation, scale)); }
public static Animation ConvertFromAssimpScene(Ai.Scene aiScene, Ai.Animation aiAnimation, AnimationConverterOptions options) { var animation = new Animation(options.Version); animation.Duration = ConvertTime(aiAnimation.DurationInTicks, aiAnimation.TicksPerSecond); foreach (var aiChannel in aiAnimation.NodeAnimationChannels) { if (AssimpConverterCommon.MeshAttachmentNameRegex.IsMatch(aiChannel.NodeName)) { continue; } var nodeName = AssimpConverterCommon.UnescapeName(aiChannel.NodeName); var controller = new AnimationController(options.Version) { TargetKind = TargetKind.Node, TargetName = nodeName, TargetId = GetTargetIdForNode(aiScene.RootNode, nodeName) }; var track = new KeyframeTrack(options.Version); // NodePRS only for now track.KeyframeType = KeyframeType.NodePRS; // Fetch the unique key frame timings from all position, rotation and scale keys. var keyframeTimings = aiChannel.PositionKeys .Select(x => x.Time) .Concat(aiChannel.RotationKeys.Select(x => x.Time)) .Concat(aiChannel.ScalingKeys.Select(x => x.Time)) .Distinct() .OrderBy(x => x); // Convert the times to our scale and save them. track.KeyframeTimings = keyframeTimings .Select(x => ConvertTime(x, aiAnimation.TicksPerSecond)) .ToList(); // Decompose the local transform of the affected node so we can use them as the base values for our keyframes aiScene.RootNode.FindNode(nodeName).Transform .Decompose(out var nodeBaseScale, out var nodeBaseRotation, out var nodeBaseTranslation); // Keep track of the last position, rotation and scale used to ensure that interpolation works properly var lastPosition = nodeBaseTranslation; var lastRotation = nodeBaseRotation; var lastScale = nodeBaseScale; foreach (var time in keyframeTimings) { // Start building the keyframe var keyframe = new KeyframePRS(track.KeyframeType) { Position = new Vector3(lastPosition.X, lastPosition.Y, lastPosition.Z), Rotation = new Quaternion(lastRotation.X, lastRotation.Y, lastRotation.Z, lastRotation.W), Scale = new Vector3(lastScale.X, lastScale.Y, lastScale.Z) }; // Fetch the Assimp keys for this time var aiPositionKey = aiChannel.PositionKeys.SingleOrDefault(x => x.Time == time); var aiRotationKey = aiChannel.RotationKeys.SingleOrDefault(x => x.Time == time); var aiScaleKey = aiChannel.ScalingKeys.SingleOrDefault(x => x.Time == time); if (aiPositionKey != default(Ai.VectorKey)) { keyframe.Position = new Vector3(aiPositionKey.Value.X, aiPositionKey.Value.Y, aiPositionKey.Value.Z); lastPosition = aiPositionKey.Value; } if (aiRotationKey != default(Ai.QuaternionKey)) { keyframe.Rotation = new Quaternion(aiRotationKey.Value.X, aiRotationKey.Value.Y, aiRotationKey.Value.Z, aiRotationKey.Value.W); lastRotation = aiRotationKey.Value; } if (aiScaleKey != default(Ai.VectorKey)) { keyframe.Scale = new Vector3(aiScaleKey.Value.X, aiScaleKey.Value.Y, aiScaleKey.Value.Z); lastScale = aiScaleKey.Value; } track.Keyframes.Add(keyframe); } controller.Tracks.Add(track); animation.Controllers.Add(controller); } return(animation); }
private string BuildFrameAnimation(Animation anim, Node rootNodeAnim, Matrix4x4 curMat, int frameIndex, ref string result) { NodeAnimationChannel nodeAnim = AssimpUtil.FindNodeAnim(anim, rootNodeAnim.Name); Matrix4x4 resMatrix = StackMatrix(curMat, nodeAnim, frameIndex); result += String.Format("{0} {1} {2} {3} {4}\r\n", rootNodeAnim.Name.GetHashCode(), resMatrix.A4, resMatrix.C4, resMatrix.B4, rootNodeAnim.Parent.Name.GetHashCode()); foreach (Node childNode in rootNodeAnim.Children) BuildFrameAnimation(anim, childNode, resMatrix, frameIndex, ref result); return result; }
void WriteAnimation (Animation anim, BinaryWriter writer) { writer.Write(anim.Name); writer.Write(anim.DurationInTicks); writer.Write(anim.TicksPerSecond); var count = anim.NodeAnimationChannelCount; writer.Write(count); for (var i = 0; i < count; i++) { var chan = anim.NodeAnimationChannels[i]; writer.Write(chan.NodeName); writer.Write((int)chan.PreState); writer.Write((int)chan.PostState); var keyCount = chan.PositionKeyCount; writer.Write(keyCount); for (var j = 0; j < keyCount; j++) { var key = chan.PositionKeys[j]; writer.Write(key.Time); writer.Write(key.Value); } keyCount = chan.RotationKeyCount; writer.Write(keyCount); for (var j = 0; j < keyCount; j++) { var key = chan.RotationKeys[j]; writer.Write(key.Time); writer.Write(key.Value); } keyCount = chan.ScalingKeyCount; writer.Write(keyCount); for (var j = 0; j < keyCount; j++) { var key = chan.ScalingKeys[j]; writer.Write(key.Time); writer.Write(key.Value); } } }
public static Animations.Animation CreateGenericAnimation(Assimp.Animation animation) { Animations.Animation STanim = new Animations.Animation(); STanim.Text = animation.Name; float TicksPerSecond = animation.TicksPerSecond != 0 ? (float)animation.TicksPerSecond : 25.0f; float Duriation = (float)animation.DurationInTicks; STanim.FrameCount = (int)(Duriation * 30); //Load node animations if (animation.HasNodeAnimations) { var _channels = new NodeAnimationChannel[animation.NodeAnimationChannelCount]; for (int i = 0; i < _channels.Length; i++) { _channels[i] = new NodeAnimationChannel(); var boneAnim = new Animations.Animation.KeyNode(_channels[i].NodeName); boneAnim.RotType = Animations.Animation.RotationType.EULER; STanim.Bones.Add(boneAnim); STConsole.WriteLine($"Creating Bone Anims {boneAnim.Text} "); for (int frame = 0; frame < STanim.FrameCount; i++) { if (_channels[i].HasPositionKeys) { for (int key = 0; key < _channels[i].PositionKeyCount; key++) { if (frame == _channels[i].PositionKeys[key].Time) { boneAnim.XPOS.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].PositionKeys[key].Value.X, Frame = frame, }); boneAnim.YPOS.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].PositionKeys[key].Value.Y, Frame = frame, }); boneAnim.ZPOS.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].PositionKeys[key].Value.Z, Frame = frame, }); } } } if (_channels[i].HasRotationKeys) { for (int key = 0; key < _channels[i].RotationKeyCount; key++) { if (frame == _channels[i].RotationKeys[key].Time) { var quat = _channels[i].RotationKeys[key].Value; var euler = STMath.ToEulerAngles(quat.X, quat.Y, quat.Z, quat.W); boneAnim.XROT.Keys.Add(new Animations.Animation.KeyFrame() { Value = euler.X, Frame = frame, }); boneAnim.YROT.Keys.Add(new Animations.Animation.KeyFrame() { Value = euler.Y, Frame = frame, }); boneAnim.ZROT.Keys.Add(new Animations.Animation.KeyFrame() { Value = euler.Z, Frame = frame, }); boneAnim.WROT.Keys.Add(new Animations.Animation.KeyFrame() { Value = 1, Frame = frame, }); } } } if (_channels[i].HasScalingKeys) { for (int key = 0; key < _channels[i].ScalingKeyCount; key++) { if (frame == _channels[i].ScalingKeys[key].Time) { boneAnim.XSCA.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].ScalingKeys[key].Value.X, Frame = frame, }); boneAnim.YSCA.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].ScalingKeys[key].Value.Y, Frame = frame, }); boneAnim.ZSCA.Keys.Add(new Animations.Animation.KeyFrame() { Value = _channels[i].ScalingKeys[key].Value.Z, Frame = frame, }); } } } } } } //Load mesh animations if (animation.HasMeshAnimations) { var _meshChannels = new MeshAnimationChannel[animation.MeshAnimationChannelCount]; for (int i = 0; i < _meshChannels.Length; i++) { _meshChannels[i] = new MeshAnimationChannel(); } } return(STanim); }
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); }
/// <summary> /// Constructs a new Scene. /// </summary> /// <param name="scene">Unmanaged AiScene struct.</param> internal Scene(AiScene scene) { _flags = scene.Flags; //Read materials if(scene.NumMaterials > 0 && scene.Materials != IntPtr.Zero) { AiMaterial[] materials = MemoryHelper.MarshalArray<AiMaterial>(scene.Materials, (int) scene.NumMaterials, true); _materials = new Material[materials.Length]; for(int i = 0; i < _materials.Length; i++) { _materials[i] = new Material(materials[i]); } } //Read scenegraph if(scene.RootNode != IntPtr.Zero) { _rootNode = new Node(MemoryHelper.MarshalStructure<AiNode>(scene.RootNode), null); } //Read meshes if(scene.NumMeshes > 0 && scene.Meshes != IntPtr.Zero) { AiMesh[] meshes = MemoryHelper.MarshalArray<AiMesh>(scene.Meshes, (int) scene.NumMeshes, true); _meshes = new Mesh[meshes.Length]; for(int i = 0; i < _meshes.Length; i++) { _meshes[i] = new Mesh(meshes[i]); } } //Read lights if(scene.NumLights > 0 && scene.Lights != IntPtr.Zero) { AiLight[] lights = MemoryHelper.MarshalArray<AiLight>(scene.Lights, (int) scene.NumLights, true); _lights = new Light[lights.Length]; for(int i = 0; i < _lights.Length; i++) { _lights[i] = new Light(lights[i]); } } //Read cameras if(scene.NumCameras > 0 && scene.Cameras != IntPtr.Zero) { AiCamera[] cameras = MemoryHelper.MarshalArray<AiCamera>(scene.Cameras, (int) scene.NumCameras, true); _cameras = new Camera[cameras.Length]; for(int i = 0; i < _cameras.Length; i++) { _cameras[i] = new Camera(cameras[i]); } } //Read Textures if(scene.NumTextures > 0 && scene.Textures != IntPtr.Zero) { AiTexture[] textures = MemoryHelper.MarshalArray<AiTexture>(scene.Textures, (int) scene.NumTextures, true); _textures = new Texture[textures.Length]; for(int i = 0; i < _textures.Length; i++) { _textures[i] = Texture.CreateTexture(textures[i]); } } //Read animations if(scene.NumAnimations > 0 && scene.Animations != IntPtr.Zero) { AiAnimation[] animations = MemoryHelper.MarshalArray<AiAnimation>(scene.Animations, (int) scene.NumAnimations, true); _animations = new Animation[animations.Length]; for(int i = 0; i < _animations.Length; i++) { _animations[i] = new Animation(animations[i]); } } }
/// <summary> /// Get the data from Session /// </summary> private void GetCurrentModelData() { assimpAnimation = Session.CurrentSession.CurrentProject.CurrentModel3D.Animation.AssimpAnimation; firstNode = Session.CurrentSession.CurrentProject.CurrentModel3D.Scene.RootNode.Children[0]; content = Session.CurrentSession.CurrentProject.CurrentModel3D.Content; joints = Session.CurrentSession.CurrentProject.CurrentModel3D.Joints; bones = Session.CurrentSession.CurrentProject.CurrentModel3D.Bones; }
/// <summary> /// Export a skeleton.out file that can be used by Pinocchio /// </summary> /// <param name="anim"></param> /// <param name="rootNodeAnim"></param> /// <returns></returns> public void ExportToPinocchioFormat(string projectPath, Animation anim, Node rootNodeAnim, int i, int frameIndex = 0) { string exportPinocchio = BuildPinocchioAnimation(anim, rootNodeAnim.Children[i], frameIndex); string dirSkelPathFile = Path.Combine(projectPath, PINOCCHIO_TMP_DIR_INPUT); string skelPathFile = Path.Combine(dirSkelPathFile, "skeleton.out"); File.WriteAllText(skelPathFile, exportPinocchio); }
/** * Convert a KinectJoint into a NodeAnimationChannel and add it in an Animation. * This method also take care if there NodeJoint already exist or not in the Animation * and create it if not (In fact some kinect joint can appear wheareas they didnt exist before) * @param joint The KinectJoint which will be converted * @param curAnim The animation in which the converted kinectJoint will be added */ private void AddJointAtTimeframeEnd(Scene scene, Joint joint, Animation curAnim, double time) { //We try to find the KinectJoint in the Assimp recorder (curAnim) // \todo Apparently .toString() on a enumerate is obsolete, so need to check on that NodeAnimationChannel matchedNode = (from nodeAnimTmp in curAnim.NodeAnimationChannels where nodeAnimTmp.NodeName == joint.JointType.ToString() select nodeAnimTmp).First(); //If we dont, we add it in the Channel if (matchedNode == null) { NodeAnimationChannel newAnimJoint = new NodeAnimationChannel(); newAnimJoint.NodeName = joint.JointType.ToString(); curAnim.NodeAnimationChannels.Add(newAnimJoint); matchedNode = newAnimJoint; } this.KinectJointToNode(scene, joint, matchedNode, time); }
private int FindAnimationIndex(Animation animation) { int i = 0; foreach (Animation anim in _scene.Raw.Animations) { if (anim == animation) { return i; } ++i; } return -1; }
public static Animation MergeAnimations(Animation animFrom, Animation animTo) { Animation anim1Copy = AssimpUtil.DuplicateAnimation(animFrom); return AssimpUtil.CopyAnimationInto(anim1Copy, animTo); }
/// <summary> /// Rename an animation. /// /// Does not create UndoStack entries itself, caller must do this. /// </summary> /// <param name="animation"></param> /// <param name="newName"></param> public void RenameAnimation(Animation animation, string newName) { animation.Name = newName; }
/** * This function will Initialize (names, size, ect...) * the mChannels array in Animation newly created class. * @param skeleton Skeleton Fetch on the kinect stream */ private void InitAnimBones(Scene scene, Skeleton skeleton) { Animation newAnim = new Animation(); //We set 0 by defaults but it should be interesting to check tickpersecond for a skeleton record newAnim.TicksPerSecond = 0; newAnim.DurationInTicks = 0; scene.Animations.Add(newAnim); //this.animList.Add(new Tuple<Int32, Animation>(skeleton.TrackingId, newAnim)); foreach (Joint joint in skeleton.Joints) { NodeAnimationChannel bone = new NodeAnimationChannel(); bone.NodeName = joint.JointType.ToString(); newAnim.NodeAnimationChannels.Add(bone); } }
private string BuildPinocchioAnimation(Animation anim, Node rootNodeAnim, int frameIndex) { string animStrRes = ""; BuildFrameAnimation(anim, rootNodeAnim, Matrix4x4.Identity, frameIndex, ref animStrRes); return animStrRes; }
/// <summary> /// Allow to find a NodeAnimationChannel inside a NodeAnimationChannels /// </summary> /// <param name="anim">The animation in which we are looking for our NodeAnimationChannel</param> /// <param name="nodeName">The node anim name that we are looking for</param> /// <returns>The founded NodeAnimationChannel</returns> public static NodeAnimationChannel FindNodeAnim(Animation anim, string nodeName) { NodeAnimationChannel matchedNode = (from nodeAnimTmp in anim.NodeAnimationChannels where nodeAnimTmp.NodeName == nodeName select nodeAnimTmp).First(); return (matchedNode); }
private SEAAnimationBase AppendKeyFrameAnimation(Scene scene, Animation animation) { return null; }
/// <summary> /// Take an Hand argument which will be converted and added into one of the animation present in /// the animList property /// </summary> /// <param name="hand"></param> private void RecordHand(Hand hand) { ModelType type = hand.IsLeft ? ModelType.LEAPMOTIONLEFT : ModelType.LEAPMOTIONRIGHT; KineapScene extentScene = this.GetOrCreateScene(hand.Id, type); Scene skelScene = extentScene.Scene; Animation handAnim; if (skelScene.Animations.Count == 0) { handAnim = new Animation(); handAnim.DurationInTicks = 0; handAnim.TicksPerSecond = 0; skelScene.Animations.Add(handAnim); CreateNodeHierarchy(hand, skelScene); if (hand.IsLeft) extentScene.MetaDatas.Add(ExtentSceneMetaData.HAND_TYPE, 1); else extentScene.MetaDatas.Add(ExtentSceneMetaData.HAND_TYPE, 2); } else { handAnim = skelScene.Animations[0]; handAnim.DurationInTicks += 1; } AddNewFrame(hand, handAnim); OnFrame(new NewFrameArgs(skelScene, handAnim, handAnim.DurationInTicks)); }