{"version":3,"file":"Geometry.mjs","sources":["../../../../../src/rendering/renderers/shared/geometry/Geometry.ts"],"sourcesContent":["import EventEmitter from 'eventemitter3';\nimport { Bounds } from '../../../../scene/container/bounds/Bounds';\nimport { uid } from '../../../../utils/data/uid';\nimport { Buffer } from '../buffer/Buffer';\nimport { ensureIsBuffer } from './utils/ensureIsBuffer';\nimport { getGeometryBounds } from './utils/getGeometryBounds';\n\nimport type { TypedArray } from '../buffer/Buffer';\nimport type { Topology, VertexFormat } from './const';\n\nexport type IndexBufferArray = Uint16Array | Uint32Array;\n\n/**\n * The attribute data for a geometries attributes\n * @memberof rendering\n */\nexport interface Attribute\n{\n    /** the buffer that this attributes data belongs to */\n    buffer: Buffer;\n    /** the format of the attribute */\n    format?: VertexFormat;\n    /** the stride of the data in the buffer*/\n    stride?: number;\n    /** the offset of the attribute from the buffer, defaults to 0 */\n    offset?: number;\n    /** is this an instanced buffer? (defaults to false) */\n    instance?: boolean;\n    /** the number of elements to be rendered. If not specified, all vertices after the starting vertex will be drawn. */\n    size?: number;\n    /** the type of attribute  */\n    type?: number;\n    /**\n     * the starting vertex in the geometry to start drawing from. If not specified,\n     *  drawing will start from the first vertex.\n     */\n    start?: number;\n    /**\n     * attribute divisor for instanced rendering. Note: this is a **WebGL-only** feature, the WebGPU renderer will\n     * issue a warning if one of the attributes has divisor set.\n     */\n    divisor?: number;\n}\n\n/**\n * The attribute options used by the constructor for adding geometries attributes\n * extends {@link rendering.Attribute} but allows for the buffer to be a typed or number array\n * @memberof rendering\n */\ntype AttributeOption = Omit<Attribute, 'buffer'> & { buffer: Buffer | TypedArray | number[]}\n| Buffer | TypedArray | number[];\n\nexport type AttributeOptions = Record<string, AttributeOption>;\n\n/**\n * the interface that describes the structure of the geometry\n * @memberof rendering\n */\nexport interface GeometryDescriptor\n{\n    /** an optional label to easily identify the geometry */\n    label?: string;\n    /** the attributes that make up the geometry */\n    attributes: AttributeOptions;\n    /** optional index buffer for this geometry */\n    indexBuffer?: Buffer | TypedArray | number[];\n    /** the topology of the geometry, defaults to 'triangle-list' */\n    topology?: Topology;\n\n    instanceCount?: number;\n}\nfunction ensureIsAttribute(attribute: AttributeOption): Attribute\n{\n    if (attribute instanceof Buffer || Array.isArray(attribute) || (attribute as TypedArray).BYTES_PER_ELEMENT)\n    {\n        attribute = {\n            buffer: attribute as Buffer | TypedArray | number[],\n        };\n    }\n\n    (attribute as Attribute).buffer = ensureIsBuffer(attribute.buffer as Buffer | TypedArray | number[], false);\n\n    return attribute as Attribute;\n}\n\n/**\n * A Geometry is a low-level object that represents the structure of 2D shapes in terms of vertices and attributes.\n * It's a crucial component for rendering as it describes the shape and format of the data that will go through the shaders.\n * Essentially, a Geometry object holds the data you'd send to a GPU buffer.\n *\n * A geometry is basically made of two components:\n * <br>\n * <b>Attributes</b>: These are essentially arrays that define properties of the vertices like position, color,\n * texture coordinates, etc. They map directly to attributes in your vertex shaders.\n * <br>\n * <b>Indices</b>: An optional array that describes how the vertices are connected.\n * If not provided, vertices will be interpreted in the sequence they're given.\n * @example\n *\n * const geometry = new Geometry({\n *   attributes: {\n *     aPosition: [ // add some positions\n *       0, 0,\n *       0, 100,\n *       100, 100,\n *       100,   0,\n *     ],\n *     aUv: [ // add some uvs\n *       0, 0,\n *       0, 1,\n *       1, 1,\n *       1, 0,\n *     ]\n *   }\n * });\n * @memberof rendering\n * @class\n */\nexport class Geometry extends EventEmitter<{\n    update: Geometry,\n    destroy: Geometry,\n}>\n{\n    /** The topology of the geometry. */\n    public topology: Topology;\n    /** The unique id of the geometry. */\n    public readonly uid: number = uid('geometry');\n    /** A record of the attributes of the geometry. */\n    public readonly attributes: Record<string, Attribute>;\n    /** The buffers that the attributes use */\n    public readonly buffers: Buffer[];\n    /** The index buffer of the geometry */\n    public readonly indexBuffer: Buffer;\n\n    /**\n     * the layout key will be generated by WebGPU all geometries that have the same structure\n     * will have the same layout key. This is used to cache the pipeline layout\n     * @internal\n     * @ignore\n     */\n    public _layoutKey = 0;\n\n    /** the instance count of the geometry to draw */\n    public instanceCount = 1;\n\n    private readonly _bounds: Bounds = new Bounds();\n    private _boundsDirty = true;\n\n    /**\n     * Create a new instance of a geometry\n     * @param options - The options for the geometry.\n     */\n    constructor(options: GeometryDescriptor)\n    {\n        const { attributes, indexBuffer, topology } = options;\n\n        super();\n\n        this.attributes = attributes as Record<string, Attribute>;\n        this.buffers = [];\n\n        this.instanceCount = options.instanceCount || 1;\n\n        for (const i in attributes)\n        {\n            const attribute = attributes[i] = ensureIsAttribute(attributes[i]);\n\n            const bufferIndex = this.buffers.indexOf(attribute.buffer);\n\n            if (bufferIndex === -1)\n            {\n                this.buffers.push(attribute.buffer);\n\n                // two events here - one for a resize (new buffer change)\n                // and one for an update (existing buffer change)\n                attribute.buffer.on('update', this.onBufferUpdate, this);\n                attribute.buffer.on('change', this.onBufferUpdate, this);\n            }\n        }\n\n        if (indexBuffer)\n        {\n            this.indexBuffer = ensureIsBuffer(indexBuffer, true);\n            this.buffers.push(this.indexBuffer);\n        }\n\n        this.topology = topology || 'triangle-list';\n    }\n\n    protected onBufferUpdate(): void\n    {\n        this._boundsDirty = true;\n        this.emit('update', this);\n    }\n\n    /**\n     * Returns the requested attribute.\n     * @param id - The name of the attribute required\n     * @returns - The attribute requested.\n     */\n    public getAttribute(id: string): Attribute\n    {\n        return this.attributes[id];\n    }\n\n    /**\n     * Returns the index buffer\n     * @returns - The index buffer.\n     */\n    public getIndex(): Buffer\n    {\n        return this.indexBuffer;\n    }\n\n    /**\n     * Returns the requested buffer.\n     * @param id - The name of the buffer required.\n     * @returns - The buffer requested.\n     */\n    public getBuffer(id: string): Buffer\n    {\n        return this.getAttribute(id).buffer;\n    }\n\n    /**\n     * Used to figure out how many vertices there are in this geometry\n     * @returns the number of vertices in the geometry\n     */\n    public getSize(): number\n    {\n        for (const i in this.attributes)\n        {\n            const attribute = this.attributes[i];\n            const buffer = attribute.buffer;\n\n            // TODO use SIZE again like v7..\n            return (buffer.data as any).length / ((attribute.stride / 4) || attribute.size);\n        }\n\n        return 0;\n    }\n\n    /** Returns the bounds of the geometry. */\n    get bounds(): Bounds\n    {\n        if (!this._boundsDirty) return this._bounds;\n\n        this._boundsDirty = false;\n\n        return getGeometryBounds(this, 'aPosition', this._bounds);\n    }\n\n    /**\n     * destroys the geometry.\n     * @param destroyBuffers - destroy the buffers associated with this geometry\n     */\n    public destroy(destroyBuffers = false): void\n    {\n        this.emit('destroy', this);\n\n        this.removeAllListeners();\n\n        if (destroyBuffers)\n        {\n            this.buffers.forEach((buffer) => buffer.destroy());\n        }\n\n        (this.attributes as null) = null;\n        (this.buffers as null) = null;\n        (this.indexBuffer as null) = null;\n        (this._bounds as null) = null;\n    }\n}\n"],"names":[],"mappings":"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"}