예제 #1
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        public void CopyDataToUnityMesh(SkinnedMeshRenderer renderer)
        {
            Mesh mesh = renderer.sharedMesh;

            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];
            mesh.vertices     = vertices;
            mesh.boneWeights  = UMABoneWeight.Convert(boneWeights);
            mesh.normals      = normals;
            mesh.tangents     = tangents;
            mesh.uv           = uv;
            mesh.uv2          = uv2;
            mesh.uv3          = uv3;
            mesh.uv4          = uv4;
            mesh.colors32     = colors32;
            mesh.bindposes    = bindPoses;

            var subMeshCount = submeshes.Length;

            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                mesh.SetTriangles(submeshes[i].triangles, i);
            }

            renderer.bones    = bones;
            renderer.rootBone = rootBone;

            mesh.RecalculateBounds();
            renderer.sharedMesh = mesh;
        }
예제 #2
0
        public static UMAMeshData ShallowInstanceMesh(UMAMeshData source, BitArray[] triangleMask = null)
        {
            var target = new UMAMeshData();

            target.bindPoses        = source.bindPoses;
            target.boneNameHashes   = source.boneNameHashes;
            target.unityBoneWeights = UMABoneWeight.Convert(source.boneWeights);
            target.colors32         = source.colors32;
            target.normals          = source.normals;
            target.rootBoneHash     = source.rootBoneHash;
            target.subMeshCount     = source.subMeshCount;
            target.tangents         = source.tangents;
            target.umaBoneCount     = source.umaBoneCount;
            target.umaBones         = source.umaBones;
            target.uv          = source.uv;
            target.uv2         = source.uv2;
            target.uv3         = source.uv3;
            target.uv4         = source.uv4;
            target.vertexCount = source.vertexCount;
            target.vertices    = source.vertices;
            target.blendShapes = source.blendShapes;

            if (triangleMask != null)
            {
                target.submeshes = new SubMeshTriangles[source.subMeshCount];

                for (int i = 0; i < source.subMeshCount; i++)
                {
                    int   sourceLength   = source.submeshes[i].triangles.Length;
                    int   triangleLength = sourceLength - (UMAUtils.GetCardinality(triangleMask[i]) * 3);
                    int[] destTriangles  = new int[triangleLength];

                    MaskedCopyIntArrayAdd(source.submeshes[i].triangles, 0, destTriangles, 0, sourceLength, 0, triangleMask[i]);
                    target.submeshes[i].triangles = destTriangles;
                }
            }
            else
            {
                target.submeshes = source.submeshes;
            }

            if (source.clothSkinningSerialized != null && source.clothSkinningSerialized.Length != 0)
            {
                target.clothSkinning = new ClothSkinningCoefficient[source.clothSkinningSerialized.Length];
                for (int i = 0; i < source.clothSkinningSerialized.Length; i++)
                {
                    ConvertData(ref source.clothSkinningSerialized[i], ref target.clothSkinning[i]);
                }
            }
            else
            {
                target.clothSkinning = null;
            }
            return(target);
        }
예제 #3
0
        private static void TranslateBoneWeight(ref UMABoneWeight source, ref BoneWeight dest, int[] boneMapping)
        {
            dest.weight0 = source.weight0;
            dest.weight1 = source.weight1;
            dest.weight2 = source.weight2;
            dest.weight3 = source.weight3;

            dest.boneIndex0 = boneMapping[source.boneIndex0];
            dest.boneIndex1 = boneMapping[source.boneIndex1];
            dest.boneIndex2 = boneMapping[source.boneIndex2];
            dest.boneIndex3 = boneMapping[source.boneIndex3];
        }
예제 #4
0
            public void SetData(ref UMABoneWeight source)
            {
                m_Weight0 = source.weight0;
                m_Weight1 = source.weight1;
                m_Weight2 = source.weight2;
                m_Weight3 = source.weight3;

                m_BoneIndex0 = boneMap[source.boneIndex0];
                m_BoneIndex1 = boneMap[source.boneIndex1];
                m_BoneIndex2 = boneMap[source.boneIndex2];
                m_BoneIndex3 = boneMap[source.boneIndex3];
            }
예제 #5
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        /// <param name="skeleton">Skeleton.</param>
        public void ApplyDataToUnityMesh(SkinnedMeshRenderer renderer, UMASkeleton skeleton)
        {
            CreateTransforms(skeleton);

            Mesh mesh = renderer.sharedMesh;

#if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.IsComponentAddedToPrefabInstance(renderer))
            {
                Debug.LogError("Cannot apply changes to prefab!");
            }
            if (UnityEditor.AssetDatabase.IsSubAsset(mesh))
            {
                Debug.LogError("Cannot apply changes to asset mesh!");
            }
#endif
            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];

            if (OwnSharedBuffers())
            {
                ApplySharedBuffers(mesh);
            }
            else
            {
                mesh.vertices    = vertices;
                mesh.boneWeights = unityBoneWeights != null ? unityBoneWeights : UMABoneWeight.Convert(boneWeights);
                mesh.normals     = normals;
                mesh.tangents    = tangents;
                mesh.uv          = uv;
                mesh.uv2         = uv2;
#if !UNITY_4_6
                mesh.uv3 = uv3;
                mesh.uv4 = uv4;
#endif
                mesh.colors32 = colors32;
            }
            mesh.bindposes = bindPoses;

            var subMeshCount = submeshes.Length;
            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                mesh.SetTriangles(submeshes[i].triangles, i);
            }

            mesh.RecalculateBounds();
            renderer.bones      = bones != null ? bones : skeleton.HashesToTransforms(boneNameHashes);
            renderer.sharedMesh = mesh;
            renderer.rootBone   = rootBone;
        }
예제 #6
0
        public static UMABoneWeight[] Convert(List <BoneWeight> boneWeights)
        {
            if (boneWeights == null)
            {
                return(null);
            }
            var res = new UMABoneWeight[boneWeights.Count];

            for (int i = 0; i < boneWeights.Count; i++)
            {
                res[i] = boneWeights[i];
            }
            return(res);
        }
예제 #7
0
        public static UMABoneWeight[] Convert(BoneWeight[] boneWeights)
        {
            if (boneWeights == null)
            {
                return(null);
            }
            var res = new UMABoneWeight[boneWeights.Length];

            for (int i = 0; i < boneWeights.Length; i++)
            {
                res[i] = boneWeights[i];
            }
            return(res);
        }
예제 #8
0
        /// <summary>
        /// Initialize UMA mesh data from Unity mesh.
        /// </summary>
        /// <param name="sharedMesh">Source mesh.</param>
        public void RetrieveDataFromUnityMesh(Mesh sharedMesh)
        {
            bindPoses    = sharedMesh.bindposes;
            boneWeights  = UMABoneWeight.Convert(sharedMesh.boneWeights);
            vertices     = sharedMesh.vertices;
            vertexCount  = vertices.Length;
            normals      = sharedMesh.normals;
            tangents     = sharedMesh.tangents;
            colors32     = sharedMesh.colors32;
            uv           = sharedMesh.uv;
            uv2          = sharedMesh.uv2;
            uv3          = sharedMesh.uv3;
            uv4          = sharedMesh.uv4;
            subMeshCount = sharedMesh.subMeshCount;
            submeshes    = new SubMeshTriangles[subMeshCount];
            for (int i = 0; i < subMeshCount; i++)
            {
                submeshes[i].triangles = sharedMesh.GetTriangles(i);
            }

            //Create the blendshape data on the slot asset from the unity mesh
            #region Blendshape
            blendShapes = new UMABlendShape[sharedMesh.blendShapeCount];
            for (int shapeIndex = 0; shapeIndex < sharedMesh.blendShapeCount; shapeIndex++)
            {
                blendShapes [shapeIndex]           = new UMABlendShape();
                blendShapes [shapeIndex].shapeName = sharedMesh.GetBlendShapeName(shapeIndex);

                int frameCount = sharedMesh.GetBlendShapeFrameCount(shapeIndex);
                blendShapes [shapeIndex].frames = new UMABlendFrame[frameCount];

                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    blendShapes [shapeIndex].frames [frameIndex]           = new UMABlendFrame(sharedMesh.vertexCount);
                    blendShapes[shapeIndex].frames[frameIndex].frameWeight = sharedMesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex);
                    sharedMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaVertices,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaNormals,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaTangents);
                }
            }
            #endregion
        }
예제 #9
0
        /// <summary>
        /// Initialize UMA mesh data from Unity mesh.
        /// </summary>
        /// <param name="renderer">Source renderer.</param>
        public void RetrieveDataFromUnityMesh(Mesh sharedMesh)
        {
            bindPoses   = sharedMesh.bindposes;
            boneWeights = UMABoneWeight.Convert(sharedMesh.boneWeights);
            vertices    = sharedMesh.vertices;
            vertexCount = vertices.Length;
            normals     = sharedMesh.normals;
            tangents    = sharedMesh.tangents;
            colors32    = sharedMesh.colors32;
            uv          = sharedMesh.uv;
            uv2         = sharedMesh.uv2;
#if !UNITY_4_6
            uv3 = sharedMesh.uv3;
            uv4 = sharedMesh.uv4;
#endif
            subMeshCount = sharedMesh.subMeshCount;
            submeshes    = new SubMeshTriangles[subMeshCount];
            for (int i = 0; i < subMeshCount; i++)
            {
                submeshes[i].triangles = sharedMesh.GetTriangles(i);
            }
        }
예제 #10
0
        public static UMAMeshData ShallowInstanceMesh(UMAMeshData source)
        {
            var target = new UMAMeshData();

            target.bindPoses        = source.bindPoses;
            target.boneNameHashes   = source.boneNameHashes;
            target.unityBoneWeights = UMABoneWeight.Convert(source.boneWeights);
            target.colors32         = source.colors32;
            target.normals          = source.normals;
            target.rootBoneHash     = source.rootBoneHash;
            target.subMeshCount     = source.subMeshCount;
            target.submeshes        = source.submeshes;
            target.tangents         = source.tangents;
            target.umaBoneCount     = source.umaBoneCount;
            target.umaBones         = source.umaBones;
            target.uv          = source.uv;
            target.uv2         = source.uv2;
            target.uv3         = source.uv3;
            target.uv4         = source.uv4;
            target.vertexCount = source.vertexCount;
            target.vertices    = source.vertices;
            target.blendShapes = source.blendShapes;

            if (source.clothSkinningSerialized != null && source.clothSkinningSerialized.Length != 0)
            {
                target.clothSkinning = new ClothSkinningCoefficient[source.clothSkinningSerialized.Length];
                for (int i = 0; i < source.clothSkinningSerialized.Length; i++)
                {
                    ConvertData(ref source.clothSkinningSerialized[i], ref target.clothSkinning[i]);
                }
            }
            else
            {
                target.clothSkinning = null;
            }
            return(target);
        }
예제 #11
0
        private void ApplySharedBuffers(Mesh mesh)
        {
            // Thanks for providing these awesome List<> methods rather than listening
            // to every one of your users who told you to use Array and size, Unity!
            gVertices.SetActiveSize(vertexCount);
            mesh.SetVertices(gVertices);

            // Whoops, looks like they also forgot one! Job well done.
#if USE_UNSAFE_CODE
            unsafe
            {
                fixed(void *pBoneWeights = gBoneWeightsArray)
                {
                    UIntPtr *lengthPtr = (UIntPtr *)pBoneWeights - 1;

                    try
                    {
                        *lengthPtr = (UIntPtr)vertexCount;
                        mesh.boneWeights = gBoneWeightsArray;
                    }
                    finally
                    {
                        *lengthPtr = (UIntPtr)MAX_VERTEX_COUNT;
                    }
                }
            }
#else
            if (unityBoneWeights != null)
            {
                mesh.boneWeights = unityBoneWeights;
            }
            else
            {
                mesh.boneWeights = UMABoneWeight.Convert(boneWeights);
            }
#endif
            if (normals != null)
            {
                gNormals.SetActiveSize(vertexCount);
                mesh.SetNormals(gNormals);
            }
            if (tangents != null)
            {
                gTangents.SetActiveSize(vertexCount);
                mesh.SetTangents(gTangents);
            }
            if (uv != null)
            {
                gUV.SetActiveSize(vertexCount);
                mesh.SetUVs(0, gUV);
            }
            if (uv2 != null)
            {
                gUV2.SetActiveSize(vertexCount);
                mesh.SetUVs(1, gUV2);
            }
            if (uv3 != null)
            {
                gUV3.SetActiveSize(vertexCount);
                mesh.SetUVs(2, gUV3);
            }
            if (uv4 != null)
            {
                gUV4.SetActiveSize(vertexCount);
                mesh.SetUVs(3, gUV4);
            }
            if (colors32 != null)
            {
                gColors32.SetActiveSize(vertexCount);
                mesh.SetColors(gColors32);
            }
        }
예제 #12
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        /// <param name="skeleton">Skeleton.</param>
        public void ApplyDataToUnityMesh(SkinnedMeshRenderer renderer, UMASkeleton skeleton)
        {
            if (renderer == null)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Renderer is null!");
                }
                return;
            }

            CreateTransforms(skeleton);

            Mesh mesh = renderer.sharedMesh;

#if UNITY_EDITOR
#if UNITY_2018_3_OR_NEWER
            if (UnityEditor.PrefabUtility.IsAddedComponentOverride(renderer))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to prefab!");
                }
            }
#else
            if (UnityEditor.PrefabUtility.IsComponentAddedToPrefabInstance(renderer))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to prefab!");
                }
            }
#endif
            if (UnityEditor.AssetDatabase.IsSubAsset(mesh))
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Cannot apply changes to asset mesh!");
                }
            }
#endif
            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];

            if (OwnSharedBuffers())
            {
                ApplySharedBuffers(mesh);
            }
            else
            {
                mesh.vertices    = vertices;
                mesh.boneWeights = unityBoneWeights != null ? unityBoneWeights : UMABoneWeight.Convert(boneWeights);
                mesh.normals     = normals;
                mesh.tangents    = tangents;
                mesh.uv          = uv;
                mesh.uv2         = uv2;
                mesh.uv3         = uv3;
                mesh.uv4         = uv4;
                mesh.colors32    = colors32;
            }
            mesh.bindposes = bindPoses;

            var subMeshCount = submeshes.Length;
            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                bool sharedBuffer = false;
                for (int j = 0; j < gSubmeshTris.Length; j++)
                {
                    if (gSubmeshTriIndices[j] == i)
                    {
                        sharedBuffer = true;
                        mesh.SetTriangles(gSubmeshTris[j], i);
                        gSubmeshTriIndices[j] = UNUSED_SUBMESH;
                        break;
                    }
                }

                if (!sharedBuffer)
                {
                    mesh.SetTriangles(submeshes[i].triangles, i);
                }
            }

            //Apply the blendshape data from the slot asset back to the combined UMA unity mesh.
            #region Blendshape
            mesh.ClearBlendShapes();
            if (blendShapes != null && blendShapes.Length > 0)
            {
                for (int shapeIndex = 0; shapeIndex < blendShapes.Length; shapeIndex++)
                {
                    if (blendShapes [shapeIndex] == null)
                    {
                        //Debug.LogError ("blendShapes [shapeIndex] == null!");
                        //No longer an error, this will be null if the blendshape got baked.
                        break;
                    }

                    for (int frameIndex = 0; frameIndex < blendShapes[shapeIndex].frames.Length; frameIndex++)
                    {
                        //There might be an extreme edge case where someone has the same named blendshapes on different meshes that end up on different renderers.
                        string name = blendShapes[shapeIndex].shapeName;

                        float     frameWeight   = blendShapes[shapeIndex].frames[frameIndex].frameWeight;
                        Vector3[] deltaVertices = blendShapes[shapeIndex].frames[frameIndex].deltaVertices;
                        Vector3[] deltaNormals  = blendShapes[shapeIndex].frames[frameIndex].deltaNormals;
                        Vector3[] deltaTangents = blendShapes[shapeIndex].frames[frameIndex].deltaTangents;

                        if (UMABlendFrame.isAllZero(deltaNormals))
                        {
                            deltaNormals = null;
                        }

                        if (UMABlendFrame.isAllZero(deltaTangents))
                        {
                            deltaTangents = null;
                        }

                        mesh.AddBlendShapeFrame(name, frameWeight, deltaVertices, deltaNormals, deltaTangents);
                    }
                }
            }
            #endregion

            mesh.RecalculateBounds();
            renderer.bones      = bones != null ? bones : skeleton.HashesToTransforms(boneNameHashes);
            renderer.sharedMesh = mesh;
            renderer.rootBone   = rootBone;

            if (clothSkinning != null && clothSkinning.Length > 0)
            {
                Cloth cloth = renderer.GetComponent <Cloth>();
                if (cloth != null)
                {
                    GameObject.DestroyImmediate(cloth);
                    cloth = null;
                }

                cloth = renderer.gameObject.AddComponent <Cloth>();
                UMAPhysicsAvatar physicsAvatar = renderer.gameObject.GetComponentInParent <UMAPhysicsAvatar>();
                if (physicsAvatar != null)
                {
                    cloth.sphereColliders  = physicsAvatar.SphereColliders.ToArray();
                    cloth.capsuleColliders = physicsAvatar.CapsuleColliders.ToArray();
                }

                cloth.coefficients = clothSkinning;
            }
        }
예제 #13
0
        /// <summary>
        /// Initialize UMA mesh data from Unity mesh.
        /// </summary>
        /// <param name="sharedMesh">Source mesh.</param>
        public void RetrieveDataFromUnityMesh(Mesh sharedMesh)
        {
            bindPoses    = sharedMesh.bindposes;
            boneWeights  = UMABoneWeight.Convert(sharedMesh.boneWeights);
            vertices     = sharedMesh.vertices;
            vertexCount  = vertices.Length;
            normals      = sharedMesh.normals;
            tangents     = sharedMesh.tangents;
            colors32     = sharedMesh.colors32;
            uv           = sharedMesh.uv;
            uv2          = sharedMesh.uv2;
            uv3          = sharedMesh.uv3;
            uv4          = sharedMesh.uv4;
            subMeshCount = sharedMesh.subMeshCount;
            submeshes    = new SubMeshTriangles[subMeshCount];
            for (int i = 0; i < subMeshCount; i++)
            {
                submeshes[i].triangles = sharedMesh.GetTriangles(i);
            }

            //Create the blendshape data on the slot asset from the unity mesh
            #region Blendshape
            blendShapes = new UMABlendShape[sharedMesh.blendShapeCount];

            Vector3[] deltaVertices;
            Vector3[] deltaNormals;
            Vector3[] deltaTangents;

            for (int shapeIndex = 0; shapeIndex < sharedMesh.blendShapeCount; shapeIndex++)
            {
                blendShapes [shapeIndex]           = new UMABlendShape();
                blendShapes [shapeIndex].shapeName = sharedMesh.GetBlendShapeName(shapeIndex);

                int frameCount = sharedMesh.GetBlendShapeFrameCount(shapeIndex);
                blendShapes [shapeIndex].frames = new UMABlendFrame[frameCount];

                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    deltaVertices = new Vector3[sharedMesh.vertexCount];
                    deltaNormals  = new Vector3[sharedMesh.vertexCount];
                    deltaTangents = new Vector3[sharedMesh.vertexCount];

                    bool hasNormals  = false;
                    bool hasTangents = false;

                    //Get the delta arrays first so we can determine if we don't need the delta normals or the delta tangents.
                    sharedMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, deltaVertices, deltaNormals, deltaTangents);

                    if (!UMABlendFrame.isAllZero(deltaNormals))
                    {
                        hasNormals = true;
                    }

                    if (!UMABlendFrame.isAllZero(deltaTangents))
                    {
                        hasTangents = true;
                    }

                    blendShapes [shapeIndex].frames [frameIndex]           = new UMABlendFrame();
                    blendShapes[shapeIndex].frames[frameIndex].frameWeight = sharedMesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex);

                    blendShapes[shapeIndex].frames[frameIndex].deltaVertices = deltaVertices;
                    if (hasNormals)
                    {
                        blendShapes[shapeIndex].frames[frameIndex].deltaNormals = deltaNormals;
                    }
                    if (hasTangents)
                    {
                        blendShapes[shapeIndex].frames[frameIndex].deltaTangents = deltaTangents;
                    }
                }
            }
            #endregion
        }
예제 #14
0
        /// <summary>
        /// Applies the data to a Unity mesh.
        /// </summary>
        /// <param name="renderer">Target renderer.</param>
        /// <param name="skeleton">Skeleton.</param>
        public void ApplyDataToUnityMesh(SkinnedMeshRenderer renderer, UMASkeleton skeleton)
        {
            CreateTransforms(skeleton);

            Mesh mesh = renderer.sharedMesh;

#if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.IsComponentAddedToPrefabInstance(renderer))
            {
                Debug.LogError("Cannot apply changes to prefab!");
            }
            if (UnityEditor.AssetDatabase.IsSubAsset(mesh))
            {
                Debug.LogError("Cannot apply changes to asset mesh!");
            }
#endif
            mesh.subMeshCount = 1;
            mesh.triangles    = new int[0];

            if (OwnSharedBuffers())
            {
                ApplySharedBuffers(mesh);
            }
            else
            {
                mesh.vertices    = vertices;
                mesh.boneWeights = unityBoneWeights != null ? unityBoneWeights : UMABoneWeight.Convert(boneWeights);
                mesh.normals     = normals;
                mesh.tangents    = tangents;
                mesh.uv          = uv;
                mesh.uv2         = uv2;
                mesh.uv3         = uv3;
                mesh.uv4         = uv4;
                mesh.colors32    = colors32;
            }
            mesh.bindposes = bindPoses;

            var subMeshCount = submeshes.Length;
            mesh.subMeshCount = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                mesh.SetTriangles(submeshes[i].triangles, i);
            }

            //Apply the blendshape data from the slot asset back to the combined UMA unity mesh.
            #region Blendshape
            mesh.ClearBlendShapes();
            if (blendShapes != null && blendShapes.Length > 0)
            {
                for (int shapeIndex = 0; shapeIndex < blendShapes.Length; shapeIndex++)
                {
                    if (blendShapes [shapeIndex] == null)
                    {
                        Debug.LogError("blendShapes [shapeIndex] == null!");
                        break;
                    }

                    for (int frameIndex = 0; frameIndex < blendShapes[shapeIndex].frames.Length; frameIndex++)
                    {
                        //There might be an extreme edge case where someone has the same named blendshapes on different meshes that end up on different renderers.
                        string name = blendShapes [shapeIndex].shapeName;
                        mesh.AddBlendShapeFrame(name,
                                                blendShapes [shapeIndex].frames [frameIndex].frameWeight,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaVertices,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaNormals,
                                                blendShapes [shapeIndex].frames [frameIndex].deltaTangents);
                    }
                }
            }
            #endregion

            mesh.RecalculateBounds();
            renderer.bones      = bones != null ? bones : skeleton.HashesToTransforms(boneNameHashes);
            renderer.sharedMesh = mesh;
            renderer.rootBone   = rootBone;
        }