private void CaptureSnapShot(AnimationClip animClip, float bakeFrames, GPUAnimation meshAnim, GameObject sampleGO)
    {
        List <GPUAnimationFrameData> verts = new List <GPUAnimationFrameData>();
        List <Vector3> meshesInFrame       = new List <Vector3>();
        float          lastFrameTime       = 0;

        for (int i = 0; i <= bakeFrames; i += frameSkips[animClip.name])
        {
            float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames));
            EditorUtility.DisplayProgressBar("Baking Animation", string.Format("Processing: {0} Frame: {1}", animClip.name, i), bakeDelta);
            float animationTime = bakeDelta * animClip.length;
            if (requiresAnimator)
            {
                float normalizedTime = animationTime / animClip.length;
                animator.Play(animClip.name, 0, normalizedTime);
                if (lastFrameTime == 0)
                {
                    float nextBakeDelta     = Mathf.Clamp01(((float)(i += frameSkips[animClip.name]) / bakeFrames));
                    float nextAnimationTime = nextBakeDelta * animClip.length;
                    lastFrameTime = animationTime - nextAnimationTime;
                }
                animator.Update(animationTime - lastFrameTime);
                lastFrameTime = animationTime;
            }
            else
            {
                GameObject sampleObject    = sampleGO;
                Animation  legacyAnimation = sampleObject.GetComponentInChildren <Animation>();
                if (animator && animator.gameObject != sampleObject)
                {
                    sampleObject = animator.gameObject;
                }
                else if (legacyAnimation && legacyAnimation.gameObject != sampleObject)
                {
                    sampleObject = legacyAnimation.gameObject;
                }
                animClip.SampleAnimation(sampleObject, animationTime);
            }
            meshesInFrame.Clear();

            Mesh m = null;

            SkinnedMeshRenderer sampleSr = sampleGO.GetComponentInChildren <SkinnedMeshRenderer>();
            m = new Mesh();
            sampleSr.BakeMesh(m);
            Vector3[] v = m.vertices;
            for (int vIndex = 0; vIndex < v.Length; vIndex++)
            {
                v[vIndex] = sampleSr.transform.TransformPoint(v[vIndex]);
            }
            meshesInFrame.AddRange(v);
            DestroyImmediate(m);

            GPUAnimationFrameData data = new GPUAnimationFrameData();
            data.SetVerts(meshesInFrame.ToArray());
            verts.Add(data);
        }
        meshAnim.verts = verts.ToArray();
    }
Beispiel #2
0
                internal GPUAnimationState(GPUAnimation owner, GPUAnimations.Animation animation)
                {
                    _owner = owner;

                    WrapMode wrapMode = animation._wrapMode;

                    if (wrapMode == WrapMode.Default)
                    {
                        wrapMode = WrapMode.Once;
                    }

                    _player = new GPUAnimationPlayer(animation, wrapMode);
                }
    private void InitAnimationBones(GameObject animationTarget, GPUAnimation meshAnim)
    {
        bonesMap.Clear();
        Transform child = animationTarget.transform.Find("Bip01");

        joints            = child.GetComponentsInChildren <Transform>();
        skeletonPoses     = new Matrix4x4[joints.Length];
        bindSkeletonPoses = new Matrix4x4[joints.Length];
        //meshAnim.bones = new string[bones.Length];
        for (int i = 0; i < joints.Length; i++)
        {
            Transform bone = joints[i];
            bonesMap.Add(bone.name, i);
            skeletonPoses[i]     = bone.transform.localToWorldMatrix;
            bindSkeletonPoses[i] = bone.transform.worldToLocalMatrix;
            //meshAnim.bones[i] = bone.name;
        }
    }
Beispiel #4
0
    private void Initialization()
    {
        defaultAnimation = meshAnimationList.meshAnimations[0];
        totalJoints      = meshAnimationList.totalJoints;
        animations       = meshAnimationList.meshAnimations;
        if (defaultAnimation.isVertsAnimation)
        {
            skinningTexSize  = defaultAnimation.textureSize;
            pixelsStartIndex = 0;
        }
        else
        {
            skinningTexSize  = meshAnimationList.skinningTexSize;
            pixelsStartIndex = defaultAnimation.startIndex;
        }

        meshRenderer = gameObject.GetComponent <MeshRenderer>();
        meshRenderer.material.SetInt("_StartPixelIndex", pixelsStartIndex);
        meshRenderer.material.SetInt("_SkinningTexSize", skinningTexSize);
        currentAnimIndex = 0;
        totalVerts       = defaultAnimation.totalVerts;
    }
Beispiel #5
0
    public void UpdateTick(float time)
    {
        GPUAnimation cAnim = currentAnimation;

        float lodFPS      = FPS;
        float totalSpeed  = speed;
        float tickRate    = Mathf.Max(0.0001f, 1f / lodFPS / totalSpeed);
        float actualDelta = time - lastFrameTime;
        bool  finished    = false;

        float pingPongMult = pingPong ? -1 : 1;

        if (speed * playbackSpeed < 0)
        {
            currentAnimTime -= actualDelta * pingPongMult * totalSpeed;
        }
        else
        {
            currentAnimTime += actualDelta * pingPongMult * totalSpeed;
        }

        if (currentAnimTime < 0)
        {
            currentAnimTime = cAnim.length;
            finished        = true;
        }
        else if (currentAnimTime > cAnim.length)
        {
            if (cAnim.wrapMode == WrapMode.Loop)
            {
                currentAnimTime = 0;
            }
            finished = true;
        }

        nextTick      = time + tickRate;
        lastFrameTime = time;

        float normalizedTime = currentAnimTime / cAnim.length;
        int   previousFrame  = currentFrame;

        currentFrame = Mathf.Min(Mathf.RoundToInt(normalizedTime * cAnim.totalFrames), cAnim.totalFrames - 1);

        if (cAnim.wrapMode == WrapMode.PingPong)
        {
            if (finished)
            {
                pingPong = !pingPong;
            }
        }

        if (finished)
        {
            bool stopUpdate = false;
            if (cAnim.wrapMode != WrapMode.Loop && cAnim.wrapMode != WrapMode.PingPong)
            {
                nextTick   = float.MaxValue;
                stopUpdate = true;
            }
            currentAnimation.FireFinishedEvents(currentFrame);
            if (stopUpdate)
            {
                return;
            }
        }
        if (currentAnimation.isVertsAnimation)
        {
            currentPixelIndex = totalVerts * currentFrame;
        }
        else
        {
            currentPixelIndex = pixelsStartIndex + totalJoints * currentFrame * perFramePixelsCount;
        }
        meshRenderer.material.SetInt("_StartPixelIndex", currentPixelIndex);
    }
Beispiel #6
0
 internal Enumerator(GPUAnimation outer)
 {
     _outer = outer;
 }
    private void CreateSnapshots()
    {
        UnityEditor.Animations.AnimatorController bakeController = null;
        string assetPath = GetPrefabPath();

        if (string.IsNullOrEmpty(assetPath))
        {
            EditorUtility.DisplayDialog("Mesh Animator", "Unable to locate the asset path for prefab: " + prefab.name, "OK");
            return;
        }

        HashSet <string> allAssets = new HashSet <string>();

        List <AnimationClip> clips = GetClips();

        foreach (var clip in clips)
        {
            allAssets.Add(AssetDatabase.GetAssetPath(clip));
        }

        string[] split = assetPath.Split("/".ToCharArray());

        string assetFolder = string.Empty;

        for (int s = 0; s < split.Length - 1; s++)
        {
            assetFolder += split[s] + "/";
        }

        var sampleGO = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;

        if (meshFilters.Count(q => q) == 0 && skinnedRenderers.Count(q => q) == 0)
        {
            throw new System.Exception("Bake Error! No MeshFilter's or SkinnedMeshRender's found to bake!");
        }
        else
        {
            animator = sampleGO.GetComponent <Animator>();
            if (animator == null)
            {
                animator = sampleGO.GetComponentInChildren <Animator>();
            }

            InitAnimationBones(sampleGO, null);
            if (requiresAnimator)
            {
                bakeController = CreateBakeController();
                if (animator == null)
                {
                    animator = sampleGO.AddComponent <Animator>();
                    animator.runtimeAnimatorController = bakeController;
                    animator.avatar = GetAvatar();
                }
                else
                {
                    animator.runtimeAnimatorController = bakeController;
                    animator.avatar = GetAvatar();
                }
                animator.cullingMode     = AnimatorCullingMode.AlwaysAnimate;
                animator.applyRootMotion = rootMotionMode == GPUAnimation.RootMotionMode.Baked;
            }

            GPUAnimationList meshAnimationList = ScriptableObject.CreateInstance <GPUAnimationList>();
            meshAnimationList.meshAnimations = new GPUAnimation[clips.Count];

            int startIndex = bonesMap.Count * 3;

            Transform rootMotionBaker = new GameObject().transform;
            for (int x = 0; x < clips.Count; x++)
            {
                AnimationClip animClip = clips[x];
                InitAnimationClipHashPath(animClip);

                if (bakeAnims.ContainsKey(animClip.name) && bakeAnims[animClip.name] == false)
                {
                    continue;
                }
                if (frameSkips.ContainsKey(animClip.name) == false)
                {
                    Debug.LogWarningFormat("No animation with name {0} in frame skips", animClip.name);
                    continue;
                }
                string       meshAnimationPath = string.Format("{0}{1}.asset", assetFolder, FormatClipName(animClip.name));
                GPUAnimation meshAnim          = new GPUAnimation();
                meshAnim.length = animClip.length;

                int bakeFrames = Mathf.CeilToInt(animClip.length * fps);

                meshAnim.animationName = animClip.name;
                meshAnim.startIndex    = startIndex;
                meshAnim.clipJoints    = new Skeleton[bonesMap.Count];
                startIndex            += bonesMap.Count * bakeFrames * 3;
                for (int i = 0; i < bonesMap.Count; i++)
                {
                    meshAnim.clipJoints[i] = new Skeleton();
                    meshAnim.clipJoints[i].jontFrameMatrixs = new Matrix4x4[bakeFrames];
                }

                if (animClip.isLooping)
                {
                    meshAnim.wrapMode = WrapMode.Loop;
                }
                else
                {
                    meshAnim.wrapMode = animClip.wrapMode;
                }
                meshAnim.frameSkip = frameSkips[animClip.name];
                meshAnimationList.meshAnimations[x] = meshAnim;
            }

            Color[]   meshTexturePixels = null;
            Texture2D meshTexture       = null;
            int       textureSize       = 2;
            int       pixelIndex        = 0;

            if (bakeVertices == false)
            {
                while (textureSize * textureSize < startIndex)
                {
                    textureSize = textureSize << 1;
                }

                meshTexture            = new Texture2D(textureSize, textureSize, TextureFormat.RGBAHalf, false, true);
                meshTexture.filterMode = FilterMode.Point;

                meshTexturePixels = meshTexture.GetPixels();
                Matrix4x4 matrix = Matrix4x4.identity;

                for (int i = 0; i < bonesMap.Count; i++)
                {
                    meshTexturePixels[pixelIndex] = new Color(matrix.m00, matrix.m01, matrix.m02, matrix.m03);
                    pixelIndex++;
                    meshTexturePixels[pixelIndex] = new Color(matrix.m10, matrix.m11, matrix.m12, matrix.m13);
                    pixelIndex++;
                    meshTexturePixels[pixelIndex] = new Color(matrix.m20, matrix.m21, matrix.m22, matrix.m23);
                    pixelIndex++;
                }
            }

            int animCount = 0;
            for (int j = 0; j < clips.Count; j++)
            {
                AnimationClip animClip = clips[j];
                GPUAnimation  meshAnim = meshAnimationList.meshAnimations[j];

                int bakeFrames = Mathf.CeilToInt(animClip.length * fps);
                meshAnim.totalFrames = bakeFrames;
                int frame = 0;
                for (int i = 0; i <= bakeFrames; i += frameSkips[animClip.name])
                {
                    if (bakeVertices)
                    {
                        CaptureSnapShot(animClip, bakeFrames, meshAnim, sampleGO);
                    }
                    else
                    {
                        float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames));
                        EditorUtility.DisplayProgressBar("Baking Animation", string.Format("Processing: {0} Frame: {1}", animClip.name, i), bakeDelta);
                        CaptureSnapShot(animClip, bakeFrames, bakeDelta, meshAnim, meshTexturePixels, ref pixelIndex);
                    }
                    frame++;
                }
                meshAnim.meshTexturePixels = meshTexturePixels;
                animCount++;
            }
            if (bakeVertices)
            {
                for (int i = 0; i < meshAnimationList.meshAnimations.Length; i++)
                {
                    GPUAnimation animation = meshAnimationList.meshAnimations[i];
                    animation.isVertsAnimation = true;
                    int smallTextureSize = 0;
                    int totalCountPixels = 0;
                    for (int j = 0; j < animation.verts.Length; j++)
                    {
                        totalCountPixels += animation.verts[j].decompressed.Length;
                    }
                    CalculateTextureSize(ref smallTextureSize, totalCountPixels);
                    Texture2D meshSmallTexture = new Texture2D(smallTextureSize, smallTextureSize, TextureFormat.RGBAHalf, false, true);
                    animation.textureSize = smallTextureSize;
                    Color[] meshSmallTextureData = meshSmallTexture.GetPixels();
                    meshSmallTexture.filterMode = FilterMode.Point;
                    int meshSmallTextureDataIndex = 0;
                    for (int k = 0; k < animation.verts.Length; k++)
                    {
                        GPUAnimationFrameData animationFrameData = animation.verts[k];
                        animation.totalVerts = animationFrameData.decompressed.Length;

                        for (int n = 0; n < animationFrameData.decompressed.Length; n++)
                        {
                            Vector3 vert = animationFrameData.decompressed[n];
                            meshSmallTextureData[meshSmallTextureDataIndex] = new Color(vert.x, vert.y, vert.z);
                            meshSmallTextureDataIndex++;
                            //meshSmallTexture.SetPixel(n, k, new Color(vert.x, vert.y, vert.z));
                        }
                    }

                    meshSmallTexture.SetPixels(meshSmallTextureData);
                    meshSmallTexture.Apply();
                    AssetDatabase.CreateAsset(meshSmallTexture, assetFolder + "_VertsAnimationTexture.asset");
                }
                AssetDatabase.CreateAsset(meshAnimationList, assetFolder + "_VertsAnimationConfig.asset");
            }
            else
            {
                meshTexture.SetPixels(meshTexturePixels);
                meshTexture.Apply();
                AssetDatabase.CreateAsset(meshTexture, assetFolder + "_AnimationTexture.asset");
                meshAnimationList.totalJoints     = bonesMap.Count;
                meshAnimationList.skinningTexSize = textureSize;

                AssetDatabase.CreateAsset(meshAnimationList, assetFolder + "_AnimationConfig.asset");

                SkinnedMeshRenderer skinnedMeshRenderer = sampleGO.GetComponentInChildren <SkinnedMeshRenderer>();
                Mesh           sharedMesh  = skinnedMeshRenderer.sharedMesh;
                Transform[]    transforms  = skinnedMeshRenderer.bones;
                int            vertexCount = sharedMesh.vertexCount;
                List <Vector4> indices     = new List <Vector4>();
                List <Vector4> weights     = new List <Vector4>();
                Vector3[]      vertices    = new Vector3[vertexCount];
                Vector3[]      normals     = new Vector3[vertexCount];

                Matrix4x4    meshMatrix  = skeletonPoses[bonesMap[transforms[0].name]] * sharedMesh.bindposes[0];
                BoneWeight[] boneWeights = sharedMesh.boneWeights;
                for (int v = 0; v < vertexCount; v++)
                {
                    BoneWeight weight     = boneWeights[v];
                    float      weight0    = weight.weight0;
                    float      weight1    = weight.weight1;
                    float      weight2    = weight.weight2;
                    float      weight3    = weight.weight3;
                    int        boneIndex0 = bonesMap[transforms[weight.boneIndex0].name];
                    int        boneIndex1 = bonesMap[transforms[weight.boneIndex1].name];
                    int        boneIndex2 = bonesMap[transforms[weight.boneIndex2].name];
                    int        boneIndex3 = bonesMap[transforms[weight.boneIndex3].name];
                    indices.Add(new Vector4(boneIndex0, boneIndex1, boneIndex2, boneIndex3));
                    weights.Add(new Vector4(weight0, weight1, weight2, weight3));
                    vertices[v]       = meshMatrix * sharedMesh.vertices[v];
                    normals[v]        = meshMatrix * sharedMesh.normals[v];
                    weight.boneIndex0 = boneIndex0;
                    weight.boneIndex1 = boneIndex1;
                    weight.boneIndex2 = boneIndex2;
                    weight.boneIndex3 = boneIndex3;
                    boneWeights[v]    = weight;
                }

                Mesh newMesh = new Mesh();
                newMesh.vertices  = vertices;
                newMesh.normals   = normals;
                newMesh.triangles = sharedMesh.triangles;
                newMesh.uv        = sharedMesh.uv;
                newMesh.SetUVs(1, indices);
                newMesh.SetUVs(2, weights);
                skinnedMeshRenderer.bones      = joints;
                skinnedMeshRenderer.sharedMesh = newMesh;
                AssetDatabase.CreateAsset(newMesh, assetFolder + "_" + sharedMesh.name + ".asset");
            }
        }
        GameObject.DestroyImmediate(sampleGO);
        EditorUtility.ClearProgressBar();
        EditorUtility.DisplayDialog("GPU Animator", string.Format("Baked {0} animation{1} successfully!", clips.Count
                                                                  , clips.Count > 1 ? "s" : string.Empty), "OK");
        AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(bakeController));
    }
    private void CaptureSnapShot(AnimationClip animClip, float bakeFrames, float bakeDelta, GPUAnimation meshAnim, Color[] meshTexturePixels, ref int pixelIndex)
    {
        float animationTime = bakeDelta * animClip.length;

        foreach (string path in positionPathHash)
        {
            string boneName = path.Substring(path.LastIndexOf("/") + 1);
            if (bonesMap.ContainsKey(boneName))
            {
                Transform child    = joints[bonesMap[boneName]];
                float     postionX = GetAnimationClipCurve(animClip, path, positionPath + ".x", bakeDelta);
                float     postionY = GetAnimationClipCurve(animClip, path, positionPath + ".y", bakeDelta);
                float     postionZ = GetAnimationClipCurve(animClip, path, positionPath + ".z", bakeDelta);
                child.localPosition = new Vector3(postionX, postionY, postionZ);
            }
        }

        foreach (string path in rotationPathHash)
        {
            string boneName = path.Substring(path.LastIndexOf("/") + 1);
            if (bonesMap.ContainsKey(boneName))
            {
                Transform  child     = joints[bonesMap[boneName]];
                float      rotationX = GetAnimationClipCurve(animClip, path, rotationPath + ".x", bakeDelta);
                float      rotationY = GetAnimationClipCurve(animClip, path, rotationPath + ".y", bakeDelta);
                float      rotationZ = GetAnimationClipCurve(animClip, path, rotationPath + ".z", bakeDelta);
                float      rotationW = GetAnimationClipCurve(animClip, path, rotationPath + ".w", bakeDelta);
                Quaternion rotation  = new Quaternion(rotationX, rotationY, rotationZ, rotationW);
                float      r         = rotationX * rotationX + rotationY * rotationY + rotationZ * rotationZ + rotationW * rotationW;
                if (r >= .1f)
                {
                    r           = 1.0f / Mathf.Sqrt(r);
                    rotation.x *= r;
                    rotation.y *= r;
                    rotation.z *= r;
                    rotation.w *= r;
                }

                child.localRotation = rotation;
            }
        }

        for (int k = 0; k < bonesMap.Count; k++)
        {
            Transform child = joints[k];

            Matrix4x4 matrix = child.transform.localToWorldMatrix;
            meshAnim.clipJoints[k].jontFrameMatrixs[k] = matrix;
            matrix = matrix * bindSkeletonPoses[k];
            meshTexturePixels[pixelIndex] = new Color(matrix.m00, matrix.m01, matrix.m02, matrix.m03);
            pixelIndex++;
            meshTexturePixels[pixelIndex] = new Color(matrix.m10, matrix.m11, matrix.m12, matrix.m13);
            pixelIndex++;
            meshTexturePixels[pixelIndex] = new Color(matrix.m20, matrix.m21, matrix.m22, matrix.m23);
            pixelIndex++;
        }
    }