"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module WebGL
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PolylineBuffers = exports.ScreenPointsGeometry = exports.VolumeClassifierGeometry = exports.BoundaryType = exports.SingleTexturedViewportQuadGeometry = exports.Combine3TexturesGeometry = exports.CombineTexturesGeometry = exports.CopyPickBufferGeometry = exports.CompositeGeometry = exports.EVSMGeometry = exports.EDLMixGeometry = exports.EDLFilterGeometry = exports.EDLCalcFullGeometry = exports.EDLCalcBasicGeometry = exports.BlurGeometry = exports.BlurType = exports.AmbientOcclusionGeometry = exports.SkySphereViewportQuadGeometry = exports.TexturedViewportQuadGeometry = exports.ViewportQuadGeometry = exports.SkyBoxQuadsGeometry = exports.SkyBoxGeometryParams = exports.IndexedGeometry = exports.IndexedGeometryParams = exports.LUTGeometry = exports.CachedGeometry = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const FlashSettings_1 = require("../../../FlashSettings");
const RenderMemory_1 = require("../../../render/RenderMemory");
const AttributeMap_1 = require("./AttributeMap");
const LineCode_1 = require("./LineCode");
const FrustumUniforms_1 = require("./FrustumUniforms");
const GL_1 = require("./GL");
const AttributeBuffers_1 = require("./AttributeBuffers");
const System_1 = require("./System");
const TechniqueId_1 = require("./TechniqueId");
const Texture_1 = require("./Texture");
const scratchVec3a = new core_geometry_1.Vector3d();
const scratchVec3b = new core_geometry_1.Vector3d();
const scratchVec3c = new core_geometry_1.Vector3d();
const scratchPoint3a = new core_geometry_1.Point3d();
const scratchPoint3b = new core_geometry_1.Point3d();
const scratchPoint3c = new core_geometry_1.Point3d();
const scratchPoint3d = new core_geometry_1.Point3d();
/** Represents a geometric primitive ready to be submitted to the GPU for rendering.
 * @internal
 */
class CachedGeometry {
    _range;
    /**
     * Functions for obtaining a subclass of CachedGeometry.
     * IMPORTANT: Do NOT use code like `const surface = cachedGeom as SurfaceGeometry`.
     * Instanced geometry holds a reference to the shared geometry rendered for each instance - such casts will fail,
     * while the casting `functions` will forward to the shared geometry.
     */
    get asLUT() { return undefined; }
    get asSurface() { return undefined; }
    get asMesh() { return undefined; }
    get asEdge() { return undefined; }
    get asIndexedEdge() { return undefined; }
    get asRealityMesh() { return undefined; }
    get asSilhouette() { return undefined; }
    get asInstanced() { return undefined; }
    get isInstanced() { return undefined !== this.asInstanced; }
    get asPointCloud() { return undefined; }
    get asPlanarGrid() { return undefined; }
    get alwaysRenderTranslucent() { return false; }
    get allowColorOverride() { return true; }
    // Returns the edge/line weight used to render this geometry
    _getLineWeight(_params) { return 0; }
    // Returns the edge/line pattern used to render this geometry
    _getLineCode(_params) { return LineCode_1.LineCode.solid; }
    // Returns true if this is a lit surface
    get isLitSurface() { return false; }
    // Returns true if this is an unlit surface with baked-in lighting (e.g. 3mx, scalable mesh reality models)
    get hasBakedLighting() { return false; }
    // Returns true if this primitive contains auxillary animation data.
    get hasAnimation() { return false; }
    /** If false, the geometry's positions are not quantized.
     * qOrigin and qScale can still be used to derive the geometry's range, but will not be passed to the shader.
     * see VertexLUT.usesQuantizedPositions.
     */
    get usesQuantizedPositions() { return true; }
    // Intended to be overridden by specific subclasses
    get materialInfo() { return undefined; }
    get hasMaterialAtlas() {
        const mat = this.materialInfo;
        return undefined !== mat && mat.isAtlas;
    }
    get polylineBuffers() { return undefined; }
    get hasFeatures() { return false; }
    get viewIndependentOrigin() { return undefined; }
    get isViewIndependent() { return undefined !== this.viewIndependentOrigin; }
    get supportsThematicDisplay() { return false; }
    get hasCumulativeDistances() { return false; }
    get isEdge() {
        switch (this.renderOrder) {
            case 6 /* RenderOrder.Edge */:
            case 7 /* RenderOrder.Silhouette */:
            case 14 /* RenderOrder.PlanarEdge */:
            case 15 /* RenderOrder.PlanarSilhouette */:
                return true;
            default:
                return false;
        }
    }
    wantWoWReversal(params) {
        return params.target.currentViewFlags.whiteOnWhiteReversal && this._wantWoWReversal(params.target);
    }
    getLineCode(params) {
        return params.target.currentViewFlags.styles ? this._getLineCode(params) : LineCode_1.LineCode.solid;
    }
    getLineWeight(params) {
        if (!params.target.currentViewFlags.weights) {
            return 1.0;
        }
        const minWeight = 1;
        let weight = this._getLineWeight(params);
        weight = Math.max(weight, minWeight);
        weight = Math.min(weight, 31.0);
        return weight;
    }
    getFlashMode(params) {
        // By default only surfaces rendered with lighting get brightened. Overridden for reality meshes since they have lighting baked-in.
        // NB: If the reality model is classified, the classifiers are drawn without lighting, therefore we mix the hilite color.
        if (this.hasBakedLighting)
            return FlashSettings_1.FlashMode.Hilite;
        const vf = params.target.currentViewFlags;
        if (!this.isLitSurface || core_common_1.RenderMode.SmoothShade !== vf.renderMode)
            return FlashSettings_1.FlashMode.Hilite;
        return vf.lighting ? params.target.plan.flashSettings.litMode : FlashSettings_1.FlashMode.Hilite;
    }
    wantMixMonochromeColor(_target) { return false; }
    wantMonochrome(_target) { return true; }
    computeRange(output) {
        if (undefined === this._range) {
            const lowX = this.qOrigin[0];
            const lowY = this.qOrigin[1];
            const lowZ = this.qOrigin[2];
            const hiX = 0xffff * this.qScale[0] + lowX;
            const hiY = 0xffff * this.qScale[1] + lowY;
            const hiZ = 0xffff * this.qScale[2] + lowZ;
            this._range = core_geometry_1.Range3d.createXYZXYZ(lowX, lowY, lowZ, hiX, hiY, hiZ);
        }
        return this._range.clone(output);
    }
}
exports.CachedGeometry = CachedGeometry;
/** Geometry which is drawn using indices into a look-up texture of vertex data, via gl.drawArrays()
 * @internal
 */
class LUTGeometry extends CachedGeometry {
    _viewIndependentOrigin;
    get asLUT() { return this; }
    get viewIndependentOrigin() { return this._viewIndependentOrigin; }
    draw() { this._draw(0); }
    drawInstanced(numInstances, instanceBuffersContainer) { this._draw(numInstances, instanceBuffersContainer); }
    // Override this if your color varies based on the target
    getColor(_target) { return this.lut.colorInfo; }
    get usesQuantizedPositions() { return this.lut.usesQuantizedPositions; }
    get qOrigin() { return this.lut.qOrigin; }
    get qScale() { return this.lut.qScale; }
    get hasAnimation() { return this.lut.hasAnimation; }
    constructor(viewIndependentOrigin) {
        super();
        this._viewIndependentOrigin = viewIndependentOrigin;
    }
}
exports.LUTGeometry = LUTGeometry;
/** Parameters used to construct an IndexedGeometry
 * @internal
 */
class IndexedGeometryParams {
    buffers;
    positions;
    indices;
    numIndices;
    constructor(positions, indices, numIndices) {
        this.buffers = AttributeBuffers_1.BuffersContainer.create();
        const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", undefined, false);
        (0, core_bentley_1.assert)(attrPos !== undefined);
        this.buffers.addBuffer(positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
        this.buffers.addBuffer(indices, []);
        this.positions = positions;
        this.indices = indices;
        this.numIndices = numIndices;
    }
    static create(positions, qParams, indices) {
        const posBuf = AttributeBuffers_1.QBufferHandle3d.create(qParams, positions);
        const indBuf = AttributeBuffers_1.BufferHandle.createBuffer(GL_1.GL.Buffer.Target.ElementArrayBuffer, indices);
        if (undefined === posBuf || undefined === indBuf)
            return undefined;
        return new IndexedGeometryParams(posBuf, indBuf, indices.length);
    }
    static createFromList(positions, indices) {
        return IndexedGeometryParams.create(positions.toTypedArray(), positions.params, indices);
    }
    get isDisposed() {
        return this.buffers.isDisposed
            && this.positions.isDisposed
            && this.indices.isDisposed;
    }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this.buffers);
        (0, core_bentley_1.dispose)(this.positions);
        (0, core_bentley_1.dispose)(this.indices);
    }
}
exports.IndexedGeometryParams = IndexedGeometryParams;
/** A geometric primitive which is rendered using gl.drawElements() with one or more vertex buffers indexed by an index buffer.
 * @internal
 */
class IndexedGeometry extends CachedGeometry {
    _params;
    _wantWoWReversal(_target) { return false; }
    constructor(params) {
        super();
        this._params = params;
    }
    get isDisposed() { return this._params.isDisposed; }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this._params);
    }
    draw() {
        this._params.buffers.bind();
        System_1.System.instance.context.drawElements(GL_1.GL.PrimitiveType.Triangles, this._params.numIndices, GL_1.GL.DataType.UnsignedInt, 0);
        this._params.buffers.unbind();
    }
    get qOrigin() { return this._params.positions.origin; }
    get qScale() { return this._params.positions.scale; }
}
exports.IndexedGeometry = IndexedGeometry;
/** a cube of quads in normalized device coordinates for skybox rendering techniques
 * @internal
 */
class SkyBoxQuads {
    vertices;
    vertexParams;
    constructor() {
        const skyBoxSz = 1.0;
        const qVerts = new core_common_1.QPoint3dList(core_common_1.QParams3d.fromNormalizedRange());
        // NB: After applying the rotation matrix in the shader, Back becomes (Bottom), etc.
        // See the notes in the parens below.
        // ###TODO: Make this indexed.  Currently not indexed because of previous six-sided texture system.
        // Back (Bottom after rotation)
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
        // Front (Top after rotation)
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
        // Top (Front after rotation)
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
        // Bottom (Back after rotation)
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
        // Left (Right after rotation)
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6
        qVerts.add(new core_geometry_1.Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2
        // Right (Left after rotation)
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7
        qVerts.add(new core_geometry_1.Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3
        this.vertices = qVerts.toTypedArray();
        this.vertexParams = qVerts.params;
    }
    createParams() {
        return SkyBoxGeometryParams.create(this.vertices, this.vertexParams);
    }
}
/** Parameters used to construct an SkyBox
 * @internal
 */
class SkyBoxGeometryParams {
    buffers;
    positions;
    constructor(positions) {
        this.buffers = AttributeBuffers_1.BuffersContainer.create();
        const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", undefined, false);
        (0, core_bentley_1.assert)(attrPos !== undefined);
        this.buffers.addBuffer(positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
        this.positions = positions;
    }
    static create(positions, qparams) {
        const posBuf = AttributeBuffers_1.QBufferHandle3d.create(qparams, positions);
        if (undefined === posBuf)
            return undefined;
        return new SkyBoxGeometryParams(posBuf);
    }
    get isDisposed() { return this.buffers.isDisposed && this.positions.isDisposed; }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this.buffers);
        (0, core_bentley_1.dispose)(this.positions);
    }
}
exports.SkyBoxGeometryParams = SkyBoxGeometryParams;
/** @internal */
(function (SkyBoxQuads) {
    let skyBoxQuads;
    function getInstance() {
        if (undefined === skyBoxQuads)
            skyBoxQuads = new SkyBoxQuads();
        return skyBoxQuads;
    }
    SkyBoxQuads.getInstance = getInstance;
})(SkyBoxQuads || (SkyBoxQuads = {}));
/** Geometry used for view-space rendering techniques.
 * @internal
 */
class SkyBoxQuadsGeometry extends CachedGeometry {
    _techniqueId;
    cube;
    _params;
    constructor(ndxGeomParams, texture) {
        super();
        this.cube = texture;
        this._techniqueId = 23 /* TechniqueId.SkyBox */;
        this._params = ndxGeomParams;
    }
    static create(texture) {
        const sbxGeomParams = SkyBoxQuads.getInstance().createParams();
        return undefined !== sbxGeomParams ? new SkyBoxQuadsGeometry(sbxGeomParams, texture) : undefined;
    }
    collectStatistics(_stats) {
        // Not interested in tracking this.
    }
    get techniqueId() { return this._techniqueId; }
    getPass() { return "skybox"; }
    get renderOrder() { return 3 /* RenderOrder.UnlitSurface */; }
    draw() {
        this._params.buffers.bind();
        System_1.System.instance.context.drawArrays(GL_1.GL.PrimitiveType.Triangles, 0, 36);
        this._params.buffers.unbind();
    }
    get qOrigin() { return this._params.positions.origin; }
    get qScale() { return this._params.positions.scale; }
    get isDisposed() { return this._params.isDisposed; }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this._params);
    }
    _wantWoWReversal(_target) { return false; }
}
exports.SkyBoxQuadsGeometry = SkyBoxQuadsGeometry;
/** A quad with its corners mapped to the dimensions as the viewport, used for special rendering techniques.
 * @internal
 */
class ViewportQuad {
    vertices;
    vertexParams;
    indices = new Uint32Array(6);
    constructor() {
        const pt = new core_geometry_1.Point3d(-1, -1, 0);
        const vertices = new core_common_1.QPoint3dList(core_common_1.QParams3d.fromNormalizedRange());
        vertices.add(pt);
        pt.x = 1;
        vertices.add(pt);
        pt.y = 1;
        vertices.add(pt);
        pt.x = -1;
        vertices.add(pt);
        this.vertices = vertices.toTypedArray();
        this.vertexParams = vertices.params;
        this.indices[0] = 0;
        this.indices[1] = 1;
        this.indices[2] = 2;
        this.indices[3] = 0;
        this.indices[4] = 2;
        this.indices[5] = 3;
    }
    createParams() {
        return IndexedGeometryParams.create(this.vertices, this.vertexParams, this.indices);
    }
}
/** @internal */
(function (ViewportQuad) {
    let viewportQuad;
    function getInstance() {
        if (undefined === viewportQuad)
            viewportQuad = new ViewportQuad();
        return viewportQuad;
    }
    ViewportQuad.getInstance = getInstance;
})(ViewportQuad || (ViewportQuad = {}));
/** Geometry used for view-space rendering techniques.
 * @internal
 */
class ViewportQuadGeometry extends IndexedGeometry {
    _techniqueId;
    constructor(params, techniqueId) {
        super(params);
        this._techniqueId = techniqueId;
    }
    static create(techniqueId) {
        const params = ViewportQuad.getInstance().createParams();
        return undefined !== params ? new this(params, techniqueId) : undefined;
    }
    get techniqueId() { return this._techniqueId; }
    getPass() { return "opaque"; }
    get renderOrder() { return 3 /* RenderOrder.UnlitSurface */; }
    collectStatistics(_stats) {
        // NB: These don't really count...
    }
}
exports.ViewportQuadGeometry = ViewportQuadGeometry;
/** Geometry used for view-space rendering techniques which involve sampling one or more textures.
 * @internal
 */
class TexturedViewportQuadGeometry extends ViewportQuadGeometry {
    _textures;
    constructor(params, techniqueId, textures) {
        super(params, techniqueId);
        this._textures = textures;
        // TypeScript compiler will happily accept TextureHandle (or any other type) in place of WebGLTexture.
        // There is no such 'type' as WebGLTexture at run-time.
        (0, core_bentley_1.assert)(this._textures.every((tx) => !(tx instanceof Texture_1.TextureHandle)));
    }
    static createTexturedViewportQuadGeometry(techniqueId, textures) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new this(params, techniqueId, textures);
    }
}
exports.TexturedViewportQuadGeometry = TexturedViewportQuadGeometry;
/** Geometry used for rendering default gradient-style or single texture spherical skybox.
 * @internal
 */
class SkySphereViewportQuadGeometry extends ViewportQuadGeometry {
    worldPos; // LeftBottom, RightBottom, RightTop, LeftTop worl pos of frustum at mid depth.
    typeAndExponents; // [0] -1.0 for 2-color gradient, 1.0 for 4-color gradient, 0.0 for texture; [1] sky exponent (4-color only) [2] ground exponent (4-color only)
    zOffset;
    rotation;
    zenithColor;
    skyColor;
    groundColor;
    nadirColor;
    skyTexture;
    _worldPosBuff;
    _isWorldPosSet = false;
    initWorldPos(target) {
        if (this._isWorldPosSet)
            return;
        this._isWorldPosSet = true;
        this._setPointsFromFrustum(target);
        this._worldPosBuff.bindData(this.worldPos, GL_1.GL.Buffer.Usage.StreamDraw);
        const attrWorldPos = AttributeMap_1.AttributeMap.findAttribute("a_worldPos", 24 /* TechniqueId.SkySphereGradient */, false);
        (0, core_bentley_1.assert)(attrWorldPos !== undefined);
        this._params.buffers.addBuffer(this._worldPosBuff, [AttributeBuffers_1.BufferParameters.create(attrWorldPos.location, 3, GL_1.GL.DataType.Float, false, 0, 0, false)]);
    }
    _setPointsFromFrustum(target) {
        const frustum = target.planFrustum;
        const wp = this.worldPos;
        const lb = frustum.getCorner(core_common_1.Npc.LeftBottomRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.LeftBottomFront), scratchPoint3a);
        const rb = frustum.getCorner(core_common_1.Npc.RightBottomRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.RightBottomFront), scratchPoint3b);
        const rt = frustum.getCorner(core_common_1.Npc.RightTopRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.RightTopFront), scratchPoint3c);
        if (!target.plan.backgroundMapOn || !target.plan.isGlobeMode3D) {
            wp[0] = lb.x;
            wp[1] = lb.y;
            wp[2] = lb.z;
            wp[3] = rb.x;
            wp[4] = rb.y;
            wp[5] = rb.z;
            wp[6] = rt.x;
            wp[7] = rt.y;
            wp[8] = rt.z;
            const lt = frustum.getCorner(core_common_1.Npc.LeftTopRear).interpolate(0.5, frustum.getCorner(core_common_1.Npc.LeftTopFront), scratchPoint3d);
            wp[9] = lt.x;
            wp[10] = lt.y;
            wp[11] = lt.z;
        }
        else {
            // Need to fake a different frustum to orient the 4 corners properly.
            // First find true frustum center & size.
            const fCenter = lb.interpolate(0.5, rt, scratchPoint3d);
            const upScreen = core_geometry_1.Vector3d.createStartEnd(rb, rt, scratchVec3a);
            let rightScreen = core_geometry_1.Vector3d.createStartEnd(lb, rb, scratchVec3b);
            const halfWidth = upScreen.magnitude() * 0.5;
            const halfHeight = rightScreen.magnitude() * 0.5;
            // Find the projection of the globe up onto the frustum plane.
            upScreen.normalizeInPlace();
            rightScreen.normalizeInPlace();
            const projUp = target.plan.upVector.dotProduct(upScreen);
            const projRt = target.plan.upVector.dotProduct(rightScreen);
            // Find camera position (create one for ortho).
            let camPos;
            if (2 /* FrustumUniformType.Perspective */ === target.uniforms.frustum.type) {
                const farLowerLeft = frustum.getCorner(core_common_1.Npc.LeftBottomRear);
                const nearLowerLeft = frustum.getCorner(core_common_1.Npc.LeftBottomFront);
                const scale = 1.0 / (1.0 - target.planFraction);
                const zVec = core_geometry_1.Vector3d.createStartEnd(farLowerLeft, nearLowerLeft, scratchVec3c);
                camPos = (0, FrustumUniforms_1.fromSumOf)(farLowerLeft, zVec, scale, scratchPoint3a);
            }
            else {
                const delta = core_geometry_1.Vector3d.createStartEnd(frustum.getCorner(core_common_1.Npc.LeftBottomRear), frustum.getCorner(core_common_1.Npc.LeftBottomFront), scratchVec3c);
                const pseudoCameraHalfAngle = 22.5;
                const diagonal = frustum.getCorner(core_common_1.Npc.LeftBottomRear).distance(frustum.getCorner(core_common_1.Npc.RightTopRear));
                const focalLength = diagonal / (2 * Math.atan(pseudoCameraHalfAngle * core_geometry_1.Angle.radiansPerDegree));
                let zScale = focalLength / delta.magnitude();
                if (zScale < 1.000001)
                    zScale = 1.000001; // prevent worldEye front being on or inside the frustum front plane
                camPos = core_geometry_1.Point3d.createAdd3Scaled(frustum.getCorner(core_common_1.Npc.LeftBottomRear), .5, frustum.getCorner(core_common_1.Npc.RightTopRear), .5, delta, zScale, scratchPoint3a);
            }
            // Compute the distance from the camera to the frustum center.
            const camDist = camPos.distance(fCenter);
            // Now use a fixed camera direction and compute a new frustum center.
            const camDir = core_geometry_1.Vector3d.create(0.0, 1.0, 0.0, scratchVec3c);
            fCenter.setFromPoint3d(camPos);
            fCenter.addScaledInPlace(camDir, camDist);
            // Create an up vector that mimics the projection of the globl up onto the real frustum.
            upScreen.set(projRt, 0.0, projUp);
            upScreen.normalizeInPlace();
            // Compute a new right vector and then compute the 4 points for the sky.
            rightScreen = upScreen.crossProduct(camDir, scratchVec3b);
            upScreen.scaleInPlace(halfHeight);
            rightScreen.scaleInPlace(halfWidth);
            wp[0] = fCenter.x - rightScreen.x - upScreen.x; // left bottom
            wp[1] = fCenter.y - rightScreen.y - upScreen.y;
            wp[2] = fCenter.z - rightScreen.z - upScreen.z;
            wp[3] = fCenter.x + rightScreen.x - upScreen.x; // right bottom
            wp[4] = fCenter.y + rightScreen.y - upScreen.y;
            wp[5] = fCenter.z + rightScreen.z - upScreen.z;
            wp[6] = fCenter.x + rightScreen.x + upScreen.x; // right top
            wp[7] = fCenter.y + rightScreen.y + upScreen.y;
            wp[8] = fCenter.z + rightScreen.z + upScreen.z;
            wp[9] = fCenter.x - rightScreen.x + upScreen.x; // left top
            wp[10] = fCenter.y - rightScreen.y + upScreen.y;
            wp[11] = fCenter.z - rightScreen.z + upScreen.z;
        }
    }
    constructor(params, skybox, techniqueId) {
        super(params, techniqueId);
        this.worldPos = new Float32Array(4 * 3);
        this._worldPosBuff = new AttributeBuffers_1.BufferHandle(GL_1.GL.Buffer.Target.ArrayBuffer);
        this.typeAndExponents = new Float32Array(3);
        this.zenithColor = new Float32Array(3);
        this.skyColor = new Float32Array(3);
        this.groundColor = new Float32Array(3);
        this.nadirColor = new Float32Array(3);
        this.zOffset = skybox.zOffset;
        this.rotation = "sphere" === skybox.type ? skybox.rotation : 0;
        if (skybox.type === "sphere") {
            this.skyTexture = skybox.texture;
            this.typeAndExponents[0] = 0.0;
            this.typeAndExponents[1] = 1.0;
            this.typeAndExponents[2] = 1.0;
            this.zenithColor[0] = 0.0;
            this.zenithColor[1] = 0.0;
            this.zenithColor[2] = 0.0;
            this.nadirColor[0] = 0.0;
            this.nadirColor[1] = 0.0;
            this.nadirColor[2] = 0.0;
            this.skyColor[0] = 0.0;
            this.skyColor[1] = 0.0;
            this.skyColor[2] = 0.0;
            this.groundColor[0] = 0.0;
            this.groundColor[1] = 0.0;
            this.groundColor[2] = 0.0;
        }
        else {
            const gradient = skybox.gradient;
            this.zenithColor[0] = gradient.zenithColor.colors.r / 255.0;
            this.zenithColor[1] = gradient.zenithColor.colors.g / 255.0;
            this.zenithColor[2] = gradient.zenithColor.colors.b / 255.0;
            this.nadirColor[0] = gradient.nadirColor.colors.r / 255.0;
            this.nadirColor[1] = gradient.nadirColor.colors.g / 255.0;
            this.nadirColor[2] = gradient.nadirColor.colors.b / 255.0;
            if (gradient.twoColor) {
                this.typeAndExponents[0] = -1.0;
                this.typeAndExponents[1] = 4.0;
                this.typeAndExponents[2] = 4.0;
                this.skyColor[0] = 0.0;
                this.skyColor[1] = 0.0;
                this.skyColor[2] = 0.0;
                this.groundColor[0] = 0.0;
                this.groundColor[1] = 0.0;
                this.groundColor[2] = 0.0;
            }
            else {
                this.typeAndExponents[0] = 1.0;
                this.typeAndExponents[1] = gradient.skyExponent;
                this.typeAndExponents[2] = gradient.groundExponent;
                this.skyColor[0] = gradient.skyColor.colors.r / 255.0;
                this.skyColor[1] = gradient.skyColor.colors.g / 255.0;
                this.skyColor[2] = gradient.skyColor.colors.b / 255.0;
                this.groundColor[0] = gradient.groundColor.colors.r / 255.0;
                this.groundColor[1] = gradient.groundColor.colors.g / 255.0;
                this.groundColor[2] = gradient.groundColor.colors.b / 255.0;
            }
        }
    }
    static createGeometry(skybox) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        const technique = "sphere" === skybox.type ? 25 /* TechniqueId.SkySphereTexture */ : 24 /* TechniqueId.SkySphereGradient */;
        return new SkySphereViewportQuadGeometry(params, skybox, technique);
    }
    get isDisposed() { return super.isDisposed && this._worldPosBuff.isDisposed; }
    [Symbol.dispose]() {
        super[Symbol.dispose]();
        (0, core_bentley_1.dispose)(this._worldPosBuff);
    }
}
exports.SkySphereViewportQuadGeometry = SkySphereViewportQuadGeometry;
/** Geometry used when rendering ambient occlusion information to an output texture
 * @internal
 */
class AmbientOcclusionGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(depthAndOrder, depth) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params) {
            return undefined;
        }
        // Will derive positions and normals from depthAndOrder.
        return new AmbientOcclusionGeometry(params, [depth, depthAndOrder]);
    }
    get depthAndOrder() { return this._textures[1]; }
    get depth() { return this._textures[0]; }
    get noise() { return (0, core_bentley_1.expectDefined)(System_1.System.instance.noiseTexture?.getHandle()); }
    constructor(params, textures) {
        super(params, 26 /* TechniqueId.AmbientOcclusion */, textures);
    }
}
exports.AmbientOcclusionGeometry = AmbientOcclusionGeometry;
/** @internal */
var BlurType;
(function (BlurType) {
    BlurType[BlurType["NoTest"] = 0] = "NoTest";
    BlurType[BlurType["TestOrder"] = 1] = "TestOrder";
})(BlurType || (exports.BlurType = BlurType = {}));
/** @internal */
class BlurGeometry extends TexturedViewportQuadGeometry {
    blurDir;
    static createGeometry(texToBlur, depthAndOrder, depthAndOrderHidden, blurDir, blurType) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params) {
            return undefined;
        }
        if (undefined === depthAndOrderHidden || BlurType.NoTest === blurType)
            return new BlurGeometry(params, [texToBlur, depthAndOrder], blurDir, blurType);
        else
            return new BlurGeometry(params, [texToBlur, depthAndOrder, depthAndOrderHidden], blurDir, blurType);
    }
    get textureToBlur() { return this._textures[0]; }
    get depthAndOrder() { return this._textures[1]; }
    get depthAndOrderHidden() { return this._textures[2]; }
    constructor(params, textures, blurDir, blurType) {
        super(params, BlurType.NoTest === blurType ? 27 /* TechniqueId.Blur */ : 28 /* TechniqueId.BlurTestOrder */, textures);
        this.blurDir = blurDir;
    }
}
exports.BlurGeometry = BlurGeometry;
/** @internal */
class EDLCalcBasicGeometry extends TexturedViewportQuadGeometry {
    texInfo = new Float32Array(3);
    static createGeometry(colorBuffer, depthBuffer, width, height) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new EDLCalcBasicGeometry(params, [colorBuffer, depthBuffer], width, height);
    }
    get colorTexture() { return this._textures[0]; }
    get depthTexture() { return this._textures[1]; }
    constructor(params, textures, width, height) {
        super(params, 34 /* TechniqueId.EDLCalcBasic */, textures);
        this.texInfo[0] = 1.0 / width;
        this.texInfo[1] = 1.0 / height;
        this.texInfo[2] = 1.0;
    }
}
exports.EDLCalcBasicGeometry = EDLCalcBasicGeometry;
/** @internal */
class EDLCalcFullGeometry extends TexturedViewportQuadGeometry {
    texInfo = new Float32Array(3);
    static createGeometry(colorBuffer, depthBuffer, scale, width, height) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new EDLCalcFullGeometry(params, [colorBuffer, depthBuffer], scale, width, height);
    }
    get colorTexture() { return this._textures[0]; }
    get depthTexture() { return this._textures[1]; }
    constructor(params, textures, scale, width, height) {
        super(params, 35 /* TechniqueId.EDLCalcFull */, textures);
        this.texInfo[0] = 1.0 / width;
        this.texInfo[1] = 1.0 / height;
        this.texInfo[2] = scale;
    }
}
exports.EDLCalcFullGeometry = EDLCalcFullGeometry;
/** @internal */
class EDLFilterGeometry extends TexturedViewportQuadGeometry {
    texInfo = new Float32Array(3);
    static createGeometry(colorBuffer, depthBuffer, scale, width, height) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new EDLFilterGeometry(params, [colorBuffer, depthBuffer], scale, width, height);
    }
    get colorTexture() { return this._textures[0]; }
    get depthTexture() { return this._textures[1]; }
    constructor(params, textures, scale, width, height) {
        super(params, 36 /* TechniqueId.EDLFilter */, textures);
        this.texInfo[0] = 1.0 / width;
        this.texInfo[1] = 1.0 / height;
        this.texInfo[2] = scale;
    }
}
exports.EDLFilterGeometry = EDLFilterGeometry;
/** @internal */
class EDLMixGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(colorTexture1, colorTexture2, colorTexture4) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new EDLMixGeometry(params, [colorTexture1, colorTexture2, colorTexture4]);
    }
    get colorTexture1() { return this._textures[0]; }
    get colorTexture2() { return this._textures[1]; }
    get colorTexture4() { return this._textures[2]; }
    constructor(params, textures) {
        super(params, 37 /* TechniqueId.EDLMix */, textures);
    }
}
exports.EDLMixGeometry = EDLMixGeometry;
/** @internal */
class EVSMGeometry extends TexturedViewportQuadGeometry {
    stepSize = new Float32Array(2);
    static createGeometry(depthBuffer, width, height) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new EVSMGeometry(params, [depthBuffer], width, height);
    }
    get depthTexture() { return this._textures[0]; }
    constructor(params, textures, width, height) {
        super(params, 22 /* TechniqueId.EVSMFromDepth */, textures);
        this.stepSize[0] = 1.0 / width;
        this.stepSize[1] = 1.0 / height;
    }
}
exports.EVSMGeometry = EVSMGeometry;
/** Geometry used during the 'composite' pass to apply transparency and/or hilite effects.
 * @internal
 */
class CompositeGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(opaque, accum, reveal, hilite) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        const textures = [opaque, accum, reveal, hilite];
        return new CompositeGeometry(params, textures);
    }
    get opaque() { return this._textures[0]; }
    get accum() { return this._textures[1]; }
    get reveal() { return this._textures[2]; }
    get hilite() { return this._textures[3]; }
    get occlusion() {
        return this._textures.length > 4 ? this._textures[4] : undefined;
    }
    set occlusion(occlusion) {
        (0, core_bentley_1.assert)((undefined === occlusion) === (undefined !== this.occlusion));
        if (undefined !== occlusion)
            this._textures[4] = occlusion;
        else
            this._textures.length = 4;
    }
    // Invoked each frame to determine the appropriate Technique to use.
    update(flags) { this._techniqueId = this.determineTechnique(flags); }
    determineTechnique(flags) {
        return (0, TechniqueId_1.computeCompositeTechniqueId)(flags);
    }
    constructor(params, textures) {
        super(params, 9 /* TechniqueId.CompositeHilite */, textures);
        (0, core_bentley_1.assert)(4 <= this._textures.length);
    }
}
exports.CompositeGeometry = CompositeGeometry;
/** Geometry used to ping-pong the pick buffer data in between opaque passes.
 * @internal
 */
class CopyPickBufferGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(featureId, depthAndOrder) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined !== params) {
            return new CopyPickBufferGeometry(params, [featureId, depthAndOrder]);
        }
        else {
            return undefined;
        }
    }
    get featureId() { return this._textures[0]; }
    get depthAndOrder() { return this._textures[1]; }
    constructor(params, textures) {
        super(params, 17 /* TechniqueId.CopyPickBuffers */, textures);
    }
}
exports.CopyPickBufferGeometry = CopyPickBufferGeometry;
class CombineTexturesGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(texture0, texture1) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined !== params) {
            return new CombineTexturesGeometry(params, [texture0, texture1]);
        }
        else {
            return undefined;
        }
    }
    get texture0() { return this._textures[0]; }
    get texture1() { return this._textures[1]; }
    constructor(params, textures) {
        super(params, 29 /* TechniqueId.CombineTextures */, textures);
    }
}
exports.CombineTexturesGeometry = CombineTexturesGeometry;
class Combine3TexturesGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(texture0, texture1, texture2) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined !== params) {
            return new Combine3TexturesGeometry(params, [texture0, texture1, texture2]);
        }
        else {
            return undefined;
        }
    }
    get texture0() { return this._textures[0]; }
    get texture1() { return this._textures[1]; }
    get texture2() { return this._textures[2]; }
    constructor(params, textures) {
        super(params, 30 /* TechniqueId.Combine3Textures */, textures);
    }
}
exports.Combine3TexturesGeometry = Combine3TexturesGeometry;
/** @internal */
class SingleTexturedViewportQuadGeometry extends TexturedViewportQuadGeometry {
    static createGeometry(texture, techId) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params) {
            return undefined;
        }
        return new SingleTexturedViewportQuadGeometry(params, texture, techId);
    }
    get texture() { return this._textures[0]; }
    set texture(texture) { this._textures[0] = texture; }
    constructor(params, texture, techId) {
        super(params, techId, [texture]);
    }
}
exports.SingleTexturedViewportQuadGeometry = SingleTexturedViewportQuadGeometry;
/** @internal */
var BoundaryType;
(function (BoundaryType) {
    BoundaryType[BoundaryType["Outside"] = 0] = "Outside";
    BoundaryType[BoundaryType["Inside"] = 1] = "Inside";
    BoundaryType[BoundaryType["Selected"] = 2] = "Selected";
})(BoundaryType || (exports.BoundaryType = BoundaryType = {}));
/** @internal */
class VolumeClassifierGeometry extends SingleTexturedViewportQuadGeometry {
    boundaryType = BoundaryType.Inside;
    static createVCGeometry(texture) {
        const params = ViewportQuad.getInstance().createParams();
        if (undefined === params)
            return undefined;
        return new VolumeClassifierGeometry(params, texture);
    }
    constructor(params, texture) {
        super(params, texture, 32 /* TechniqueId.VolClassSetBlend */);
    }
}
exports.VolumeClassifierGeometry = VolumeClassifierGeometry;
/** A geometric primitive which renders gl points using gl.drawArrays() with one vertex buffer.
 * @internal
 */
class ScreenPointsGeometry extends CachedGeometry {
    _numPoints;
    _origin;
    _scale;
    _positions;
    buffers;
    zTexture;
    constructor(vertices, zTexture) {
        super();
        this.zTexture = zTexture;
        this._numPoints = vertices.length;
        this._positions = (0, core_bentley_1.expectDefined)(AttributeBuffers_1.QBufferHandle2d.create(vertices.params, vertices.toTypedArray()));
        this._origin = new Float32Array(3);
        this._origin[0] = this._positions.params[0];
        this._origin[1] = this._positions.params[1];
        this._origin[2] = 0.0;
        this._scale = new Float32Array(3);
        this._scale[0] = this._positions.params[2];
        this._scale[1] = this._positions.params[3];
        this._scale[2] = this._positions.params[3]; // just copy the scale from y
        this.buffers = AttributeBuffers_1.BuffersContainer.create();
        const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", 31 /* TechniqueId.VolClassCopyZ */, false);
        (0, core_bentley_1.assert)(attrPos !== undefined);
        this.buffers.addBuffer(this._positions, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 2, GL_1.GL.DataType.UnsignedShort, false, 0, 0, false)]);
    }
    static createGeometry(width, height, depth) {
        const pixWidth = 2.0 / width;
        const pixHeight = 2.0 / height;
        const startX = pixWidth * 0.5 - 1.0;
        const startY = pixHeight * 0.5 - 1.0;
        const pt = new core_geometry_1.Point2d(startX, startY);
        const vertices = new core_common_1.QPoint2dList(core_common_1.QParams2d.fromNormalizedRange());
        for (let y = 0; y < height; ++y) {
            pt.x = startX;
            for (let x = 0; x < width; ++x) {
                vertices.add(pt);
                pt.x += pixWidth;
            }
            pt.y += pixHeight;
        }
        return new ScreenPointsGeometry(vertices, depth);
    }
    draw() {
        this.buffers.bind();
        System_1.System.instance.context.drawArrays(GL_1.GL.PrimitiveType.Points, 0, this._numPoints);
        this.buffers.unbind();
    }
    get isDisposed() { return this.buffers.isDisposed && this._positions.isDisposed; }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this.buffers);
        (0, core_bentley_1.dispose)(this._positions);
    }
    collectStatistics(stats) {
        stats.addBuffer(RenderMemory_1.RenderMemory.BufferType.PointStrings, this._positions.bytesUsed);
    }
    _wantWoWReversal(_target) { return false; }
    get techniqueId() { return 31 /* TechniqueId.VolClassCopyZ */; }
    getPass() { return "classification"; }
    get renderOrder() { return 0 /* RenderOrder.None */; }
    get qOrigin() { return this._origin; }
    get qScale() { return this._scale; }
}
exports.ScreenPointsGeometry = ScreenPointsGeometry;
/** @internal */
class PolylineBuffers {
    buffers;
    indices;
    prevIndices;
    nextIndicesAndParams;
    constructor(indices, prevIndices, nextIndicesAndParams) {
        this.buffers = AttributeBuffers_1.BuffersContainer.create();
        const attrPos = AttributeMap_1.AttributeMap.findAttribute("a_pos", 1 /* TechniqueId.Polyline */, false);
        const attrPrevIndex = AttributeMap_1.AttributeMap.findAttribute("a_prevIndex", 1 /* TechniqueId.Polyline */, false);
        const attrNextIndex = AttributeMap_1.AttributeMap.findAttribute("a_nextIndex", 1 /* TechniqueId.Polyline */, false);
        const attrParam = AttributeMap_1.AttributeMap.findAttribute("a_param", 1 /* TechniqueId.Polyline */, false);
        (0, core_bentley_1.assert)(attrPos !== undefined);
        (0, core_bentley_1.assert)(attrPrevIndex !== undefined);
        (0, core_bentley_1.assert)(attrNextIndex !== undefined);
        (0, core_bentley_1.assert)(attrParam !== undefined);
        this.buffers.addBuffer(indices, [AttributeBuffers_1.BufferParameters.create(attrPos.location, 3, GL_1.GL.DataType.UnsignedByte, false, 0, 0, false)]);
        this.buffers.addBuffer(prevIndices, [AttributeBuffers_1.BufferParameters.create(attrPrevIndex.location, 3, GL_1.GL.DataType.UnsignedByte, false, 0, 0, false)]);
        this.buffers.addBuffer(nextIndicesAndParams, [
            AttributeBuffers_1.BufferParameters.create(attrNextIndex.location, 3, GL_1.GL.DataType.UnsignedByte, false, 4, 0, false),
            AttributeBuffers_1.BufferParameters.create(attrParam.location, 1, GL_1.GL.DataType.UnsignedByte, false, 4, 3, false),
        ]);
        this.indices = indices;
        this.prevIndices = prevIndices;
        this.nextIndicesAndParams = nextIndicesAndParams;
    }
    static create(polyline) {
        const indices = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.indices.data);
        const prev = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.prevIndices.data);
        const next = AttributeBuffers_1.BufferHandle.createArrayBuffer(polyline.nextIndicesAndParams);
        return undefined !== indices && undefined !== prev && undefined !== next ? new PolylineBuffers(indices, prev, next) : undefined;
    }
    collectStatistics(stats, type) {
        stats.addBuffer(type, this.indices.bytesUsed + this.prevIndices.bytesUsed + this.nextIndicesAndParams.bytesUsed);
    }
    get isDisposed() {
        return this.buffers.isDisposed
            && this.indices.isDisposed
            && this.prevIndices.isDisposed
            && this.nextIndicesAndParams.isDisposed;
    }
    [Symbol.dispose]() {
        (0, core_bentley_1.dispose)(this.buffers);
        (0, core_bentley_1.dispose)(this.indices);
        (0, core_bentley_1.dispose)(this.prevIndices);
        (0, core_bentley_1.dispose)(this.nextIndicesAndParams);
    }
}
exports.PolylineBuffers = PolylineBuffers;
//# sourceMappingURL=CachedGeometry.js.map