public void BakeVertex(GPUAnimationData anim)
        {
            float   sampleTime   = 0;
            float   perFrameTime = 0;
            Vector3 v            = new Vector3();

            perFrameTime = anim.animLength / anim.frameCount;
            anim.cols    = new Color[anim.frameCount][];
            PlayAnim(anim.clipName);
            for (int i = 0; i < anim.frameCount; i++)
            {
                SetAnimTime(anim, sampleTime);
                window.skm.BakeMesh(window.bakedMesh);
                anim.cols[i] = new Color[window.vertexCount];
                for (int j = 0; j < window.vertexCount; j++)
                {
                    v = window.bakedMesh.vertices[j];
                    v = window.matrices.MultiplyPoint3x4(v);
                    anim.cols[i][j] = new Color(v.x, v.y, v.z, 1);
                }
                sampleTime += perFrameTime;
            }
            anim.startFrame     = window.framesOfAll;
            window.framesOfAll += anim.frameCount;
        }
        void PreviewGUI()
        {
            GPUAnimationData m_Data = m_PreviewTarget.m_Data;

            string[] anims = new string[m_Data.m_Animations.Length];
            for (int i = 0; i < anims.Length; i++)
            {
                anims[i] = m_Data.m_Animations[i].m_Name.Substring(m_Data.m_Animations[i].m_Name.LastIndexOf("_") + 1);
            }

            GUILayout.BeginHorizontal();
            GUILayout.Label("Play:");
            m_PreviewAnimIndex = GUILayout.SelectionGrid(m_PreviewAnimIndex, anims, m_Data.m_Animations.Length > 5 ? 5 : m_Data.m_Animations.Length);
            if (m_PreviewTarget.m_Timer.m_AnimIndex != m_PreviewAnimIndex)
            {
                m_PreviewTarget.SetAnimation(m_PreviewAnimIndex);
            }
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.Label("Speed:");
            m_PreviewTickSpeed = GUILayout.HorizontalSlider(m_PreviewTickSpeed, 0f, 3f);
            GUILayout.Label("Replay:");
            m_PreviewReplay = GUILayout.Toggle(m_PreviewReplay, "");
            GUILayout.Label("Bounds:");
            m_BoundsViewer.SetActive(GUILayout.Toggle(m_BoundsViewer.activeSelf, ""));
            GUILayout.EndHorizontal();
        }
 public void Bake(GPUAnimationData anim)
 {
     if (window.type == bakeType.SkeletonAnim)
     {
         BakeSkeleton(anim);
     }
     if (window.type == bakeType.VertexAnim)
     {
         BakeVertex(anim);
     }
 }
        public void BakeSkeleton(GPUAnimationData anim)
        {
            float sampleTime   = 0;
            float perFrameTime = 0;

            perFrameTime = anim.animLength / anim.frameCount;
            sampleTime  += perFrameTime / 2;
            PlayAnim(anim.clipName);
            anim.boneMatrices = new Matrix4x4[anim.frameCount][];
            for (int i = 0; i < anim.frameCount; i++)
            {
                SetAnimTime(anim, sampleTime);
                // window.skm.BakeMesh (window.bakedMesh); //to do combine mesh
                anim.boneMatrices[i] = CalculateSkinMatrix(window.go.transform, window.skm.bones, window.skm.sharedMesh.bindposes);                  //根骨骼指定,window.skm.rootBone ?
                sampleTime          += perFrameTime;
            }
            anim.startFrame     = window.framesOfAll;
            window.framesOfAll += anim.frameCount;
        }
        void GenerateBoneInstanceMeshAndTexture(GameObject _targetFBX, AnimationClip[] _clips, string exposeBones)
        {
            if (!UEAsset.SelectDirectory(_targetFBX, out string savePath, out string meshName))
            {
                Debug.LogWarning("Invalid Folder Selected");
                return;
            }
            GameObject          _instantiatedObj     = GameObject.Instantiate(m_TargetPrefab);
            SkinnedMeshRenderer _skinnedMeshRenderer = _instantiatedObj.GetComponentInChildren <SkinnedMeshRenderer>();

            try
            {
                Matrix4x4[] bindPoses = _skinnedMeshRenderer.sharedMesh.bindposes;
                Transform[] bones     = _skinnedMeshRenderer.bones;
                #region Record Expose Bone
                List <AnimationInstanceExposeBone> exposeBoneParam = new List <AnimationInstanceExposeBone>();
                if (exposeBones != "")
                {
                    Transform[] activeTransforms = _instantiatedObj.GetComponentsInChildren <Transform>();
                    for (int i = 0; i < activeTransforms.Length; i++)
                    {
                        if (!System.Text.RegularExpressions.Regex.Match(activeTransforms[i].name, exposeBones).Success)
                        {
                            continue;
                        }
                        int       relativeBoneIndex = -1;
                        Transform relativeBone      = activeTransforms[i];
                        while (relativeBone != null)
                        {
                            relativeBoneIndex = System.Array.FindIndex(bones, p => p == relativeBone);
                            if (relativeBoneIndex != -1)
                            {
                                break;
                            }
                            relativeBone = relativeBone.parent;
                        }
                        if (relativeBoneIndex == -1)
                        {
                            continue;
                        }

                        Matrix4x4 rootWorldToLocal = _skinnedMeshRenderer.transform.worldToLocalMatrix;

                        exposeBoneParam.Add(new AnimationInstanceExposeBone()
                        {
                            m_BoneIndex = relativeBoneIndex,
                            m_BoneName  = activeTransforms[i].name,
                            m_Position  = rootWorldToLocal.MultiplyPoint(activeTransforms[i].transform.position),
                            m_Direction = rootWorldToLocal.MultiplyVector(activeTransforms[i].transform.forward)
                        });
                    }
                }
                #endregion
                #region Bake Animation Atlas
                int boneCount  = _skinnedMeshRenderer.sharedMesh.bindposes.Length;
                int totalWdith = boneCount * 3;
                int totalFrame = GetInstanceParams(_clips, out AnimationInstanceParam[] instanceParams);
                List <AnimationInstanceEvent> instanceEvents = new List <AnimationInstanceEvent>();

                Texture2D atlasTexture = new Texture2D(Mathf.NextPowerOfTwo(totalWdith), Mathf.NextPowerOfTwo(totalFrame), TextureFormat.RGBAHalf, false);
                atlasTexture.filterMode = FilterMode.Point;
                atlasTexture.wrapModeU  = TextureWrapMode.Clamp;
                atlasTexture.wrapModeV  = TextureWrapMode.Repeat;
                UBoundsChecker.Begin();
                for (int i = 0; i < _clips.Length; i++)
                {
                    AnimationClip clip       = _clips[i];
                    float         length     = clip.length;
                    float         frameRate  = clip.frameRate;
                    int           frameCount = (int)(length * frameRate);
                    int           startFrame = instanceParams[i].m_FrameBegin;
                    for (int j = 0; j < frameCount; j++)
                    {
                        clip.SampleAnimation(_instantiatedObj, length * j / frameCount);
                        for (int k = 0; k < boneCount; k++)
                        {
                            Matrix4x4 curFrameBoneMatrix = _skinnedMeshRenderer.transform.worldToLocalMatrix * bones[k].localToWorldMatrix * bindPoses[k];
                            atlasTexture.SetPixel(k * 3, startFrame + j, UColor.VectorToColor(curFrameBoneMatrix.GetRow(0)));
                            atlasTexture.SetPixel(k * 3 + 1, startFrame + j, UColor.VectorToColor(curFrameBoneMatrix.GetRow(1)));
                            atlasTexture.SetPixel(k * 3 + 2, startFrame + j, UColor.VectorToColor(curFrameBoneMatrix.GetRow(2)));
                        }

                        Mesh boundsCheckMesh = new Mesh();
                        _skinnedMeshRenderer.BakeMesh(boundsCheckMesh);
                        Vector3[] verticies = boundsCheckMesh.vertices;
                        for (int k = 0; k < verticies.Length; k++)
                        {
                            UBoundsChecker.CheckBounds(verticies[k].Divide(_skinnedMeshRenderer.transform.localScale));
                        }

                        boundsCheckMesh.Clear();
                    }
                }
                atlasTexture.Apply();
                #endregion
                #region Bake Mesh
                Mesh         instanceMesh = _skinnedMeshRenderer.sharedMesh.Copy();
                BoneWeight[] boneWeights  = instanceMesh.boneWeights;
                Vector4[]    uv1          = new Vector4[boneWeights.Length];
                Vector4[]    uv2          = new Vector4[boneWeights.Length];
                for (int i = 0; i < boneWeights.Length; i++)
                {
                    uv1[i] = new Vector4(boneWeights[i].boneIndex0, boneWeights[i].boneIndex1, boneWeights[i].boneIndex2, boneWeights[i].boneIndex3);
                    uv2[i] = new Vector4(boneWeights[i].weight0, boneWeights[i].weight1, boneWeights[i].weight2, boneWeights[i].weight3);
                }
                instanceMesh.SetUVs(1, uv1);
                instanceMesh.SetUVs(2, uv2);
                instanceMesh.boneWeights = null;
                instanceMesh.bindposes   = null;
                instanceMesh.bounds      = UBoundsChecker.CalculateBounds();
                #endregion
                DestroyImmediate(_instantiatedObj);

                GPUAnimationData data = ScriptableObject.CreateInstance <GPUAnimationData>();
                data.m_Animations  = instanceParams;
                data.m_ExposeBones = exposeBoneParam.ToArray();

                data = UEAsset.CreateAssetCombination(savePath + meshName + "_GPU_Bone.asset", data, new KeyValuePair <string, Object>(meshName + "_AnimationAtlas", atlasTexture), new KeyValuePair <string, Object>(meshName + "_InstanceMesh", instanceMesh));
                Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(data));
                foreach (var asset in assets)
                {
                    Texture2D atlas = asset as Texture2D;
                    Mesh      mesh  = asset as Mesh;
                    if (atlas)
                    {
                        data.m_AnimationAtlas = atlas;
                    }
                    if (mesh)
                    {
                        data.m_InstancedMesh = mesh;
                    }
                }
                AssetDatabase.SaveAssets();
            }
            catch (System.Exception e)
            {
                Debug.LogError("Generate Failed:" + e.Message);
                DestroyImmediate(_instantiatedObj);
            }
        }
        void GenerateVertexTexture(GameObject _targetFBX, AnimationClip[] _clips)
        {
            if (!UEAsset.SelectDirectory(_targetFBX, out string savePath, out string meshName))
            {
                Debug.LogWarning("Invalid Folder Selected");
                return;
            }
            GameObject          instantiatedObj     = GameObject.Instantiate(m_TargetPrefab);
            SkinnedMeshRenderer skinnedMeshRenderer = instantiatedObj.GetComponentInChildren <SkinnedMeshRenderer>();

            #region Bake Animation Atlas
            int vertexCount       = skinnedMeshRenderer.sharedMesh.vertexCount;
            int totalVertexRecord = vertexCount * 2;
            int totalFrame        = GetInstanceParams(_clips, out AnimationInstanceParam[] instanceParams);

            Texture2D atlasTexture = new Texture2D(Mathf.NextPowerOfTwo(totalVertexRecord), Mathf.NextPowerOfTwo(totalFrame), TextureFormat.RGBAHalf, false);
            atlasTexture.filterMode = FilterMode.Point;
            atlasTexture.wrapModeU  = TextureWrapMode.Clamp;
            atlasTexture.wrapModeV  = TextureWrapMode.Repeat;
            UBoundsChecker.Begin();
            for (int i = 0; i < _clips.Length; i++)
            {
                AnimationClip clip           = _clips[i];
                Mesh          vertexBakeMesh = new Mesh();
                float         length         = clip.length;
                float         frameRate      = clip.frameRate;
                int           frameCount     = (int)(length * frameRate);
                int           startFrame     = instanceParams[i].m_FrameBegin;
                for (int j = 0; j < frameCount; j++)
                {
                    clip.SampleAnimation(instantiatedObj, length * j / frameCount);
                    skinnedMeshRenderer.BakeMesh(vertexBakeMesh);
                    Vector3[] vertices = vertexBakeMesh.vertices;
                    Vector3[] normals  = vertexBakeMesh.normals;
                    for (int k = 0; k < vertexCount; k++)
                    {
                        UBoundsChecker.CheckBounds(vertices[k]);
                        atlasTexture.SetPixel(k * 2, startFrame + j, UColor.VectorToColor(vertices[k]));
                        atlasTexture.SetPixel(k * 2 + 1, startFrame + j, UColor.VectorToColor(normals[k]));
                    }
                }
                vertexBakeMesh.Clear();
            }
            atlasTexture.Apply();
            #endregion

            #region Bake Mesh
            Mesh instanceMesh = skinnedMeshRenderer.sharedMesh.Copy();
            instanceMesh.normals     = null;
            instanceMesh.tangents    = null;
            instanceMesh.boneWeights = null;
            instanceMesh.bindposes   = null;
            instanceMesh.bounds      = UBoundsChecker.CalculateBounds();
            #endregion
            DestroyImmediate(instantiatedObj);

            GPUAnimationData data = ScriptableObject.CreateInstance <GPUAnimationData>();
            data.m_Animations = instanceParams;
            data = UEAsset.CreateAssetCombination(savePath + meshName + "_GPU_Vertex.asset", data, new KeyValuePair <string, Object>(meshName + "_AnimationAtlas", atlasTexture), new KeyValuePair <string, Object>(meshName + "_InstanceMesh", instanceMesh));
            Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(data));
            foreach (var asset in assets)
            {
                Texture2D atlas = asset as Texture2D;
                Mesh      mesh  = asset as Mesh;
                if (atlas)
                {
                    data.m_AnimationAtlas = atlas;
                }
                if (mesh)
                {
                    data.m_InstancedMesh = mesh;
                }
            }
            AssetDatabase.SaveAssets();
        }
 protected override void SetAnimTime(GPUAnimationData anim, float sampleTime)
 {
     anim.stateClip.time = sampleTime;
     window.animation.Sample();
 }
 protected override void SetAnimTime(GPUAnimationData anim, float sampleTime)
 {
     anim.animClip.SampleAnimation(window.animator.gameObject, sampleTime);
 }
 protected virtual void SetAnimTime(GPUAnimationData anim, float f)
 {
 }