public void FromTransform(Matrix4 transform) { Scale = transform.ExtractScale(); Position = transform.ExtractTranslation(); rotation = transform.ExtractRotation(); eulerRotation = STMath.ToEulerAngles(rotation); }
//jakeroo123's animation adding code. public static void ExportAnimation(string FileName, Toolbox.Library.Animations.Animation anim = null, STSkeleton skeleton = null, List <int> NodeArray = null) { //Always use the same settings ExportSettings settings = new ExportSettings(); settings.SuppressConfirmDialog = true; settings.UseMatrixTransform = false; List <string> failedTextureExport = new List <string>(); STProgressBar progressBar = new STProgressBar(); progressBar.Task = "Exporting Animation \"" + anim.Text + "\"..."; progressBar.Value = 0; progressBar.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; progressBar.Show(); progressBar.Refresh(); /* I don't see any way to use this * if (settings.UseOldExporter) * { * AssimpSaver saver = new AssimpSaver(); * STGenericModel model = new STGenericModel(); * model.Objects = Meshes; * model.Materials = Materials; * saver.SaveFromModel(model, FileName, Textures, skeleton, NodeArray); * return; * } */ string TexturePath = System.IO.Path.GetDirectoryName(FileName); using (ColladaWriter writer = new ColladaWriter(FileName, settings)) { writer.WriteAsset(); //This is where the magic happens - Iterate through bones, and add animations. if (anim != null && skeleton != null) { writer.StartLibraryAnimations(); float[] frames = new float[anim.FrameCount + 1]; for (int i = 0; i <= anim.FrameCount; i++) { frames[i] = i / 30f; //DAE appears to save frame times - This is saving the animation as 30 FPS, regardless of anything else. } string[] interp = new string[anim.FrameCount + 1]; for (int i = 0; i <= anim.FrameCount; i++) { interp[i] = "LINEAR"; //Just use linear. } foreach (STBone bone in skeleton.bones) { skeleton.reset(); string aid = anim.Text + "_" + bone.Text; //The prefix for animation string bid = "Armature_" + bone.Text; Vector3 defaultRotation = bone.EulerRotation; //Three arrays, for float[] rotateX = new float[anim.FrameCount + 1]; float[] rotateY = new float[anim.FrameCount + 1]; float[] rotateZ = new float[anim.FrameCount + 1]; Vector3[] scale = new Vector3[anim.FrameCount + 1]; Vector3[] translate = new Vector3[anim.FrameCount + 1]; anim.SetFrame(0); for (int i = 0; i <= anim.FrameCount; i++) { anim.NextFrame(skeleton, false, true, bone.Text); //Rotation Vector3 eul = STMath.ToEulerAngles(bone.rot); rotateX[i] = eul.X * Rad2Deg; //- defaultRotation.X; rotateY[i] = eul.Y * Rad2Deg; //- defaultRotation.Y; rotateZ[i] = eul.Z * Rad2Deg; //- defaultRotation.Z; //Scaling and translation scale[i] = bone.GetScale(); translate[i] = bone.GetPosition(); } writer.WriteAnimationVector(aid + "_translate", frames, interp, translate, bid + "/location"); writer.WriteAnimationAngle(aid + "_rotateX", frames, interp, rotateX, bid + "/rotationX.ANGLE"); writer.WriteAnimationAngle(aid + "_rotateY", frames, interp, rotateY, bid + "/rotationY.ANGLE"); writer.WriteAnimationAngle(aid + "_rotateZ", frames, interp, rotateZ, bid + "/rotationZ.ANGLE"); writer.WriteAnimationVector(aid + "_scale", frames, interp, scale, bid + "/scale"); } writer.EndLibraryAnimations(); } skeleton.reset(); //Don't bother exporting any textures - It's not really necessary, at this point. writer.WriteLibraryImages(); if (skeleton != null) { //Don't bother searching for rigging, because the mesh will simply be empty. foreach (var bone in skeleton.bones) { //Set the inverse matrix var inverse = skeleton.GetBoneTransform(bone).Inverted(); var transform = bone.GetTransform(); float[] Transform = new float[] { transform.M11, transform.M21, transform.M31, transform.M41, transform.M12, transform.M22, transform.M32, transform.M42, transform.M13, transform.M23, transform.M33, transform.M43, transform.M14, transform.M24, transform.M34, transform.M44 }; float[] InvTransform = new float[] { inverse.M11, inverse.M21, inverse.M31, inverse.M41, inverse.M12, inverse.M22, inverse.M32, inverse.M42, inverse.M13, inverse.M23, inverse.M33, inverse.M43, inverse.M14, inverse.M24, inverse.M34, inverse.M44 }; writer.AddJoint(bone.Text, bone.parentIndex == -1 ? "" : skeleton.bones[bone.parentIndex].Text, Transform, InvTransform, new float[3] { bone.Position.X, bone.Position.Y, bone.Position.Z }, new float[3] { bone.EulerRotation.X *Rad2Deg, bone.EulerRotation.Y *Rad2Deg, bone.EulerRotation.Z *Rad2Deg }, new float[3] { bone.Scale.X, bone.Scale.Y, bone.Scale.Z }); } } writer.StartLibraryGeometries(); //Try to not write meshes? Let's hope this works. writer.EndGeometrySection(); } progressBar?.Close(); }
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); }
private void CreateByNode(Node node, STSkeleton skeleton, string ParentArmatureName, short SmoothIndex, short RigidIndex, bool IsRoot, ref Assimp.Matrix4x4 rootTransform) { Matrix4x4 trafo = node.Transform; Matrix4x4 world = trafo; var transformMat = AssimpHelper.TKMatrix(world); int matchedBoneIndex = skeleton.bones.FindIndex(item => item.Name == node.Name); if (matchedBoneIndex < 0) { tempBoneNodes.Add(node); STBone bone = new STBone(); bone.skeletonParent = skeleton; bone.RotationType = STBone.BoneRotationType.Euler; skeleton.bones.Add(bone); if (DaeHelper.IDMapToName.ContainsKey(node.Name)) { bone.Text = DaeHelper.IDMapToName[node.Name]; } else { bone.Text = node.Name; } bone.SmoothMatrixIndex = (short)skeleton.bones.IndexOf(bone); bone.RigidMatrixIndex = -1; //Todo calculate these STConsole.WriteLine($"-".Repeat(30)); STConsole.WriteLine($"Processing Bone {bone.Text}"); STConsole.WriteLine($"SmoothMatrixIndex {bone.SmoothMatrixIndex}"); STConsole.WriteLine($"RigidMatrixIndex {bone.RigidMatrixIndex}"); STConsole.WriteLine($"Transform Matrix {transformMat}"); STConsole.WriteLine($"-".Repeat(30)); if (IsRoot) { bone.parentIndex = -1; if (RotateSkeleton) { transformMat = AssimpHelper.TKMatrix(world * Matrix4x4.FromRotationX(MathHelper.DegreesToRadians(RotateSkeletonAmount))); } else { transformMat = AssimpHelper.TKMatrix(world); } } else { if (tempBoneNodes.Contains(node.Parent)) { bone.parentIndex = tempBoneNodes.IndexOf(node.Parent); } } var scale = transformMat.ExtractScale(); var rotation = transformMat.ExtractRotation(); var position = transformMat.ExtractTranslation(); var rotEular = STMath.ToEulerAngles(rotation); bone.position = new float[] { position.X, position.Y, position.Z }; bone.scale = new float[] { scale.X, scale.Y, scale.Z }; bone.rotation = new float[] { rotEular.X, rotEular.Y, rotEular.Z, 1 }; } else { STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red); } foreach (Node child in node.Children) { CreateByNode(child, skeleton, ParentArmatureName, SmoothIndex, RigidIndex, false, ref rootTransform); } }