static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {

		const animationToMorphTargets = {};

		// tested with https://regex101.com/ on trick sequences
		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
		const pattern = /^([\w-]*?)([\d]+)$/;

		// sort morph target names into animation groups based
		// patterns like Walk_001, Walk_002, Run_001, Run_002
		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {

			const morphTarget = morphTargets[ i ];
			const parts = morphTarget.name.match( pattern );

			if ( parts && parts.length > 1 ) {

				const name = parts[ 1 ];

				let animationMorphTargets = animationToMorphTargets[ name ];

				if ( ! animationMorphTargets ) {

					animationToMorphTargets[ name ] = animationMorphTargets = [];

				}

				animationMorphTargets.push( morphTarget );

			}

		}

		const clips = [];

		for ( const name in animationToMorphTargets ) {

			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );

		}

		return clips;

	}
Returns an array of new AnimationClips created from the morph target
sequences of a geometry, trying to sort morph target names into
animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".

See {@link MD2Loader#parse} as an example for how the method should be used.

@static
@param {Array<Object>} morphTargets - A sequence of morph targets.
@param {number} fps - The Frames-Per-Second value.
@param {boolean} noLoop - Whether the clip should be no loop or not.
@return {Array<AnimationClip>} An array of new animation clips.