public static AnimationWithSampleCurves Export(AnimationClip clip, Transform root, List <Transform> nodes) { var animation = new AnimationWithSampleCurves { Animation = new glTFAnimation(), }; List <AnimationCurveData> curveDatas = new List <AnimationCurveData>(); foreach (var binding in AnimationUtility.GetCurveBindings(clip)) { var curve = AnimationUtility.GetEditorCurve(clip, binding); var property = AnimationExporter.PropertyToTarget(binding.propertyName); if (property == glTFAnimationTarget.AnimationPropertys.NotImplemented || property == glTFAnimationTarget.AnimationPropertys.BlendShape) { Debug.LogWarning("Not Implemented keyframe property : " + binding.propertyName); continue; } if (property == glTFAnimationTarget.AnimationPropertys.EulerRotation) { Debug.LogWarning("Interpolation setting of AnimationClip should be Quaternion"); continue; } var nodeIndex = GetNodeIndex(root, nodes, binding.path); var samplerIndex = animation.Animation.AddChannelAndGetSampler(nodeIndex, property); // 同一のsamplerIndexが割り当てられているcurveDataがある場合はそれを使用し、無ければ作る var curveData = curveDatas.FirstOrDefault(x => x.SamplerIndex == samplerIndex); if (curveData == null) { curveData = new AnimationCurveData(AnimationUtility.GetKeyRightTangentMode(curve, 0), property, samplerIndex); curveDatas.Add(curveData); } // 全てのキーフレームを回収 var elementOffset = AnimationExporter.GetElementOffset(binding.propertyName); for (int i = 0; i < curve.keys.Length; i++) { curveData.SetKeyframeData(curve.keys[i].time, curve.keys[i].value, elementOffset); } } //キー挿入 foreach (var curve in curveDatas) { if (curve.Keyframes.Count == 0) { continue; } curve.RecountEmptyKeyframe(); var elementNum = curve.Keyframes.First().MValues.Length; var values = default(InputOutputValues); if (!animation.SamplerMap.TryGetValue(curve.SamplerIndex, out values)) { values = new InputOutputValues(); values.Input = new float[curve.Keyframes.Count]; values.Output = new float[curve.Keyframes.Count * elementNum]; animation.SamplerMap[curve.SamplerIndex] = values; animation.Animation.samplers[curve.SamplerIndex].interpolation = curve.GetInterpolation(); } int keyframeIndex = 0; foreach (var keyframe in curve.Keyframes) { values.Input[keyframeIndex] = keyframe.Time; Buffer.BlockCopy(keyframe.GetRightHandCoordinate(), 0, values.Output, keyframeIndex * elementNum * sizeof(float), elementNum * sizeof(float)); keyframeIndex++; } } return(animation); }
public static AnimationWithSampleCurves Export(AnimationClip clip, Transform root, List <Transform> nodes) { var animation = new AnimationWithSampleCurves { Animation = new glTFAnimation(), }; List <AnimationCurveData> curveDatum = new List <AnimationCurveData>(); foreach (var binding in AnimationUtility.GetCurveBindings(clip)) { var curve = AnimationUtility.GetEditorCurve(clip, binding); if (!curve.keys.Any()) { throw new Exception("There is no keyframe in AnimationCurve : " + clip.name); } var property = AnimationExporter.PropertyToTarget(binding.propertyName); if (property == glTFAnimationTarget.AnimationProperties.NotImplemented) { Debug.LogWarning("Not Implemented keyframe property : " + binding.propertyName); continue; } if (property == glTFAnimationTarget.AnimationProperties.EulerRotation) { Debug.LogWarning("Interpolation setting of AnimationClip should be Quaternion"); continue; } var nodeIndex = GetNodeIndex(root, nodes, binding.path); var samplerIndex = animation.Animation.AddChannelAndGetSampler(nodeIndex, property); var elementCount = 0; if (property == glTFAnimationTarget.AnimationProperties.BlendShape) { var mesh = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh; elementCount = mesh.blendShapeCount; } else { elementCount = glTFAnimationTarget.GetElementCount(property); } // 同一のsamplerIndexが割り当てられているcurveDataがある場合はそれを使用し、無ければ作る var curveData = curveDatum.FirstOrDefault(x => x.SamplerIndex == samplerIndex); if (curveData == null) { curveData = new AnimationCurveData(AnimationUtility.GetKeyRightTangentMode(curve, 0), property, samplerIndex, elementCount); curveDatum.Add(curveData); } // 全てのキーフレームを回収 int elementOffset = 0; float valueFactor = 1.0f; if (property == glTFAnimationTarget.AnimationProperties.BlendShape) { var mesh = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh; var blendShapeName = binding.propertyName.Replace("blendShape.", ""); elementOffset = mesh.GetBlendShapeIndex(blendShapeName); valueFactor = 0.01f; } else { elementOffset = AnimationExporter.GetElementOffset(binding.propertyName); } if (elementOffset >= 0 && elementOffset < elementCount) { for (int i = 0; i < curve.keys.Length; i++) { curveData.SetKeyframeData(curve.keys[i].time, curve.keys[i].value * valueFactor, elementOffset); } } } //キー挿入 foreach (var curve in curveDatum) { if (curve.Keyframes.Count == 0) { continue; } curve.RecountEmptyKeyframe(); var elementNum = curve.Keyframes.First().Values.Length; var values = default(InputOutputValues); if (!animation.SamplerMap.TryGetValue(curve.SamplerIndex, out values)) { values = new InputOutputValues(); values.Input = new float[curve.Keyframes.Count]; values.Output = new float[curve.Keyframes.Count * elementNum]; animation.SamplerMap[curve.SamplerIndex] = values; animation.Animation.samplers[curve.SamplerIndex].interpolation = curve.GetInterpolation(); } int keyframeIndex = 0; foreach (var keyframe in curve.Keyframes) { values.Input[keyframeIndex] = keyframe.Time; Buffer.BlockCopy(keyframe.GetRightHandCoordinate(), 0, values.Output, keyframeIndex * elementNum * sizeof(float), elementNum * sizeof(float)); keyframeIndex++; } } return(animation); }