Example #1
0
        /// <summary>
        /// Bake all animation clips to texture in format:
        /// [clip0[frame0[bone0[row0, row1, row0]..boneN[row0, row1, row0]]..frameM[bone0[row0, row1, row0]..boneN[row0, row1, row0]]]..clipK[..
        /// </summary>
        /// <returns>BakedData - baked animation matrix to texture</returns>
        public static BakedData BakeClips(GameObject prototype, float frameRate = 30f)
        {
            var go = Object.Instantiate(prototype);

            go.transform.localPosition = Vector3.zero;
            go.transform.localRotation = Quaternion.identity;
            go.SetActive(true);

            var skinnedMeshRenderer = go.GetComponentInChildren <SkinnedMeshRenderer>();

            var sampledBoneMatrices = SampleAnimationClips(go,
                                                           skinnedMeshRenderer,
                                                           frameRate,
                                                           out var animationClips,
                                                           out var numberOfKeyFrames,
                                                           out var numberOfBones);
            var buffer = new Vector4[numberOfBones * numberOfKeyFrames * MATRIX_ROWS_COUNT];

            var bakedDataBuilder = BakedData.Create()
                                   .SetFrameRate(frameRate)
                                   .SetBonesCount(numberOfBones);

            var clipOffset = 0;

            for (var clipIndex = 0; clipIndex < sampledBoneMatrices.Count; clipIndex++)
            {
                var framesCount = sampledBoneMatrices[clipIndex].GetLength(0);
                for (var keyframeIndex = 0; keyframeIndex < framesCount; keyframeIndex++)
                {
                    var frameOffset = keyframeIndex * numberOfBones * MATRIX_ROWS_COUNT;
                    for (var boneIndex = 0; boneIndex < numberOfBones; boneIndex++)
                    {
                        var index  = clipOffset + frameOffset + boneIndex * MATRIX_ROWS_COUNT;
                        var matrix = sampledBoneMatrices[clipIndex][keyframeIndex, boneIndex];

                        if (buffer[index + 0] != Vector4.zero)
                        {
                            Debug.LogError($"Index {index + 0} not empty");
                        }
                        if (buffer[index + 1] != Vector4.zero)
                        {
                            Debug.LogError($"Index {index + 1} not empty");
                        }
                        if (buffer[index + 2] != Vector4.zero)
                        {
                            Debug.LogError($"Index {index + 2} not empty");
                        }

                        buffer[index + 0] = matrix.GetRow(0);
                        buffer[index + 1] = matrix.GetRow(1);
                        buffer[index + 2] = matrix.GetRow(2);
                    }
                }

                var clip  = animationClips[clipIndex];
                var start = clipOffset;

                var clipData = ClipData.Create(clip.name,
                                               clip.length,
                                               clip.wrapMode,
                                               start,
                                               framesCount);

                bakedDataBuilder.AddClip(clipData);

                clipOffset += framesCount * numberOfBones * MATRIX_ROWS_COUNT;
            }
            bakedDataBuilder.SetBuffer(buffer);

            clipOffset = 0;
            for (var clipIndex = 0; clipIndex < sampledBoneMatrices.Count; clipIndex++)
            {
                var framesCount = sampledBoneMatrices[clipIndex].GetLength(0);
                for (var keyframeIndex = 0; keyframeIndex < framesCount; keyframeIndex++)
                {
                    var frameOffset = keyframeIndex * numberOfBones * MATRIX_ROWS_COUNT;
                    for (var boneIndex = 0; boneIndex < numberOfBones; boneIndex++)
                    {
                        var index  = clipOffset + frameOffset + boneIndex * MATRIX_ROWS_COUNT;
                        var matrix = sampledBoneMatrices[clipIndex][keyframeIndex, boneIndex];

                        var data0 = buffer[index];
                        var row0  = (Color)matrix.GetRow(0);
                        index++;

                        var data1 = buffer[index];
                        var row1  = (Color)matrix.GetRow(1);
                        index++;

                        var data2 = buffer[index];
                        var row2  = (Color)matrix.GetRow(2);

                        if (!Verify(row0, data0, clipIndex, keyframeIndex, boneIndex))
                        {
                            break;
                        }
                        if (!Verify(row1, data1, clipIndex, keyframeIndex, boneIndex))
                        {
                            break;
                        }
                        if (!Verify(row2, data2, clipIndex, keyframeIndex, boneIndex))
                        {
                            break;
                        }
                    }
                }

                clipOffset += numberOfBones * framesCount * MATRIX_ROWS_COUNT;
            }

            var data = bakedDataBuilder.Build();

            go.SetActive(false);
            Object.Destroy(go);
            return(data);
        }