private static bool Verify(Vector4 row, Vector4 data, int clipIndex, int keyframeIndex, int boneIndex) { if (row != data) { Debug.LogError("Error at (" + clipIndex + ", " + keyframeIndex + ", " + boneIndex + ")" + " expected " + BakeryUtils.Format(row) + " in data array " + BakeryUtils.Format(data)); return(false); } return(true); }
private static bool Verify(Color pixel, Color row, Color color, Vector2Int index2D, int clipIndex, int keyframeIndex, int boneIndex) { if (pixel != row && row != color) { Debug.LogError("Error at (" + clipIndex + ", " + keyframeIndex + ", " + boneIndex + ")" + " expected " + BakeryUtils.Format(row) + " Texture(" + BakeryUtils.Format(index2D) + " but got " + BakeryUtils.Format(pixel) + " in color array " + BakeryUtils.Format(color)); return(false); } return(true); }
private static List <AnimationClip> GetAllAnimationClips(GameObject go) { var animator = go.GetComponent <Animator>(); if (animator != null) { return(BakeryUtils.GetAllAnimationClips(animator)); } var animation = go.GetComponent <Animation>(); if (animation != null) { return(BakeryUtils.GetAllAnimationClips(animation)); } return(new List <AnimationClip>()); }
/// <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 BakedData BakeClips(float frameRate = 30f) { OnBeginBakeClips(); var bakedDataBuilder = BakedData.Bulder(1) .SetMaterial(CreateMaterial()) .SetMesh(CreateMesh()) .SetFrameRate(frameRate); var sampledBoneMatrices = SampleAnimationClips(frameRate, out var animationClips, out var numberOfKeyFrames, out var numberOfBones); // find minimum square texture size, size should be power of 2 var size = BakeryUtils.NextPowerOfTwo( (int)Math.Sqrt(numberOfBones * numberOfKeyFrames * MATRIX_ROWS_COUNT)); var texture = new Texture2D(size, size, TextureFormat.RGBAFloat, false) { wrapMode = TextureWrapMode.Clamp, filterMode = FilterMode.Point, anisoLevel = 0 }; var textureColor = new Color[texture.width * texture.height]; bakedDataBuilder.SetTexture(0, texture); bakedDataBuilder.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 ((Vector4)textureColor[index + 0] != Vector4.zero) { Debug.LogError($"Index {index + 0} not empty"); } if ((Vector4)textureColor[index + 1] != Vector4.zero) { Debug.LogError($"Index {index + 1} not empty"); } if ((Vector4)textureColor[index + 2] != Vector4.zero) { Debug.LogError($"Index {index + 2} not empty"); } textureColor[index + 0] = matrix.GetRow(0); textureColor[index + 1] = matrix.GetRow(1); textureColor[index + 2] = matrix.GetRow(2); } } var clip = animationClips[clipIndex]; var start = clipOffset; var end = clipOffset + (framesCount - 1) * MATRIX_ROWS_COUNT; var clipData = AnimationClipData.Create(clip, start, end, framesCount); bakedDataBuilder.AddClip(clipData); clipOffset += framesCount * numberOfBones * MATRIX_ROWS_COUNT; } texture.SetPixels(textureColor); texture.Apply(false, false); 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 color0 = textureColor[index]; var index2D0 = BakeryUtils.To2D(index, texture.width); var pixel0 = texture.GetPixel(index2D0.x, index2D0.y); var row0 = (Color)matrix.GetRow(0); index++; var color1 = textureColor[index]; var index2D1 = BakeryUtils.To2D(index, texture.width); var pixel1 = texture.GetPixel(index2D1.x, index2D1.y); var row1 = (Color)matrix.GetRow(1); index++; var color2 = textureColor[index]; var index2D2 = BakeryUtils.To2D(index, texture.width); var pixel2 = texture.GetPixel(index2D2.x, index2D2.y); var row2 = (Color)matrix.GetRow(2); if (!Verify(pixel0, row0, color0, index2D0, clipIndex, keyframeIndex, boneIndex)) { break; } if (!Verify(pixel1, row1, color1, index2D1, clipIndex, keyframeIndex, boneIndex)) { break; } if (!Verify(pixel2, row2, color2, index2D2, clipIndex, keyframeIndex, boneIndex)) { break; } } } clipOffset += numberOfBones * framesCount * MATRIX_ROWS_COUNT; } var data = bakedDataBuilder.Build(); OnEndBakeClips(); return(data); }