public void LoadScene() { objects.Clear(); materials.Clear(); skeleton = new STSkeleton(); processNode(); var idenity = Matrix4x4.Identity; BuildSkeletonNodes(scene.RootNode, BoneNames, skeleton, ref idenity); skeleton.update(); skeleton.reset(); if (scene.HasMaterials) { foreach (Material mat in scene.Materials) { materials.Add(CreateGenericMaterial(mat)); } } foreach (Assimp.Animation animation in scene.Animations) { } foreach (var tex in scene.Textures) { } }
public STBone(STSkeleton skl) { skeletonParent = skl; ImageKey = "bone"; SelectedImageKey = "bone"; Checked = true; }
private void SaveBones(Node parentBone, STBone bone, STSkeleton skeleton) { Node boneNode = new Node(bone.Text); parentBone.Children.Add(boneNode); boneNode.Transform = AssimpHelper.GetBoneMatrix(bone); foreach (STBone child in bone.GetChildren()) { SaveBones(boneNode, child, skeleton); } }
private void BuildSkeletonNodes(Node node, List <string> boneNames, STSkeleton skeleton, ref Matrix4x4 rootTransform) { Matrix4x4 trafo = node.Transform; Matrix4x4 world = trafo * rootTransform; Matrix4 worldTK = AssimpHelper.TKMatrix(world); string Name = node.Name; string ParentArmatureName = node.Parent != null ? node.Parent.Name : ""; if (DaeHelper.IDMapToName.ContainsKey(node.Name)) { Name = DaeHelper.IDMapToName[node.Name]; } if (ParentArmatureName != string.Empty && DaeHelper.IDMapToName.ContainsKey(ParentArmatureName)) { ParentArmatureName = DaeHelper.IDMapToName[ParentArmatureName]; } bool IsBone = boneNames.Contains(Name) && !boneNames.Contains(ParentArmatureName) || Name.Contains("Skl_Root") || Name.Contains("nw4f_root") || Name.Contains("skl_root") || Name.Contains("_root") || Name.Contains("skeleton_root"); short SmoothIndex = 0; short RigidIndex = -1; //Loop through all the bones. If the parent is not in the bone list, then it's Parent is the root if (IsBone) { var idenity = Matrix4x4.Identity; var Root = node; if (node.Parent != null) { Root = node.Parent; } CreateByNode(node, skeleton, ParentArmatureName, SmoothIndex, RigidIndex, true, ref idenity); } else { if (node.HasChildren) { foreach (Node child in node.Children) { BuildSkeletonNodes(child, boneNames, skeleton, ref world); } } } }
private void SaveMeshes(Scene scene, STGenericModel model, STSkeleton skeleton, string FileName, List <int> NodeArray) { int MeshIndex = 0; foreach (var obj in model.Nodes[0].Nodes) { var mesh = SaveMesh((STGenericObject)obj, MeshIndex, skeleton, NodeArray); scene.Meshes.Add(mesh); MeshIndex++; } Node geomNode = new Node(Path.GetFileNameWithoutExtension(FileName), scene.RootNode); for (int ob = 0; ob < scene.MeshCount; ob++) { geomNode.MeshIndices.Add(ob); } scene.RootNode.Children.Add(geomNode); }
private void SaveSkeleton(STSkeleton skeleton, Node parentNode) { Node root = new Node("skeleton_root"); parentNode.Children.Add(root); if (skeleton.bones.Count > 0) { Node boneNode = new Node(skeleton.bones[0].Text); boneNode.Transform = AssimpHelper.GetBoneMatrix(skeleton.bones[0]); root.Children.Add(boneNode); foreach (STBone child in skeleton.bones[0].GetChildren()) { SaveBones(boneNode, child, skeleton); } } }
private void CreateByNode(Node node, STSkeleton skeleton, short SmoothIndex, short RigidIndex, bool IsRoot, ref Assimp.Matrix4x4 rootTransform) { Matrix4x4 trafo = node.Transform; Matrix4x4 world = trafo * rootTransform; 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; skeleton.bones.Add(bone); 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; transformMat = AssimpHelper.TKMatrix(world * Matrix4x4.FromRotationX(MathHelper.DegreesToRadians(BoneRotation))); } 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 = AssimpHelper.ToEular(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, 0 }; } else { STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red); } foreach (Node child in node.Children) { CreateByNode(child, skeleton, SmoothIndex, RigidIndex, false, ref rootTransform); } }
public void SaveFromModel(STGenericModel model, string FileName, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null) { ExtractedTextures.Clear(); Scene scene = new Scene(); scene.RootNode = new Node("RootNode"); progressBar = new STProgressBar(); progressBar.Task = "Exorting Skeleton..."; progressBar.Value = 0; progressBar.StartPosition = FormStartPosition.CenterScreen; progressBar.Show(); progressBar.Refresh(); SaveSkeleton(skeleton, scene.RootNode); SaveMaterials(scene, model, FileName, Textures); progressBar.Task = "Exorting Meshes..."; progressBar.Value = 50; SaveMeshes(scene, model, skeleton, FileName, NodeArray); progressBar.Task = "Saving File..."; progressBar.Value = 80; SaveScene(FileName, scene, model.GetObjects()); progressBar.Value = 100; progressBar.Close(); progressBar.Dispose(); }
private Mesh SaveMesh(STGenericObject genericObj, int index, STSkeleton skeleton, List <int> NodeArray) { //Assimp is weird so use mesh_# for the name. We'll change it back after save Mesh mesh = new Mesh($"mesh_{ index }", PrimitiveType.Triangle); mesh.MaterialIndex = genericObj.MaterialIndex; List <Vector3D> textureCoords0 = new List <Vector3D>(); List <Vector3D> textureCoords1 = new List <Vector3D>(); List <Vector3D> textureCoords2 = new List <Vector3D>(); List <Color4D> vertexColors = new List <Color4D>(); int vertexID = 0; foreach (Vertex v in genericObj.vertices) { mesh.Vertices.Add(new Vector3D(v.pos.X, v.pos.Y, v.pos.Z)); mesh.Normals.Add(new Vector3D(v.nrm.X, v.nrm.Y, v.nrm.Z)); textureCoords0.Add(new Vector3D(v.uv0.X, v.uv0.Y, 0)); textureCoords1.Add(new Vector3D(v.uv1.X, v.uv1.Y, 0)); textureCoords2.Add(new Vector3D(v.uv2.X, v.uv2.Y, 0)); vertexColors.Add(new Color4D(v.col.X, v.col.Y, v.col.Z, v.col.W)); mesh.TextureCoordinateChannels[0] = textureCoords0; mesh.TextureCoordinateChannels[1] = textureCoords1; mesh.TextureCoordinateChannels[2] = textureCoords2; mesh.VertexColorChannels[0] = vertexColors; if (skeleton != null) { for (int j = 0; j < v.boneIds.Count; j++) { if (j < genericObj.VertexSkinCount) { //Get the bone via the node array and bone index from the vertex STBone STbone = skeleton.bones[NodeArray[v.boneIds[j]]]; //Find the index of a bone. If it doesn't exist then we add it int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text); if (boneInd == -1) { var matrices = Switch_Toolbox.Library.IO.MatrixExenstion.CalculateInverseMatrix(STbone); //Set the inverse matrix Matrix4x4 transform = matrices.inverse.FromNumerics(); //Create a new assimp bone Bone bone = new Bone(); bone.Name = STbone.Text; bone.OffsetMatrix = STbone.invert.ToMatrix4x4(); mesh.Bones.Add(bone); BoneNames.Add(bone.Name); boneInd = mesh.Bones.IndexOf(bone); //Set the index of the bone for the vertex weight } int MinWeightAmount = 0; //Check if the max amount of weights is higher than the current bone id if (v.boneWeights.Count > j && v.boneWeights[j] > MinWeightAmount) { if (v.boneWeights[j] <= 1) { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, v.boneWeights[j])); } else { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } else if (v.boneWeights.Count == 0 || v.boneWeights[j] > MinWeightAmount) { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } } } vertexID++; } List <int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces; for (int f = 0; f < faces.Count; f++) { mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] })); } mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0); return(mesh); }
public void NextFrame(STSkeleton skeleton, bool isChild = false) { if (Frame >= FrameCount) { return; } if (Frame == 0 && !isChild) { skeleton.reset(); } foreach (object child in Children) { if (child is Animation) { ((Animation)child).SetFrame(Frame); ((Animation)child).NextFrame(skeleton, isChild: true); } } bool Updated = false; // no need to update skeleton of animations that didn't change foreach (KeyNode node in Bones) { // Get Skeleton Node STBone b = null; b = skeleton.getBone(node.Text); if (b == null) { continue; } Updated = true; b.pos.X = node.XPOS.GetValue(Frame); b.pos.Y = node.YPOS.GetValue(Frame); b.pos.Z = node.ZPOS.GetValue(Frame); if (node.XSCA.HasAnimation()) { b.sca.X = node.XSCA.GetValue(Frame); } else { b.sca.X = 1; } if (node.YSCA.HasAnimation()) { b.sca.Y = node.YSCA.GetValue(Frame); } else { b.sca.Y = 1; } if (node.ZSCA.HasAnimation()) { b.sca.Z = node.ZSCA.GetValue(Frame); } else { b.sca.Z = 1; } if (node.XROT.HasAnimation() || node.YROT.HasAnimation() || node.ZROT.HasAnimation()) { if (node.RotType == RotationType.QUATERNION) { KeyFrame[] x = node.XROT.GetFrame(Frame); KeyFrame[] y = node.YROT.GetFrame(Frame); KeyFrame[] z = node.ZROT.GetFrame(Frame); KeyFrame[] w = node.WROT.GetFrame(Frame); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == Frame) { b.rot = q1; } else if (x[1].Frame == Frame) { b.rot = q2; } else { b.rot = Quaternion.Slerp(q1, q2, (Frame - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (node.RotType == RotationType.EULER) { float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.rotation[0]; float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.rotation[1]; float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.rotation[2]; b.rot = EulerToQuat(z, y, x); } } } Frame += 1f; if (Frame >= FrameCount) { Frame = 0; } if (!isChild && Updated) { skeleton.update(); } }
private void SaveMeshes(Scene scene, STGenericModel model, STSkeleton skeleton, string FileName, List <int> NodeArray) { int MeshIndex = 0; foreach (var obj in model.Nodes[0].Nodes) { var genericObj = (STGenericObject)obj; Mesh mesh = new Mesh(genericObj.Text, PrimitiveType.Triangle); mesh.MaterialIndex = genericObj.MaterialIndex; List <Vector3D> textureCoords0 = new List <Vector3D>(); List <Vector3D> textureCoords1 = new List <Vector3D>(); List <Vector3D> textureCoords2 = new List <Vector3D>(); List <Color4D> vertexColors = new List <Color4D>(); int vertexID = 0; foreach (Vertex v in genericObj.vertices) { mesh.Vertices.Add(new Vector3D(v.pos.X, v.pos.Y, v.pos.Z)); mesh.Normals.Add(new Vector3D(v.nrm.X, v.nrm.Y, v.nrm.Z)); textureCoords0.Add(new Vector3D(v.uv0.X, v.uv0.Y, 0)); textureCoords1.Add(new Vector3D(v.uv1.X, v.uv1.Y, 0)); textureCoords2.Add(new Vector3D(v.uv2.X, v.uv2.Y, 0)); vertexColors.Add(new Color4D(v.col.X, v.col.Y, v.col.Z, v.col.W)); mesh.TextureCoordinateChannels[0] = textureCoords0; mesh.TextureCoordinateChannels[1] = textureCoords1; mesh.TextureCoordinateChannels[2] = textureCoords2; mesh.VertexColorChannels[0] = vertexColors; for (int j = 0; j < v.boneIds.Count; j++) { if (j < genericObj.VertexSkinCount) { //Get the bone via the node array and bone index from the vertex STBone STbone = skeleton.bones[NodeArray[v.boneIds[j]]]; //Find the index of a bone. If it doesn't exist then we add it int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text); if (boneInd == -1) { var matrices = Switch_Toolbox.Library.IO.MatrixExenstion.CalculateInverseMatrix(STbone); //Set the inverse matrix Matrix4x4 transform = matrices.inverse.FromNumerics(); //Create a new assimp bone Bone bone = new Bone(); bone.Name = STbone.Text; bone.OffsetMatrix = transform; mesh.Bones.Add(bone); BoneNames.Add(bone.Name); boneInd = mesh.Bones.IndexOf(bone); //Set the index of the bone for the vertex weight } //Check if the max amount of weights is higher than the current bone id if (v.boneWeights.Count > j) { if (v.boneWeights[j] <= 1) { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, v.boneWeights[j])); } else { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } else { mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1)); } } } vertexID++; } List <int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces; for (int f = 0; f < faces.Count; f++) { mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] })); } mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0); scene.Meshes.Add(mesh); MeshIndex++; } Node geomNode = new Node(Path.GetFileNameWithoutExtension(FileName), scene.RootNode); for (int ob = 0; ob < scene.MeshCount; ob++) { geomNode.MeshIndices.Add(ob); } scene.RootNode.Children.Add(geomNode); }
public void SaveFromModel(STGenericModel model, string FileName, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null) { Scene scene = new Scene(); scene.RootNode = new Node("RootNode"); SaveSkeleton(skeleton, scene.RootNode); SaveMaterials(scene, model, FileName, Textures); SaveMeshes(scene, model, skeleton, FileName, NodeArray); using (var v = new AssimpContext()) { string ext = System.IO.Path.GetExtension(FileName); string formatID = "collada"; if (ext == ".obj") { formatID = "obj"; } if (ext == ".3ds") { formatID = "3ds"; } if (ext == ".dae") { formatID = "collada"; } if (ext == ".ply") { formatID = "ply"; } if (v.ExportFile(scene, FileName, formatID, PostProcessSteps.ValidateDataStructure)) { MessageBox.Show($"Exported {FileName} Successfuly!"); } else { MessageBox.Show($"Failed to export {FileName}!"); } } }
public static Animation read(string filename, STSkeleton vbn) { StreamReader reader = File.OpenText(filename); string line; bool isHeader = true; string angularUnit, linearUnit, timeUnit; int startTime = 0; int endTime = 0; List <AnimBone> bones = new List <AnimBone>(); Animation.KeyNode current = null; Animation.KeyFrame att = new Animation.KeyFrame(); bool inKeys = false; string type = ""; Animation a = new Animation(filename); while ((line = reader.ReadLine()) != null) { string[] args = line.Replace(";", "").TrimStart().Split(' '); if (isHeader) { if (args [0].Equals("anim")) { isHeader = false; } else if (args [0].Equals("angularUnit")) { angularUnit = args [1]; } else if (args [0].Equals("endTime")) { endTime = (int)Math.Ceiling(float.Parse(args [1])); } else if (args [0].Equals("startTime")) { startTime = (int)Math.Ceiling(float.Parse(args [1])); } } if (!isHeader) { if (inKeys) { if (args[0].Equals("}")) { inKeys = false; continue; } Animation.KeyFrame k = new Animation.KeyFrame(); //att.keys.Add (k); if (type.Contains("translate")) { if (type.Contains("X")) { current.XPOS.Keys.Add(k); } if (type.Contains("Y")) { current.YPOS.Keys.Add(k); } if (type.Contains("Z")) { current.ZPOS.Keys.Add(k); } } if (type.Contains("rotate")) { if (type.Contains("X")) { current.XROT.Keys.Add(k); } if (type.Contains("Y")) { current.YROT.Keys.Add(k); } if (type.Contains("Z")) { current.ZROT.Keys.Add(k); } } if (type.Contains("scale")) { if (type.Contains("X")) { current.XSCA.Keys.Add(k); } if (type.Contains("Y")) { current.YSCA.Keys.Add(k); } if (type.Contains("Z")) { current.ZSCA.Keys.Add(k); } } k.Frame = float.Parse(args [0]) - 1; k.Value = float.Parse(args [1]); if (type.Contains("rotate")) { k.Value *= (float)(Math.PI / 180f); } //k.intan = (args [2]); //k.outtan = (args [3]); if (args.Length > 7 && att.Weighted) { k.In = float.Parse(args[7]) * (float)(Math.PI / 180f); k.Out = float.Parse(args[8]) * (float)(Math.PI / 180f); } } if (args [0].Equals("anim")) { inKeys = false; if (args.Length == 5) { //TODO: finish this type // can be name of attribute } if (args.Length == 7) { // see of the bone of this attribute exists current = null; foreach (Animation.KeyNode b in a.Bones) { if (b.Text.Equals(args [3])) { current = b; break; } } if (current == null) { current = new Animation.KeyNode(args[3]); current.RotType = Animation.RotationType.EULER; a.Bones.Add(current); } current.Text = args [3]; att = new Animation.KeyFrame(); att.InterType = Animation.InterpolationType.HERMITE; type = args [2]; //current.Nodes.Add (att); // row child attribute aren't needed here } } /*if (args [0].Equals ("input")) * att.input = args [1]; * if (args [0].Equals ("output")) * att.output = args [1]; * if (args [0].Equals ("preInfinity")) * att.preInfinity = args [1]; * if (args [0].Equals ("postInfinity")) * att.postInfinity = args [1];*/ if (args[0].Equals("weighted")) { att.Weighted = args[1].Equals("1"); } // begining keys section if (args [0].Contains("keys")) { inKeys = true; } } } a.FrameCount = endTime - 1; reader.Close(); return(a); }
public static void CreateANIM(string fname, Animation a, STSkeleton vbn) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@fname)) { file.WriteLine("animVersion 1.1;"); file.WriteLine("mayaVersion 2014 x64;\ntimeUnit ntscf;\nlinearUnit cm;\nangularUnit deg;\nstartTime 1;\nendTime " + (a.FrameCount + 1) + ";"); a.SetFrame(a.FrameCount - 1); //from last frame for (int li = 0; li < a.FrameCount; ++li) //go through each frame with nextFrame { a.NextFrame(vbn); } a.NextFrame(vbn); //go on first frame int i = 0; // writing node attributes foreach (STBone b in vbn.getBoneTreeOrder()) { i = vbn.boneIndex(b.Text); if (a.HasBone(b.Text)) { // write the bone attributes // count the attributes Animation.KeyNode n = a.GetBone(b.Text); int ac = 0; if (n.XPOS.HasAnimation()) { file.WriteLine("anim translate.translateX translateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XPOS, n, a.Size(), "translateX"); file.WriteLine("}"); } if (n.YPOS.HasAnimation()) { file.WriteLine("anim translate.translateY translateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YPOS, n, a.Size(), "translateY"); file.WriteLine("}"); } if (n.ZPOS.HasAnimation()) { file.WriteLine("anim translate.translateZ translateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZPOS, n, a.Size(), "translateZ"); file.WriteLine("}"); } if (n.XROT.HasAnimation()) { file.WriteLine("anim rotate.rotateX rotateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XROT, n, a.Size(), "rotateX"); file.WriteLine("}"); } if (n.YROT.HasAnimation()) { file.WriteLine("anim rotate.rotateY rotateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YROT, n, a.Size(), "rotateY"); file.WriteLine("}"); } if (n.ZROT.HasAnimation()) { file.WriteLine("anim rotate.rotateZ rotateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZROT, n, a.Size(), "rotateZ"); file.WriteLine("}"); } if (n.XSCA.HasAnimation()) { file.WriteLine("anim scale.scaleX scaleX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XSCA, n, a.Size(), "scaleX"); file.WriteLine("}"); } if (n.YSCA.HasAnimation()) { file.WriteLine("anim scale.scaleY scaleY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YSCA, n, a.Size(), "scaleY"); file.WriteLine("}"); } if (n.ZSCA.HasAnimation()) { file.WriteLine("anim scale.scaleZ scaleZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZSCA, n, a.Size(), "scaleZ"); file.WriteLine("}"); } } else { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } } }