示例#1
0
        public void AddFrames(string nameLocal, List <Vector3[]> pFrames, MeshAnimationBoneGroup pBoneGroup)
        {
            Name       = nameLocal;
            FrameCount = pFrames.Count;
            if (pFrames.Count < 1)
            {
                return;
            }

            FrameSize = pFrames[0].Length;
            List <float> list = new List <float>();

            foreach (Vector3[] current in pFrames)
            {
                Vector3[] array = current;
                for (int i = 0; i < array.Length; i++)
                {
                    Vector3 vector = array[i];
                    list.Add(vector.x);
                    list.Add(vector.y);
                    list.Add(vector.z);
                }
            }

            FloatFrames = list.ToArray();
            list.Clear();
            BoneNames = pBoneGroup.BoneNames.ToArray();
            foreach (KeyValuePair <string, MeshAnimationBoneTransform> current2 in pBoneGroup.Bones)
            {
                foreach (Vector3 current3 in current2.Value.Positions)
                {
                    list.Add(current3.x);
                    list.Add(current3.y);
                    list.Add(current3.z);
                }
            }

            FloatBonePositions = list.ToArray();
            list.Clear();
            foreach (KeyValuePair <string, MeshAnimationBoneTransform> current4 in pBoneGroup.Bones)
            {
                foreach (Quaternion current5 in current4.Value.Rotations)
                {
                    list.Add(current5.x);
                    list.Add(current5.y);
                    list.Add(current5.z);
                    list.Add(current5.w);
                }
            }

            FloatBoneRotations = list.ToArray();
            list.Clear();
        }
    public static void ExportCombinedTexture(GameObject pFbxInstance, ExportParameters pSettings, System.Action <float> pProgressBarUpdater = null)
    {
        if (!AreParametersValid(pFbxInstance, pSettings))
        {
            return;
        }

        //List<AnimationClip> exportClips = GetClips ();
        //List<Transform> exportBoneTransforms = GetBoneTransforms ();
        //List<string> exportBoneNames = GetBoneNames ();
        AnimationClip[] exportClips          = pSettings.animationClips;
        Transform[]     exportBoneTransforms = pSettings.boneTransforms;
        string[]        exportBoneNames      = pSettings.boneNames;
        string[]        animationNames       = pSettings.animationNames;

        GameObject model         = pFbxInstance;
        Transform  baseTransform = model.transform;
        Animation  animation     = model.GetComponentInChildren <Animation>();

        ///origin code
        //SkinnedMeshRenderer renderer = model.GetComponentInChildren<SkinnedMeshRenderer>();
        //Mesh mesh = renderer.sharedMesh;

        SkinnedMeshRenderer[] renderArray = model.GetComponentsInChildren <SkinnedMeshRenderer>();
        int arrayLength = renderArray.Length;

        Mesh[] meshArray = new Mesh[arrayLength];
        for (int i = 0; i < arrayLength; i++)
        {
            meshArray[i] = renderArray[i].sharedMesh;
        }

        float frameInterval = 1.0f / pSettings.framerate;

        //清空并重建目标目录
        if (!System.IO.Directory.Exists(pSettings.outputFilePath))
        {
            System.IO.Directory.CreateDirectory(pSettings.outputFilePath);
        }

        string filePath = pSettings.outputFilePath + model.name + ".asset";

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }

        ///modify by niexin
        ///Attack1","Win","Dead","Hit","Run","Skill1","Wait1","Wait2" 8 default animations
        ///first line marked as attached model info, first color to number,following by vertex counts for each sub mesh,which is the width of texture
        ///某行首位标记attach数量信息,如0则无,那2行则为该物体动画数据,否则往上推,后续像素r分别写入顶点数,即动画纹理宽度
        ///8个动画的顺序依次标记首位8个像素,r通道填入是否存在的信息,g,b分别对应初始行,结束行位置,

        int totalframeCount = 0;

        totalframeCount = 1 + arrayLength;

        int aniFrameCount = 0;

        //pre cacl the length of all frames
        for (int i = 0; i < exportClips.Length; i++)
        {
            AnimationClip clip = exportClips[i];

            if (null == clip)
            {
                continue;
            }

            float clipLength = clip.length;

            //Mesh frameMesh;
            //List<Vector3[]> frameVertices = new List<Vector3[]>();

            // Get the list of times for each frame
            List <float> frameTimes = GetFrameTimes(clipLength, frameInterval);
            aniFrameCount += frameTimes.Count;
        }

        totalframeCount += aniFrameCount * arrayLength;

        int[] vertexCount    = new int[arrayLength];
        int   maxVertexCount = 0;

        for (int i = 0; i < arrayLength; i++)
        {
            int count = meshArray[i].vertexCount;
            vertexCount[i] = count;
            if (count > maxVertexCount)
            {
                maxVertexCount = count;
            }
        }

        Vector3[][] defaultAnimationInfos = new Vector3[arrayLength][];
        for (int i = 0; i < arrayLength; i++)
        {
            defaultAnimationInfos[i] = new Vector3[8];
            for (int j = 0; j < 8; j++)
            {
                defaultAnimationInfos[i][j] = new Vector3(0, 0, 0);
            }
        }

        string[]      defaultAnimationArray = new string[] { "Attack1", "Win", "Dead", "Hit", "Run", "Skill1", "Wait1", "Wait2" };
        List <string> defaultAnimationList  = new List <string>();

        for (int i = 0; i < defaultAnimationArray.Length; i++)
        {
            defaultAnimationList.Add(defaultAnimationArray[i].ToUpper());
        }

        MeshSkinDataProxy data = MeshSkinDataProxy.CreateInstance <MeshSkinDataProxy>();

        data.isLoadAllInMainScene = pSettings.isLoadAllInMainScene;
        data.arrayLength          = arrayLength;
        data.maxVertexCount       = maxVertexCount;
        data.vertexCounts         = vertexCount;
        data.meshes = new MeshSkinDataProxy.SubMeshData[arrayLength];

        Texture2D combinedTex = new Texture2D(maxVertexCount, totalframeCount, TextureFormat.RGBAHalf, false);

        combinedTex.SetPixel(0, 0, new Color(arrayLength, maxVertexCount, 0));

        int countData = 1 + arrayLength;

        for (int i = 0; i < arrayLength; i++)
        {
            combinedTex.SetPixel(i + 1, 0, new Color(vertexCount[i], 0, 0));
            countData += meshArray[i].uv.Length / 2 + meshArray[i].triangles.Length / 3;
        }

        //////配置纹理 fps uv count, uv, tri count tri

        int texSize = 64; //不要问我为什么是64
        int texH    = (int)Mathf.Ceil(countData / (float)texSize);
        int texW    = texSize;

        Texture2D cfgTexture = new Texture2D(texW, texH, TextureFormat.RGBAHalf, false);

        Color[] colors = new Color[texW * texH];

        int cfgDataIdx = 0;

        colors[cfgDataIdx++] = new Color(arrayLength, 0, 0);

        for (int i = 0; i < arrayLength; i++)
        {
            colors[cfgDataIdx++] = new Color(pSettings.framerate, meshArray[i].uv.Length, meshArray[i].triangles.Length);
        }

        int frame = 1 + arrayLength;

        for (int submeshCount = 0; submeshCount < arrayLength; submeshCount++)
        {
            data.meshes[submeshCount].clips     = new MeshSkinDataProxy.ClipData[defaultAnimationArray.Length];
            data.meshes[submeshCount].framerate = pSettings.framerate;

            for (int i = 0; i < exportClips.Length; i++)
            {
                if (pProgressBarUpdater != null)
                {
                    pProgressBarUpdater((float)i / (float)(exportClips.Length + 1));
                }
                MeshAnimationBoneGroup boneGroup = new MeshAnimationBoneGroup(exportBoneNames.ToList(), exportBoneNames.Length);

                // Set the animation clip to export
                AnimationClip clip = exportClips[i];

                if (null == clip)
                {
                    continue;
                }

                int infoIdx = -1;

                string clipName = clip.name;
                if (clipName.Equals("walk"))
                {
                    clipName = "Hit";
                }
                else if (clipName.Equals("cut"))
                {
                    clipName = "Skill1";
                }
                else if (clipName.Equals("victory"))
                {
                    clipName = "Dead";
                }

                string upperName = clipName.ToUpper();
                if (defaultAnimationList.Contains(upperName))
                {
                    infoIdx = defaultAnimationList.IndexOf(upperName);
                    defaultAnimationInfos[submeshCount][infoIdx].x = 1;
                }

                animation.AddClip(clip, clip.name);
                animation.clip = clip;
                AnimationState state = animation[clip.name];
                state.enabled = true;
                state.weight  = 1;

                float clipLength = clip.length;

                //Mesh frameMesh;
                //List<Vector3[]> frameVertices = new List<Vector3[]>();

                // Get the list of times for each frame
                List <float> frameTimes = GetFrameTimes(clipLength, frameInterval);

                ////顶点纹理 r->x,g->y,b->z,a->s

                //sample each sub mesh

                //start frame position
                try
                {
                    defaultAnimationInfos[submeshCount][infoIdx].y = frame;
                }
                catch
                {
                    Debug.LogError(pFbxInstance.name + "," + defaultAnimationInfos.Length + "," + defaultAnimationInfos.LongLength + "," + submeshCount + "," + infoIdx);
                    continue;
                }

                data.meshes[submeshCount].clips[infoIdx].frames = new MeshSkinDataProxy.FrameData[frameTimes.Count];

                int index = 0;
                foreach (float time in frameTimes)
                {
                    state.time = time;

                    animation.Play();
                    animation.Sample();

                    // Grab the position and rotation for each bone at the current frame
                    for (int k = 0; k < exportBoneTransforms.Length; k++)
                    {
                        string name = exportBoneNames[k];

                        Vector3    pos = baseTransform.InverseTransformPoint(exportBoneTransforms[k].position);
                        Quaternion rot = exportBoneTransforms[k].rotation * Quaternion.Inverse(baseTransform.rotation);

                        boneGroup.Bones[name].Positions.Add(pos);
                        boneGroup.Bones[name].Rotations.Add(rot);
                    }

                    Mesh bakeMesh = null;

                    //if (pSettings.quaternionOffset != Quaternion.identity)
                    //{
                    //    Matrix4x4 matrix = new Matrix4x4();
                    //    matrix.SetTRS(Vector2.zero, pSettings.quaternionOffset, Vector3.one);
                    //    bakeMesh = BakeFrameAfterMatrixTransform(renderArray[submeshCount], matrix);
                    //}
                    //else
                    //{
                    //    bakeMesh = new Mesh();
                    //    renderArray[submeshCount].BakeMesh(bakeMesh);
                    //}
                    Matrix4x4 matrix = new Matrix4x4();
                    matrix   = renderArray[submeshCount].transform.localToWorldMatrix;
                    bakeMesh = BakeFrameAfterMatrixTransform(renderArray[submeshCount], matrix);

                    data.meshes[submeshCount].clips[infoIdx].frames[index++].vertexs = bakeMesh.vertices;

                    for (int k = 0; k < bakeMesh.vertexCount; k++)
                    {
                        Vector3 vertex = bakeMesh.vertices[k];
                        combinedTex.SetPixel(k, frame, new Color(vertex.x, vertex.y, vertex.z));
                    }

                    bakeMesh.Clear();
                    Object.DestroyImmediate(bakeMesh);

                    frame++;

                    animation.Stop();
                }
                //end frame position,exclude
                defaultAnimationInfos[submeshCount][infoIdx].z = frame;
            }

            data.meshes[submeshCount].uvs       = meshArray[submeshCount].uv;
            data.meshes[submeshCount].triangles = meshArray[submeshCount].triangles;

            for (int i = 0; i < meshArray[submeshCount].uv.Length / 2; i++)
            {
                int uvIdx = i * 2;
                colors[cfgDataIdx++] = new Color(meshArray[submeshCount].uv[uvIdx].x, meshArray[submeshCount].uv[uvIdx].y, meshArray[submeshCount].uv[uvIdx + 1].x, meshArray[submeshCount].uv[uvIdx + 1].y);
            }
            for (int i = 0; i < meshArray[submeshCount].triangles.Length / 3; i++)
            {
                int triIdx = i * 3;
                colors[cfgDataIdx++] = new Color(meshArray[submeshCount].triangles[triIdx], meshArray[submeshCount].triangles[triIdx + 1], meshArray[submeshCount].triangles[triIdx + 2]);
            }
        }
        //group.AddAnimation(animationNames[i], frameVertices, boneGroup);

        for (int j = 0; j < arrayLength; j++)
        {
            for (int i = 0; i < 8; i++)
            {
                combinedTex.SetPixel(i, j + 1, new Color(defaultAnimationInfos[j][i].x, defaultAnimationInfos[j][i].y, defaultAnimationInfos[j][i].z));
            }
        }

        combinedTex.Apply(false);

        string dataPath = string.Format("{0}{1}.asset", pSettings.outputFilePath, pFbxInstance.name);

        AssetDatabase.CreateAsset(data, dataPath);

        if (pProgressBarUpdater != null)
        {
            pProgressBarUpdater((float)exportClips.Length / (float)(exportClips.Length + 1));
        }

        AssetDatabase.Refresh();
    }
    public static void Export(GameObject pFbxInstance, ExportParameters pSettings, System.Action <float> pProgressBarUpdater = null)
    {
        if (AreParametersValid(pFbxInstance, pSettings))
        {
            //List<AnimationClip> exportClips = GetClips ();
            //List<Transform> exportBoneTransforms = GetBoneTransforms ();
            //List<string> exportBoneNames = GetBoneNames ();
            AnimationClip[] exportClips          = pSettings.animationClips;
            Transform[]     exportBoneTransforms = pSettings.boneTransforms;
            string[]        exportBoneNames      = pSettings.boneNames;
            string[]        animationNames       = pSettings.animationNames;

            GameObject          model         = pFbxInstance;
            Transform           baseTransform = model.transform;
            SkinnedMeshRenderer renderer      = model.GetComponentInChildren <SkinnedMeshRenderer>();
            Mesh      mesh      = renderer.sharedMesh;
            Animation animation = model.GetComponentInChildren <Animation>();

            // Set up the basic MeshAnimationGroupSerializable properties
            //MeshAnimationGroupSerializable group = new MeshAnimationGroupSerializable();
            //group.SetUV(mesh.uv);
            //group.SetTriangles(mesh.triangles);
            //group.SetFrameInterval(pSettings.framerate);
            //group.modelName = pFbxInstance.name;
            //group.boneCount = exportBoneTransforms.Length;

            float frameInterval = 1.0f / pSettings.framerate;

            //Mesh modifiedMesh = GameObject.Instantiate(mesh);
            //List<Vector4> modifiedTangent = new List<Vector4>();
            //for (int mi = 0; mi < mesh.vertexCount; mi++) {
            //    Vector4 tangent = new Vector4(mi, 0, 0);
            //    modifiedTangent.Add(tangent);
            //}

            //modifiedMesh.SetTangents(modifiedTangent);

            //AssetDatabase.CreateAsset(modifiedMesh, "Assets/GpuInstance/ooxx.asset");

            //清空并重建目标目录
            if (!System.IO.Directory.Exists(pSettings.outputFilePath))
            {
                System.IO.Directory.CreateDirectory(pSettings.outputFilePath);
            }
            else
            {
                System.IO.Directory.Delete(pSettings.outputFilePath, true);
                System.IO.Directory.CreateDirectory(pSettings.outputFilePath);
            }

            for (int i = 0; i < exportClips.Length; i++)
            {
                if (pProgressBarUpdater != null)
                {
                    pProgressBarUpdater((float)i / (float)(exportClips.Length + 1));
                }
                MeshAnimationBoneGroup boneGroup = new MeshAnimationBoneGroup(exportBoneNames.ToList(), exportBoneNames.Length);

                // Set the animation clip to export
                AnimationClip clip = exportClips[i];

                if (null == clip)
                {
                    continue;
                }

                animation.AddClip(clip, clip.name);
                animation.clip = clip;
                AnimationState state = animation[clip.name];
                state.enabled = true;
                state.weight  = 1;

                float clipLength = clip.length;

                //Mesh frameMesh;
                //List<Vector3[]> frameVertices = new List<Vector3[]>();

                // Get the list of times for each frame
                List <float> frameTimes = GetFrameTimes(clipLength, frameInterval);

                ////顶点纹理 r->x,g->y,b->z,a->s
                Texture2D vertexTex = new Texture2D(mesh.vertexCount, frameTimes.Count, TextureFormat.RGBAHalf, false);

                int frame = 0;

                foreach (float time in frameTimes)
                {
                    state.time = time;

                    animation.Play();
                    animation.Sample();

                    // Grab the position and rotation for each bone at the current frame
                    for (int k = 0; k < exportBoneTransforms.Length; k++)
                    {
                        string name = exportBoneNames[k];

                        Vector3    pos = baseTransform.InverseTransformPoint(exportBoneTransforms[k].position);
                        Quaternion rot = exportBoneTransforms[k].rotation * Quaternion.Inverse(baseTransform.rotation);

                        boneGroup.Bones[name].Positions.Add(pos);
                        boneGroup.Bones[name].Rotations.Add(rot);
                    }

                    Mesh bakeMesh = null;

                    //if (pSettings.quaternionOffset != Quaternion.identity) {
                    //    Matrix4x4 matrix = new Matrix4x4();
                    //    matrix.SetTRS(Vector2.zero, pSettings.quaternionOffset, Vector3.one);
                    //    bakeMesh = BakeFrameAfterMatrixTransform(renderer, matrix);
                    //} else {
                    //    bakeMesh = new Mesh();
                    //    renderer.BakeMesh(bakeMesh);
                    //}
                    Matrix4x4 matrix = new Matrix4x4();
                    //matrix.SetTRS(Vector2.zero, pSettings.quaternionOffset, Vector3.one);
                    matrix   = renderer.transform.localToWorldMatrix;
                    bakeMesh = BakeFrameAfterMatrixTransform(renderer, matrix);

                    for (int k = 0; k < bakeMesh.vertexCount; k++)
                    {
                        Vector3 vertex = bakeMesh.vertices[k];
                        vertexTex.SetPixel(k, frame, new Color(vertex.x, vertex.y, vertex.z));
                    }

                    bakeMesh.Clear();
                    Object.DestroyImmediate(bakeMesh);

                    frame++;

                    animation.Stop();
                }
                //group.AddAnimation(animationNames[i], frameVertices, boneGroup);

                vertexTex.Apply(false);

                string dataPath = pSettings.outputFilePath + "/" + pSettings.animationNames[i] + ".asset";

                AssetDatabase.CreateAsset(vertexTex, dataPath);
            }

            ////配置纹理 fps uv count, uv, tri count tri
            int countData = mesh.uv.Length / 2 + mesh.triangles.Length / 3 + 1;
            int texSize   = 64; //不要问我为什么是64
            int texH      = (int)Mathf.Ceil(countData / (float)texSize);
            int texW      = texSize;

            Texture2D cfgTexture = new Texture2D(texW, texH, TextureFormat.RGBAHalf, false);
            Color[]   colors     = new Color[texW * texH];

            int cfgDataIdx = 0;
            colors[cfgDataIdx++] = new Color(pSettings.framerate, mesh.uv.Length, mesh.triangles.Length);
            for (int i = 0; i < mesh.uv.Length / 2; i++)
            {
                int uvIdx = i * 2;
                colors[cfgDataIdx++] = new Color(mesh.uv[uvIdx].x, mesh.uv[uvIdx].y, mesh.uv[uvIdx + 1].x, mesh.uv[uvIdx + 1].y);
            }
            for (int i = 0; i < mesh.triangles.Length / 3; i++)
            {
                int triIdx = i * 3;
                colors[cfgDataIdx++] = new Color(mesh.triangles[triIdx], mesh.triangles[triIdx + 1], mesh.triangles[triIdx + 2]);
            }

            cfgTexture.SetPixels(colors);
            cfgTexture.Apply();

            //Test(cfgTexture);

            AssetDatabase.CreateAsset(cfgTexture, pSettings.outputFilePath + "/" + pFbxInstance.name + ".asset");

            if (pProgressBarUpdater != null)
            {
                pProgressBarUpdater((float)exportClips.Length / (float)(exportClips.Length + 1));
            }

            //MeshAnimationProtobufHelper.SerializeObject<MeshAnimationGroupSerializable>(pSettings.outputFilePath + "/" + pFbxInstance.name + ".bytes", group);

            EditorUtility.DisplayDialog("Tip", "Mesh Animation Export Complete" + pFbxInstance.name, "OK");
            AssetDatabase.Refresh();
        }
    }