示例#1
0
        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("all_root") || Name.Contains("_root") || Name.Contains("Root");

            if (DaeHelper.VisualSceneNodeTypes.ContainsKey(Name))
            {
                if (DaeHelper.VisualSceneNodeTypes[Name] == "JOINT")
                {
                    IsBone = true;
                }
            }

            //Root set saved by this tool
            //Get our root manually as it's a child to this
            bool IsRootSkeleton = Name == "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;
                CreateByNode(node, skeleton, ParentArmatureName, SmoothIndex, RigidIndex, true, ref rootTransform);
            }
            else if (IsRootSkeleton && node.HasChildren)
            {
                var idenity = Matrix4x4.Identity;
                CreateByNode(node.Children[0], skeleton, ParentArmatureName, SmoothIndex, RigidIndex, true, ref world);
            }
            else
            {
                if (node.HasChildren)
                {
                    foreach (Node child in node.Children)
                    {
                        BuildSkeletonNodes(child, boneNames, skeleton, ref world);
                    }
                }
            }
        }
示例#2
0
        private void SaveSkeleton(STSkeleton skeleton, Node parentNode)
        {
            Node root = new Node("skeleton_root");

            parentNode.Children.Add(root);

            Console.WriteLine($"bones {skeleton.bones.Count}");

            if (skeleton.bones.Count > 0)
            {
                foreach (var bone in skeleton.bones)
                {
                    //Get each root bone and find children
                    if (bone.parentIndex == -1)
                    {
                        Node boneNode = new Node(bone.Text);
                        boneNode.Transform = AssimpHelper.GetBoneMatrix(bone);
                        root.Children.Add(boneNode);

                        foreach (STBone child in bone.GetChildren())
                        {
                            SaveBones(boneNode, child, skeleton);
                        }
                    }
                }
            }
        }
示例#3
0
        public STBone(STSkeleton skl)
        {
            skeletonParent   = skl;
            ImageKey         = "bone";
            SelectedImageKey = "bone";

            Checked = true;
        }
示例#4
0
        public void LoadScene()
        {
            objects.Clear();
            materials.Clear();
            BoneNames.Clear();
            skeleton = new STSkeleton();

            processNode();

            if (scene.RootNode != null)
            {
                var     rootTransform = scene.RootNode.Transform;
                Matrix4 transformMat  = AssimpHelper.TKMatrix(rootTransform);

                var scale    = transformMat.ExtractScale();
                var rotation = transformMat.ExtractRotation();
                var position = transformMat.ExtractTranslation();

                STConsole.WriteLine($"-".Repeat(30));
                STConsole.WriteLine($"rootTransform {transformMat}");
                STConsole.WriteLine($"scale {scale}");
                STConsole.WriteLine($"rotation {rotation}");
                STConsole.WriteLine($"position {position}");
                STConsole.WriteLine($"-".Repeat(30));

                var SklRoot = GetSklRoot(scene.RootNode, BoneNames);
                if (SklRoot != null)
                {
                    BuildSkeletonNodes(SklRoot, BoneNames, skeleton, ref rootTransform);
                }
                else
                {
                    BuildSkeletonNodes(scene.RootNode, BoneNames, skeleton, ref rootTransform);
                }

                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)
            {
            }
        }
示例#5
0
        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);
            }
        }
示例#6
0
        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);
                }
            }
        }
示例#7
0
        public Matrix4 GetTransform()
        {
            Vector3 mPos = new Vector3(position[0], position[1], position[2]);

            Quaternion mRot;

            if (RotationType == STBone.BoneRotationType.Quaternion)
            {
                mRot = (STSkeleton.FromQuaternionAngles(rotation[2], rotation[1], rotation[0], rotation[3]));
            }
            else
            {
                mRot = (STSkeleton.FromEulerAngles(rotation[2], rotation[1], rotation[0]));
            }

            Vector3 mSca = new Vector3(scale[0], scale[1], scale[2]);

            return(Matrix4.CreateScale(mSca) * Matrix4.CreateFromQuaternion(mRot) * Matrix4.CreateTranslation(mPos));
        }
示例#8
0
        public void LoadScene()
        {
            objects.Clear();
            materials.Clear();
            BoneNames.Clear();
            skeleton = new STSkeleton();

            processNode();

            if (scene.RootNode != null)
            {
                var idenity = Matrix4x4.Identity;

                var SklRoot = GetSklRoot(scene.RootNode, BoneNames);
                if (SklRoot != null)
                {
                    BuildSkeletonNodes(SklRoot, BoneNames, skeleton, ref idenity);
                }
                else
                {
                    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)
            {
            }
        }
示例#9
0
        private void SaveMeshes(Scene scene, List <STGenericObject> Meshes, STSkeleton skeleton, string FileName, List <int> NodeArray)
        {
            int MeshIndex = 0;

            foreach (var obj in Meshes)
            {
                var mesh = SaveMesh((STGenericObject)obj, scene, MeshIndex++, skeleton, NodeArray);
                scene.Meshes.Add(mesh);
            }
            Node geomNode = new Node(Path.GetFileNameWithoutExtension(FileName), scene.RootNode);

            for (int ob = 0; ob < scene.MeshCount; ob++)
            {
                geomNode.MeshIndices.Add(ob);

                //     if (!scene.Meshes[ob].HasBones)
            }

            scene.RootNode.Children.Add(geomNode);
        }
示例#10
0
        public void CreateGenericModel(string FileName)
        {
            skeleton = new STSkeleton();

            var seModel = SELib.SEModel.Read(FileName);

            for (int i = 0; i < seModel.MeshCount; i++)
            {
                objects.Add(CreateGenericObject(seModel, seModel.Meshes[i]));
            }

            for (int i = 0; i < seModel.MaterialCount; i++)
            {
                materials.Add(CreateGenericMaterial(seModel, seModel.Materials[i]));
            }

            for (int i = 0; i < seModel.BoneCount; i++)
            {
                skeleton.bones.Add(CreateGenericBone(seModel, seModel.Bones[i]));
            }
        }
示例#11
0
 public static void Export(string FileName, ExportSettings settings, STGenericModel model, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null)
 {
     Export(FileName, settings, model.Objects.ToList(), model.Materials.ToList(), Textures, skeleton, NodeArray);
 }
示例#12
0
        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 * 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;
                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

                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();

                STConsole.WriteLine($"-".Repeat(30));
                STConsole.WriteLine($"Processing Bone {bone.Text}");
                STConsole.WriteLine($"scale {scale}");
                STConsole.WriteLine($"rotation {rotation}");
                STConsole.WriteLine($"position {position}");
                STConsole.WriteLine($"-".Repeat(30));

                bone.FromTransform(transformMat);
            }
            else
            {
                STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red);
            }

            var identity = Matrix4x4.Identity;

            foreach (Node child in node.Children)
            {
                CreateByNode(child, skeleton, ParentArmatureName, SmoothIndex, RigidIndex, false, ref identity);
            }
        }
示例#13
0
 public void SaveFromModel(STGenericModel model, string FileName, List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null)
 {
     SaveFromModel(model.Objects.ToList(), model.Materials.ToList(), FileName, Textures, skeleton, NodeArray);
 }
示例#14
0
        public void SaveFromModel(List <STGenericObject> Meshes, List <STGenericMaterial> Materials, 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          = "Exporting Skeleton...";
            progressBar.Value         = 0;
            progressBar.StartPosition = FormStartPosition.CenterScreen;
            progressBar.Show();
            progressBar.Refresh();

            SaveSkeleton(skeleton, scene.RootNode);
            SaveMaterials(scene, Materials, FileName, Textures);

            progressBar.Task  = "Exporting Meshes...";
            progressBar.Value = 50;

            SaveMeshes(scene, Meshes, skeleton, FileName, NodeArray);

            progressBar.Task  = "Saving File...";
            progressBar.Value = 80;

            SaveScene(FileName, scene, Meshes);

            progressBar.Value = 100;
            progressBar.Close();
            progressBar.Dispose();
        }
示例#15
0
        private Mesh SaveMesh(STGenericObject genericObj, Scene scene, 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);

            if (genericObj.MaterialIndex < scene.MaterialCount && genericObj.MaterialIndex > 0)
            {
                mesh.MaterialIndex = genericObj.MaterialIndex;
            }
            else
            {
                mesh.MaterialIndex = 0;
            }

            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));

                if (skeleton != null)
                {
                    for (int j = 0; j < v.boneIds.Count; j++)
                    {
                        if (j < genericObj.VertexSkinCount)
                        {
                            STBone STbone = null;
                            if (NodeArray != null)
                            {
                                //Get the bone via the node array and bone index from the vertex
                                STbone = skeleton.bones[NodeArray[v.boneIds[j]]];
                            }
                            else
                            {
                                STbone = skeleton.bones[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 = 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++;
            }

            if (genericObj.lodMeshes.Count != 0)
            {
                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] }));
                }
            }
            if (genericObj.PolygonGroups.Count != 0)
            {
                for (int p = 0; p < genericObj.PolygonGroups.Count; p++)
                {
                    var polygonGroup = genericObj.PolygonGroups[p];
                    for (int f = 0; f < polygonGroup.faces.Count; f++)
                    {
                        if (f < polygonGroup.faces.Count - 2)
                        {
                            mesh.Faces.Add(new Face(new int[] { polygonGroup.faces[f++], polygonGroup.faces[f++], polygonGroup.faces[f] }));
                        }
                    }
                }
            }

            mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0);
            mesh.TextureCoordinateChannels.SetValue(textureCoords1, 1);
            mesh.TextureCoordinateChannels.SetValue(textureCoords2, 2);
            mesh.VertexColorChannels.SetValue(vertexColors, 0);

            return(mesh);
        }
示例#16
0
        //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();
        }
示例#17
0
 public bool ExportFile(string FileName, List <STGenericObject> meshes, STSkeleton skeleton = null)
 {
     return(false);
 }
示例#18
0
        public static void Export(string FileName, ExportSettings settings,
                                  List <STGenericObject> Meshes, List <STGenericMaterial> Materials,
                                  List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null)
        {
            if (Materials == null)
            {
                Materials = new List <STGenericMaterial>();
            }
            if (skeleton != null && skeleton.BoneIndices != null)
            {
                NodeArray = skeleton.BoneIndices.ToList();
            }

            List <string> failedTextureExport = new List <string>();

            STProgressBar progressBar = new STProgressBar();

            progressBar.Task          = "Exporting Model...";
            progressBar.Value         = 0;
            progressBar.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            progressBar.Show();
            progressBar.Refresh();

            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);
            Dictionary <string, STGenericMaterial> MaterialRemapper = new Dictionary <string, STGenericMaterial>();

            using (ColladaWriter writer = new ColladaWriter(FileName, settings))
            {
                writer.WriteAsset();

                if (Materials.Count > 0)
                {
                    List <string> textureNames = new List <string>();
                    for (int i = 0; i < Textures?.Count; i++)
                    {
                        if (!textureNames.Contains(Textures[i].Text))
                        {
                            textureNames.Add(Textures[i].Text);
                        }

                        if (settings.ExportTextures)
                        {
                            progressBar.Task  = $"Exporting Texture {Textures[i].Text}";
                            progressBar.Value = ((i * 100) / Textures.Count);
                            progressBar.Refresh();

                            try
                            {
                                var bitmap = Textures[i].GetBitmap();
                                if (bitmap != null)
                                {
                                    if (settings.UseTextureChannelComponents)
                                    {
                                        bitmap = Textures[i].GetComponentBitmap(bitmap);
                                    }
                                    string textureName = Textures[i].Text;
                                    if (textureName.RemoveIllegaleFileNameCharacters() != textureName)
                                    {
                                        string properName = textureName.RemoveIllegaleFileNameCharacters();
                                        for (int m = 0; m < Materials?.Count; m++)
                                        {
                                            foreach (var tex in Materials[m].TextureMaps)
                                            {
                                                if (tex.Name == textureName)
                                                {
                                                    tex.Name = properName;
                                                }
                                            }
                                        }

                                        textureName = properName;
                                    }

                                    bitmap.Save($"{TexturePath}/{textureName}.png");
                                    bitmap.Dispose();

                                    GC.Collect();
                                }
                            }
                            catch (Exception ex) {
                                failedTextureExport.Add(Textures[i].Text);
                            }
                        }
                    }

                    List <Material> materials = new List <Material>();
                    foreach (var mat in Materials)
                    {
                        Material material = new Material();
                        material.Name = mat.Text;

                        if (!MaterialRemapper.ContainsKey(mat.Text))
                        {
                            MaterialRemapper.Add(mat.Text, mat);
                        }
                        else
                        {
                            string name = Utils.RenameDuplicateString(MaterialRemapper.Keys.ToList(), mat.Text);
                            MaterialRemapper.Add(name, mat);
                            material.Name = name;
                        }

                        materials.Add(material);

                        foreach (var tex in mat.TextureMaps)
                        {
                            TextureMap texMap = new TextureMap();
                            texMap.Name = tex.Name;
                            if (tex.Type == STGenericMatTexture.TextureType.Diffuse)
                            {
                                texMap.Type = PhongTextureType.diffuse;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Normal)
                            {
                                texMap.Type = PhongTextureType.bump;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Specular)
                            {
                                texMap.Type = PhongTextureType.specular;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Emission)
                            {
                                texMap.Type = PhongTextureType.emission;
                            }
                            else
                            {
                                continue; //Skip adding unknown types
                            }
                            if (tex.WrapModeS == STTextureWrapMode.Repeat)
                            {
                                texMap.WrapModeS = SamplerWrapMode.WRAP;
                            }
                            else if (tex.WrapModeS == STTextureWrapMode.Mirror)
                            {
                                texMap.WrapModeS = SamplerWrapMode.MIRROR;
                            }
                            else if (tex.WrapModeS == STTextureWrapMode.Clamp)
                            {
                                texMap.WrapModeS = SamplerWrapMode.CLAMP;
                            }


                            if (tex.WrapModeT == STTextureWrapMode.Repeat)
                            {
                                texMap.WrapModeT = SamplerWrapMode.WRAP;
                            }
                            else if (tex.WrapModeT == STTextureWrapMode.Mirror)
                            {
                                texMap.WrapModeT = SamplerWrapMode.MIRROR;
                            }
                            else if (tex.WrapModeT == STTextureWrapMode.Clamp)
                            {
                                texMap.WrapModeT = SamplerWrapMode.CLAMP;
                            }


                            //If no textures are saved, still keep images references
                            //So the user can still dump textures after
                            if (Textures?.Count == 0 && !textureNames.Contains(texMap.Name))
                            {
                                textureNames.Add($"{texMap.Name}");
                            }

                            material.Textures.Add(texMap);
                        }
                    }

                    writer.WriteLibraryImages(textureNames.ToArray());

                    writer.WriteLibraryMaterials(materials);
                    writer.WriteLibraryEffects(materials);
                }
                else
                {
                    writer.WriteLibraryImages();
                }

                if (skeleton != null)
                {
                    //Search for bones with rigging first
                    List <string> riggedBones = new List <string>();
                    if (settings.OnlyExportRiggedBones)
                    {
                        for (int i = 0; i < Meshes.Count; i++)
                        {
                            for (int v = 0; v < Meshes[i].vertices.Count; v++)
                            {
                                var vertex = Meshes[i].vertices[v];
                                for (int j = 0; j < vertex.boneIds.Count; j++)
                                {
                                    int id = -1;
                                    if (NodeArray != null && NodeArray.Count > vertex.boneIds[j])
                                    {
                                        id = NodeArray[vertex.boneIds[j]];
                                    }
                                    else
                                    {
                                        id = vertex.boneIds[j];
                                    }

                                    if (id < skeleton.bones.Count && id != -1)
                                    {
                                        riggedBones.Add(skeleton.bones[id].Text);
                                    }
                                }
                            }
                        }
                    }

                    foreach (var bone in skeleton.bones)
                    {
                        if (settings.OnlyExportRiggedBones && !riggedBones.Contains(bone.Text))
                        {
                            Console.WriteLine("Skipping " + bone.Text);
                            continue;
                        }

                        //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
                        });
                    }
                }

                int meshIndex = 0;

                writer.StartLibraryGeometries();
                foreach (var mesh in Meshes)
                {
                    progressBar.Task  = $"Exporting Mesh {mesh.Text}";
                    progressBar.Value = ((meshIndex++ *100) / Meshes.Count);
                    progressBar.Refresh();

                    int[] IndexTable = null;
                    if (NodeArray != null)
                    {
                        IndexTable = NodeArray.ToArray();
                    }

                    writer.StartGeometry(mesh.Text);

                    if (mesh.MaterialIndex != -1 && Materials.Count > mesh.MaterialIndex)
                    {
                        writer.CurrentMaterial = Materials[mesh.MaterialIndex].Text;
                        Console.WriteLine($"MaterialIndex {mesh.MaterialIndex } {Materials[mesh.MaterialIndex].Text}");
                    }


                    if (settings.TransformColorUVs)
                    {
                        List <Vertex> transformedVertices = new List <Vertex>();
                        foreach (var poly in mesh.PolygonGroups)
                        {
                            var mat = poly.Material;
                            if (mat == null)
                            {
                                continue;
                            }

                            var faces = poly.GetDisplayFace();
                            for (int v = 0; v < poly.displayFaceSize; v += 3)
                            {
                                if (faces.Count < v + 2)
                                {
                                    break;
                                }

                                var diffuse = mat.TextureMaps.FirstOrDefault(x => x.Type == STGenericMatTexture.TextureType.Diffuse);
                                STTextureTransform transform = new STTextureTransform();
                                if (diffuse != null)
                                {
                                    transform = diffuse.Transform;
                                }

                                var vertexA = mesh.vertices[faces[v]];
                                var vertexB = mesh.vertices[faces[v + 1]];
                                var vertexC = mesh.vertices[faces[v + 2]];

                                if (!transformedVertices.Contains(vertexA))
                                {
                                    vertexA.uv0 = (vertexA.uv0 * transform.Scale) + transform.Translate;
                                    transformedVertices.Add(vertexA);
                                }
                                if (!transformedVertices.Contains(vertexB))
                                {
                                    vertexB.uv0 = (vertexB.uv0 * transform.Scale) + transform.Translate;
                                    transformedVertices.Add(vertexB);
                                }
                                if (!transformedVertices.Contains(vertexC))
                                {
                                    vertexC.uv0 = (vertexC.uv0 * transform.Scale) + transform.Translate;
                                    transformedVertices.Add(vertexC);
                                }
                            }
                        }
                    }

                    // collect sources
                    List <float>   Position    = new List <float>();
                    List <float>   Normal      = new List <float>();
                    List <float>   UV0         = new List <float>();
                    List <float>   UV1         = new List <float>();
                    List <float>   UV2         = new List <float>();
                    List <float>   UV3         = new List <float>();
                    List <float>   Color       = new List <float>();
                    List <float>   Color2      = new List <float>();
                    List <int[]>   BoneIndices = new List <int[]>();
                    List <float[]> BoneWeights = new List <float[]>();

                    bool HasNormals = false;
                    bool HasColors  = false;
                    bool HasColors2 = false;
                    bool HasUV0     = false;
                    bool HasUV1     = false;
                    bool HasUV2     = false;
                    bool HasBoneIds = false;

                    foreach (var vertex in mesh.vertices)
                    {
                        if (vertex.nrm != Vector3.Zero)
                        {
                            HasNormals = true;
                        }
                        if (vertex.col != Vector4.One && settings.UseVertexColors)
                        {
                            HasColors = true;
                        }
                        if (vertex.col2 != Vector4.One && settings.UseVertexColors)
                        {
                            HasColors2 = true;
                        }
                        if (vertex.uv0 != Vector2.Zero)
                        {
                            HasUV0 = true;
                        }
                        if (vertex.uv1 != Vector2.Zero)
                        {
                            HasUV1 = true;
                        }
                        if (vertex.uv2 != Vector2.Zero)
                        {
                            HasUV2 = true;
                        }
                        if (vertex.boneIds.Count > 0)
                        {
                            HasBoneIds = true;
                        }

                        Position.Add(vertex.pos.X); Position.Add(vertex.pos.Y); Position.Add(vertex.pos.Z);
                        Normal.Add(vertex.nrm.X); Normal.Add(vertex.nrm.Y); Normal.Add(vertex.nrm.Z);

                        if (settings.FlipTexCoordsVertical)
                        {
                            UV0.Add(vertex.uv0.X); UV0.Add(1 - vertex.uv0.Y);
                            UV1.Add(vertex.uv1.X); UV1.Add(1 - vertex.uv1.Y);
                            UV2.Add(vertex.uv2.X); UV2.Add(1 - vertex.uv2.Y);
                        }
                        else
                        {
                            UV0.Add(vertex.uv0.X); UV0.Add(vertex.uv0.Y);
                            UV1.Add(vertex.uv1.X); UV1.Add(vertex.uv1.Y);
                            UV2.Add(vertex.uv2.X); UV2.Add(vertex.uv2.Y);
                        }

                        Color.AddRange(new float[] { vertex.col.X, vertex.col.Y, vertex.col.Z, vertex.col.W });
                        Color2.AddRange(new float[] { vertex.col2.X, vertex.col2.Y, vertex.col2.Z, vertex.col2.W });

                        List <int>   bIndices = new List <int>();
                        List <float> bWeights = new List <float>();
                        for (int b = 0; b < vertex.boneIds.Count; b++)
                        {
                            if (b > mesh.VertexSkinCount - 1)
                            {
                                continue;
                            }

                            //Skip 0 weights
                            if (vertex.boneWeights.Count > b)
                            {
                                if (vertex.boneWeights[b] == 0)
                                {
                                    continue;
                                }
                            }

                            int index = -1;
                            if (IndexTable != null)
                            {
                                index = (int)IndexTable[vertex.boneIds[b]];
                            }
                            else
                            {
                                index = (int)vertex.boneIds[b];
                            }

                            //Only map for valid weights/indices
                            bool hasValidIndex  = index != -1 && index < skeleton?.bones.Count;
                            bool hasValidWeight = vertex.boneWeights.Count > b;
                            if (hasValidIndex)
                            {
                                bIndices.Add(index);
                            }

                            if (hasValidWeight && hasValidIndex)
                            {
                                bWeights.Add(vertex.boneWeights[b]);
                            }
                        }
                        //Rigid bodies with no direct bone indices
                        if (bIndices.Count == 0 && mesh.BoneIndex != -1)
                        {
                            HasBoneIds = true;
                            bIndices.Add(mesh.BoneIndex);
                            bWeights.Add(1);
                        }
                        //Bone indices with no weights directly mapped
                        if (bWeights.Count == 0 && bIndices.Count > 0)
                        {
                            bWeights.Add(1.0f);
                        }

                        BoneIndices.Add(bIndices.ToArray());
                        BoneWeights.Add(bWeights.ToArray());
                    }

                    List <TriangleList> triangleLists = new List <TriangleList>();
                    if (mesh.lodMeshes.Count > 0)
                    {
                        TriangleList triangleList = new TriangleList();
                        triangleLists.Add(triangleList);

                        var lodMesh = mesh.lodMeshes[mesh.DisplayLODIndex];

                        List <int> faces = new List <int>();
                        if (lodMesh.PrimativeType == STPrimitiveType.TrangleStrips)
                        {
                            faces = STGenericObject.ConvertTriangleStripsToTriangles(lodMesh.faces);
                        }
                        else
                        {
                            faces = lodMesh.faces;
                        }

                        for (int i = 0; i < faces.Count; i++)
                        {
                            triangleList.Indices.Add((uint)faces[i]);
                        }
                    }
                    if (mesh.PolygonGroups.Count > 0)
                    {
                        foreach (var group in mesh.PolygonGroups)
                        {
                            TriangleList triangleList = new TriangleList();

                            triangleLists.Add(triangleList);

                            STGenericMaterial material = new STGenericMaterial();

                            if (group.MaterialIndex != -1 && Materials.Count > group.MaterialIndex)
                            {
                                material = Materials[group.MaterialIndex];
                            }

                            if (group.Material != null)
                            {
                                material = group.Material;
                            }

                            if (MaterialRemapper.Values.Any(x => x == material))
                            {
                                var key = MaterialRemapper.FirstOrDefault(x => x.Value == material).Key;
                                triangleList.Material = key;
                            }
                            else if (material.Text != string.Empty)
                            {
                                triangleList.Material = material.Text;
                            }

                            List <int> faces = new List <int>();
                            if (group.PrimativeType == STPrimitiveType.TrangleStrips)
                            {
                                faces = STGenericObject.ConvertTriangleStripsToTriangles(group.faces);
                            }
                            else
                            {
                                faces = group.faces;
                            }

                            for (int i = 0; i < faces.Count; i++)
                            {
                                triangleList.Indices.Add((uint)faces[i]);
                            }
                        }
                    }

                    // write sources
                    writer.WriteGeometrySource(mesh.Text, SemanticType.POSITION, Position.ToArray(), triangleLists.ToArray());

                    if (HasNormals)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.NORMAL, Normal.ToArray(), triangleLists.ToArray());
                    }

                    if (HasColors)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color.ToArray(), triangleLists.ToArray(), 0);
                    }

                    if (HasColors2)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color2.ToArray(), triangleLists.ToArray(), 1);
                    }

                    if (HasUV0)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV0.ToArray(), triangleLists.ToArray(), 0);
                    }

                    if (HasUV1)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV1.ToArray(), triangleLists.ToArray(), 1);
                    }

                    if (HasUV2)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV2.ToArray(), triangleLists.ToArray(), 2);
                    }

                    if (HasBoneIds)
                    {
                        writer.AttachGeometryController(BoneIndices, BoneWeights);
                    }

                    writer.EndGeometryMesh();
                }
                writer.EndGeometrySection();
            }

            progressBar?.Close();

            if (!settings.SuppressConfirmDialog)
            {
                System.Windows.Forms.MessageBox.Show($"Exported {FileName} Successfuly!");
            }
        }
示例#19
0
        public static void Export(string FileName, ExportSettings settings,
                                  List <STGenericObject> Meshes, List <STGenericMaterial> Materials,
                                  List <STGenericTexture> Textures, STSkeleton skeleton = null, List <int> NodeArray = null)
        {
            if (Materials == null)
            {
                Materials = new List <STGenericMaterial>();
            }

            List <string> failedTextureExport = new List <string>();

            STProgressBar progressBar = new STProgressBar();

            progressBar.Task          = "Exporting Model...";
            progressBar.Value         = 0;
            progressBar.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            progressBar.Show();
            progressBar.Refresh();

            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();

                if (Materials.Count > 0)
                {
                    List <string> textureNames = new List <string>();
                    for (int i = 0; i < Textures?.Count; i++)
                    {
                        textureNames.Add(Textures[i].Text);

                        if (settings.ExportTextures)
                        {
                            progressBar.Task  = $"Exporting Texture {Textures[i].Text}";
                            progressBar.Value = ((i * 100) / Textures.Count);
                            progressBar.Refresh();

                            try
                            {
                                var bitmap = Textures[i].GetBitmap();
                                if (bitmap != null)
                                {
                                    string textureName = Textures[i].Text;
                                    if (textureName.RemoveIllegaleFileNameCharacters() != textureName)
                                    {
                                        string properName = textureName.RemoveIllegaleFileNameCharacters();
                                        for (int m = 0; m < Materials?.Count; m++)
                                        {
                                            foreach (var tex in Materials[m].TextureMaps)
                                            {
                                                if (tex.Name == textureName)
                                                {
                                                    tex.Name = properName;
                                                }
                                            }
                                        }

                                        textureName = properName;
                                    }

                                    bitmap.Save($"{TexturePath}/{textureName}.png");
                                    bitmap.Dispose();

                                    GC.Collect();
                                }
                            }
                            catch (Exception ex) {
                                failedTextureExport.Add(Textures[i].Text);
                            }
                        }
                    }

                    List <Material> materials = new List <Material>();
                    foreach (var mat in Materials)
                    {
                        Material material = new Material();
                        material.Name = mat.Text;
                        materials.Add(material);

                        foreach (var tex in mat.TextureMaps)
                        {
                            TextureMap texMap = new TextureMap();
                            texMap.Name = tex.Name;
                            if (tex.Type == STGenericMatTexture.TextureType.Diffuse)
                            {
                                texMap.Type = PhongTextureType.diffuse;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Normal)
                            {
                                texMap.Type = PhongTextureType.bump;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Specular)
                            {
                                texMap.Type = PhongTextureType.specular;
                            }
                            else if (tex.Type == STGenericMatTexture.TextureType.Emission)
                            {
                                texMap.Type = PhongTextureType.emission;
                            }
                            else
                            {
                                continue; //Skip adding unknown types
                            }
                            if (tex.WrapModeS == STTextureWrapMode.Repeat)
                            {
                                texMap.WrapModeS = SamplerWrapMode.WRAP;
                            }
                            else if (tex.WrapModeS == STTextureWrapMode.Mirror)
                            {
                                texMap.WrapModeS = SamplerWrapMode.MIRROR;
                            }
                            else if (tex.WrapModeS == STTextureWrapMode.Clamp)
                            {
                                texMap.WrapModeS = SamplerWrapMode.CLAMP;
                            }


                            if (tex.WrapModeT == STTextureWrapMode.Repeat)
                            {
                                texMap.WrapModeT = SamplerWrapMode.WRAP;
                            }
                            else if (tex.WrapModeT == STTextureWrapMode.Mirror)
                            {
                                texMap.WrapModeT = SamplerWrapMode.MIRROR;
                            }
                            else if (tex.WrapModeT == STTextureWrapMode.Clamp)
                            {
                                texMap.WrapModeT = SamplerWrapMode.CLAMP;
                            }


                            //If no textures are saved, still keep images references
                            //So the user can still dump textures after
                            if (Textures?.Count == 0)
                            {
                                textureNames.Add($"{texMap.Name}");
                            }

                            material.Textures.Add(texMap);
                        }
                    }

                    writer.WriteLibraryImages(textureNames.ToArray());

                    writer.WriteLibraryMaterials(materials);
                    writer.WriteLibraryEffects(materials);
                }
                else
                {
                    writer.WriteLibraryImages();
                }

                if (skeleton != null)
                {
                    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);
                    }
                }

                int meshIndex = 0;

                writer.StartLibraryGeometries();
                foreach (var mesh in Meshes)
                {
                    progressBar.Task  = $"Exporting Mesh {mesh.Text}";
                    progressBar.Value = ((meshIndex++ *100) / Meshes.Count);
                    progressBar.Refresh();

                    int[] IndexTable = null;
                    if (NodeArray != null)
                    {
                        IndexTable = NodeArray.ToArray();
                    }

                    writer.StartGeometry(mesh.Text);

                    if (mesh.MaterialIndex != -1 && Materials.Count > mesh.MaterialIndex)
                    {
                        writer.CurrentMaterial = Materials[mesh.MaterialIndex].Text;
                    }

                    // collect sources
                    List <float>   Position    = new List <float>();
                    List <float>   Normal      = new List <float>();
                    List <float>   UV0         = new List <float>();
                    List <float>   UV1         = new List <float>();
                    List <float>   UV2         = new List <float>();
                    List <float>   UV3         = new List <float>();
                    List <float>   Color       = new List <float>();
                    List <int[]>   BoneIndices = new List <int[]>();
                    List <float[]> BoneWeights = new List <float[]>();

                    bool HasNormals = false;
                    bool HasColors  = false;
                    bool HasUV0     = false;
                    bool HasUV1     = false;
                    bool HasUV2     = false;
                    bool HasBoneIds = false;

                    foreach (var vertex in mesh.vertices)
                    {
                        //Remove zero weights
                        if (settings.OptmizeZeroWeights)
                        {
                            float MaxWeight = 1;
                            for (int i = 0; i < 4; i++)
                            {
                                if (vertex.boneWeights.Count <= i)
                                {
                                    continue;
                                }

                                if (vertex.boneIds.Count < i + 1)
                                {
                                    vertex.boneWeights[i] = 0;
                                    MaxWeight             = 0;
                                }
                                else
                                {
                                    float weight = vertex.boneWeights[i];
                                    if (vertex.boneWeights.Count == i + 1)
                                    {
                                        weight = MaxWeight;
                                    }

                                    if (weight >= MaxWeight)
                                    {
                                        weight    = MaxWeight;
                                        MaxWeight = 0;
                                    }
                                    else
                                    {
                                        MaxWeight -= weight;
                                    }

                                    vertex.boneWeights[i] = weight;
                                }
                            }
                        }


                        if (vertex.nrm != Vector3.Zero)
                        {
                            HasNormals = true;
                        }
                        if (vertex.col != Vector4.One && settings.UseVertexColors)
                        {
                            HasColors = true;
                        }
                        if (vertex.uv0 != Vector2.Zero)
                        {
                            HasUV0 = true;
                        }
                        if (vertex.uv1 != Vector2.Zero)
                        {
                            HasUV1 = true;
                        }
                        if (vertex.uv2 != Vector2.Zero)
                        {
                            HasUV2 = true;
                        }
                        if (vertex.boneIds.Count > 0)
                        {
                            HasBoneIds = true;
                        }

                        Position.Add(vertex.pos.X); Position.Add(vertex.pos.Y); Position.Add(vertex.pos.Z);
                        Normal.Add(vertex.nrm.X); Normal.Add(vertex.nrm.Y); Normal.Add(vertex.nrm.Z);

                        if (settings.FlipTexCoordsVertical)
                        {
                            UV0.Add(vertex.uv0.X); UV0.Add(1 - vertex.uv0.Y);
                            UV1.Add(vertex.uv1.X); UV1.Add(1 - vertex.uv1.Y);
                            UV2.Add(vertex.uv2.X); UV2.Add(1 - vertex.uv2.Y);
                        }
                        else
                        {
                            UV0.Add(vertex.uv0.X); UV0.Add(vertex.uv0.Y);
                            UV1.Add(vertex.uv1.X); UV1.Add(vertex.uv1.Y);
                            UV2.Add(vertex.uv2.X); UV2.Add(vertex.uv2.Y);
                        }

                        Color.AddRange(new float[] { vertex.col.X, vertex.col.Y, vertex.col.Z, vertex.col.W });

                        List <int>   bIndices = new List <int>();
                        List <float> bWeights = new List <float>();
                        for (int b = 0; b < vertex.boneIds.Count; b++)
                        {
                            if (b > mesh.VertexSkinCount - 1)
                            {
                                continue;
                            }

                            if (vertex.boneWeights.Count > b)
                            {
                                if (vertex.boneWeights[b] == 0)
                                {
                                    continue;
                                }
                            }

                            int index = -1;
                            if (IndexTable != null)
                            {
                                index = (int)IndexTable[vertex.boneIds[b]];
                            }
                            else
                            {
                                index = (int)vertex.boneIds[b];
                            }

                            if (index != -1 && index < skeleton?.bones.Count)
                            {
                                bIndices.Add(index);
                            }

                            //Some models may only use indices (single bind, rigid skin)
                            if (vertex.boneWeights.Count > b)
                            {
                                bWeights.Add(vertex.boneWeights[b]);
                            }
                            else
                            {
                                bWeights.Add(1);
                            }
                        }

                        if (bIndices.Count == 0 && mesh.BoneIndex != -1)
                        {
                            HasBoneIds = true;
                            bIndices.Add(mesh.BoneIndex);
                            bWeights.Add(1);
                        }

                        BoneIndices.Add(bIndices.ToArray());
                        BoneWeights.Add(bWeights.ToArray());
                    }

                    List <TriangleList> triangleLists = new List <TriangleList>();
                    if (mesh.lodMeshes.Count > 0)
                    {
                        TriangleList triangleList = new TriangleList();
                        triangleLists.Add(triangleList);

                        var lodMesh = mesh.lodMeshes[mesh.DisplayLODIndex];

                        List <int> faces = new List <int>();
                        if (lodMesh.PrimativeType == STPrimitiveType.TrangleStrips)
                        {
                            faces = STGenericObject.ConvertTriangleStripsToTriangles(lodMesh.faces);
                        }
                        else
                        {
                            faces = lodMesh.faces;
                        }

                        for (int i = 0; i < faces.Count; i++)
                        {
                            triangleList.Indices.Add((uint)faces[i]);
                        }
                    }
                    if (mesh.PolygonGroups.Count > 0)
                    {
                        foreach (var group in mesh.PolygonGroups)
                        {
                            TriangleList triangleList = new TriangleList();

                            triangleLists.Add(triangleList);

                            if (group.MaterialIndex != -1 && Materials.Count > group.MaterialIndex)
                            {
                                triangleList.Material = Materials[group.MaterialIndex].Text;
                            }

                            List <int> faces = new List <int>();
                            if (group.PrimativeType == STPrimitiveType.TrangleStrips)
                            {
                                faces = STGenericObject.ConvertTriangleStripsToTriangles(group.faces);
                            }
                            else
                            {
                                faces = group.faces;
                            }

                            for (int i = 0; i < faces.Count; i++)
                            {
                                triangleList.Indices.Add((uint)faces[i]);
                            }
                        }
                    }

                    // write sources
                    writer.WriteGeometrySource(mesh.Text, SemanticType.POSITION, Position.ToArray(), triangleLists.ToArray());

                    if (HasNormals)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.NORMAL, Normal.ToArray(), triangleLists.ToArray());
                    }

                    if (HasColors)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.COLOR, Color.ToArray(), triangleLists.ToArray());
                    }

                    if (HasUV0)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV0.ToArray(), triangleLists.ToArray(), 0);
                    }

                    if (HasUV1)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV1.ToArray(), triangleLists.ToArray(), 1);
                    }

                    if (HasUV2)
                    {
                        writer.WriteGeometrySource(mesh.Text, SemanticType.TEXCOORD, UV2.ToArray(), triangleLists.ToArray(), 2);
                    }

                    if (HasBoneIds)
                    {
                        writer.AttachGeometryController(BoneIndices, BoneWeights);
                    }

                    writer.EndGeometryMesh();
                }
                writer.EndGeometrySection();
            }

            progressBar?.Close();

            if (!settings.SuppressConfirmDialog)
            {
                System.Windows.Forms.MessageBox.Show($"Exported {FileName} Successfuly!");
            }
        }