<!-- NEW4 — TEST 4 · THE QUILT · part 97 -->
ertex
 * positions, face indices, normals, colors, UVs, and custom attributes
 * within buffers, reducing the cost of passing all this data to the GPU.
 *
 * ```js
 * const geometry = new THREE.BufferGeometry();
 * // create a simple square shape. We duplicate the top left and bottom right
 * // vertices because each vertex needs to appear once per triangle.
 * const vertices = new Float32Array( [
 * 	-1.0, -1.0,  1.0, // v0
 * 	 1.0, -1.0,  1.0, // v1
 * 	 1.0,  1.0,  1.0, // v2
 *
 * 	 1.0,  1.0,  1.0, // v3
 * 	-1.0,  1.0,  1.0, // v4
 * 	-1.0, -1.0,  1.0  // v5
 * ] );
 * // itemSize = 3 because there are 3 values (components) per vertex
 * geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
 * const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
 * const mesh = new THREE.Mesh( geometry, material );
 * ```
 *
 * @augments EventDispatcher
 */
class BufferGeometry extends EventDispatcher {

	/**
	 * Constructs a new geometry.
	 */
	constructor() {

		super();

		/**
		 * This flag can be used for type testing.
		 *
		 * @type {boolean}
		 * @readonly
		 * @default true
		 */
		this.isBufferGeometry = true;

		/**
		 * The ID of the geometry.
		 *
		 * @name BufferGeometry#id
		 * @type {number}
		 * @readonly
		 */
		Object.defineProperty( this, 'id', { value: _id$1 ++ } );

		/**
		 * The UUID of the geometry.
		 *
		 * @type {string}
		 * @readonly
		 */
		this.uuid = generateUUID();

		/**
		 * The name of the geometry.
		 *
		 * @type {string}
		 */
		this.name = '';
		this.type = 'BufferGeometry';

		/**
		 * Allows for vertices to be re-used across multiple triangles; this is
		 * called using "indexed triangles". Each triangle is associated with the
		 * indices of three vertices. This attribute therefore stores the index of
		 * each vertex for each triangular face. If this attribute is not set, the
		 * renderer assumes that each three contiguous positions represent a single triangle.
		 *
		 * @type {?BufferAttribute}
		 * @default null
		 */
		this.index = null;

		/**
		 * A (storage) buffer attribute which was generated with a compute shader and
		 * now defines indirect draw calls.
		 *
		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
		 *
		 * @type {?BufferAttribute}
		 * @default null
		 */
		this.indirect = null;

		/**
		 * The offset, in bytes, into the indirect drawing buffer where the value data begins. If an array is provided, multiple indirect draw calls will be made for each offset.
		 *
		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
		 *
		 * @type {number|Array<number>}
		 * @default 0
		 */
		this.indirectOffset = 0;

		/**
		 * This dictionary has as id the name of the attribute to be set and as value
		 * the buffer attribute to set it to. Rather than accessing this property directly,
		 * use `setAttribute()` and `getAttribute()` to access attributes of this geometry.
		 *
		 * @type {Object<string,(BufferAttribute|InterleavedBufferAttribute)>}
		 */
		this.attributes = {};

		/**
		 * This dictionary holds the morph targets of the geometry.
		 *
		 * Note: Once the geometry has been rendered, the morph attribute data cannot
		 * be changed. You will have to call `dispose()`, and create a new geometry instance.
		 *
		 * @type {Object}
		 */
		this.morphAttributes = {};

		/**
		 * Used to control the morph target behavior; when set to `true`, the morph
		 * target data is treated as relative offsets, rather than as absolute
		 * positions/normals.
		 *
		 * @type {boolean}
		 * @default false
		 */
		this.morphTargetsRelative = false;

		/**
		 * Split the geometry into groups, each of which will be rendered in a
		 * separate draw call. This allows an array of materials to be used with the geometry.
		 *
		 * Use `addGroup()` and `clearGroups()` to edit groups, rather than modifying this array directly.
		 *
		 * Every vertex and index must belong to exactly one group — groups must not share vertices or
		 * indices, and must not leave vertices or indices unused.
		 *
		 * @type {Array<Object>}
		 */
		this.groups = [];

		/**
		 * Bounding box for the geometry which can be calculated with `computeBoundingBox()`.
		 *
		 * @type {?Box3}
		 * @default null
		 */
		this.boundingBox = null;

		/**
		 * Bounding sphere for the geometry which can be calculated with `computeBoundingSphere()`.
		 *
		 * @type {?Sphere}
		 * @default null
		 */
		this.boundingSphere = null;

		/**
		 * Determines the part of the geometry to render. This should not be set directly,
		 * instead use `setDrawRange()`.
		 *
		 * @type {{start:number,count:number}}
		 */
		this.drawRange = { start: 0, count: Infinity };

		/**
		 * An object that can be used to store custom data about the geometry.
		 * It should not hold references to functions as these will not be cloned.
		 *
		 * @type {Object}
		 */
		this.userData = {};

		/**
		 * `true` when the geometry has