Ejemplo n.º 1
0
        public unsafe static void importBR2(string sourceFilename, string outputFilename, GrannyContext grannyContext)
        {
            IGrannyFile file = CivNexusSixApplicationForm.form.OpenFileAsTempFileCopy(CivNexusSixApplicationForm.form.modelTemplateFilename, "tempimport");

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumVertexDatas(0);
            fileWrapper.setNumSkeletons(0);
            fileWrapper.setNumTriTopologies(0);

            GrannyModelInfo modelInfo = loadModelInfo(sourceFilename);

            doBoneBindings(modelInfo);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo));
            }

            IGrannyModel       model        = file.Models[0];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(file, meshFile, 0);
            }

            fileWrapper.setNumMeshes(0);
            file.Meshes.Clear();

            foreach (IGrannyMesh mesh in file.Models[0].MeshBindings)
            {
                file.AddMeshReference(mesh);
            }

            GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(file.Models[0].Skeleton);

            skeletonWrapper.writeSkeletonInfo(modelInfo.skeleton);

            string worldBoneName = modelInfo.skeleton.bones[0].name;

            modelWrapper.setName(worldBoneName);
            skeletonWrapper.setName(worldBoneName);

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            float[] matrix = { 1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f };
            fileWrapper.setMatrix(matrix);
            CivNexusSixApplicationForm.SetExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.addSkeletonPointer((int)skeletonWrapper.m_pkSkeleton);

            CivNexusSixApplicationForm.form.SaveAsAction(file, outputFilename, false);
        }
Ejemplo n.º 2
0
        public static void overwriteMeshes(IGrannyFile file, string sourceFilename, GrannyContext grannyContext, int currentModelIndex, int vertexFormat)
        {
            string filename = file.Filename;

            GrannyModelInfo modelInfo = loadModelInfos(sourceFilename, vertexFormat)[0];

            doBoneBindings(modelInfo);

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo, getTemplateFilename(vertexFormat)));
            }

            IGrannyModel       model        = file.Models[currentModelIndex];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(file, meshFile, currentModelIndex);
            }

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumTriTopologies(0);
            fileWrapper.setNumVertexDatas(0);
            file.Meshes.Clear();

            int meshesCount = 0;

            foreach (IGrannyModel loopModel in file.Models)
            {
                foreach (IGrannyMesh mesh in loopModel.MeshBindings)
                {
                    file.AddMeshReference(mesh);
                    meshesCount++;
                }
            }

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            //fileWrapper.setUnitsPerMeter(10.7f);
            CivNexusSixApplicationForm.SetExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.setNumMeshes(meshesCount);
            CivNexusSixApplicationForm.form.SaveAsAction(file, filename, false);

            List <GrannyModelInfo> modelInfos = new List <GrannyModelInfo>();

            modelInfos.Add(modelInfo);

            createAndBindMaterials(filename, file, modelInfos);
        }
Ejemplo n.º 3
0
        public unsafe static void overwriteMeshes(IGrannyFile file, string sourceFilename, GrannyContext grannyContext, Int32 currentModelIndex)
        {
            string filename = file.Filename;

            GrannyModelInfo modelInfo = loadModelInfo(sourceFilename);

            doBoneBindings(modelInfo);

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo));
            }

            IGrannyModel       model        = file.Models[currentModelIndex];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(grannyContext, file, meshFile, currentModelIndex);
            }

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumTriTopologies(0);
            fileWrapper.setNumVertexDatas(0);
            file.Meshes.Clear();

            int meshesCount = 0;

            foreach (IGrannyModel loopModel in file.Models)
            {
                foreach (IGrannyMesh mesh in loopModel.MeshBindings)
                {
                    file.AddMeshReference(mesh);
                    meshesCount++;
                }
            }

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            fileWrapper.setUnitsPerMeter(10.7f);
            NexusBuddyApplicationForm.setExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.setNumMeshes(meshesCount);
            NexusBuddyApplicationForm.form.saveAsAction(file, filename, false);
        }
Ejemplo n.º 4
0
        private static void doBoneBindings(GrannyModelInfo modelInfo)
        {
            GrannySkeletonInfo skeletonInfo = modelInfo.skeleton;

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                HashSet <int> distinctBoneIds = new HashSet <int>();

                foreach (GrannyVertexInfo vertexInfo in meshInfo.vertices)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        distinctBoneIds.Add(vertexInfo.boneIndices[i]);
                    }
                }

                Dictionary <int, int> globalToLocalBoneIdDict = new Dictionary <int, int>();
                List <int>            distinctBoneIdList      = distinctBoneIds.ToList();
                List <string>         boneBindingNames        = new List <string>();
                for (int i = 0; i < distinctBoneIdList.Count; i++)
                {
                    boneBindingNames.Add(skeletonInfo.bones[distinctBoneIdList[i]].name);
                    globalToLocalBoneIdDict.Add(distinctBoneIdList[i], i);
                }

                foreach (GrannyVertexInfo vertexInfo in meshInfo.vertices)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        int localBoneId = globalToLocalBoneIdDict[vertexInfo.boneIndices[i]];
                        vertexInfo.boneIndices[i] = localBoneId;
                    }
                }

                meshInfo.boneBindings = boneBindingNames;
            }
        }
Ejemplo n.º 5
0
        private static GrannyModelInfo loadModelInfo(string filename)
        {
            string currentLine = "";
            string numberRegex = "([-+]?[0-9]+\\.?[0-9]*) ";

            StreamReader streamReader = new StreamReader(filename);

            while (!currentLine.StartsWith("skeleton"))
            {
                currentLine = streamReader.ReadLine();
            }

            GrannyModelInfo modelInfo = new GrannyModelInfo();

            GrannySkeletonInfo    skeletonInfo  = new GrannySkeletonInfo();
            List <GrannyBoneInfo> skeletonBones = new List <GrannyBoneInfo>();

            while (!currentLine.StartsWith("meshes"))
            {
                currentLine = streamReader.ReadLine();
                if (!currentLine.StartsWith("meshes"))
                {
                    string regexString = "([0-9]+) \"(.+)\" ";
                    for (int i = 0; i < 24; i++)
                    {
                        regexString = regexString + numberRegex;
                    }

                    Regex           regex = new Regex(regexString.Trim());
                    MatchCollection mc    = regex.Matches(currentLine);
                    foreach (Match m in mc)
                    {
                        GrannyBoneInfo      boneInfo      = new GrannyBoneInfo();
                        GrannyTransformInfo transformInfo = new GrannyTransformInfo();

                        //int boneindex = NumberUtils.parseInt(m.Groups[1].Value.Trim());
                        string boneName    = m.Groups[2].Value;
                        int    parentIndex = NumberUtils.parseInt(m.Groups[3].Value.Trim());

                        float[] position = new float[3];
                        position[0] = NumberUtils.parseFloat(m.Groups[4].Value.Trim());
                        position[1] = NumberUtils.parseFloat(m.Groups[5].Value.Trim());
                        position[2] = NumberUtils.parseFloat(m.Groups[6].Value.Trim());

                        float[] orientation = new float[4];
                        orientation[0] = NumberUtils.parseFloat(m.Groups[7].Value.Trim());
                        orientation[1] = NumberUtils.parseFloat(m.Groups[8].Value.Trim());
                        orientation[2] = NumberUtils.parseFloat(m.Groups[9].Value.Trim());
                        orientation[3] = NumberUtils.parseFloat(m.Groups[10].Value.Trim());

                        float[] scaleShear = new float[9];
                        scaleShear[0] = 1.0f;
                        scaleShear[1] = 0.0f;
                        scaleShear[2] = 0.0f;
                        scaleShear[3] = 0.0f;
                        scaleShear[4] = 1.0f;
                        scaleShear[5] = 0.0f;
                        scaleShear[6] = 0.0f;
                        scaleShear[7] = 0.0f;
                        scaleShear[8] = 1.0f;

                        float[] invWorld = new float[16];

                        for (int j = 0; j < 16; j++)
                        {
                            invWorld[j] = NumberUtils.parseFloat(m.Groups[j + 11].Value.Trim());
                        }


                        bool hasPosition    = true;
                        bool hasOrientation = true;
                        int  flags          = 0;

                        if (NumberUtils.almostEquals(position[0], 0.0f, 4) && NumberUtils.almostEquals(position[1], 0.0f, 4) && NumberUtils.almostEquals(position[2], 0.0f, 4))
                        {
                            hasPosition = false;
                        }

                        if (NumberUtils.almostEquals(orientation[0], 0.0f, 5) && NumberUtils.almostEquals(orientation[1], 0.0f, 5) &&
                            NumberUtils.almostEquals(orientation[2], 0.0f, 5) && NumberUtils.almostEquals(orientation[3], 1.0f, 5))
                        {
                            hasOrientation = false;
                        }

                        if (hasPosition)
                        {
                            flags = flags + 1;
                        }

                        if (hasOrientation)
                        {
                            flags = flags + 2;
                        }

                        transformInfo.flags       = flags;
                        transformInfo.position    = position;
                        transformInfo.orientation = orientation;
                        transformInfo.scaleShear  = scaleShear;

                        boneInfo.name                  = boneName;
                        boneInfo.parentIndex           = parentIndex;
                        boneInfo.localTransform        = transformInfo;
                        boneInfo.inverseWorldTransform = invWorld;
                        boneInfo.LODError              = 0;

                        skeletonBones.Add(boneInfo);
                    }
                }
            }

            skeletonInfo.bones = skeletonBones;

            // Read Meshes
            int numMeshes = NumberUtils.parseInt(currentLine.Replace("meshes:", ""));
            List <GrannyMeshInfo> meshInfos = new List <GrannyMeshInfo>();

            for (int meshId = 0; meshId < numMeshes; meshId++)
            {
                string meshName = "";
                while (!currentLine.StartsWith("mesh:"))
                {
                    currentLine = streamReader.ReadLine();
                }

                string          regexString = "\"(.+)\"";
                Regex           regex       = new Regex(regexString);
                MatchCollection mc          = regex.Matches(currentLine);

                foreach (Match m in mc)
                {
                    meshName = m.Groups[1].Value;
                }

                // Read Vertices
                List <GrannyVertexInfo> vertexInfos = new List <GrannyVertexInfo>();
                while (!currentLine.StartsWith("triangles"))
                {
                    currentLine = streamReader.ReadLine();
                    if (!currentLine.StartsWith("vertices") && !currentLine.StartsWith("triangles"))
                    {
                        int spacesCount = 0;
                        foreach (char c in currentLine)
                        {
                            if (c == ' ')
                            {
                                spacesCount++;
                            }
                        }
                        bool hasBinormalsAndTangents = spacesCount > 15;

                        regexString = "";
                        for (int i = 0; i < 16; i++)
                        {
                            regexString = regexString + numberRegex;
                        }

                        if (hasBinormalsAndTangents)
                        {
                            for (int i = 0; i < 6; i++)
                            {
                                regexString = regexString + numberRegex;
                            }
                        }

                        regex = new Regex(regexString.Trim());
                        mc    = regex.Matches(currentLine);
                        foreach (Match m in mc)
                        {
                            GrannyVertexInfo vertexInfo = new GrannyVertexInfo();

                            float[] position = new float[3];
                            position[0] = NumberUtils.parseFloat(m.Groups[1].Value.Trim());
                            position[1] = NumberUtils.parseFloat(m.Groups[2].Value.Trim());
                            position[2] = NumberUtils.parseFloat(m.Groups[3].Value.Trim());

                            float[] normal = new float[3];
                            normal[0] = NumberUtils.parseFloat(m.Groups[4].Value.Trim());
                            normal[1] = NumberUtils.parseFloat(m.Groups[5].Value.Trim());
                            normal[2] = NumberUtils.parseFloat(m.Groups[6].Value.Trim());

                            float[] uv = new float[2];
                            uv[0] = NumberUtils.parseFloat(m.Groups[7].Value.Trim());
                            uv[1] = NumberUtils.parseFloat(m.Groups[8].Value.Trim());

                            int[] boneIndices = new int[4];
                            boneIndices[0] = NumberUtils.parseInt(m.Groups[9].Value.Trim());
                            boneIndices[1] = NumberUtils.parseInt(m.Groups[10].Value.Trim());
                            boneIndices[2] = NumberUtils.parseInt(m.Groups[11].Value.Trim());
                            boneIndices[3] = NumberUtils.parseInt(m.Groups[12].Value.Trim());

                            int[] boneWeights = new int[4];
                            boneWeights[0] = NumberUtils.parseInt(m.Groups[13].Value.Trim());
                            boneWeights[1] = NumberUtils.parseInt(m.Groups[14].Value.Trim());
                            boneWeights[2] = NumberUtils.parseInt(m.Groups[15].Value.Trim());
                            boneWeights[3] = NumberUtils.parseInt(m.Groups[16].Value.Trim());

                            if (hasBinormalsAndTangents)
                            {
                                float[] tangent = new float[3];
                                tangent[0] = NumberUtils.parseFloat(m.Groups[17].Value.Trim());
                                tangent[1] = NumberUtils.parseFloat(m.Groups[18].Value.Trim());
                                tangent[2] = NumberUtils.parseFloat(m.Groups[19].Value.Trim());

                                float[] binormal = new float[3];
                                binormal[0] = NumberUtils.parseFloat(m.Groups[20].Value.Trim());
                                binormal[1] = NumberUtils.parseFloat(m.Groups[21].Value.Trim());
                                binormal[2] = NumberUtils.parseFloat(m.Groups[22].Value.Trim());

                                vertexInfo.binormal = binormal;
                                vertexInfo.tangent  = tangent;
                            }

                            vertexInfo.position    = position;
                            vertexInfo.normal      = normal;
                            vertexInfo.boneIndices = boneIndices;
                            vertexInfo.boneWeights = boneWeights;
                            vertexInfo.uv          = uv;

                            vertexInfos.Add(vertexInfo);
                        }
                    }
                }

                // Read Triangles
                List <int[]> triangles = new List <int[]>();
                while (!currentLine.StartsWith("mesh") && !currentLine.StartsWith("end"))
                {
                    currentLine = streamReader.ReadLine();
                    if (!currentLine.StartsWith("mesh") && !currentLine.StartsWith("end"))
                    {
                        regexString = "";
                        for (int i = 0; i < 3; i++)
                        {
                            regexString = regexString + "([-+]?[0-9]+\\.?[0-9]*) ";
                        }

                        regex = new Regex(regexString.Trim());
                        mc    = regex.Matches(currentLine);
                        foreach (Match m in mc)
                        {
                            int[] triangle = new int[3];
                            triangle[0] = NumberUtils.parseInt(m.Groups[1].Value.Trim());
                            triangle[1] = NumberUtils.parseInt(m.Groups[2].Value.Trim());
                            triangle[2] = NumberUtils.parseInt(m.Groups[3].Value.Trim());

                            triangles.Add(triangle);
                        }
                    }
                }

                List <PrimaryTopologyGroupInfo> groupInfos = new List <PrimaryTopologyGroupInfo>();
                groupInfos.Add(new PrimaryTopologyGroupInfo(0, 0, triangles.Count));

                GrannyMeshInfo meshInfo = new GrannyMeshInfo();
                meshInfo.name      = meshName;
                meshInfo.vertices  = vertexInfos;
                meshInfo.triangles = triangles;
                meshInfo.primaryTopologyGroupInfos = groupInfos;
                meshInfo.materialBindingNames      = new List <string> {
                    "DefaultMaterialBinding"
                };
                meshInfos.Add(meshInfo);
            }

            modelInfo.skeleton     = skeletonInfo;
            modelInfo.meshBindings = meshInfos;

            streamReader.Close();

            return(modelInfo);
        }
Ejemplo n.º 6
0
        private static List <GrannyModelInfo> loadModelInfos(string filename, int vertexFormat)
        {
            string currentLine = "";
            string numberRegex = "([-+]?[0-9]+\\.?[0-9]*) ";

            StreamReader streamReader = new StreamReader(filename);

            bool endOfFile = false;

            List <GrannyModelInfo> modelInfos = new List <GrannyModelInfo>();


            while (!endOfFile)
            {
                while (!currentLine.StartsWith("skeleton"))
                {
                    if (currentLine.Equals("end"))
                    {
                        endOfFile = true;
                        break;
                    }
                    currentLine = streamReader.ReadLine();
                }

                if (endOfFile)
                {
                    break;
                }

                GrannyModelInfo modelInfo = new GrannyModelInfo();

                GrannySkeletonInfo    skeletonInfo  = new GrannySkeletonInfo();
                List <GrannyBoneInfo> skeletonBones = new List <GrannyBoneInfo>();

                while (!currentLine.StartsWith("meshes"))
                {
                    currentLine = streamReader.ReadLine();
                    if (!currentLine.StartsWith("meshes"))
                    {
                        string regexString = "([0-9]+) \"(.+)\" ";
                        for (int i = 0; i < 24; i++)
                        {
                            regexString = regexString + numberRegex;
                        }

                        Regex           regex = new Regex(regexString.Trim());
                        MatchCollection mc    = regex.Matches(currentLine);
                        foreach (Match m in mc)
                        {
                            GrannyBoneInfo      boneInfo      = new GrannyBoneInfo();
                            GrannyTransformInfo transformInfo = new GrannyTransformInfo();

                            //int boneindex = NumberUtils.parseInt(m.Groups[1].Value.Trim());
                            string boneName    = m.Groups[2].Value;
                            int    parentIndex = NumberUtils.parseInt(m.Groups[3].Value.Trim());

                            float[] position = new float[3];
                            position[0] = NumberUtils.parseFloat(m.Groups[4].Value.Trim());
                            position[1] = NumberUtils.parseFloat(m.Groups[5].Value.Trim());
                            position[2] = NumberUtils.parseFloat(m.Groups[6].Value.Trim());

                            float[] orientation = new float[4];
                            orientation[0] = NumberUtils.parseFloat(m.Groups[7].Value.Trim());
                            orientation[1] = NumberUtils.parseFloat(m.Groups[8].Value.Trim());
                            orientation[2] = NumberUtils.parseFloat(m.Groups[9].Value.Trim());
                            orientation[3] = NumberUtils.parseFloat(m.Groups[10].Value.Trim());

                            float[] scaleShear = new float[9];
                            scaleShear[0] = 1.0f;
                            scaleShear[1] = 0.0f;
                            scaleShear[2] = 0.0f;
                            scaleShear[3] = 0.0f;
                            scaleShear[4] = 1.0f;
                            scaleShear[5] = 0.0f;
                            scaleShear[6] = 0.0f;
                            scaleShear[7] = 0.0f;
                            scaleShear[8] = 1.0f;

                            float[] invWorld = new float[16];

                            for (int j = 0; j < 16; j++)
                            {
                                invWorld[j] = NumberUtils.parseFloat(m.Groups[j + 11].Value.Trim());
                            }


                            bool hasPosition    = true;
                            bool hasOrientation = true;
                            int  flags          = 0;

                            if (NumberUtils.almostEquals(position[0], 0.0f, 4) && NumberUtils.almostEquals(position[1], 0.0f, 4) && NumberUtils.almostEquals(position[2], 0.0f, 4))
                            {
                                hasPosition = false;
                            }

                            if (NumberUtils.almostEquals(orientation[0], 0.0f, 5) && NumberUtils.almostEquals(orientation[1], 0.0f, 5) &&
                                NumberUtils.almostEquals(orientation[2], 0.0f, 5) && NumberUtils.almostEquals(orientation[3], 1.0f, 5))
                            {
                                hasOrientation = false;
                            }

                            if (hasPosition)
                            {
                                flags = flags + 1;
                            }

                            if (hasOrientation)
                            {
                                flags = flags + 2;
                            }

                            transformInfo.flags       = flags;
                            transformInfo.position    = position;
                            transformInfo.orientation = orientation;
                            transformInfo.scaleShear  = scaleShear;

                            boneInfo.name                  = boneName;
                            boneInfo.parentIndex           = parentIndex;
                            boneInfo.localTransform        = transformInfo;
                            boneInfo.inverseWorldTransform = invWorld;
                            boneInfo.LODError              = 0;

                            skeletonBones.Add(boneInfo);
                        }
                    }
                }

                skeletonInfo.bones = skeletonBones;

                // Read Meshes
                int numMeshes = NumberUtils.parseInt(currentLine.Replace("meshes:", ""));
                List <GrannyMeshInfo> meshInfos = new List <GrannyMeshInfo>();
                for (int meshId = 0; meshId < numMeshes; meshId++)
                {
                    string meshName = "";
                    while (!currentLine.StartsWith("mesh:"))
                    {
                        currentLine = streamReader.ReadLine();
                    }

                    string          regexString = "\"(.+)\"";
                    Regex           regex       = new Regex(regexString);
                    MatchCollection mc          = regex.Matches(currentLine);

                    foreach (Match m in mc)
                    {
                        meshName = m.Groups[1].Value.Replace("#M", "");
                    }

                    // Read Materials
                    List <string> materialNames = new List <string>();
                    while (!currentLine.StartsWith("vertices"))
                    {
                        currentLine = streamReader.ReadLine();
                        if (!currentLine.StartsWith("materials") && !currentLine.StartsWith("vertices"))
                        {
                            mc = regex.Matches(currentLine);

                            foreach (Match m in mc)
                            {
                                string materialName = m.Groups[1].Value;
                                materialNames.Add(materialName);
                            }
                        }
                    }

                    // Read Vertices
                    int unweightedVertexCount = 0;

                    List <GrannyVertexInfo> vertexInfos = new List <GrannyVertexInfo>();
                    while (!currentLine.StartsWith("triangles"))
                    {
                        currentLine = streamReader.ReadLine();
                        if (!currentLine.StartsWith("vertices") && !currentLine.StartsWith("triangles"))
                        {
                            regexString = "";
                            for (int i = 0; i < 34; i++)
                            {
                                regexString = regexString + numberRegex;
                            }

                            regex = new Regex(regexString.Trim());
                            mc    = regex.Matches(currentLine);
                            foreach (Match m in mc)
                            {
                                GrannyVertexInfo vertexInfo = new GrannyVertexInfo();

                                float[] position = new float[3];
                                position[0] = NumberUtils.parseFloat(m.Groups[1].Value.Trim());
                                position[1] = NumberUtils.parseFloat(m.Groups[2].Value.Trim());
                                position[2] = NumberUtils.parseFloat(m.Groups[3].Value.Trim());

                                float[] normal = new float[3];
                                normal[0] = NumberUtils.parseFloat(m.Groups[4].Value.Trim());
                                normal[1] = NumberUtils.parseFloat(m.Groups[5].Value.Trim());
                                normal[2] = NumberUtils.parseFloat(m.Groups[6].Value.Trim());

                                float[] tangent = new float[3];
                                tangent[0] = NumberUtils.parseFloat(m.Groups[7].Value.Trim());
                                tangent[1] = NumberUtils.parseFloat(m.Groups[8].Value.Trim());
                                tangent[2] = NumberUtils.parseFloat(m.Groups[9].Value.Trim());

                                float[] binormal = new float[3];
                                binormal[0] = NumberUtils.parseFloat(m.Groups[10].Value.Trim());
                                binormal[1] = NumberUtils.parseFloat(m.Groups[11].Value.Trim());
                                binormal[2] = NumberUtils.parseFloat(m.Groups[12].Value.Trim());

                                float[] uv = new float[2];
                                uv[0] = NumberUtils.parseFloat(m.Groups[13].Value.Trim());
                                uv[1] = NumberUtils.parseFloat(m.Groups[14].Value.Trim());

                                float[] uv2 = new float[2];
                                uv2[0] = NumberUtils.parseFloat(m.Groups[15].Value.Trim());
                                uv2[1] = NumberUtils.parseFloat(m.Groups[16].Value.Trim());

                                float[] uv3 = new float[2];
                                uv3[0] = NumberUtils.parseFloat(m.Groups[17].Value.Trim());
                                uv3[1] = NumberUtils.parseFloat(m.Groups[18].Value.Trim());

                                int[] boneIndices = new int[8];
                                for (int j = 0; j < 8; j++)
                                {
                                    boneIndices[j] = NumberUtils.parseInt(m.Groups[j + 19].Value.Trim());
                                }

                                int[] boneWeights = new int[8];
                                for (int j = 0; j < 8; j++)
                                {
                                    boneWeights[j] = NumberUtils.parseInt(m.Groups[j + 27].Value.Trim());
                                }

                                // Assign unweighted vertices to root bone and record count
                                if (boneWeights[0] == -1)
                                {
                                    for (int j = 0; j < 8; j++)
                                    {
                                        boneIndices[j] = 0;
                                    }

                                    boneWeights[0] = 255;

                                    for (int j = 1; j < 8; j++)
                                    {
                                        boneWeights[j] = 0;
                                    }

                                    unweightedVertexCount++;
                                }

                                vertexInfo.position = position;
                                vertexInfo.normal   = normal;
                                vertexInfo.tangent  = tangent;
                                vertexInfo.binormal = binormal;

                                vertexInfo.uv  = uv;
                                vertexInfo.uv2 = uv2;
                                vertexInfo.uv3 = uv3;

                                vertexInfo.boneIndices = boneIndices;
                                vertexInfo.boneWeights = boneWeights;

                                vertexInfos.Add(vertexInfo);
                            }
                        }
                    }

                    if (unweightedVertexCount > 0 && vertexFormat == 0)
                    {
                        MessageBox.Show(unweightedVertexCount + " unweighted vertices have been assigned to root bone.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    }

                    // Read Triangles
                    List <int[]> triangles = new List <int[]>();
                    while (!currentLine.StartsWith("mesh") && !currentLine.StartsWith("end") && !currentLine.StartsWith("skeleton"))
                    {
                        currentLine = streamReader.ReadLine();
                        if (!currentLine.StartsWith("mesh") && !currentLine.StartsWith("end"))
                        {
                            regexString = "";
                            for (int i = 0; i < 4; i++)
                            {
                                regexString = regexString + "([-+]?[0-9]+\\.?[0-9]*) ";
                            }

                            regex = new Regex(regexString.Trim());
                            mc    = regex.Matches(currentLine);


                            foreach (Match m in mc)
                            {
                                int[] triangle = new int[4];
                                triangle[0] = NumberUtils.parseInt(m.Groups[1].Value.Trim());
                                triangle[1] = NumberUtils.parseInt(m.Groups[2].Value.Trim());
                                triangle[2] = NumberUtils.parseInt(m.Groups[3].Value.Trim());
                                triangle[3] = NumberUtils.parseInt(m.Groups[4].Value.Trim());

                                triangles.Add(triangle);
                            }
                        }
                    }

                    List <PrimaryTopologyGroupInfo> groupInfos = new List <PrimaryTopologyGroupInfo>();

                    int maxMaterialIndex = 0;
                    int groupIndexStart  = 0;
                    int triIndex;
                    for (triIndex = 0; triIndex < triangles.Count; triIndex++)
                    {
                        int[] triangle         = triangles[triIndex];
                        int   triMaterialIndex = triangle[3];

                        if (triMaterialIndex > maxMaterialIndex)
                        {
                            groupInfos.Add(new PrimaryTopologyGroupInfo(maxMaterialIndex, groupIndexStart, triIndex - groupIndexStart));
                            maxMaterialIndex = triMaterialIndex;
                            groupIndexStart  = triIndex;
                        }
                    }

                    groupInfos.Add(new PrimaryTopologyGroupInfo(maxMaterialIndex, groupIndexStart, triIndex - groupIndexStart));

                    GrannyMeshInfo meshInfo = new GrannyMeshInfo();
                    meshInfo.name      = meshName;
                    meshInfo.vertices  = vertexInfos;
                    meshInfo.triangles = triangles;
                    meshInfo.primaryTopologyGroupInfos = groupInfos;
                    meshInfo.materialBindingNames      = materialNames;

                    meshInfos.Add(meshInfo);
                }

                modelInfo.skeleton     = skeletonInfo;
                modelInfo.meshBindings = meshInfos;
                modelInfos.Add(modelInfo);
            }

            streamReader.Close();

            return(modelInfos);
        }