/// <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); }