示例#1
0
        public static void Main()
        {
            Directory.CreateDirectory("LISTTRAK");

            if (File.Exists(@"LISTTRAK\vars.txt"))
            {
                vars.Parse(@"LISTTRAK\vars.txt");
            }

            using (TextWriter writer = new StreamWriter("output.txt"))
            {
                Regex r = new Regex(@"[0-9a-fA-F]{8}\.[0-9a-zA-Z]{3}", RegexOptions.IgnoreCase);
                foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"LISTTRAK"))
                         .Where(x => r.IsMatch(Path.GetFileName(x)))
                         .Select(x => new
                {
                    FilePath = x,
                    FileNumber = Convert.ToInt32(Path.GetFileNameWithoutExtension(x), 16)
                })
                         .OrderBy(x => x.FileNumber))
                {
                    writer.WriteLine("--------------------------------------------------");
                    writer.WriteLine("#{0} {1}", file.FileNumber, vars.GetText("TRACKS", file.FileNumber, string.Empty));
                    writer.WriteLine("--------------------------------------------------");
                    Dump(file.FilePath, writer);
                }
            }
        }
示例#2
0
    void RefreshLeftText()
    {
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.AppendFormat("{0} {1}/{2} <color=#00c864>{3}</color>",
                                   Path.GetFileNameWithoutExtension(modelFolders[modelFolderIndex]),
                                   modelIndex, modelCount - 1,
                                   varParser.GetText("BODYS", modelIndex));

        if (EnableAnimation.BoolValue)
        {
            stringBuilder.Append("\r\n");
            stringBuilder.AppendFormat("{0} {1}/{2} <color=#00c864>{3}</color>",
                                       Path.GetFileNameWithoutExtension(animFolders[modelFolderIndex]),
                                       animIndex, animCount - 1,
                                       varParser.GetText("ANIMS", animIndex));
        }

        if (ShowAdditionalInfo.BoolValue)
        {
            stringBuilder.Append("\r\n\r\n");
            stringBuilder.AppendFormat("Bounding box: <color=#00c864>{0} {1} {2}</color>\r\n",
                                       boundingUpper.x - boundingLower.x,
                                       boundingUpper.y - boundingLower.y,
                                       boundingUpper.z - boundingLower.z);
        }

        if (EnableAnimation.BoolValue && ShowAdditionalInfo.BoolValue && animFrames != null)
        {
            int index = 0;
            foreach (Frame frame in animFrames)
            {
                stringBuilder.AppendFormat("Frame {0}: <color=#00c864>{1} {2} {3} {4}</color>\r\n", index, frame.Time, frame.Offset.x, frame.Offset.y, -frame.Offset.z);
                index++;
            }
        }

        LeftText.text = stringBuilder.ToString();
        frameDistance = Vector3.zero;
    }
示例#3
0
    void LoadBody(bool resetcamera = true)
    {
        int    fileIndex  = modelFiles[modelIndex].Key;
        string varName    = varParser.GetText("BODYS", fileIndex);
        string folderName = modelFolders[modelFolderIndex];

        leftTextBody = folderName.Substring(folderName.Length - 4) + " " + fileIndex + "/" + modelFiles[modelFiles.Count - 1].Key + " <color=#00c864>" + varName + "</color>";
        RefreshLeftText();

        //camera
        if (resetcamera)
        {
            autoRotate     = true;
            cameraPosition = Vector2.zero;
        }

        //clear model
        SkinnedMeshRenderer filter = this.gameObject.GetComponent <SkinnedMeshRenderer>();

        filter.sharedMesh = null;

        //delete all bones
        foreach (Transform child in transform)
        {
            GameObject.Destroy(child.gameObject);
        }

        //load data
        string filename = modelFiles[modelIndex].Value;

        byte[] allbytes = File.ReadAllBytes(filename);
        int    i        = 0;

        //header
        modelFlags = allbytes.ReadShort(i + 0);

        //bounding box
        allbytes.ReadBoundingBox(i + 2, out boundingLower, out boundingUpper);

        i += 0xE;
        i += allbytes.ReadShort(i + 0) + 2;

        //vertexes
        int count = allbytes.ReadShort(i + 0);

        i += 2;

        List <Vector3> vertices = new List <Vector3>();

        for (int j = 0; j < count; j++)
        {
            Vector3 position = new Vector3(allbytes.ReadShort(i + 0), -allbytes.ReadShort(i + 2), allbytes.ReadShort(i + 4));
            vertices.Add(position / 1000.0f);
            i += 6;
        }

        bones = new List <Transform>();
        List <Matrix4x4>      bindPoses         = new List <Matrix4x4>();
        Dictionary <int, int> bonesPerVertex    = new Dictionary <int, int>();
        List <Vector3>        vertexNoTransform = vertices.ToList();

        if ((modelFlags & 2) == 2)         //check if model has bones
        {
            //bones
            count = allbytes.ReadShort(i + 0);
            i    += 2;
            i    += count * 2;

            Dictionary <int, Transform> bonesPerIndex = new Dictionary <int, Transform>();

            bonesPerIndex.Add(255, transform);
            for (int n = 0; n < count; n++)
            {
                int startindex  = allbytes.ReadShort(i + 0) / 6;
                int numpoints   = allbytes.ReadShort(i + 2);
                int vertexindex = allbytes.ReadShort(i + 4) / 6;
                int parentindex = allbytes[i + 6];
                int boneindex   = allbytes[i + 7];

                //create bone
                Transform bone = new GameObject("BONE").transform;
                bonesPerIndex.Add(boneindex, bone);

                bone.parent        = bonesPerIndex[parentindex];
                bone.localRotation = Quaternion.identity;
                bone.localPosition = vertexNoTransform[vertexindex];
                bones.Add(bone);

                //create pose
                Matrix4x4 bindPose = new Matrix4x4();
                bindPose = bone.worldToLocalMatrix * transform.localToWorldMatrix;
                bindPoses.Add(bindPose);

                //apply bone transformation
                Vector3 position = vertices[vertexindex];
                for (int u = 0; u < numpoints; u++)
                {
                    vertices[startindex] += position;
                    bonesPerVertex.Add(startindex, bones.Count - 1);
                    startindex++;
                }

                if ((modelFlags & 8) == 8)
                {
                    i += 0x18;
                }
                else
                {
                    i += 0x10;
                }
            }
        }
        else
        {
            //if no bones add dummy values
            for (int u = 0; u < vertices.Count; u++)
            {
                bonesPerVertex.Add(u, 0);
            }
        }

        //compute line size
        Bounds bounds = new Bounds();

        foreach (Vector3 vector in vertices)
        {
            bounds.Encapsulate(vector);
        }
        float linesize  = bounds.size.magnitude / 250.0f;
        float noisesize = 0.8f / bounds.size.magnitude;

        //primitives
        count = allbytes.ReadShort(i + 0);
        i    += 2;

        //load palette
        Color32[] paletteColors = PaletteTexture[paletteIndex].GetPixels32();

        List <BoneWeight> boneWeights = new List <BoneWeight>();

        allVertices = new List <Vector3>();
        uv          = new List <Vector2>();
        uvDepth     = new List <Vector2>();
        List <Color32> colors = new List <Color32>();

        List <int>[] indices = new List <int> [5];

        for (int n = 0; n < indices.Length; n++)
        {
            indices[n] = new List <int>();
        }

        gradientPolygonList = new List <List <int> >();
        gradientPolygonType = new List <int>();

        for (int n = 0; n < count; n++)
        {
            int primitiveType = allbytes[i + 0];
            i++;

            switch (primitiveType)
            {
            //line
            case 0:
            {
                i++;
                int colorIndex = allbytes[i + 0];
                i += 2;

                Color32    color           = paletteColors[colorIndex];
                int        pointIndexA     = allbytes.ReadShort(i + 0) / 6;
                int        pointIndexB     = allbytes.ReadShort(i + 2) / 6;
                Vector3    directionVector = vertices[pointIndexA] - vertices[pointIndexB];
                Vector3    middle          = (vertices[pointIndexA] + vertices[pointIndexB]) / 2.0f;
                Quaternion rotation        = Quaternion.LookRotation(directionVector);

                uv.AddRange(CubeMesh.uv);
                uvDepth.AddRange(CubeMesh.vertices.Select(x => Vector2.zero));
                indices[0].AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(CubeMesh.vertices.Select(x =>
                                                              rotation * (Vector3.Scale(x, new Vector3(linesize, linesize, directionVector.magnitude)))
                                                              + middle));
                colors.AddRange(CubeMesh.vertices.Select(x => color));
                boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[x.z > 0 ? pointIndexA : pointIndexB], weight0 = 1
                    }));

                i += 4;
                break;
            }

            //polygon
            case 1:
            {
                int numPoints  = allbytes[i + 0];
                int polyType   = allbytes[i + 1];
                int colorIndex = allbytes[i + 2];
                i += 3;

                Color32    color        = GetPaletteColor(paletteColors, colorIndex, polyType);
                List <int> triangleList = indices[GetTriangleListIndex(polyType)];

                //add vertices
                List <int> polyVertices  = new List <int>();
                int        verticesCount = allVertices.Count;
                for (int m = 0; m < numPoints; m++)
                {
                    int pointIndex = allbytes.ReadShort(i + 0) / 6;
                    i += 2;

                    colors.Add(color);
                    polyVertices.Add(allVertices.Count);
                    allVertices.Add(vertices[pointIndex]);
                    boneWeights.Add(new BoneWeight()
                        {
                            boneIndex0 = bonesPerVertex[pointIndex], weight0 = 1
                        });
                }

                gradientPolygonType.Add(polyType);
                gradientPolygonList.Add(polyVertices);

                if (polyType == 1 && NoiseMaterial.BoolValue)
                {
                    Vector3 forward, left;
                    ComputeUV(polyVertices, out forward, out left);

                    foreach (int pointIndex in polyVertices)
                    {
                        Vector3 poly = allVertices[pointIndex];

                        uv.Add(new Vector2(
                                   Vector3.Dot(poly, left) * noisesize,
                                   Vector3.Dot(poly, forward) * noisesize
                                   ));
                    }
                }
                else
                {
                    uv.AddRange(polyVertices.Select(x => Vector2.zero));
                }

                uvDepth.AddRange(polyVertices.Select(x => Vector2.zero));

                //triangulate
                int  v0   = 0;
                int  v1   = 1;
                int  v2   = numPoints - 1;
                bool swap = true;

                while (v1 < v2)
                {
                    triangleList.Add(verticesCount + v0);
                    triangleList.Add(verticesCount + v1);
                    triangleList.Add(verticesCount + v2);

                    if (swap)
                    {
                        v0 = v1;
                        v1++;
                    }
                    else
                    {
                        v0 = v2;
                        v2--;
                    }

                    swap = !swap;
                }

                break;
            }

            //sphere
            case 3:
            {
                int polyType = allbytes[i];
                i++;
                int        colorIndex   = allbytes[i];
                Color32    color        = GetPaletteColor(paletteColors, colorIndex, polyType);
                List <int> triangleList = indices[GetTriangleListIndex(polyType)];

                i += 2;

                int size = allbytes.ReadShort(i + 0);
                i += 2;
                int pointSphereIndex = allbytes.ReadShort(i + 0) / 6;
                i += 2;

                Vector3 position = vertices[pointSphereIndex];
                float   scale    = size / 500.0f;
                float   uvScale  = noisesize * size / 200.0f;

                if ((polyType == 3 || polyType == 4 || polyType == 5 || polyType == 6) && GradientMaterial.BoolValue)
                {
                    gradientPolygonType.Add(polyType);
                    gradientPolygonList.Add(Enumerable.Range(allVertices.Count, SphereMesh.vertices.Length).ToList());
                }

                uv.AddRange(SphereMesh.uv.Select(x => x * uvScale));
                uvDepth.AddRange(SphereMesh.vertices.Select(x => Vector2.zero));
                triangleList.AddRange(SphereMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(SphereMesh.vertices.Select(x => x * scale + position));
                colors.AddRange(SphereMesh.vertices.Select(x => color));
                boneWeights.AddRange(SphereMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[pointSphereIndex], weight0 = 1
                    }));
                break;
            }

            case 2:                     //1x1 pixel
            case 6:                     //2x2 square
            case 7:                     //NxN square, size depends projected z-value
            {
                i++;
                int colorIndex = allbytes[i];
                i += 2;
                int cubeIndex = allbytes.ReadShort(i + 0) / 6;
                i += 2;

                Color32 color    = paletteColors[colorIndex];
                Vector3 position = vertices[cubeIndex];

                float pointsize;
                if (primitiveType == 2)
                {
                    pointsize = linesize;
                }
                else
                {
                    pointsize = linesize * 2.5f;
                }

                uv.AddRange(CubeMesh.uv);
                uvDepth.AddRange(CubeMesh.vertices.Select(x => Vector2.zero));
                indices[0].AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(CubeMesh.vertices.Select(x => x * pointsize + position));
                colors.AddRange(CubeMesh.vertices.Select(x => color));
                boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[cubeIndex], weight0 = 1
                    }));
                break;
            }

            case 4:
            case 5:                     //should be ignored
                break;

            default:
                throw new UnityException("unknown primitive " + primitiveType.ToString() + " at " + i.ToString());
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices = allVertices.ToArray();
        msh.colors32 = colors.ToArray();

        //separate transparent/opaque triangles

        msh.subMeshCount = 5;
        msh.SetTriangles(indices[0], 0);
        msh.SetTriangles(indices[1], 1);
        msh.SetTriangles(indices[2], 2);
        msh.SetTriangles(indices[3], 3);
        msh.SetTriangles(indices[4], 4);
        msh.SetUVs(0, uv);
        msh.SetUVs(1, uvDepth);
        msh.RecalculateNormals();
        msh.RecalculateBounds();

        //apply bones
        if (bones.Count > 0)
        {
            msh.boneWeights = boneWeights.ToArray();
            msh.bindposes   = bindPoses.ToArray();
            GetComponent <SkinnedMeshRenderer>().bones = bones.ToArray();
            initialBonesPosition = bones.Select(x => x.localPosition).ToList();
        }

        filter.localBounds = msh.bounds;
        filter.sharedMesh  = msh;
    }
示例#4
0
        void GridCellEnter(object sender, CellEventArgs e)
        {
            string text = varParser.GetText(e.Var.Type, e.Var.Index);

            toolTip.Show(string.Format("#{0}\n{1}", e.Var.Index, text), e.Rectangle);
        }
示例#5
0
    void LoadBody(string filename, bool resetcamera = true)
    {
        string varName = varParser.GetText("BODYS", modelIndex);

        LeftTextBody = Path.GetFileName(Path.GetDirectoryName(filename)) + " " + modelIndex + "/" + (modelFiles.Count - 1) + " <color=#00c864>" + varName + "</color>";
        RefreshLeftText();

        //camera
        if (resetcamera)
        {
            autoRotate     = true;
            cameraPosition = Vector2.zero;
        }

        //clear model
        SkinnedMeshRenderer filter = this.gameObject.GetComponent <SkinnedMeshRenderer>();

        filter.sharedMesh = null;

        //delete all bones
        foreach (Transform child in transform)
        {
            GameObject.Destroy(child.gameObject);
        }

        //load data
        byte[] allbytes = File.ReadAllBytes(filename);
        int    i        = 0;

        //header
        int flags = Utils.ReadShort(allbytes, i + 0);

        i += 0xE;
        i += Utils.ReadShort(allbytes, i + 0) + 2;

        //vertexes
        int count = Utils.ReadShort(allbytes, i + 0);

        i += 2;

        List <Vector3> vertices = new List <Vector3>();

        for (int j = 0; j < count; j++)
        {
            Vector3 position = new Vector3(Utils.ReadShort(allbytes, i + 0), -Utils.ReadShort(allbytes, i + 2), Utils.ReadShort(allbytes, i + 4));
            vertices.Add(position / 1000.0f);
            i += 6;
        }

        //check if model has bones
        bones = new List <Transform>();
        List <Matrix4x4>      bindPoses         = new List <Matrix4x4>();
        Dictionary <int, int> bonesPerVertex    = new Dictionary <int, int>();
        List <Vector3>        vertexNoTransform = vertices.ToList();

        if ((flags & 2) == 2)
        {
            //bones
            count = Utils.ReadShort(allbytes, i + 0);
            i    += 2;
            i    += count * 2;

            Dictionary <int, Transform> bonesPerIndex = new Dictionary <int, Transform>();

            bonesPerIndex.Add(255, transform);
            for (int n = 0; n < count; n++)
            {
                int startindex  = Utils.ReadShort(allbytes, i + 0) / 6;
                int numpoints   = Utils.ReadShort(allbytes, i + 2);
                int vertexindex = Utils.ReadShort(allbytes, i + 4) / 6;
                int parentindex = allbytes[i + 6];
                int boneindex   = allbytes[i + 7];

                //create bone
                Transform bone = new GameObject("BONE").transform;
                bonesPerIndex.Add(boneindex, bone);

                bone.parent        = bonesPerIndex[parentindex];
                bone.localRotation = Quaternion.identity;
                bone.localPosition = vertexNoTransform[vertexindex];
                bones.Add(bone);

                //create pose
                Matrix4x4 bindPose = new Matrix4x4();
                bindPose = bone.worldToLocalMatrix * transform.localToWorldMatrix;
                bindPoses.Add(bindPose);

                //apply bone transformation
                Vector3 position = vertices[vertexindex];
                for (int u = 0; u < numpoints; u++)
                {
                    vertices[startindex] += position;
                    bonesPerVertex.Add(startindex, bones.Count - 1);
                    startindex++;
                }

                i += 0x10;
            }
        }
        else
        {
            //if no bones add dummy values
            for (int u = 0; u < vertices.Count; u++)
            {
                bonesPerVertex.Add(u, 0);
            }
        }

        //compute line size
        Bounds bounds = new Bounds();

        foreach (Vector3 vector in vertices)
        {
            bounds.Encapsulate(vector);
        }
        float linesize  = bounds.size.magnitude / 250.0f;
        float noisesize = 0.8f / bounds.size.magnitude;

        //primitives
        count = Utils.ReadShort(allbytes, i + 0);
        i    += 2;

        //load palette
        Color32[] paletteColors = PaletteTexture[PaletteIndex].GetPixels32();

        List <BoneWeight> boneWeights = new List <BoneWeight>();
        List <Vector3>    allVertices = new List <Vector3>();
        List <Color32>    colors      = new List <Color32>();
        List <int>        indices     = new List <int>();
        List <Vector2>    uv          = new List <Vector2>();

        for (int n = 0; n < count; n++)
        {
            int primitiveType = allbytes[i + 0];
            i++;

            switch (primitiveType)
            {
            //line
            case 0:
            {
                i++;
                int colorIndex = allbytes[i + 0];
                i += 2;

                Color32    color           = paletteColors[colorIndex];
                int        pointIndexA     = Utils.ReadShort(allbytes, i + 0) / 6;
                int        pointIndexB     = Utils.ReadShort(allbytes, i + 2) / 6;
                Vector3    directionVector = vertices[pointIndexA] - vertices[pointIndexB];
                Vector3    middle          = (vertices[pointIndexA] + vertices[pointIndexB]) / 2.0f;
                Quaternion rotation        = Quaternion.LookRotation(directionVector);

                uv.AddRange(CubeMesh.uv);
                indices.AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(CubeMesh.vertices.Select(x =>
                                                              rotation * (Vector3.Scale(x, new Vector3(linesize, linesize, directionVector.magnitude)))
                                                              + middle));
                colors.AddRange(CubeMesh.vertices.Select(x => color));
                boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[x.z > 0 ? pointIndexA : pointIndexB], weight0 = 1
                    }));

                i += 4;
                break;
            }

            //polygon
            case 1:
            {
                int numPoints  = allbytes[i + 0];
                int polyType   = allbytes[i + 1];
                int colorIndex = allbytes[i + 2];
                i += 3;

                Color32 color = GetPaletteColor(paletteColors, colorIndex, polyType);

                //add vertices
                List <Vector3> polyVertices  = new List <Vector3>();
                int            verticesCount = allVertices.Count;
                for (int m = 0; m < numPoints; m++)
                {
                    int pointIndex = Utils.ReadShort(allbytes, i + 0) / 6;
                    i += 2;

                    colors.Add(color);
                    allVertices.Add(vertices[pointIndex]);
                    polyVertices.Add(vertices[pointIndex]);
                    boneWeights.Add(new BoneWeight()
                        {
                            boneIndex0 = bonesPerVertex[pointIndex], weight0 = 1
                        });
                }

                if (polyType == 1 && NoiseMaterial.BoolValue)
                {
                    Vector3 forward, left;
                    ComputeUV(polyVertices, out forward, out left);

                    foreach (Vector3 poly in polyVertices)
                    {
                        uv.Add(new Vector2(
                                   Vector3.Dot(poly, left) * noisesize,
                                   Vector3.Dot(poly, forward) * noisesize
                                   ));
                    }
                }
                else
                {
                    uv.AddRange(polyVertices.Select(x => Vector2.zero));
                }

                //triangulate
                int  v0   = 0;
                int  v1   = 1;
                int  v2   = numPoints - 1;
                bool swap = true;

                while (v1 < v2)
                {
                    indices.Add(verticesCount + v0);
                    indices.Add(verticesCount + v1);
                    indices.Add(verticesCount + v2);

                    if (swap)
                    {
                        v0 = v1;
                        v1++;
                    }
                    else
                    {
                        v0 = v2;
                        v2--;
                    }

                    swap = !swap;
                }

                break;
            }

            //sphere
            case 3:
            {
                int polyType = allbytes[i];
                i++;
                int     colorIndex = allbytes[i];
                Color32 color      = GetPaletteColor(paletteColors, colorIndex, polyType);
                i += 2;

                int size = Utils.ReadShort(allbytes, i + 0);
                i += 2;
                int pointSphereIndex = Utils.ReadShort(allbytes, i + 0) / 6;
                i += 2;

                Vector3 position = vertices[pointSphereIndex];
                float   scale    = size / 500.0f;
                float   uvScale  = noisesize * size / 200.0f;

                uv.AddRange(SphereMesh.uv.Select(x => x * uvScale));
                indices.AddRange(SphereMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(SphereMesh.vertices.Select(x => x * scale + position));
                colors.AddRange(SphereMesh.vertices.Select(x => color));
                boneWeights.AddRange(SphereMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[pointSphereIndex], weight0 = 1
                    }));
                break;
            }

            case 2:                     //1x1 pixel
            case 6:                     //square
            case 7:
            {
                i++;
                int colorIndex = allbytes[i];
                i += 2;
                int cubeIndex = Utils.ReadShort(allbytes, i + 0) / 6;
                i += 2;

                Color32 color    = paletteColors[colorIndex];
                Vector3 position = vertices[cubeIndex];

                float pointsize;
                if (primitiveType == 2)
                {
                    pointsize = linesize;
                }
                else
                {
                    pointsize = linesize * 2.5f;
                }

                uv.AddRange(CubeMesh.uv);
                indices.AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count));
                allVertices.AddRange(CubeMesh.vertices.Select(x => x * pointsize + position));
                colors.AddRange(CubeMesh.vertices.Select(x => color));
                boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight()
                    {
                        boneIndex0 = bonesPerVertex[cubeIndex], weight0 = 1
                    }));
                break;
            }

            default:
                throw new UnityException("unknown primitive " + primitiveType.ToString() + " at " + i.ToString());
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices = allVertices.ToArray();
        msh.colors32 = colors.ToArray();

        //separate transparent/opaque triangles
        List <int> opaque      = new List <int>();
        List <int> noise       = new List <int>();
        List <int> transparent = new List <int>();
        List <int> gradient    = new List <int>();

        for (int t = 0; t < indices.Count; t += 3)
        {
            List <int> trianglesList;
            float      alpha = colors[indices[t]].a;
            if (alpha == 255)
            {
                trianglesList = opaque;
            }
            else if (alpha == 254)
            {
                trianglesList = noise;
            }
            else if (alpha == 253)
            {
                trianglesList = gradient;
            }
            else
            {
                trianglesList = transparent;
            }

            trianglesList.Add(indices[t + 0]);
            trianglesList.Add(indices[t + 1]);
            trianglesList.Add(indices[t + 2]);
        }

        msh.subMeshCount = 4;
        msh.SetTriangles(opaque, 0);
        msh.SetTriangles(transparent, 1);
        msh.SetTriangles(noise, 2);
        msh.SetTriangles(gradient, 3);
        msh.SetUVs(0, uv);

        msh.RecalculateNormals();
        msh.RecalculateBounds();

        //apply bones
        if (bones.Count > 0)
        {
            msh.boneWeights = boneWeights.ToArray();
            msh.bindposes   = bindPoses.ToArray();
            GetComponent <SkinnedMeshRenderer>().bones = bones.ToArray();
            initialBonesPosition = bones.Select(x => x.localPosition).ToList();
        }

        filter.localBounds = msh.bounds;
        filter.sharedMesh  = msh;
    }