Exemple #1
0
        public bool CopyIntoSVI(xxFrame meshFrame, int submeshIdx, bool positions, bool bones, bool normals, bool uvs, bool unrestricted, bool nearestBones, bool nearestNormals, bool nearestUVs)
        {
            bool argPositions = positions, argBones = bones, argNormals = normals, argUVs = uvs;

            foreach (sviParser submeshSection in Parser.sections)
            {
                if (submeshSection.meshName == meshFrame.Name && submeshSection.submeshIdx == submeshIdx)
                {
                    xxSubmesh submesh = meshFrame.Mesh.SubmeshList[submeshIdx];
                    int[]     nearestVertexIndices = null;
                    if (nearestBones || nearestNormals || nearestUVs)
                    {
                        if (submeshSection.positionsPresent == 1)
                        {
                            nearestVertexIndices = new int[submesh.VertexList.Count];
                            for (ushort i = 0; i < submesh.VertexList.Count; i++)
                            {
                                int    bestIdx     = -1;
                                double nearestDist = Double.MaxValue;
                                for (ushort j = 0; j < submeshSection.positions.Length; j++)
                                {
                                    double distSquare = (submeshSection.positions[j].X - submesh.VertexList[i].Position.X) * (submeshSection.positions[j].X - submesh.VertexList[i].Position.X)
                                                        + (submeshSection.positions[j].Y - submesh.VertexList[i].Position.Y) * (submeshSection.positions[j].Y - submesh.VertexList[i].Position.Y)
                                                        + (submeshSection.positions[j].Z - submesh.VertexList[i].Position.Z) * (submeshSection.positions[j].Z - submesh.VertexList[i].Position.Z);
                                    if (distSquare < nearestDist)
                                    {
                                        bestIdx     = j;
                                        nearestDist = distSquare;
                                    }
                                }
                                nearestVertexIndices[i] = bestIdx;
                            }
                        }
                        else
                        {
                            Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has no positions in " + Parser.Name + ".");
                            return(false);
                        }
                    }
                    Vector3[] newNormals      = submeshSection.normals;
                    Vector2[] newUVs          = submeshSection.uvs;
                    byte[][]  newBoneIndices  = submeshSection.boneIndices;
                    float[][] newBoneWeights3 = submeshSection.boneWeights3;
                    if (submeshSection.indices.Length != submesh.VertexList.Count)
                    {
                        if (unrestricted)
                        {
                            submeshSection.indices = new ushort[submesh.VertexList.Count];
                            for (ushort i = 0; i < submeshSection.indices.Length; i++)
                            {
                                submeshSection.indices[i] = i;
                            }
                            if (submeshSection.positionsPresent == 1)
                            {
                                submeshSection.positions = new Vector3[submesh.VertexList.Count];
                            }
                            if (submeshSection.bonesPresent == 1)
                            {
                                newBoneWeights3 = new float[submesh.VertexList.Count][];
                                newBoneIndices  = new byte[submesh.VertexList.Count][];
                            }
                            if (submeshSection.normalsPresent == 1)
                            {
                                newNormals = new Vector3[submesh.VertexList.Count];
                            }
                            if (submeshSection.uvsPresent == 1)
                            {
                                newUVs = new Vector2[submesh.VertexList.Count];
                            }

                            positions = bones = normals = uvs = true;
                        }
                        else
                        {
                            Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has a different number of vertices than defined in the sviex(" + submesh.VertexList.Count + "/" + submeshSection.indices.Length + ").");
                            return(false);
                        }
                    }
                    if (positions && submeshSection.positionsPresent == 1)
                    {
                        for (ushort i = 0; i < submeshSection.positions.Length; i++)
                        {
                            submeshSection.positions[i] = submesh.VertexList[submeshSection.indices[i]].Position;
                        }
                    }
                    if (bones && submeshSection.bonesPresent == 1)
                    {
                        if (nearestBones)
                        {
                            for (ushort i = 0; i < newBoneWeights3.Length; i++)
                            {
                                newBoneWeights3[i] = (float[])submeshSection.boneWeights3[nearestVertexIndices[submeshSection.indices[i]]].Clone();
                                newBoneIndices[i]  = (byte[])submeshSection.boneIndices[nearestVertexIndices[submeshSection.indices[i]]].Clone();
                            }
                        }
                        else
                        {
                            for (ushort i = 0; i < newBoneWeights3.Length; i++)
                            {
                                newBoneWeights3[i] = (float[])submesh.VertexList[submeshSection.indices[i]].Weights3.Clone();
                                newBoneIndices[i]  = (byte[])submesh.VertexList[submeshSection.indices[i]].BoneIndices.Clone();
                            }

                            submeshSection.bones = new sviParser.sviBone[meshFrame.Mesh.BoneList.Count];
                            for (ushort i = 0; i < submeshSection.bones.Length; i++)
                            {
                                sviParser.sviBone bone = new sviParser.sviBone();
                                bone.name               = (string)meshFrame.Mesh.BoneList[i].Name.Clone();
                                bone.boneIdx            = meshFrame.Mesh.BoneList[i].Index;
                                bone.matrix             = meshFrame.Mesh.BoneList[i].Matrix;
                                submeshSection.bones[i] = bone;
                            }
                        }
                        submeshSection.boneWeights3 = newBoneWeights3;
                        submeshSection.boneIndices  = newBoneIndices;
                    }
                    if (normals && submeshSection.normalsPresent == 1)
                    {
                        if (nearestNormals)
                        {
                            for (ushort i = 0; i < submesh.VertexList.Count; i++)
                            {
                                newNormals[i] = submeshSection.normals[nearestVertexIndices[submeshSection.indices[i]]];
                            }
                        }
                        else
                        {
                            for (ushort i = 0; i < submesh.VertexList.Count; i++)
                            {
                                newNormals[i] = submesh.VertexList[submeshSection.indices[i]].Normal;
                            }
                        }
                        submeshSection.normals = newNormals;
                    }
                    if (uvs && submeshSection.uvsPresent == 1)
                    {
                        if (nearestUVs)
                        {
                            for (ushort i = 0; i < submesh.VertexList.Count; i++)
                            {
                                newUVs[i] = submeshSection.uvs[nearestVertexIndices[submeshSection.indices[i]]];
                            }
                        }
                        else
                        {
                            for (ushort i = 0; i < submesh.VertexList.Count; i++)
                            {
                                float[] uv = submesh.VertexList[submeshSection.indices[i]].UV;
                                newUVs[i] = new Vector2(uv[0], uv[1]);
                            }
                        }
                        submeshSection.uvs = newUVs;
                    }
                    return(true);
                }
            }
            return(false);
        }
Exemple #2
0
        public bool CopyToSubmesh(xxFrame meshFrame, int submeshIdx, bool positions, bool bones, bool normals, bool uvs)
        {
            foreach (sviParser submeshSection in Parser.sections)
            {
                if (submeshSection.meshName == meshFrame.Name && submeshSection.submeshIdx == submeshIdx)
                {
                    xxSubmesh submesh = meshFrame.Mesh.SubmeshList[submeshIdx];
                    if (submeshSection.indices.Length != submesh.VertexList.Count)
                    {
                        Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has a different number of vertices than defined in the sviex(" + submesh.VertexList.Count + "/" + submeshSection.indices.Length + ").");
                        return(false);
                    }
                    if (positions && submeshSection.positionsPresent == 1)
                    {
                        for (ushort i = 0; i < submeshSection.positions.Length; i++)
                        {
                            submesh.VertexList[submeshSection.indices[i]].Position = submeshSection.positions[i];
                        }
                    }
                    if (bones && submeshSection.bonesPresent == 1)
                    {
                        for (ushort i = 0; i < submeshSection.boneWeights3.Length; i++)
                        {
                            submesh.VertexList[submeshSection.indices[i]].Weights3 = (float[])submeshSection.boneWeights3[i].Clone();
                        }
                        for (ushort i = 0; i < submeshSection.boneIndices.Length; i++)
                        {
                            submesh.VertexList[submeshSection.indices[i]].BoneIndices = (byte[])submeshSection.boneIndices[i].Clone();
                        }

                        meshFrame.Mesh.BoneList.Clear();
                        for (ushort i = 0; i < submeshSection.bones.Length; i++)
                        {
                            xxBone bone = new xxBone();
                            bone.Name   = (string)submeshSection.bones[i].name.Clone();
                            bone.Index  = submeshSection.bones[i].boneIdx;
                            bone.Matrix = submeshSection.bones[i].matrix;
                            meshFrame.Mesh.BoneList.Add(bone);
                        }
                    }
                    if (normals && submeshSection.normalsPresent == 1)
                    {
                        for (ushort i = 0; i < submeshSection.normals.Length; i++)
                        {
                            submesh.VertexList[submeshSection.indices[i]].Normal = submeshSection.normals[i];
                        }
                    }
                    if (uvs && submeshSection.uvsPresent == 1)
                    {
                        for (ushort i = 0; i < submeshSection.uvs.Length; i++)
                        {
                            submesh.VertexList[submeshSection.indices[i]].UV = new float[2] {
                                submeshSection.uvs[i].X, submeshSection.uvs[i].Y
                            };
                        }
                    }
                    meshFrame.Mesh.VertexListDuplicate = xx.CreateVertexListDup(meshFrame.Mesh.SubmeshList);
                    return(true);
                }
            }
            return(false);
        }
Exemple #3
0
        public void CopyNearestNormals(object[] srcMeshes, object[] srcSubmeshes, object[] dstMeshes, object[] dstSubmeshes, sviexParser dstParser, double nearVertexThreshold, bool nearestNormal, bool automatic)
        {
            xxFrame[]           srcMeshArr = Utility.Convert <xxFrame>(srcMeshes);
            double[]            srcSubmeshDoubleIndices = Utility.Convert <double>(srcSubmeshes);
            HashSet <xxSubmesh> srcSubmeshSet           = new HashSet <xxSubmesh>();
            int srcSubmeshIdxIdx  = 0;
            int srcTotalSubmeshes = 0;

            foreach (xxFrame meshFrame in srcMeshArr)
            {
                int numSubmeshes = (int)srcSubmeshDoubleIndices[srcSubmeshIdxIdx++];
                srcTotalSubmeshes += numSubmeshes;
                for (int i = 0; i < numSubmeshes; i++)
                {
                    int srcSubmeshIdx = (int)srcSubmeshDoubleIndices[srcSubmeshIdxIdx++];
                    foreach (sviParser section in SortedParser.sections)
                    {
                        if (section.meshName == meshFrame.Name && section.submeshIdx == srcSubmeshIdx)
                        {
                            xxSubmesh submesh = meshFrame.Mesh.SubmeshList[srcSubmeshIdx];
                            srcSubmeshSet.Add(submesh);
                            break;
                        }
                    }
                }
            }
            if (srcTotalSubmeshes != srcSubmeshSet.Count)
            {
                Report.ReportLog("Not all source submeshes exist in " + SortedParser.Name + ". Using only " + srcSubmeshSet.Count + ".");
            }

            xxFrame[]        dstMeshArr = Utility.Convert <xxFrame>(dstMeshes);
            double[]         dstSubmeshDoubleIndices = Utility.Convert <double>(dstSubmeshes);
            List <xxSubmesh> dstSubmeshList          = new List <xxSubmesh>();
            int dstSubmeshIdxIdx = 0;

            foreach (xxFrame meshFrame in dstMeshArr)
            {
                int numSubmeshes = (int)dstSubmeshDoubleIndices[dstSubmeshIdxIdx++];
                if (numSubmeshes == -1)
                {
                    dstSubmeshList.AddRange(meshFrame.Mesh.SubmeshList);
                }
                else
                {
                    for (int i = 0; i < numSubmeshes; i++)
                    {
                        int       dstSubmeshIdx = (int)dstSubmeshDoubleIndices[dstSubmeshIdxIdx++];
                        xxSubmesh submesh       = meshFrame.Mesh.SubmeshList[dstSubmeshIdx];
                        dstSubmeshList.Add(submesh);
                    }
                }
            }

            sviexParser newParser = new sviexParser();

            foreach (xxFrame dstMeshFrame in dstMeshArr)
            {
                foreach (xxSubmesh dstSubmesh in dstMeshFrame.Mesh.SubmeshList)
                {
                    if (!dstSubmeshList.Contains(dstSubmesh))
                    {
                        continue;
                    }

                    if (progressBar != null)
                    {
                        progressBar.Maximum += dstSubmesh.VertexList.Count;
                    }
                    sviParser newSection = new sviParser();
                    newSection.meshName       = dstMeshFrame.Name;
                    newSection.submeshIdx     = dstMeshFrame.Mesh.SubmeshList.IndexOf(dstSubmesh);
                    newSection.indices        = new ushort[dstSubmesh.VertexList.Count];
                    newSection.normalsPresent = 1;
                    newSection.normals        = new Vector3[dstSubmesh.VertexList.Count];
                    for (ushort i = 0; i < dstSubmesh.VertexList.Count; i++)
                    {
                        xxVertex dstVertex = dstSubmesh.VertexList[i];
                        if (automatic)
                        {
                            nearestNormal = false;
                            for (int j = 0; j < dstSubmesh.VertexList.Count; j++)
                            {
                                if (j != i)
                                {
                                    xxVertex vert       = dstSubmesh.VertexList[j];
                                    double   distSquare = (vert.Position.X - dstVertex.Position.X) * (vert.Position.X - dstVertex.Position.X)
                                                          + (vert.Position.Y - dstVertex.Position.Y) * (vert.Position.Y - dstVertex.Position.Y)
                                                          + (vert.Position.Z - dstVertex.Position.Z) * (vert.Position.Z - dstVertex.Position.Z);
                                    if (distSquare <= nearVertexThreshold)
                                    {
                                        nearestNormal = true;
                                        break;
                                    }
                                }
                            }
                        }

                        Dictionary <xxFrame, Dictionary <xxSubmesh, List <int> > > bestFindings = new Dictionary <xxFrame, Dictionary <xxSubmesh, List <int> > >();
                        int       totalFindings = 0;
                        xxFrame   bestMeshFrame = null;
                        xxSubmesh bestSubmesh   = null;
                        int       bestIdx       = -1;
                        double    bestDist      = double.MaxValue;
                        foreach (xxFrame srcMeshFrame in srcMeshArr)
                        {
                            Dictionary <xxSubmesh, List <int> > bestSubmeshFindings = new Dictionary <xxSubmesh, List <int> >();
                            foreach (xxSubmesh srcSubmesh in srcMeshFrame.Mesh.SubmeshList)
                            {
                                if (!srcSubmeshSet.Contains(srcSubmesh))
                                {
                                    continue;
                                }

                                List <int> bestIndexFindings = new List <int>(srcSubmesh.VertexList.Count);
                                for (int j = 0; j < srcSubmesh.VertexList.Count; j++)
                                {
                                    xxVertex srcVertex  = srcSubmesh.VertexList[j];
                                    double   distSquare = (srcVertex.Position.X - dstVertex.Position.X) * (srcVertex.Position.X - dstVertex.Position.X)
                                                          + (srcVertex.Position.Y - dstVertex.Position.Y) * (srcVertex.Position.Y - dstVertex.Position.Y)
                                                          + (srcVertex.Position.Z - dstVertex.Position.Z) * (srcVertex.Position.Z - dstVertex.Position.Z);
                                    if (distSquare <= nearVertexThreshold)
                                    {
                                        bestIndexFindings.Add(j);
                                        totalFindings++;
                                        continue;
                                    }
                                    if (totalFindings == 0 && distSquare < bestDist)
                                    {
                                        bestMeshFrame = srcMeshFrame;
                                        bestSubmesh   = srcSubmesh;
                                        bestIdx       = j;
                                        bestDist      = distSquare;
                                    }
                                }
                                if (bestIndexFindings.Count > 0)
                                {
                                    bestSubmeshFindings.Add(srcSubmesh, bestIndexFindings);
                                }
                            }
                            if (bestSubmeshFindings.Count > 0)
                            {
                                bestFindings.Add(srcMeshFrame, bestSubmeshFindings);
                            }
                        }
                        if (totalFindings > 0)
                        {
                            Vector3 normalSummed  = new Vector3();
                            Vector3 normalNearest = new Vector3();
                            double  nearestDist   = Double.MaxValue;
                            foreach (var finding in bestFindings)
                            {
                                foreach (sviParser srcSection in SortedParser.sections)
                                {
                                    if (srcSection.meshName == finding.Key.Name)
                                    {
                                        foreach (var submeshFinding in finding.Value)
                                        {
                                            if (srcSection.submeshIdx == finding.Key.Mesh.SubmeshList.IndexOf(submeshFinding.Key))
                                            {
                                                foreach (int j in submeshFinding.Value)
                                                {
                                                    if (nearestNormal)
                                                    {
                                                        double distSquare = (srcSection.normals[j].X - dstVertex.Normal.X) * (srcSection.normals[j].X - dstVertex.Normal.X)
                                                                            + (srcSection.normals[j].Y - dstVertex.Normal.Y) * (srcSection.normals[j].Y - dstVertex.Normal.Y)
                                                                            + (srcSection.normals[j].Z - dstVertex.Normal.Z) * (srcSection.normals[j].Z - dstVertex.Normal.Z);
                                                        if (distSquare < nearestDist)
                                                        {
                                                            normalNearest = srcSection.normals[j];
                                                            nearestDist   = distSquare;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        normalSummed += srcSection.normals[j];
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if (totalFindings > 1)
                            {
                                normalSummed.Normalize();
                            }

                            newSection.indices[i] = i;
                            newSection.normals[i] = nearestNormal ? normalNearest : normalSummed;
                        }
                        else
                        {
                            int bestSubmeshIdx = bestMeshFrame.Mesh.SubmeshList.IndexOf(bestSubmesh);
                            foreach (sviParser srcSection in SortedParser.sections)
                            {
                                if (srcSection.meshName == bestMeshFrame.Name && srcSection.submeshIdx == bestSubmeshIdx)
                                {
                                    newSection.indices[i] = i;
                                    newSection.normals[i] = srcSection.normals[bestIdx];
                                    break;
                                }
                            }
                        }

                        if (progressBar != null)
                        {
                            progressBar.PerformStep();
                        }
                    }
                    newParser.sections.Add(newSection);
                }
            }

            dstParser.sections = newParser.sections;
        }
Exemple #4
0
        private static void SwapNormals(ComboBoxItemXX cbItem, string sviexName)
        {
            Dictionary <xxVertex, Vector3> originalNormals = new Dictionary <xxVertex, Vector3>();
            sviexParser targetParser = PluginsPPD.OpenSVIEX((ppParser)Gui.Scripting.Variables[cbItem.ppForm.ParserVar], sviexName);

            foreach (sviParser section in targetParser.sections)
            {
                bool meshFound = false;
                foreach (ComboBoxItemMesh itemMesh in cbItem.meshes)
                {
                    if (section.meshName == itemMesh.meshFrame.Name)
                    {
                        meshFound = true;
                        xxSubmesh submesh = itemMesh.meshFrame.Mesh.SubmeshList[section.submeshIdx];
                        if (section.indices.Length != submesh.VertexList.Count)
                        {
                            Report.ReportLog("Unmatching SVIEX mesh=" + section.meshName + " submeshIdx=" + section.submeshIdx + " has " + section.indices.Length + " indices.");
                            break;
                        }
                        for (int i = 0; i < section.indices.Length; i++)
                        {
                            ushort   vIdx = section.indices[i];
                            Vector3  norm = section.normals[i];
                            xxVertex vert = submesh.VertexList[vIdx];
                            originalNormals.Add(vert, vert.Normal);
                            vert.Normal = norm;
                        }
                        break;
                    }
                }
                if (!meshFound)
                {
                    Report.ReportLog("SVIEX Normals not copied for " + section.meshName);
                }
            }

            cbItem.xxForm.RecreateRenderObjects();

            foreach (sviParser section in targetParser.sections)
            {
                foreach (ComboBoxItemMesh itemMesh in cbItem.meshes)
                {
                    if (section.meshName == itemMesh.meshFrame.Name)
                    {
                        xxSubmesh submesh = itemMesh.meshFrame.Mesh.SubmeshList[section.submeshIdx];
                        if (section.indices.Length != submesh.VertexList.Count)
                        {
                            break;
                        }
                        for (int i = 0; i < section.indices.Length; i++)
                        {
                            ushort   vIdx = section.indices[i];
                            xxVertex vert = submesh.VertexList[vIdx];
                            Vector3  norm = originalNormals[vert];
                            vert.Normal = norm;
                        }
                        break;
                    }
                }
            }
        }
Exemple #5
0
        protected xxFrame ParseFrame()
        {
            xxFrame frame = new xxFrame();
            frame.Name = reader.ReadName();

            int numChildFrames = reader.ReadInt32();
            frame.InitChildren(numChildFrames);

            frame.Matrix = reader.ReadMatrix();
            frame.Unknown1 = (Format >= 7) ? reader.ReadBytes(32) : reader.ReadBytes(16);

            int numSubmeshes = reader.ReadInt32();

            frame.Bounds = new BoundingBox(reader.ReadVector3(), reader.ReadVector3());
            frame.Unknown2 = (Format >= 7) ? reader.ReadBytes(64) : reader.ReadBytes(16);

            if (Format >= 6)
            {
                frame.Name2 = reader.ReadName();
            }

            if (numSubmeshes > 0)
            {
                xxMesh mesh = new xxMesh();
                frame.Mesh = mesh;
                mesh.NumVector2PerVertex = reader.ReadByte();

                mesh.SubmeshList = new List<xxSubmesh>(numSubmeshes);
                for (int i = 0; i < numSubmeshes; i++)
                {
                    xxSubmesh submesh = new xxSubmesh();
                    mesh.SubmeshList.Add(submesh);

                    submesh.Unknown1 = (Format >= 7) ? reader.ReadBytes(64) : reader.ReadBytes(16);
                    submesh.MaterialIndex = reader.ReadInt32();

                    submesh.FaceList = ParseFaceList();
                    submesh.VertexList = ParseVertexList();

                    if (Format >= 7)
                    {
                        submesh.Unknown2 = reader.ReadBytes(20);
                    }

                    if (mesh.NumVector2PerVertex > 0)
                    {
                        submesh.Vector2Lists = new List<List<Vector2>>(submesh.VertexList.Count);
                        for (int j = 0; j < submesh.VertexList.Count; j++)
                        {
                            List<Vector2> vectorList = new List<Vector2>(mesh.NumVector2PerVertex);
                            submesh.Vector2Lists.Add(vectorList);
                            for (byte k = 0; k < mesh.NumVector2PerVertex; k++)
                            {
                                vectorList.Add(reader.ReadVector2());
                            }
                        }
                    }

                    if (Format >= 2)
                    {
                        submesh.Unknown3 = reader.ReadBytes(100); // 96 + 4
                    }

                    if (Format >= 7)
                    {
                        submesh.Unknown4 = reader.ReadBytes(284); // 256 + 28

                        if (Format >= 8)
                        {
                            byte format = reader.ReadByte();
                            string nullFrame = reader.ReadName();
                            byte[] u5end = reader.ReadBytes(12 + 4);

                            byte[] encryptedName = Utility.EncryptName(nullFrame);
                            submesh.Unknown5 = new byte[1 + 4 + encryptedName.Length + 12 + 4];
                            submesh.Unknown5[0] = format;
                            BitConverter.GetBytes(encryptedName.Length).CopyTo(submesh.Unknown5, 1);
                            encryptedName.CopyTo(submesh.Unknown5, 1 + 4);
                            u5end.CopyTo(submesh.Unknown5, 1 + 4 + encryptedName.Length);
                        }
                    }
                    else
                    {
                        if (Format >= 3)
                        {
                            submesh.Unknown4 = reader.ReadBytes(64);
                        }
                        if (Format >= 5)
                        {
                            submesh.Unknown5 = reader.ReadBytes(20);
                        }
                        if (Format >= 6)
                        {
                            submesh.Unknown6 = reader.ReadBytes(28);
                        }
                    }
                }

                ushort numVerticesDup = reader.ReadUInt16();
                mesh.VertexListDuplicate = new List<xxVertex>(numVerticesDup);
                mesh.VertexListDuplicateUnknown = reader.ReadBytes(8);  // 4 + 4
                for (int i = 0; i < numVerticesDup; i++)
                {
                    mesh.VertexListDuplicate.Add(ParseVertex());
                }

                mesh.BoneList = ParseBoneList();
            }

            for (int i = 0; i < numChildFrames; i++)
            {
                frame.AddChild(ParseFrame());
            }

            return frame;
        }
        public static xxMesh CreateMesh(WorkspaceMesh mesh, int xxFormat, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption)
        {
            int numUncheckedSubmeshes = 0;
            foreach (ImportedSubmesh submesh in mesh.SubmeshList)
            {
                if (!mesh.isSubmeshEnabled(submesh))
                    numUncheckedSubmeshes++;
            }
            int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes;
            materialNames = new string[numSubmeshes];
            indices = new int[numSubmeshes];
            worldCoords = new bool[numSubmeshes];
            replaceSubmeshesOption = new bool[numSubmeshes];

            xxMesh xxMesh = new xxMesh();
            xxMesh.BoneList = CreateBoneList(mesh.BoneList);

            xxMesh.SubmeshList = new List<xxSubmesh>(mesh.SubmeshList.Count);
            for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++)
            {
                while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx]))
                    submeshIdx++;

                xxSubmesh xxSubmesh = new xxSubmesh();
                xxMesh.SubmeshList.Add(xxSubmesh);

                xxSubmesh.MaterialIndex = -1;
                materialNames[i] = mesh.SubmeshList[submeshIdx].Material;
                indices[i] = mesh.SubmeshList[submeshIdx].Index;
                worldCoords[i] = mesh.SubmeshList[submeshIdx].WorldCoords;
                replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(mesh.SubmeshList[submeshIdx]);

                List<ImportedVertex> vertexList = mesh.SubmeshList[submeshIdx].VertexList;
                List<xxVertex> xxVertexList = new List<xxVertex>(vertexList.Count);
                for (int j = 0; j < vertexList.Count; j++)
                {
                    ImportedVertex vert = vertexList[j];
                    xxVertex xxVertex;
                    if (xxFormat >= 4)
                    {
                        xxVertex = new xxVertexUShort();
                        CreateUnknown(xxVertex);
                    }
                    else
                    {
                        xxVertex = new xxVertexInt();
                    }

                    xxVertex.Index = j;
                    xxVertex.Normal = vert.Normal;
                    xxVertex.UV = (float[])vert.UV.Clone();
                    xxVertex.Weights3 = new float[3] { vert.Weights[0], vert.Weights[1], vert.Weights[2] };
                    xxVertex.BoneIndices = (byte[])vert.BoneIndices.Clone();
                    xxVertex.Position = vert.Position;
                    xxVertexList.Add(xxVertex);
                }
                xxSubmesh.VertexList = xxVertexList;

                List<ImportedFace> faceList = mesh.SubmeshList[submeshIdx].FaceList;
                List<xxFace> xxFaceList = new List<xxFace>(faceList.Count);
                for (int j = 0; j < faceList.Count; j++)
                {
                    int[] vertexIndices = faceList[j].VertexIndices;
                    xxFace xxFace = new xxFace();
                    xxFace.VertexIndices = new ushort[3] { (ushort)vertexIndices[0], (ushort)vertexIndices[1], (ushort)vertexIndices[2] };
                    xxFaceList.Add(xxFace);
                }
                xxSubmesh.FaceList = xxFaceList;
            }

            xxMesh.VertexListDuplicate = CreateVertexListDup(xxMesh.SubmeshList);
            return xxMesh;
        }