void GenerateSkinning()
        {
            SkinTools     t              = target as SkinTools;
            SkinToolsData data           = t.Data;
            bool          referenceExist = data.ReferenceSMR != null;

            Vector3[] rVertices      = data.SourceGeometryMF.sharedMesh.vertices;
            Vector3[] rNormals       = data.SourceGeometryMF.sharedMesh.normals;
            Vector3[] rWorldVertices = new Vector3[rVertices.Length];
            Vector2[] rMapVertices   = data.SourceGeometryMF.sharedMesh.uv;
            Matrix4x4 smLTW          = data.SourceGeometryMF.transform.localToWorldMatrix;
            Matrix4x4 tWTL           = t.transform.worldToLocalMatrix;

            for (int v = 0; v < rVertices.Length; v++)
            {
                rWorldVertices[v] = smLTW.MultiplyPoint3x4(rVertices[v]);
                rVertices[v]      = tWTL.MultiplyPoint3x4(rWorldVertices[v]);
                rNormals[v]       = smLTW.MultiplyVector(rNormals[v]);
                rNormals[v]       = tWTL.MultiplyVector(rNormals[v]);
            }


            data.ResultMesh = Instantiate(data.SourceGeometryMF.sharedMesh) as Mesh;
            string[] splittedPath = data.OutputMeshPath.Split("/.".ToCharArray());
            string   meshName     = splittedPath[splittedPath.Length - 2];

            data.ResultMesh.name = meshName;

            data.ResultMesh.vertices = rVertices;
            data.ResultMesh.normals  = rNormals;
            data.ResultMesh.RecalculateBounds();

            data.resultSMR.localBounds = new Bounds(data.ResultMesh.bounds.center, data.ResultMesh.bounds.size * 2);

            SourceSMRCollider _collider  = null;
            SourceSMRCollider _icollider = null;

            BoneWeight[] existingWeights   = null;
            Transform[]  sourceBones       = null;
            int[]        sourceSMRTris     = null;
            Ray[]        frays             = null;
            bool[]       excludedTriangles = null;

            if (referenceExist)
            {
                _collider         = new SourceSMRCollider(data.ReferenceSMR, false);
                _icollider        = new SourceSMRCollider(data.ReferenceSMR, true);
                existingWeights   = data.ReferenceSMR.sharedMesh.boneWeights;
                sourceBones       = data.ReferenceSMR.bones;
                sourceSMRTris     = data.ReferenceSMR.sharedMesh.triangles;
                excludedTriangles = new bool[data.ReferenceSMR.sharedMesh.triangles.Length / 3];
                if (data.ReferenceSMRGeometry != null && data.ReferenceSMRGeometry.IsValid)
                {
                    excludedTriangles = data.ReferenceSMRGeometry.ExcludedTris;
                }

                if (data.BakingQuality == 0)
                {
                    frays = new Ray[ResourceHolder.Rays362.Length];
                    for (int i = 0; i < frays.Length; i++)
                    {
                        frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays362[i]);
                    }
                }
                else if (data.BakingQuality == 1)
                {
                    frays = new Ray[ResourceHolder.Rays642.Length];
                    for (int i = 0; i < frays.Length; i++)
                    {
                        frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays642[i]);
                    }
                }
                else if (data.BakingQuality == 2)
                {
                    frays = new Ray[ResourceHolder.Rays1002.Length];
                    for (int i = 0; i < frays.Length; i++)
                    {
                        frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays1002[i]);
                    }
                }
            }

            ExtBoneWeight[]  ebws         = new ExtBoneWeight[rWorldVertices.Length];
            List <Transform> newBonesList = new List <Transform>();

            for (int b = 0; b < data.MapBones.Count; b++)
            {
                newBonesList.Add(data.MapBones[b].Tr);
            }

            EditorUtility.DisplayProgressBar("Bake", "Baking vertices", 0);
            int progressPercent = 0;

            for (int v = 0; v < rWorldVertices.Length; v++)
            {
                ebws[v] = new ExtBoneWeight(  );

                if (data.SourceGeometry.HasUV0)
                {
                    Vector2 uv = rMapVertices[v];
                    for (int b = 0; b < data.MapBones.Count; b++)
                    {
                        float val = data.MapBones[b].Map.GetPixelBilinear(uv.x, uv.y).grayscale;
                        ebws[v].AddMask(data.MapBones[b].Tr, val);
                    }
                }

                if (referenceExist)
                {
                    RaycastHit hit = GetNearestHit(frays, _collider._Collider, _icollider._Collider, rWorldVertices[v], excludedTriangles);
                    BoneWeight bwA = existingWeights [sourceSMRTris[hit.triangleIndex * 3]];
                    BoneWeight bwB = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 1]];
                    BoneWeight bwC = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 2]];
                    for (int i = 0; i < 4; i++)
                    {
                        Transform nbA = sourceBones[bwA.GetBoneIdx(i)];
                        Transform nbB = sourceBones[bwB.GetBoneIdx(i)];
                        Transform nbC = sourceBones[bwC.GetBoneIdx(i)];

                        if (!data.ReferenceSMRBones[nbA].Excluded)
                        {
                            if (!newBonesList.Contains(nbA))
                            {
                                newBonesList.Add(nbA);
                            }
                            ebws[v].Add(nbA, bwA.GetWeight(i) * hit.barycentricCoordinate.x, 0);
                        }

                        if (!data.ReferenceSMRBones[nbB].Excluded)
                        {
                            if (!newBonesList.Contains(nbB))
                            {
                                newBonesList.Add(nbB);
                            }
                            ebws[v].Add(nbB, bwB.GetWeight(i) * hit.barycentricCoordinate.y, 0);
                        }

                        if (!data.ReferenceSMRBones[nbC].Excluded)
                        {
                            if (!newBonesList.Contains(nbC))
                            {
                                newBonesList.Add(nbC);
                            }
                            ebws[v].Add(nbC, bwC.GetWeight(i) * hit.barycentricCoordinate.z, 0);
                        }
                    }
                }
                float progress = v / (float)rWorldVertices.Length;
                int   percent  = Mathf.FloorToInt(progress * 100);
                if (progressPercent != percent)
                {
                    progressPercent = percent;
                    string progressBarName = string.Format("Bake {0}", data.ResultMesh.name);
                    string progressInfo    = string.Format("baking vertices {0} of {1} with {2} quality ", v, rWorldVertices.Length, data.BakingQualityNames[data.BakingQuality]);
                    EditorUtility.DisplayProgressBar(progressBarName, progressInfo, progress);
                }
            }

            EditorUtility.ClearProgressBar();

            BoneWeight[] newweights = new BoneWeight[rWorldVertices.Length];

            Transform[] newBonesArray = newBonesList.ToArray();
            for (int w = 0; w < ebws.Length; w++)
            {
                ebws[w].FillIndeces(newBonesArray);
                newweights[w] = ebws[w].GetClampedBW();
            }

            data.resultSMR.bones = newBonesArray;
            Matrix4x4[] bindBones = new Matrix4x4[newBonesArray.Length];

            for (int b = 0; b < newBonesArray.Length; b++)
            {
                bindBones[b] = newBonesArray[b].worldToLocalMatrix * t.transform.localToWorldMatrix;
            }

            data.ResultMesh.bindposes   = bindBones;
            data.ResultMesh.boneWeights = newweights;

            if (referenceExist)
            {
                _collider.Destroy();
                _icollider.Destroy();
            }

            AssetDatabase.DeleteAsset(data.OutputMeshPath);
            AssetDatabase.CreateAsset(data.ResultMesh, data.OutputMeshPath);
            AssetDatabase.SaveAssets();
            data.ResultMesh           = AssetDatabase.LoadAssetAtPath(data.OutputMeshPath, typeof(Mesh)) as Mesh;
            data.resultSMR.sharedMesh = data.ResultMesh;
            data.UpdateResultInfo();
            data.ApplyResultVisual();
        }