private List <Action <float> > LoadAnimations(Animation[] animations, List <byte[]> byteBuffers) { var animationController = new List <Action <float> >(); if (animations is null) { return(animationController); } if (byteBuffers is null) { throw new ArgumentNullException(nameof(byteBuffers)); } var accessorBuffers = new Dictionary <int, Array>(); TYPE[] GetBuffer <TYPE>(int accessorId) where TYPE : struct { if (accessorBuffers.TryGetValue(accessorId, out var buf)) { return(buf as TYPE[]); } var accessor = gltf.Accessors[accessorId]; var view = gltf.BufferViews[accessor.BufferView.Value]; var buffer = FromByteArray <TYPE>(byteBuffers[view.Buffer], view.ByteOffset + accessor.ByteOffset, accessor.Count); accessorBuffers.Add(accessorId, buffer); return(buffer); } foreach (var animation in animations) { void AddAnimationControllerTranslate(AnimationChannel channel) { var sampler = animation.Samplers[channel.Sampler]; var bufferTimes = GetBuffer <float>(sampler.Input); var bufferOutput = GetBuffer <Vector3>(sampler.Output); var controlPoints = new ControlPoints <Vector3>(bufferTimes, bufferOutput); var node = gltf.Nodes[channel.Target.Node.Value]; void Interpolator(float t) { var inter = controlPoints.FindPair(t); var interpolated = Vector3.Lerp(inter.Item1, inter.Item2, inter.Item3); node.Translation = interpolated.ToArray(); localTransforms[channel.Target.Node.Value] = CreateLocalTransform(node); } animationController.Add(Interpolator); } void AddAnimationControllerRotation(AnimationChannel channel) { var sampler = animation.Samplers[channel.Sampler]; var bufferTimes = GetBuffer <float>(sampler.Input); var bufferOutput = GetBuffer <Quaternion>(sampler.Output); var controlPoints = new ControlPoints <Quaternion>(bufferTimes, bufferOutput); var node = gltf.Nodes[channel.Target.Node.Value]; void Interpolator(float t) { var inter = controlPoints.FindPair(t); var interpolated = Quaternion.Lerp(inter.Item1, inter.Item2, inter.Item3); node.Rotation = interpolated.ToArray(); localTransforms[channel.Target.Node.Value] = CreateLocalTransform(node); } animationController.Add(Interpolator); } void AddAnimationControllerScale(AnimationChannel channel) { var sampler = animation.Samplers[channel.Sampler]; var bufferTimes = GetBuffer <float>(sampler.Input); var node = gltf.Nodes[channel.Target.Node.Value]; var bufferOutput = GetBuffer <Vector3>(sampler.Output); var controlPoints = new ControlPoints <Vector3>(bufferTimes, bufferOutput); void Interpolator(float t) { var inter = controlPoints.FindPair(t); var interpolated = Vector3.Lerp(inter.Item1, inter.Item2, inter.Item3); node.Scale = interpolated.ToArray(); localTransforms[channel.Target.Node.Value] = CreateLocalTransform(node); } animationController.Add(Interpolator); } foreach (var channel in animation.Channels) { if (!channel.Target.Node.HasValue) { continue; } switch (channel.Target.Path) { case AnimationChannelTarget.PathEnum.rotation: AddAnimationControllerRotation(channel); break; case AnimationChannelTarget.PathEnum.translation: AddAnimationControllerTranslate(channel); break; case AnimationChannelTarget.PathEnum.scale: AddAnimationControllerScale(channel); break; default: break; } } } return(animationController); }