485 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			485 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.Collections;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace DigitalOpus.MB.Core
 | |
| {
 | |
| 
 | |
|     public partial class MB3_MeshCombinerSingle : MB3_MeshCombiner
 | |
|     {
 | |
|         public class MB3_MeshCombinerSimpleBones
 | |
|         {
 | |
|             MB3_MeshCombinerSingle combiner;
 | |
|             List<MB3_MeshCombinerSingle.MB_DynamicGameObject>[] boneIdx2dgoMap = null;
 | |
|             HashSet<int> boneIdxsToDelete = new HashSet<int>();
 | |
|             HashSet<MB3_MeshCombinerSingle.BoneAndBindpose> bonesToAdd = new HashSet<MB3_MeshCombinerSingle.BoneAndBindpose>();
 | |
|             Dictionary<BoneAndBindpose, int> boneAndBindPose2idx = new Dictionary<BoneAndBindpose, int>();
 | |
| 
 | |
|             public MB3_MeshCombinerSimpleBones(MB3_MeshCombinerSingle cm)
 | |
|             {
 | |
|                 combiner = cm;
 | |
|             }
 | |
| 
 | |
|             public HashSet<MB3_MeshCombinerSingle.BoneAndBindpose> GetBonesToAdd()
 | |
|             {
 | |
|                 return bonesToAdd;
 | |
|             }
 | |
| 
 | |
|             public int GetNumBonesToDelete()
 | |
|             {
 | |
|                 return boneIdxsToDelete.Count;
 | |
|             }
 | |
| 
 | |
|             private bool _didSetup = false;
 | |
|             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 void FindBonesToDelete(MB_DynamicGameObject dgo)
 | |
|             {
 | |
|                 Debug.Assert(_didSetup);
 | |
|                 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. Track if we need to delete a bone or not.
 | |
|                 for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
 | |
|                 {
 | |
|                     int idxOfUsedBone = dgo.indexesOfBonesUsed[j];
 | |
|                     List<MB_DynamicGameObject> dgosThatUseBone = boneIdx2dgoMap[idxOfUsedBone];
 | |
|                     if (dgosThatUseBone.Contains(dgo))
 | |
|                     {
 | |
|                         dgosThatUseBone.Remove(dgo);
 | |
|                         if (dgosThatUseBone.Count == 0)
 | |
|                         {
 | |
|                             boneIdxsToDelete.Add(idxOfUsedBone);
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             public int GetNewBonesLength()
 | |
|             {
 | |
|                 return combiner.bindPoses.Length + bonesToAdd.Count - boneIdxsToDelete.Count;
 | |
|             }
 | |
| 
 | |
|             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);
 | |
|                 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;
 | |
|             }
 | |
| 
 | |
|             private List<MB3_MeshCombinerSingle.MB_DynamicGameObject>[] _buildBoneIdx2dgoMap()
 | |
|             {
 | |
|                 List<MB3_MeshCombinerSingle.MB_DynamicGameObject>[] boneIdx2dgoMap = new List<MB3_MeshCombinerSingle.MB_DynamicGameObject>[combiner.bones.Length];
 | |
|                 for (int i = 0; i < boneIdx2dgoMap.Length; i++) boneIdx2dgoMap[i] = new List<MB3_MeshCombinerSingle.MB_DynamicGameObject>();
 | |
|                 // build the map of bone indexes to objects that use them
 | |
|                 for (int i = 0; i < combiner.mbDynamicObjectsInCombinedMesh.Count; i++)
 | |
|                 {
 | |
|                     MB3_MeshCombinerSingle.MB_DynamicGameObject dgo = combiner.mbDynamicObjectsInCombinedMesh[i];
 | |
|                     for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
 | |
|                     {
 | |
|                         boneIdx2dgoMap[dgo.indexesOfBonesUsed[j]].Add(dgo);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 return boneIdx2dgoMap;
 | |
|             }
 | |
| 
 | |
|             public void CopyBonesWeAreKeepingToNewBonesArrayAndAdjustBWIndexes(Transform[] nbones, Matrix4x4[] nbindPoses, BoneWeight[] nboneWeights, int totalDeleteVerts)
 | |
|             {
 | |
|                 // bones are copied separately because some dgos share bones
 | |
|                 if (boneIdxsToDelete.Count > 0)
 | |
|                 {
 | |
|                     int[] boneIdxsToDel = new int[boneIdxsToDelete.Count];
 | |
|                     boneIdxsToDelete.CopyTo(boneIdxsToDel);
 | |
|                     Array.Sort(boneIdxsToDel);
 | |
|                     //bones are being moved in bones array so need to do some remapping
 | |
|                     int[] oldBonesIndex2newBonesIndexMap = new int[combiner.bones.Length];
 | |
|                     int newIdx = 0;
 | |
|                     int indexInDeleteList = 0;
 | |
| 
 | |
|                     //bones were deleted so we need to rebuild bones and bind poses
 | |
|                     //and build a map of old bone indexes to new bone indexes
 | |
|                     //do this by copying old to new skipping ones we are deleting
 | |
|                     for (int i = 0; i < combiner.bones.Length; i++)
 | |
|                     {
 | |
|                         if (indexInDeleteList < boneIdxsToDel.Length &&
 | |
|                             boneIdxsToDel[indexInDeleteList] == i)
 | |
|                         {
 | |
|                             //we are deleting this bone so skip its index
 | |
|                             indexInDeleteList++;
 | |
|                             oldBonesIndex2newBonesIndexMap[i] = -1;
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             oldBonesIndex2newBonesIndexMap[i] = newIdx;
 | |
|                             nbones[newIdx] = combiner.bones[i];
 | |
|                             nbindPoses[newIdx] = combiner.bindPoses[i];
 | |
|                             newIdx++;
 | |
|                         }
 | |
|                     }
 | |
|                     //adjust the indexes on the boneWeights
 | |
|                     int numVertKeeping = combiner.boneWeights.Length - totalDeleteVerts;
 | |
|                     {
 | |
|                         for (int i = 0; i < numVertKeeping; i++)
 | |
|                         {
 | |
|                             BoneWeight bw = nboneWeights[i];
 | |
|                             bw.boneIndex0 = oldBonesIndex2newBonesIndexMap[bw.boneIndex0];
 | |
|                             bw.boneIndex1 = oldBonesIndex2newBonesIndexMap[bw.boneIndex1];
 | |
|                             bw.boneIndex2 = oldBonesIndex2newBonesIndexMap[bw.boneIndex2];
 | |
|                             bw.boneIndex3 = oldBonesIndex2newBonesIndexMap[bw.boneIndex3];
 | |
|                             nboneWeights[i] = bw;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     /*
 | |
|                     unsafe
 | |
|                     {
 | |
|                         fixed (BoneWeight* boneWeightFirstPtr = &nboneWeights[0])
 | |
|                         {
 | |
|                             BoneWeight* boneWeightPtr = boneWeightFirstPtr;
 | |
|                             for (int i = 0; i < numVertKeeping; i++)
 | |
|                             {
 | |
|                                 boneWeightPtr->boneIndex0 = oldBonesIndex2newBonesIndexMap[boneWeightPtr->boneIndex0];
 | |
|                                 boneWeightPtr->boneIndex1 = oldBonesIndex2newBonesIndexMap[boneWeightPtr->boneIndex1];
 | |
|                                 boneWeightPtr->boneIndex2 = oldBonesIndex2newBonesIndexMap[boneWeightPtr->boneIndex2];
 | |
|                                 boneWeightPtr->boneIndex3 = oldBonesIndex2newBonesIndexMap[boneWeightPtr->boneIndex3];
 | |
|                                 boneWeightPtr++;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     */
 | |
| 
 | |
|                     //adjust the bone indexes on the dgos from old to new
 | |
|                     for (int i = 0; i < combiner.mbDynamicObjectsInCombinedMesh.Count; i++)
 | |
|                     {
 | |
|                         MB_DynamicGameObject dgo = combiner.mbDynamicObjectsInCombinedMesh[i];
 | |
|                         for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
 | |
|                         {
 | |
|                             dgo.indexesOfBonesUsed[j] = oldBonesIndex2newBonesIndexMap[dgo.indexesOfBonesUsed[j]];
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 { //no bones are moving so can simply copy bones from old to new
 | |
|                     Array.Copy(combiner.bones, nbones, combiner.bones.Length);
 | |
|                     Array.Copy(combiner.bindPoses, nbindPoses, combiner.bindPoses.Length);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             public static void AddBonesToNewBonesArrayAndAdjustBWIndexes(MB3_MeshCombinerSingle combiner, MB_DynamicGameObject dgo, Renderer r, int vertsIdx,
 | |
|                                                              Transform[] nbones, BoneWeight[] nboneWeights, MeshChannelsCache meshChannelCache)
 | |
|             {
 | |
|                 Transform[] dgoBones = dgo._tmpSMR_CachedBones;
 | |
|                 Matrix4x4[] dgoBindPoses = dgo._tmpSMR_CachedBindposes;
 | |
|                 BoneWeight[] dgoBoneWeights = dgo._tmpSMR_CachedBoneWeights;
 | |
|                 int[] srcIndex2combinedIndexMap = new int[dgoBones.Length];
 | |
|                 for (int j = 0; j < dgo._tmpSMRIndexesOfSourceBonesUsed.Length; j++)
 | |
|                 {
 | |
|                     int dgoBoneIdx = dgo._tmpSMRIndexesOfSourceBonesUsed[j];
 | |
| 
 | |
|                     for (int k = 0; k < nbones.Length; k++)
 | |
|                     {
 | |
|                         if (dgoBones[dgoBoneIdx] == nbones[k])
 | |
|                         {
 | |
|                             if (dgoBindPoses[dgoBoneIdx] == combiner.bindPoses[k])
 | |
|                             {
 | |
|                                 srcIndex2combinedIndexMap[dgoBoneIdx] = k;
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 //remap the bone weights for this dgo
 | |
|                 //build a list of usedBones, can't trust dgoBones because it contains all bones in the rig
 | |
|                 for (int j = 0; j < dgoBoneWeights.Length; j++)
 | |
|                 {
 | |
|                     int newVertIdx = vertsIdx + j;
 | |
|                     nboneWeights[newVertIdx].boneIndex0 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex0];
 | |
|                     nboneWeights[newVertIdx].boneIndex1 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex1];
 | |
|                     nboneWeights[newVertIdx].boneIndex2 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex2];
 | |
|                     nboneWeights[newVertIdx].boneIndex3 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex3];
 | |
|                     nboneWeights[newVertIdx].weight0 = dgoBoneWeights[j].weight0;
 | |
|                     nboneWeights[newVertIdx].weight1 = dgoBoneWeights[j].weight1;
 | |
|                     nboneWeights[newVertIdx].weight2 = dgoBoneWeights[j].weight2;
 | |
|                     nboneWeights[newVertIdx].weight3 = dgoBoneWeights[j].weight3;
 | |
|                 }
 | |
| 
 | |
|                 // repurposing the _tmpIndexesOfSourceBonesUsed since
 | |
|                 //we don't need it anymore and this saves a memory allocation . remap the indexes that point to source bones to combined bones.
 | |
|                 for (int j = 0; j < dgo._tmpSMRIndexesOfSourceBonesUsed.Length; j++)
 | |
|                 {
 | |
|                     dgo._tmpSMRIndexesOfSourceBonesUsed[j] = srcIndex2combinedIndexMap[dgo._tmpSMRIndexesOfSourceBonesUsed[j]];
 | |
|                 }
 | |
|                 dgo.indexesOfBonesUsed = dgo._tmpSMRIndexesOfSourceBonesUsed;
 | |
|                 dgo._tmpSMRIndexesOfSourceBonesUsed = null;
 | |
|                 dgo._tmpSMR_CachedBones = null;
 | |
|                 dgo._tmpSMR_CachedBindposes = null;
 | |
|                 dgo._tmpSMR_CachedBoneWeights = null;
 | |
| 
 | |
|                 //check original bones and bindPoses
 | |
|                 /*
 | |
|                 for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++) {
 | |
|                     Transform bone = bones[dgo.indexesOfBonesUsed[j]];
 | |
|                     Matrix4x4 bindpose = bindPoses[dgo.indexesOfBonesUsed[j]];
 | |
|                     bool found = false;
 | |
|                     for (int k = 0; k < dgo._originalBones.Length; k++) {
 | |
|                         if (dgo._originalBones[k] == bone && dgo._originalBindPoses[k] == bindpose) {
 | |
|                             found = true;
 | |
|                         }
 | |
|                     }
 | |
|                     if (!found) Debug.LogError("A Mismatch between original bones and bones array. " + dgo.name);
 | |
|                 }
 | |
|                 */
 | |
|             }
 | |
| 
 | |
|             internal void CopyVertsNormsTansToBuffers(MB_DynamicGameObject dgo, MB_IMeshBakerSettings settings, int vertsIdx, Vector3[] nnorms, Vector4[] ntangs, Vector3[] nverts, Vector3[] normals, Vector4[] tangents, Vector3[] verts)
 | |
|             {
 | |
|                 bool isMeshRenderer = dgo.gameObject.GetComponent<Renderer>() is MeshRenderer;
 | |
|                 if (settings.smrNoExtraBonesWhenCombiningMeshRenderers &&
 | |
|                     isMeshRenderer &&
 | |
|                     dgo._tmpSMR_CachedBones[0] != dgo.gameObject.transform // bone may not have a parent ancestor that is a bone
 | |
|                     )
 | |
|                 {
 | |
|                     // transform all the verticies, norms and tangents into the parent bone's local space (adjusted by the parent bone's bind pose).
 | |
|                     // there should be only one bone and bind pose for a mesh renderer dgo. 
 | |
|                     // The bone and bind pose should be the parent-bone's NOT the MeshRenderers.
 | |
|                     Matrix4x4 l2parentMat = dgo._tmpSMR_CachedBindposes[0].inverse * dgo._tmpSMR_CachedBones[0].worldToLocalMatrix * dgo.gameObject.transform.localToWorldMatrix;
 | |
| 
 | |
|                     // Similar to local2world but with translation removed and we are using the inverse transpose.
 | |
|                     // We use this for normals and tangents because it handles scaling correctly.
 | |
|                     Matrix4x4 l2parentRotScale = l2parentMat;
 | |
|                     l2parentRotScale[0, 3] = l2parentRotScale[1, 3] = l2parentRotScale[2, 3] = 0f;
 | |
|                     l2parentRotScale = l2parentRotScale.inverse.transpose;
 | |
| 
 | |
|                     //can't modify the arrays we get from the cache because they will be modified multiple times if the same mesh is being added multiple times.
 | |
|                     for (int j = 0; j < nverts.Length; j++)
 | |
|                     {
 | |
|                         int vIdx = vertsIdx + j;
 | |
|                         verts[vertsIdx + j] = l2parentMat.MultiplyPoint3x4(nverts[j]);
 | |
|                         if (settings.doNorm)
 | |
|                         {
 | |
|                             normals[vIdx] = l2parentRotScale.MultiplyPoint3x4(nnorms[j]).normalized;
 | |
|                         }
 | |
|                         if (settings.doTan)
 | |
|                         {
 | |
|                             float w = ntangs[j].w; //need to preserve the w value
 | |
|                             tangents[vIdx] = l2parentRotScale.MultiplyPoint3x4(((Vector3)ntangs[j])).normalized;
 | |
|                             tangents[vIdx].w = w;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (settings.doNorm) nnorms.CopyTo(normals, vertsIdx);
 | |
|                     if (settings.doTan) ntangs.CopyTo(tangents, vertsIdx);
 | |
|                     nverts.CopyTo(verts, vertsIdx);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override void UpdateSkinnedMeshApproximateBounds()
 | |
|         {
 | |
|             UpdateSkinnedMeshApproximateBoundsFromBounds();
 | |
|         }
 | |
| 
 | |
|         public override void UpdateSkinnedMeshApproximateBoundsFromBones()
 | |
|         {
 | |
|             if (outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Can't UpdateSkinnedMeshApproximateBounds when output type is bakeMeshAssetsInPlace");
 | |
|                 return;
 | |
|             }
 | |
|             if (bones.Length == 0)
 | |
|             {
 | |
|                 if (verts.Length > 0) if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("No bones in SkinnedMeshRenderer. Could not UpdateSkinnedMeshApproximateBounds.");
 | |
|                 return;
 | |
|             }
 | |
|             if (_targetRenderer == null)
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not set. No point in calling UpdateSkinnedMeshApproximateBounds.");
 | |
|                 return;
 | |
|             }
 | |
|             if (!_targetRenderer.GetType().Equals(typeof(SkinnedMeshRenderer)))
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not a SkinnedMeshRenderer. No point in calling UpdateSkinnedMeshApproximateBounds.");
 | |
|                 return;
 | |
|             }
 | |
|             UpdateSkinnedMeshApproximateBoundsFromBonesStatic(bones, (SkinnedMeshRenderer)targetRenderer);
 | |
|         }
 | |
| 
 | |
|         public override void UpdateSkinnedMeshApproximateBoundsFromBounds()
 | |
|         {
 | |
|             if (outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Can't UpdateSkinnedMeshApproximateBoundsFromBounds when output type is bakeMeshAssetsInPlace");
 | |
|                 return;
 | |
|             }
 | |
|             if (verts.Length == 0 || mbDynamicObjectsInCombinedMesh.Count == 0)
 | |
|             {
 | |
|                 if (verts.Length > 0) if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Nothing in SkinnedMeshRenderer. CoulddoBlendShapes not UpdateSkinnedMeshApproximateBoundsFromBounds.");
 | |
|                 return;
 | |
|             }
 | |
|             if (_targetRenderer == null)
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not set. No point in calling UpdateSkinnedMeshApproximateBoundsFromBounds.");
 | |
|                 return;
 | |
|             }
 | |
|             if (!_targetRenderer.GetType().Equals(typeof(SkinnedMeshRenderer)))
 | |
|             {
 | |
|                 if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not a SkinnedMeshRenderer. No point in calling UpdateSkinnedMeshApproximateBoundsFromBounds.");
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             UpdateSkinnedMeshApproximateBoundsFromBoundsStatic(objectsInCombinedMesh, (SkinnedMeshRenderer)targetRenderer);
 | |
|         }
 | |
|     }
 | |
| }
 |