public void refreshGeneratorInfo()
    {
        animData = new GpuSkinningAnimData();
        int totalFrame = 0;
        int clipFrame  = 0;

        clipsData.Clear();

        boneIds = resortBone(curGameObject);
        animData.totalBoneNum = boneIds.Count;

        animClips = clipList.ToArray();
        for (int i = 0; i < animClips.Length; ++i)
        {
            AnimationClip clip = animClips[i];
            clipFrame = (int)(clip.frameRate * clip.length);

            GpuSkinningAnimClip clipData = new GpuSkinningAnimClip(clip.name, totalFrame, totalFrame + clipFrame - 1);
            clipsData.Add(clipData);

            totalFrame += clipFrame;
        }
        animData.totalFrame = totalFrame;
        animData.clips      = clipsData.ToArray();

        if (genType == GenerateType.VerticesAnim)
        {
            Mesh mesh = selectedSkinnedMeshRenderer.sharedMesh;
            animData.texWidth  = mesh.vertices.Length;
            animData.texHeight = totalFrame * 2; // vec3需要两个像素表示(rgba32->float16)
        }
        else
        {
            long totalPixels = boneIds.Count * DEFAULT_PER_FRAME_BONE_DATASPACE * totalFrame;
            calTextureSize(totalPixels, out animData.texWidth, out animData.texHeight);
        }
    }
    public void generateTexAndMesh(string parentFolder, string savePath, string dataFileName)
    {
        int numBones = animData.totalBoneNum;

        // 重新生成mesh
        rebuildAllMeshes(savePath, parentFolder);

        // 将骨骼矩阵写入纹理
        var tex2D = new Texture2D(animData.texWidth, animData.texHeight, TextureFormat.RGBA32, false);

        tex2D.filterMode = FilterMode.Point;
        int                 clipIdx  = 0;
        int                 pixelIdx = 0;
        Vector2Int          pixelUv;
        GpuSkinningAnimClip boneAnimation = null;
        AnimationClip       clip          = null;
        List <Matrix4x4>    boneMatrices  = null;

        for (clipIdx = 0; clipIdx < animClips.Length; ++clipIdx)
        {
            boneAnimation = animData.clips[clipIdx];
            clip          = animClips[clipIdx];
            for (int frameIndex = 0; frameIndex < boneAnimation.Length(); frameIndex++)
            {
                boneMatrices = samplerAnimationClipBoneMatrices(curGameObject, clip, (float)frameIndex / clip.frameRate);
                for (int boneIndex = 0; boneIndex < numBones; boneIndex++)
                {
                    Matrix4x4  matrix   = boneMatrices[boneIndex];
                    Quaternion rotation = ToQuaternion(matrix);
                    Vector3    scale    = matrix.lossyScale;
                    float      sx       = Mathf.Floor(scale.x * 100.0f);
                    float      sy       = Mathf.Floor(scale.y * 100.0f);
                    float      sz       = Mathf.Floor(scale.z * 100.0f);
                    if ((sx - sy) > 5.0f ||
                        (sx - sz) > 5.0f ||
                        (sy - sz) > 5.0f)
                    {
                        Transform remapBone = null;
                        foreach (var key in boneIds.Keys)
                        {
                            if (boneIds[key] == boneIndex)
                            {
                                remapBone = key;
                                break;
                            }
                        }
                        string strLog = string.Format("AnimClip scale X Y Z not equal: {0} -> {1} {2}", curGameObject.name, boneAnimation.name, remapBone.transform.name);
                        Warning("AnimClip scale", strLog);
                    }

                    pixelUv = convertPixel2UV(pixelIdx++);

                    Color color1 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(rotation.x), convertFloat32toFloat16Bytes(rotation.y));
                    tex2D.SetPixel(pixelUv.x, pixelUv.y, color1);
                    pixelUv = convertPixel2UV(pixelIdx++);
                    Color color2 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(rotation.z), convertFloat32toFloat16Bytes(rotation.w));
                    tex2D.SetPixel(pixelUv.x, pixelUv.y, color2);
                    pixelUv = convertPixel2UV(pixelIdx++);
                    Color color3 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(matrix.GetColumn(3).x), convertFloat32toFloat16Bytes(matrix.GetColumn(3).y));
                    tex2D.SetPixel(pixelUv.x, pixelUv.y, color3);
                    pixelUv = convertPixel2UV(pixelIdx++);
                    Color color4 = convertFloat16Bytes2Color(convertFloat32toFloat16Bytes(matrix.GetColumn(3).z), convertFloat32toFloat16Bytes(Mathf.Clamp01(matrix.lossyScale.magnitude)));
                    tex2D.SetPixel(pixelUv.x, pixelUv.y, color4);

                    //Debug.Log("==============frameIndex========start========"+ frameIndex);
                    //Debug.Log("=======rotation==========="+ rotation.x+", "+ rotation.y+", " + rotation.z +", "+rotation.w);
                    //Vector4 rrrr = convertColors2Halfs(color1, color2);
                    //Debug.Log("=======rotation===22======" + rrrr.x + ", " + rrrr.y + ", " + rrrr.z + ", " + rrrr.w);
                    //Debug.Log("=======translation===========" + matrix.GetColumn(3).x + ", " + matrix.GetColumn(3).y + ", " + matrix.GetColumn(3).z + ", " + Mathf.Clamp01(matrix.lossyScale.magnitude));
                    //Vector4 ttttt = convertColors2Halfs(color3, color4);
                    //Debug.Log("=======translation===22======" + ttttt.x + ", " + ttttt.y + ", " + ttttt.z + ", " + ttttt.w);
                    //Debug.Log("==============frameIndex========end========" + frameIndex);
                }
            }
        }
        tex2D.Apply();
        // 导出动画纹理
        animTexturePath = savePath + dataFileName.Replace(".bytes", "") + ".png";
        exportTexture(tex2D, animTexturePath);
        setAnimationTextureProperties(animTexturePath);

        // 序列化后存储
        byte[] array    = MessagePackSerializer.Serialize(animData);
        string filePath = Path.Combine(parentFolder, savePath + dataFileName);

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }
        FileStream fs = new FileStream(filePath, FileMode.Create);

        fs.Write(array, 0, array.Length);
        fs.Close();
        AssetDatabase.Refresh();
    }
    public void generateTexAndMesh_verticesAnim(string parentFolder, string savePath, string dataFileName)
    {
        // 重新生成mesh(这一步生成的mesh还是带骨骼indices和骨骼权重的,但顶点动画是不需要这些数据的,后面会删掉)
        rebuildAllMeshes(savePath, parentFolder);

        // 将骨骼矩阵写入纹理
        var tex2D = new Texture2D(animData.texWidth, animData.texHeight, TextureFormat.RGB24, false);

        tex2D.filterMode = FilterMode.Point;
        int clipIdx         = 0;
        int pixelIdx        = 0;
        int totalFrameIndex = 0;
        GpuSkinningAnimClip boneAnimation = null;
        AnimationClip       clip = null;
        List <Matrix4x4>    boneMatrices = null;
        Vector4             boneIndices, boneWeights;
        Matrix4x4           boneMatrix0, boneMatrix1, boneMatrix2, boneMatrix3;
        Vector3             src_vertex;
        Vector4             vertex, position;

        for (clipIdx = 0; clipIdx < animClips.Length; ++clipIdx)
        {
            boneAnimation = animData.clips[clipIdx];
            clip          = animClips[clipIdx];
            for (int frameIndex = 0; frameIndex < boneAnimation.Length(); frameIndex++)
            {
                boneMatrices = samplerAnimationClipBoneMatrices(curGameObject, clip, (float)frameIndex / clip.frameRate);
                for (int vertexIndex = 0; vertexIndex < instMesh.vertices.Length; ++vertexIndex)
                {
                    src_vertex  = instMesh.vertices[vertexIndex];
                    vertex      = new Vector4(src_vertex.x, src_vertex.y, src_vertex.z, 1);
                    boneIndices = boneIndicesList[vertexIndex];
                    boneWeights = boneWeightsList[vertexIndex];
                    boneMatrix0 = boneMatrices[Mathf.RoundToInt(boneIndices.x)];
                    boneMatrix1 = boneMatrices[Mathf.RoundToInt(boneIndices.y)];
                    boneMatrix2 = boneMatrices[Mathf.RoundToInt(boneIndices.z)];
                    boneMatrix3 = boneMatrices[Mathf.RoundToInt(boneIndices.w)];
                    matrixMulFloat(ref boneMatrix0, boneWeights.x);
                    matrixMulFloat(ref boneMatrix1, boneWeights.y);
                    matrixMulFloat(ref boneMatrix2, boneWeights.z);
                    matrixMulFloat(ref boneMatrix3, boneWeights.w);
                    position = (matrixAddMatrix(matrixAddMatrix(boneMatrix0, boneMatrix1), matrixAddMatrix(boneMatrix2, boneMatrix3))) * vertex;
                    Color[] colors = convertThreeFloat16Bytes2TwoColor(convertFloat32toFloat16Bytes(position.x), convertFloat32toFloat16Bytes(position.y), convertFloat32toFloat16Bytes(position.z));
                    tex2D.SetPixel(vertexIndex, totalFrameIndex * 2, colors[0]);
                    tex2D.SetPixel(vertexIndex, totalFrameIndex * 2 + 1, colors[1]);
                }

                ++totalFrameIndex;
            }
        }
        tex2D.Apply();
        // 导出动画纹理
        animTexturePath = savePath + dataFileName.Replace(".bytes", "") + ".png";
        exportTexture(tex2D, animTexturePath);
        setAnimationTextureProperties(animTexturePath);

        // 序列化后存储
        byte[] array    = MessagePackSerializer.Serialize(animData);
        string filePath = Path.Combine(parentFolder, savePath + dataFileName);

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }
        FileStream fs   = new FileStream(filePath, FileMode.Create);

        fs.Write(array, 0, array.Length);
        fs.Close();
        AssetDatabase.Refresh();

        // 删除mesh的骨骼信息
        instMesh.uv2 = null;
        instMesh.uv3 = null;
        // 添加mesh的顶点索引 (TODO: unity shader中是否可以直接获取?)
        List <Vector4> indices = new List <Vector4>();

        for (int vertexIndex = 0; vertexIndex < instMesh.vertices.Length; ++vertexIndex)
        {
            indices.Add(new Vector4(vertexIndex, vertexIndex, vertexIndex, vertexIndex));
        }
        instMesh.SetUVs(1, indices);

        EditorUtility.SetDirty(instMesh);
        AssetDatabase.Refresh();
        AssetDatabase.SaveAssets();

        AssetDatabase.Refresh();
    }