Example #1
0
        public GrannySkeletonInfo readSkeletonInfo()
        {
            GrannySkeletonInfo    skeletonInfo = new GrannySkeletonInfo();
            List <GrannyBoneInfo> boneInfos    = new List <GrannyBoneInfo>();

            for (int bi = 0; bi < wrappedSkeleton.Bones.Count; bi++)
            {
                IGrannyBone    bone     = wrappedSkeleton.Bones[bi];
                GrannyBoneInfo boneInfo = new GrannyBoneInfo();
                boneInfo.name        = bone.Name;
                boneInfo.parentIndex = bone.ParentIndex;
                GrannyTransformInfo boneTransformInfo = new GrannyTransformInfo();

                IGrannyTransform boneTransform = bone.LocalTransform;
                boneTransformInfo.flags = GrannyTransformInfo.getFlagsInt(boneTransform.Flags);

                GrannyBoneWrapper boneWrapper = new GrannyBoneWrapper(bone);
                boneTransformInfo.orientation = boneWrapper.getOrientation();
                boneTransformInfo.position    = boneWrapper.getPosition();
                boneTransformInfo.scaleShear  = boneWrapper.getScaleShear();

                boneInfo.localTransform = boneTransformInfo;

                boneInfo.inverseWorldTransform = bone.InverseWorldTransform;
                boneInfo.LODError = bone.LODError;

                boneInfos.Add(boneInfo);
            }

            skeletonInfo.bones = boneInfos;
            return(skeletonInfo);
        }
Example #2
0
        public void writeSkeletonInfo(GrannySkeletonInfo skeletonInfo)
        {
            int bonesCount = skeletonInfo.bones.Count;

            setNumBones(bonesCount);

            int oldBonesPtr = *(int *)getBonesPtr();

            *(int *)(getBonesPtr()) = (int)Marshal.AllocHGlobal(bonesCount * boneSize);
            int newBonesPtr = *(int *)getBonesPtr();

            List <GrannyBoneInfo> boneInfos = skeletonInfo.bones;

            for (int i = 0; i < bonesCount; i++)
            {
                MemoryUtil.MemCpy((void *)(newBonesPtr + i * boneSize), (void *)oldBonesPtr, (uint)boneSize);

                GrannyBoneInfo currentBone = boneInfos[i];

                *(int *)(newBonesPtr + (i * boneSize) + 0) = (int)MemoryUtil.getStringIntPtr(currentBone.name);

                *(int *)(newBonesPtr + (i * boneSize) + 4) = currentBone.parentIndex;

                int flags = currentBone.localTransform.flags;

                *(int *)(newBonesPtr + (i * boneSize) + 8) = flags;

                *(float *)(newBonesPtr + (i * boneSize) + 12) = currentBone.localTransform.position[0];
                *(float *)(newBonesPtr + (i * boneSize) + 16) = currentBone.localTransform.position[1];
                *(float *)(newBonesPtr + (i * boneSize) + 20) = currentBone.localTransform.position[2];

                *(float *)(newBonesPtr + (i * boneSize) + 24) = currentBone.localTransform.orientation[0];
                *(float *)(newBonesPtr + (i * boneSize) + 28) = currentBone.localTransform.orientation[1];
                *(float *)(newBonesPtr + (i * boneSize) + 32) = currentBone.localTransform.orientation[2];
                *(float *)(newBonesPtr + (i * boneSize) + 36) = currentBone.localTransform.orientation[3];

                for (int j = 0; j < 9; j++)
                {
                    *(float *)(newBonesPtr + (i * boneSize) + 40 + (j * 4)) = currentBone.localTransform.scaleShear[j];
                }

                for (int j = 0; j < 16; j++)
                {
                    *(float *)(newBonesPtr + (i * boneSize) + 76 + (j * 4)) = currentBone.inverseWorldTransform[j];
                }

                *(float *)(newBonesPtr + (i * boneSize) + 140) = 1.0f;

                // +140 LOD Error
                // +144 Num Extended Datas
                // +148 Extended Datas Pointer
            }
        }
Example #3
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;
            }
        }
Example #4
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);
        }
Example #5
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);
        }