public void BuildBoneIdx2DGOMapIfNecessary(int[] _goToDelete) { _didSetup = false; if (combiner.settings.renderType == MB_RenderType.skinnedMeshRenderer) { if (_goToDelete.Length > 0) { boneIdx2dgoMap = _buildBoneIdx2dgoMap(); } for (int i = 0; i < combiner.bones.Length; i++) { BoneAndBindpose bn = new BoneAndBindpose(combiner.bones[i], combiner.bindPoses[i]); boneAndBindPose2idx.Add(bn, i); //myBone2idx.Add(combiner.bones[i], i); } _didSetup = true; } }
public bool CollectBonesToAddForDGO(MB_DynamicGameObject dgo, Renderer r, bool noExtraBonesForMeshRenderers, MeshChannelsCache meshChannelCache) { bool success = true; Debug.Assert(_didSetup, "Need to setup first."); Debug.Assert(combiner.settings.renderType == MB_RenderType.skinnedMeshRenderer); // We could be working with adding and deleting smr body parts from the same rig. Different smrs will share // the same bones. //cache the bone data that we will be adding. Matrix4x4[] dgoBindPoses = dgo._tmpSMR_CachedBindposes = meshChannelCache.GetBindposes(r, out dgo.isSkinnedMeshWithBones); BoneWeight[] dgoBoneWeights = dgo._tmpSMR_CachedBoneWeights = meshChannelCache.GetBoneWeights(r, dgo.numVerts, dgo.isSkinnedMeshWithBones); Transform[] dgoBones = dgo._tmpSMR_CachedBones = combiner._getBones(r, dgo.isSkinnedMeshWithBones); for (int i = 0; i < dgoBones.Length; i++) { if (dgoBones[i] == null) { Debug.LogError("Source mesh r had a 'null' bone. Bones must not be null: " + r); success = false; } } if (!success) { return(success); } if (noExtraBonesForMeshRenderers) { if (MB_Utility.GetRenderer(dgo.gameObject) is MeshRenderer) { // We are visiting a single dgo which is a MeshRenderer. // It may be the child decendant of a bone in another skinned mesh that is being baked or is already in the combined mesh. We need to find that bone if it exists. // We need to check our parent ancestors and search the bone lists of the other dgos being added or previously baked looking for bones that may have been added Debug.Assert(dgoBones.Length == 1 && dgoBindPoses.Length == 1); // find and cache the parent bone for this MeshRenderer (it may not be the transform.parent) bool foundBoneParent = false; BoneAndBindpose boneParent = new BoneAndBindpose(); { Transform t = dgo.gameObject.transform.parent; while (t != null) { // Look for parent peviously baked in the combined mesh. foreach (BoneAndBindpose b in boneAndBindPose2idx.Keys) { if (b.bone == t) { boneParent = b; foundBoneParent = true; break; } } // Look for parent in something we are adding. foreach (BoneAndBindpose b in bonesToAdd) { if (b.bone == t) { boneParent = b; foundBoneParent = true; break; } } if (foundBoneParent) { break; } else { t = t.parent; } } } if (foundBoneParent) { dgoBones[0] = boneParent.bone; dgoBindPoses[0] = boneParent.bindPose; } } } // The mesh being added may not use all bones on the rig. Find the bones actually used. int[] usedBoneIdx2srcMeshBoneIdx; { /* * HashSet<int> usedBones = new HashSet<int>(); * for (int j = 0; j < dgoBoneWeights.Length; j++) * { * usedBones.Add(dgoBoneWeights[j].boneIndex0); * usedBones.Add(dgoBoneWeights[j].boneIndex1); * usedBones.Add(dgoBoneWeights[j].boneIndex2); * usedBones.Add(dgoBoneWeights[j].boneIndex3); * } * * usedBoneIdx2srcMeshBoneIdx = new int[usedBones.Count]; * usedBones.CopyTo(usedBoneIdx2srcMeshBoneIdx); */ } { usedBoneIdx2srcMeshBoneIdx = new int[dgoBones.Length]; for (int i = 0; i < usedBoneIdx2srcMeshBoneIdx.Length; i++) { usedBoneIdx2srcMeshBoneIdx[i] = i; } } // For each bone see if it exists in the bones array (with the same bindpose.). // We might be baking several skinned meshes on the same rig. We don't want duplicate bones in the bones array. for (int i = 0; i < dgoBones.Length; i++) { bool foundInBonesList = false; int bidx; int dgoBoneIdx = usedBoneIdx2srcMeshBoneIdx[i]; BoneAndBindpose bb = new BoneAndBindpose(dgoBones[dgoBoneIdx], dgoBindPoses[dgoBoneIdx]); if (boneAndBindPose2idx.TryGetValue(bb, out bidx)) { if (dgoBones[dgoBoneIdx] == combiner.bones[bidx] && !boneIdxsToDelete.Contains(bidx) && dgoBindPoses[dgoBoneIdx] == combiner.bindPoses[bidx]) { foundInBonesList = true; } } if (!foundInBonesList) { if (!bonesToAdd.Contains(bb)) { bonesToAdd.Add(bb); } } } dgo._tmpSMRIndexesOfSourceBonesUsed = usedBoneIdx2srcMeshBoneIdx; return(success); }