function mergeBufferAttributes( attributes ) {

    	let TypedArray;
    	let itemSize;
    	let normalized;
    	let arrayLength = 0;

    	for ( let i = 0; i < attributes.length; ++ i ) {

    		const attribute = attributes[ i ];

    		if ( attribute.isInterleavedBufferAttribute ) {

    			console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. InterleavedBufferAttributes are not supported.' );
    			return null;

    		}

    		if ( TypedArray === undefined ) TypedArray = attribute.array.constructor;
    		if ( TypedArray !== attribute.array.constructor ) {

    			console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.' );
    			return null;

    		}

    		if ( itemSize === undefined ) itemSize = attribute.itemSize;
    		if ( itemSize !== attribute.itemSize ) {

    			console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.' );
    			return null;

    		}

    		if ( normalized === undefined ) normalized = attribute.normalized;
    		if ( normalized !== attribute.normalized ) {

    			console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.' );
    			return null;

    		}

    		arrayLength += attribute.array.length;

    	}

    	const array = new TypedArray( arrayLength );
    	let offset = 0;

    	for ( let i = 0; i < attributes.length; ++ i ) {

    		array.set( attributes[ i ].array, offset );

    		offset += attributes[ i ].array.length;

    	}

    	return new BufferAttribute( array, itemSize, normalized );

    }
@param {Array<BufferAttribute>} attributes
@return {BufferAttribute}