private static void ProcessAnimation(AnimationClip clip, MouthModel mouthModel, Transform animationRoot, Transform jawRoot)
    {
        var bindings = AnimationUtility.GetCurveBindings(clip);
        var uBinding = bindings.FirstOrDefault(binding => binding.propertyName == "material._MainTex_mouth_ST.z");
        var vBinding = bindings.FirstOrDefault(binding => binding.propertyName == "material._MainTex_mouth_ST.w");

        if (uBinding.path == null || vBinding.path == null)
        {
            Debug.LogWarning("Couldn't find animation binding for clip " + clip.name);
            return;
        }

        var uCurve = AnimationUtility.GetEditorCurve(clip, uBinding);
        var vCurve = AnimationUtility.GetEditorCurve(clip, vBinding);
        
        var snapshotsAtPath = new Dictionary<string, AnimationSnapshotData>();

        for (int i = 0; i < uCurve.keys.Length; i++)
        {
            // We can assume that that the curves for the U and V value have the same keyframes
            Vector2 uvValue = new Vector2(uCurve.keys[i].value, vCurve.keys[i].value);
            mouthModel.CurrentPoseIndex = RtdxTextureToMouthType.ContainsKey(uvValue) ? RtdxTextureToMouthType[uvValue] : 0;
            
            TraverseRig(jawRoot, snapshotsAtPath, GetRelativePath(jawRoot, animationRoot), uCurve.keys[i].time);
        }
        
        foreach (var snapshot in snapshotsAtPath)
        {
            snapshot.Value.ApplyToClip(clip);
            clip.EnsureQuaternionContinuity();
        }
        AnimationHelpers.SetAnimationTangentsToConstant(clip);
    }
Пример #2
0
    private static UnityEngine.AnimationClip ProcessClip(AssetStudio.AnimationClip animationClip, string savePath, string bundleName,
                                                         string materialAttributeName, CoordinateAttributeSet attributeSet, UnityEngine.SkinnedMeshRenderer[] skinnedMeshRenderers)
    {
        var uCurve = new UnityEngine.AnimationCurve();
        var vCurve = new UnityEngine.AnimationCurve();

        var clip                = animationClip.m_MuscleClip.m_Clip;
        var streamedFrames      = clip.m_StreamedClip.ReadData();
        var clipBindingConstant = animationClip.m_ClipBindingConstant;

        for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
        {
            StreamedClip.StreamedCurveKey uCoordKey = null, vCoordKey = null;
            foreach (var key in streamedFrames[frameIndex].keyList)
            {
                var binding = clipBindingConstant.FindBinding(key.index);
                if (binding.attribute == attributeSet.UAttribute)
                {
                    uCoordKey = key;
                }
                else if (binding.attribute == attributeSet.VAttribute)
                {
                    vCoordKey = key;
                }
            }

            if (uCoordKey == null || vCoordKey == null)
            {
                continue;
            }

            // Round to 0.25 steps since the input UVs might not match perfectly
            var roundedUv = new Vector2(Mathf.Round(uCoordKey.value * 4) / 4, Mathf.Round(vCoordKey.value * 4) / 4);
            var value = RtdxTextureTo2x4Mappings[roundedUv];

            uCurve.AddKey(streamedFrames[frameIndex].time, value.x);
            vCurve.AddKey(streamedFrames[frameIndex].time, value.y);
        }

        var newClip = new UnityEngine.AnimationClip {
            frameRate = animationClip.m_SampleRate
        };

        foreach (var skinnedMeshRenderer in skinnedMeshRenderers)
        {
            AnimationUtility.SetEditorCurve(newClip, new EditorCurveBinding
            {
                path         = skinnedMeshRenderer.gameObject.name,
                type         = typeof(UnityEngine.SkinnedMeshRenderer),
                propertyName = $"material.{materialAttributeName}.z"
            }, uCurve);
            AnimationUtility.SetEditorCurve(newClip, new EditorCurveBinding
            {
                path         = skinnedMeshRenderer.gameObject.name,
                type         = typeof(UnityEngine.SkinnedMeshRenderer),
                propertyName = $"material.{materialAttributeName}.w"
            }, vCurve);
        }

        // We need to use this stupid workaround instead of doing it when adding the key because
        // apparently it glitches if the curve wasn't added to an animation
        AnimationHelpers.SetAnimationTangentsToConstant(newClip);

        string animationPath = $"{savePath}/{animationClip.m_Name}.anim";

        AssetDatabase.CreateAsset(newClip, animationPath);
        AssetImporter.GetAtPath(animationPath).assetBundleName = bundleName;

        return(newClip);
    }