/// <summary>
        /// Slice by Human Bone.
        /// </summary>
        /// <param name="humanBone">The Human Bone to slice.</param>
        /// <param name="hasNotSplit"></param>
        /// <param name="info">Struct containing slice info.</param>
        /// <param name="useGlobalThreshold">Turn off global threshold or individual bone threshold.</param>
        public void Slice(HumanBodyBones humanBone, bool hasNotSplit, out DismemberedInfo info, bool useGlobalThreshold = false)
        {
            info = new DismemberedInfo();

            Transform bone;

            if (!ValidateHumanBone(humanBone, out bone))
            {
                return;
            }

            int index = -1;

            if (useSliceable)
            {
                index = ContainsBone(humanBone);
                if (index == -1)
                {
                    return;
                }
            }

            if (hasNotSplit)
            {
                if (hasSplit.Contains(bone))
                {
                    return;
                }
            }

            if (!useSliceable || useGlobalThreshold)
            {
                SliceInternal(bone, globalThreshold, ref info);
            }
            else
            {
                SliceInternal(bone, sliceableHumanBones[index].threshold, ref info);
            }
        }
        private void SliceInternal(Transform bone, float threshold, ref DismemberedInfo info)
        {
            if (bone == null)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Bone is null!");
                }
                return;
            }
            //Profiler.BeginSample("Slice");
            edges.Clear();
            weights.Clear();
            smr.sharedMesh.GetBoneWeights(weights);

            Transform[] smrBones        = smr.bones;
            bool[]      boneMask        = GenerateBoneNumbers(bone);
            bool[]      computedWeights = new bool[weights.Count];
            Mesh        innerMesh       = Instantiate <Mesh>(smr.sharedMesh);

            //Create new root GameObject and all it's children bones
            GameObject splitRootObj = new GameObject(bone.name, typeof(SkinnedMeshRenderer));

            splitRootObj.transform.position   = gameObject.transform.position;
            splitRootObj.transform.rotation   = gameObject.transform.rotation;
            splitRootObj.transform.localScale = gameObject.transform.localScale;

            GameObject root = gameObject.transform.Find("Root").gameObject;

            Transform[] newBones;
            Transform   targetBone;

            CreateBones(root, splitRootObj, smrBones, smrBones.Length, bone, out newBones, out targetBone);


            //Create the new renderer to copy the split mesh to.
            SkinnedMeshRenderer newSmr = splitRootObj.GetComponent <SkinnedMeshRenderer>();

            newSmr.bones           = newBones;
            newSmr.sharedMesh      = innerMesh;
            newSmr.sharedMesh.name = bone.name;

            //precompute the weights so we aren't wasting computation on the same vertex.
            for (int i = 0; i < computedWeights.Length; i++)
            {
                computedWeights[i] = IsPartOf(weights[i], boneMask, threshold);
            }

            for (int subMeshIndex = 0; subMeshIndex < smr.sharedMesh.subMeshCount; subMeshIndex++)
            {
                tris.Clear();
                innerMesh.GetTriangles(tris, subMeshIndex);
                innerTris.Clear();
                outerTris.Clear();

                for (int i = 0; i < tris.Count; i += 3)
                {
                    bool vert1 = computedWeights[tris[i]];
                    bool vert2 = computedWeights[tris[i + 1]];
                    bool vert3 = computedWeights[tris[i + 2]];

                    if (vert1 || vert2 || vert3)
                    {
                        if (vert1 && !vert2 && !vert3)
                        {
                            edges.Add(tris[i + 1]); edges.Add(tris[i + 2]);
                        }
                        if (!vert1 && vert2 && !vert3)
                        {
                            edges.Add(tris[i + 2]); edges.Add(tris[i + 0]);
                        }
                        if (!vert1 && !vert2 && vert3)
                        {
                            edges.Add(tris[i + 0]); edges.Add(tris[i + 1]);
                        }

                        innerTris.Add(tris[i]);
                        innerTris.Add(tris[i + 1]);
                        innerTris.Add(tris[i + 2]);
                    }
                    else
                    {
                        outerTris.Add(tris[i]);
                        outerTris.Add(tris[i + 1]);
                        outerTris.Add(tris[i + 2]);
                    }
                }

                smr.sharedMesh.SetTriangles(outerTris, subMeshIndex);
                innerMesh.SetTriangles(innerTris, subMeshIndex);
            }

            CapMesh(newSmr.sharedMesh, edges, false);
            CapMesh(smr.sharedMesh, edges, true);

            //Copy over materials and add the chopFill materials
            int matCount = smr.sharedMaterials.Length;

            Material[] materials = new Material[matCount + 1];
            for (int i = 0; i < matCount; i++)
            {
                materials[i] = smr.sharedMaterials[i];
            }
            materials[matCount]    = sliceFillInstance;
            newSmr.sharedMaterials = materials;
            smr.sharedMaterials    = materials;

            hasSplit.Add(bone);

            //Fill out DismemberedInfo
            info.root       = splitRootObj.transform;
            info.targetBone = targetBone;

            //Event callback
            if (useEvents)
            {
                DismemberedEvent.Invoke(splitRootObj.transform, targetBone);
            }
            //Profiler.EndSample();
        }
 /// <summary>
 /// Slice by bone transform.
 /// </summary>
 /// <param name="bone">The bone transform to slice.</param>
 /// <param name="threshold">Threshold to determine whether a vertex is sliced or not.</param>
 /// <param name="info">Struct containing slice info.</param>
 public void Slice(Transform bone, float threshold, out DismemberedInfo info)
 {
     info = new DismemberedInfo();
     SliceInternal(bone, threshold, ref info);
 }