private void LoadAnimation(GLTF.Schema.Animation gltfAnimation, int index, AnimationClip clip)
        {
            clip.name = gltfAnimation.Name != null && gltfAnimation.Name.Length > 0 ? gltfAnimation.Name : "GLTFAnimation_" + index;
            for (int i = 0; i < gltfAnimation.Channels.Count; ++i)
            {
                AnimationChannel channel = gltfAnimation.Channels[i];
                addGLTFChannelDataToClip(gltfAnimation.Channels[i], clip);
            }

            clip.EnsureQuaternionContinuity();
        }
        private GLTF.Schema.Animation SaveAnimationClip(Transform tr, AnimationClip clip, string prefix)
        {
            if (_animClip2anim.ContainsKey(clip))
            {
                return _animClip2anim[clip];
            }

            var anim = new GLTF.Schema.Animation { Name = prefix + "@" + clip.name };
            var targets = BakeAnimationClip(anim, tr, clip);
            var accessors = _animClip2Accessors[clip];
            var timeAccessorId = _animClip2TimeAccessor[clip];

            int targetId = 0;
            int accessorId = 0;
            foreach (var target in targets)
            {
                var targetTr = tr.Find(targets[targetId]);
                var targetNode = tr2node[targetTr];

                foreach (var accessor in accessors[targetId])
                {
                    var path = accessor.Key;

                    anim.Channels.Add(
                        new AnimationChannel
                        {
                            Sampler = new AnimationSamplerId { Id = accessorId },
                            Target = new AnimationChannelTarget { Path = path, Node = new NodeId { Id = root.Nodes.IndexOf(targetNode) } }
                        }
                    );

                    anim.Samplers.Add(
                        new AnimationSampler {
                            Input = timeAccessorId,
                            Output = accessor.Value,
                            Interpolation = InterpolationType.LINEAR
                        }
                    );

                    accessorId += 1;
                }

                targetId += 1;
            }

            root.Animations.Add(anim);
            _animClip2anim.Add(clip, anim);

            return anim;
        }
        private List<string> BakeAnimationClip(GLTF.Schema.Animation anim, Transform tr, AnimationClip clip)
        {
            var needGenerate = !_animClip2Accessors.ContainsKey(clip);
            Dictionary<string, Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>> curves = null;
            Dictionary<string, bool> rotationIsEuler = null;

            if (needGenerate)
            {
                curves = new Dictionary<string, Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>>();
                rotationIsEuler = new Dictionary<string, bool>();
            }

            List<string> targets = new List<string>();

            foreach (var binding in AnimationUtility.GetCurveBindings(clip))
            {
                var path = binding.path;
                var curve = AnimationUtility.GetEditorCurve(clip, binding);

                if (!curves.ContainsKey(path))
                {
                    targets.Add(path);
                    if (needGenerate)
                    {
                        curves.Add(path, new Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>());
                        rotationIsEuler.Add(path, false);
                    }
                }

                if (!needGenerate)
                {
                    continue;
                }

                var current = curves[path];
                if (binding.propertyName.Contains("m_LocalPosition"))
                {
                    if (!current.ContainsKey(GLTFAnimationChannelPath.translation))
                    {
                        current.Add(GLTFAnimationChannelPath.translation, new AnimationCurve[3]);
                    }
                    if (binding.propertyName.Contains(".x"))
                        current[GLTFAnimationChannelPath.translation][0] = curve;
                    else if (binding.propertyName.Contains(".y"))
                        current[GLTFAnimationChannelPath.translation][1] = curve;
                    else if (binding.propertyName.Contains(".z"))
                        current[GLTFAnimationChannelPath.translation][2] = curve;
                }
                else if (binding.propertyName.Contains("m_LocalScale"))
                {
                    if (!current.ContainsKey(GLTFAnimationChannelPath.scale))
                    {
                        current.Add(GLTFAnimationChannelPath.scale, new AnimationCurve[3]);
                    }
                    if (binding.propertyName.Contains(".x"))
                        current[GLTFAnimationChannelPath.scale][0] = curve;
                    else if (binding.propertyName.Contains(".y"))
                        current[GLTFAnimationChannelPath.scale][1] = curve;
                    else if (binding.propertyName.Contains(".z"))
                        current[GLTFAnimationChannelPath.scale][2] = curve;
                }
                else if (binding.propertyName.ToLower().Contains("localrotation"))
                {
                    if (!current.ContainsKey(GLTFAnimationChannelPath.rotation))
                    {
                        current.Add(GLTFAnimationChannelPath.rotation, new AnimationCurve[4]);
                    }
                    if (binding.propertyName.Contains(".x"))
                        current[GLTFAnimationChannelPath.rotation][0] = curve;
                    else if (binding.propertyName.Contains(".y"))
                        current[GLTFAnimationChannelPath.rotation][1] = curve;
                    else if (binding.propertyName.Contains(".z"))
                        current[GLTFAnimationChannelPath.rotation][2] = curve;
                    else if (binding.propertyName.Contains(".w"))
                        current[GLTFAnimationChannelPath.rotation][3] = curve;
                }
                // Takes into account 'localEuler', 'localEulerAnglesBaked' and 'localEulerAnglesRaw'
                else if (binding.propertyName.ToLower().Contains("localeuler"))
                {
                    if (!current.ContainsKey(GLTFAnimationChannelPath.rotation))
                    {
                        current.Add(GLTFAnimationChannelPath.rotation, new AnimationCurve[3]);
                        rotationIsEuler[path] = true;
                    }
                    if (binding.propertyName.Contains(".x"))
                        current[GLTFAnimationChannelPath.rotation][0] = curve;
                    else if (binding.propertyName.Contains(".y"))
                        current[GLTFAnimationChannelPath.rotation][1] = curve;
                    else if (binding.propertyName.Contains(".z"))
                        current[GLTFAnimationChannelPath.rotation][2] = curve;
                }
                //todo: weights
            }

            if (!needGenerate)
            {
                return targets;
            }

            
            var bufferView = CreateStreamBufferView("animation-" + anim.Name);
            int nbSamples = (int)(clip.length * 30);
            float deltaTime = clip.length / nbSamples;
            var accessors = new List<Dictionary<GLTFAnimationChannelPath, AccessorId>>();
            _animClip2Accessors.Add(clip, accessors);

            foreach (var path in curves.Keys)
            {
                var accessor = new Dictionary<GLTFAnimationChannelPath, AccessorId>();
                accessors.Add(accessor);
                float[] times = new float[nbSamples];
                Vector3[] translations = null;
                Vector3[] scales = null;
                Vector4[] rotations = null;
                foreach (var curve in curves[path])
                {
                    if (curve.Key == GLTFAnimationChannelPath.translation)
                    {
                        translations = new Vector3[nbSamples];
                    }
                    else if (curve.Key == GLTFAnimationChannelPath.scale)
                    {
                        scales = new Vector3[nbSamples];
                    }
                    else if (curve.Key == GLTFAnimationChannelPath.rotation)
                    {
                        rotations = new Vector4[nbSamples];
                    }
                }

                for (int i = 0; i < nbSamples; i += 1)
                {
                    var currentTime = i * deltaTime;
                    times[i] = currentTime;

                    if (translations != null)
                    {
                        var curve = curves[path][GLTFAnimationChannelPath.translation];
                        translations[i] = new Vector3(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime));
                    }

                    if (scales != null)
                    {
                        var curve = curves[path][GLTFAnimationChannelPath.scale];
                        scales[i] = new Vector3(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime));
                    }

                    if (rotations != null)
                    {
                        var curve = curves[path][GLTFAnimationChannelPath.rotation];
                        if (rotationIsEuler[path])
                        {
                            var q = Quaternion.Euler(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime));
                            rotations[i] = new Vector4(q.x, q.y, q.z, q.w);
                        } else
                        {
                            rotations[i] = new Vector4(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime), curve[3].Evaluate(currentTime));
                        }
                    }
                }

                if (!_animClip2TimeAccessor.ContainsKey(clip))
                {
                    var timeView = ExporterUtils.PackToBuffer(bufferView.streamBuffer, times, GLTFComponentType.Float);
                    _animClip2TimeAccessor.Add(clip, AccessorToId(timeView, bufferView));
                    timeView.Name += "-times";
                }

                AccessorId id = null;
                if (translations != null)
                {
                    id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, translations, GLTFComponentType.Float, (Vector3[] data, int i) => { return Utils.ConvertVector3LeftToRightHandedness(ref data[i]); }), bufferView);
                    accessor.Add(GLTFAnimationChannelPath.translation, id);
                    id.Value.Name += "-" + path + "-" + "translation";
                }

                if (scales != null)
                {
                    id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, scales, GLTFComponentType.Float), bufferView);
                    accessor.Add(GLTFAnimationChannelPath.scale, id);
                    id.Value.Name += "-" + path + "-" + "scales";
                }

                if (rotations != null)
                {
                    id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, rotations, GLTFComponentType.Float, (Vector4[] data, int i) => { return Utils.ConvertVector4LeftToRightHandedness(ref data[i]); }), bufferView);
                    accessor.Add(GLTFAnimationChannelPath.rotation, id);
                    id.Value.Name += "-" + path + "-" + "rotations";
                }
            }

            return targets;
        }
        private void _exportAnimation(UnityEngine.AnimationClip animationClip)
        {
            //
            var frameCount    = (int)Math.Floor(animationClip.length * animationClip.frameRate) + 1;
            var curveBinds    = UnityEditor.AnimationUtility.GetCurveBindings(animationClip);
            var ignoreCurves  = new List <UnityEditor.EditorCurveBinding>();
            var glTFAnimation = new GLTF.Schema.Animation()
            {
                Name       = animationClip.name,
                Channels   = new List <AnimationChannel>(),
                Samplers   = new List <AnimationSampler>(),
                Extensions = new Dictionary <string, IExtension>()
                {
                    {
                        AnimationExtensionFactory.EXTENSION_NAME,
                        new AnimationExtension()
                        {
                            frameRate = animationClip.frameRate,
                            clips     = new List <AnimationClip>()
                            {
                                new AnimationClip()
                                {
                                    name      = animationClip.name,
                                    playTimes = _getPlayTimes(animationClip),
                                    position  = 0.0f,
                                    duration  = (float)Math.Round(animationClip.length, 6),
                                }
                            }
                        }
                    },
                },
            };
            var ext = glTFAnimation.Extensions[AnimationExtensionFactory.EXTENSION_NAME] as AnimationExtension;

            this._root.Animations.Add(glTFAnimation);
            // Input.
            var inputAccessor = new Accessor();

            inputAccessor.Count         = frameCount;
            inputAccessor.Type          = GLTFAccessorAttributeType.SCALAR;
            inputAccessor.ComponentType = GLTFComponentType.Float;
            inputAccessor.BufferView    = new BufferViewId
            {
                Id   = 0,
                Root = _root
            };
            this._root.Accessors.Add(inputAccessor);

            // Write input.
            for (var i = 0; i < frameCount; ++i)
            {
                //_bufferWriter.Write(Math.Round(Math.Min(animationClip.length * i / (frameCount - 1), animationClip.length), 6)); // TODO
                _bufferWriter.Write(i / animationClip.frameRate);
            }

            var MainTex_STy = new List <float>();

            foreach (var curveBind in curveBinds)
            {
                // Curve has been parsed.
                if (ignoreCurves.Contains(curveBind))
                {
                    continue;
                }
                // No target.
                var animationTarget = _target.Find(curveBind.path);
                if (animationTarget == null)
                {
                    continue;
                }
                // Create node.
                var nodeIndex = _animationTargets.IndexOf(animationTarget);
                if (nodeIndex < 0)
                {
                    _animationTargets.Add(animationTarget);
                    nodeIndex = _root.Nodes.Count;
                    _root.Nodes.Add(new Node()
                    {
                        Name = _target == animationTarget ? "__root__" : animationTarget.name,
                    });

                    if (animationTarget.transform.parent == _target)
                    {
                        _root.Scenes[0].Nodes.Add(
                            new NodeId()
                        {
                            Id   = nodeIndex,
                            Root = _root,
                        }
                            );
                    }
                }
                // Output.
                var outputAccessor = new Accessor();
                outputAccessor.Count         = frameCount;
                outputAccessor.ComponentType = GLTFComponentType.Float;
                outputAccessor.BufferView    = inputAccessor.BufferView;
                outputAccessor.ByteOffset    = (int)_bufferWriter.BaseStream.Position;
                this._root.Accessors.Add(outputAccessor);
                //
                var animationSampler = new AnimationSampler()
                {
                    Input = new AccessorId()
                    {
                        Id   = this._root.Accessors.IndexOf(inputAccessor),
                        Root = _root,
                    },
                    Interpolation = InterpolationType.LINEAR,
                    Output        = new AccessorId()
                    {
                        Id   = this._root.Accessors.IndexOf(outputAccessor),
                        Root = _root,
                    },
                };
                glTFAnimation.Samplers.Add(animationSampler);
                //
                var animationChannel = new AnimationChannel()
                {
                    Sampler = new SamplerId()
                    {
                        Id   = glTFAnimation.Samplers.IndexOf(animationSampler),
                        Root = _root,
                    },
                    Target = new AnimationChannelTarget()
                    {
                        Node = new NodeId()
                        {
                            Id   = nodeIndex,
                            Root = _root,
                        }
                    }
                };
                glTFAnimation.Channels.Add(animationChannel);

                if (curveBind.type == typeof(Transform))
                {
                    var curveGroup = _getCurveGroup(curveBinds, curveBind);
                    ignoreCurves.AddRange(curveGroup);

                    switch (curveBind.propertyName)
                    {
                    case "m_LocalPosition.x":
                    case "m_LocalPosition.y":
                    case "m_LocalPosition.z":
                        animationChannel.Target.Path = GLTFAnimationChannelPath.translation;
                        outputAccessor.Type          = GLTFAccessorAttributeType.VEC3;

                        for (var i = 0; i < frameCount; ++i)
                        {
                            var time   = i / animationClip.frameRate;
                            var curveX = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[0]);
                            var curveY = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[1]);
                            var curveZ = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[2]);
                            var value  = curveX != null?curveX.Evaluate(time) : animationTarget.transform.localPosition.x;

                            _bufferWriter.Write(value);
                            value = curveY != null?curveY.Evaluate(time) : animationTarget.transform.localPosition.y;

                            _bufferWriter.Write(value);
                            value = curveZ != null?curveZ.Evaluate(time) : animationTarget.transform.localPosition.z;

                            _bufferWriter.Write(value);
                        }
                        break;

                    case "m_LocalRotation.x":
                    case "m_LocalRotation.y":
                    case "m_LocalRotation.z":
                    case "m_LocalRotation.w":
                        animationChannel.Target.Path = GLTFAnimationChannelPath.rotation;
                        outputAccessor.Type          = GLTFAccessorAttributeType.VEC4;

                        for (var i = 0; i < frameCount; ++i)
                        {
                            var time   = i / animationClip.frameRate;
                            var curveX = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[0]);
                            var curveY = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[1]);
                            var curveZ = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[2]);
                            var curveW = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[3]);
                            var valueX = curveX != null?curveX.Evaluate(time) : animationTarget.transform.localRotation.x;

                            var valueY = curveY != null?curveY.Evaluate(time) : animationTarget.transform.localRotation.y;

                            var valueZ = curveZ != null?curveZ.Evaluate(time) : animationTarget.transform.localRotation.z;

                            var valueW = curveW != null?curveW.Evaluate(time) : animationTarget.transform.localRotation.w;

                            _bufferWriter.Write(valueX);
                            _bufferWriter.Write(valueY);
                            _bufferWriter.Write(valueZ);
                            _bufferWriter.Write(valueW);
                        }
                        break;

                    case "localEulerAnglesRaw.x":
                    case "localEulerAnglesRaw.y":
                    case "localEulerAnglesRaw.z":
                        animationChannel.Target.Path = GLTFAnimationChannelPath.rotation;
                        outputAccessor.Type          = GLTFAccessorAttributeType.VEC4;

                        for (var i = 0; i < frameCount; ++i)
                        {
                            var time   = i / animationClip.frameRate;
                            var curveX = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[0]);
                            var curveY = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[1]);
                            var curveZ = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[2]);
                            var valueX = curveX != null?curveX.Evaluate(time) : animationTarget.transform.localEulerAngles.x;

                            var valueY = curveY != null?curveY.Evaluate(time) : animationTarget.transform.localEulerAngles.y;

                            var valueZ = curveZ != null?curveZ.Evaluate(time) : animationTarget.transform.localEulerAngles.z;

                            var quaternion = Quaternion.Euler(valueX, valueY, valueZ);

                            _bufferWriter.Write(quaternion.x);
                            _bufferWriter.Write(quaternion.y);
                            _bufferWriter.Write(quaternion.z);
                            _bufferWriter.Write(quaternion.w);
                        }
                        break;

                    case "m_LocalScale.x":
                    case "m_LocalScale.y":
                    case "m_LocalScale.z":
                        animationChannel.Target.Path = GLTFAnimationChannelPath.scale;
                        outputAccessor.Type          = GLTFAccessorAttributeType.VEC3;

                        for (var i = 0; i < frameCount; ++i)
                        {
                            var time   = i / animationClip.frameRate;
                            var curveX = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[0]);
                            var curveY = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[1]);
                            var curveZ = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveGroup[2]);
                            var value  = curveX != null?curveX.Evaluate(time) : animationTarget.transform.localScale.x;

                            _bufferWriter.Write(value);
                            value = curveY != null?curveY.Evaluate(time) : animationTarget.transform.localScale.y;

                            _bufferWriter.Write(value);
                            value = curveZ != null?curveZ.Evaluate(time) : animationTarget.transform.localScale.z;

                            _bufferWriter.Write(value);
                        }
                        break;
                    }
                }
                else
                {
                    animationChannel.Target.Path = GLTFAnimationChannelPath.custom;
                    outputAccessor.Type          = GLTFAccessorAttributeType.SCALAR;

                    var type       = "";
                    var property   = "";
                    var uri        = "";
                    var needUpdate = -1;

                    if (curveBind.type == typeof(GameObject))
                    {
                        type = "paper.GameObject";

                        switch (curveBind.propertyName)
                        {
                        case "m_IsActive":
                            property = "activeSelf";
                            animationSampler.Interpolation = InterpolationType.STEP;
                            break;
                        }

                        // for (var i = 0; i < frameCount; ++i) // TODO
                        // {
                        //     var time = animationClip.length * i / frameCountSO; // TODO
                        //     var curve = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveBind);
                        //     var value = curve.Evaluate(time);
                        //     _bufferWriter.Write(value);
                        // }
                    }
                    else if (curveBind.type == typeof(UnityEngine.MeshRenderer))
                    {
                        type       = "egret3d.MeshRenderer";
                        uri        = "materials/0/$/_uvTransform";
                        needUpdate = 1;
                        // animationSampler.Interpolation = InterpolationType.STEP;

                        switch (curveBind.propertyName)
                        {
                        case "material._MainTex_ST.z":
                            property = "0";
                            break;

                        case "material._MainTex_ST.w":
                            property = "1";
                            break;

                        case "material._MainTex_ST.x":
                            property = "2";
                            break;

                        case "material._MainTex_ST.y":
                            property = "3";
                            break;
                        }
                    }
                    else
                    {
                        Debug.Log("Unknown type and property." + curveBind.type.ToString() + curveBind.propertyName);
                    }

                    // Extensions.
                    animationChannel.Extensions = new Dictionary <string, IExtension>()
                    {
                        {
                            AnimationExtensionFactory.EXTENSION_NAME,
                            new AnimationChannelExtension()
                            {
                                type       = type,
                                property   = property,
                                uri        = uri,
                                needUpdate = needUpdate,
                            }
                        },
                    };

                    for (var i = 0; i < frameCount; ++i)
                    {
                        var curve = UnityEditor.AnimationUtility.GetEditorCurve(animationClip, curveBind);
                        if (curve != null)
                        {
                            var value = curve.Evaluate(i / animationClip.frameRate);
                            if (curveBind.propertyName == "material._MainTex_ST.w")
                            {
                                if (i < MainTex_STy.Count)
                                {
                                    _bufferWriter.Write(1.0f - value - MainTex_STy[i]);
                                }
                                else
                                {
                                    _bufferWriter.Write(value);
                                }
                            }
                            else
                            {
                                _bufferWriter.Write(value);
                                if (curveBind.propertyName == "material._MainTex_ST.y")
                                {
                                    MainTex_STy.Add(value);
                                }
                            }
                        }
                    }
                }
            }

            foreach (var evt in animationClip.events)
            {
                var glTFFrameEvent = new AnimationFrameEvent();
                glTFFrameEvent.name           = evt.functionName;
                glTFFrameEvent.position       = evt.time;
                glTFFrameEvent.intVariable    = evt.intParameter;
                glTFFrameEvent.floatVariable  = evt.floatParameter;
                glTFFrameEvent.stringVariable = evt.stringParameter;
                ext.events.Add(glTFFrameEvent);
            }

            ext.events.Sort();
        }
        private void ExportAnimation()
        {
            var player     = this._target.GetComponent <FB.PosePlus.AniPlayer>();
            var totalBones = player.bones.Count;
            var totalFrame = player.totalFrame();

            var bufSize = UnityEngine.Quaternion.identity.GetBytes().Length + UnityEngine.Vector3.zero.GetBytes().Length;
            var binarySingleFrameSize = totalBones * bufSize;

            var animation = new GLTF.Schema.Animation()
            {
                Name       = player.name,
                Extensions = new Dictionary <string, IExtension>()
            };

            var ext = new AnimationExtension();

            ext.frameRate = player.clips[0].fps;
            ext.clips     = new List <AnimationClip>();
            float position = 0;

            for (var aniIndex = 0; aniIndex < player.clips.Count; aniIndex++)
            {
                var rawClip = player.clips[aniIndex];
                var ani     = new AnimationClip();
                ani.name     = rawClip.clipName;
                ani.position = position;
                ani.duration = (rawClip.frames.Count - 1) / ext.frameRate;
                position    += rawClip.frames.Count / ext.frameRate;

                /*for (var evtIndex = 0; evtIndex < rawClip.events.Count; evtIndex++)
                 * {
                 *  var rawEvent = rawClip.events[evtIndex];
                 *  var evt = new Schema.FrameEvent();
                 *  evt.name = rawEvent.name;
                 *  evt.position = rawEvent.position;
                 *  evt.intVariable = rawEvent.intVariable;
                 *  evt.floatVariable = rawEvent.floatVariable;
                 *  evt.stringVariable = rawEvent.stringVariable;
                 *  ani.events.Add(evt);
                 * }*/
                ext.clips.Add(ani);
            }

            var bufferOffset = this._bufferWriter.BaseStream.Position;

            WriteBinary(player, totalFrame, binarySingleFrameSize);

            var bufferLength = this._bufferWriter.BaseStream.Position;

            var accessor = new Accessor();

            accessor.Count         = (int)(bufferLength / 4);
            accessor.Type          = GLTFAccessorAttributeType.SCALAR;
            accessor.ComponentType = GLTFComponentType.Float;
            accessor.BufferView    = ExportBufferView((int)0, (int)bufferLength);

            this._root.Accessors.Add(accessor);

            animation.Extensions.Add(AnimationExtensionFactory.EXTENSION_NAME, ext);

            this._root.Animations.Add(animation);
        }