UNPKG

@itwin/core-frontend

Version:
236 lines • 10.9 kB
"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 Rendering */ Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphicDescriptionBuilderImpl = void 0; exports.isGraphicDescription = isGraphicDescription; exports.collectGraphicDescriptionTransferables = collectGraphicDescriptionTransferables; const core_geometry_1 = require("@itwin/core-geometry"); const ImdlModel_1 = require("../../imdl/ImdlModel"); const GraphicType_1 = require("../../render/GraphicType"); const GraphicAssembler_1 = require("../../render/GraphicAssembler"); const core_common_1 = require("@itwin/core-common"); const core_bentley_1 = require("@itwin/core-bentley"); const PointStringParams_1 = require("./PointStringParams"); const PolylineParams_1 = require("./PolylineParams"); const VertexTableBuilder_1 = require("./VertexTableBuilder"); const ParseImdlDocument_1 = require("../../imdl/ParseImdlDocument"); const Symbols_1 = require("../Symbols"); const GraphicDescriptionContextImpl_1 = require("./GraphicDescriptionContextImpl"); class GraphicDescriptionBuilderImpl extends GraphicAssembler_1.GraphicAssembler { [Symbols_1._implementationProhibited] = undefined; _computeChordTolerance; _context; _viewIndependentOrigin; constructor(options) { const type = options.type; const placement = options.placement ?? core_geometry_1.Transform.createIdentity(); const wantEdges = options.generateEdges ?? type === GraphicType_1.GraphicType.Scene; const wantNormals = wantEdges || type === GraphicType_1.GraphicType.Scene; const preserveOrder = type === GraphicType_1.GraphicType.ViewOverlay || type === GraphicType_1.GraphicType.WorldOverlay || type === GraphicType_1.GraphicType.ViewBackground; super({ ...options, [Symbols_1._implementationProhibited]: undefined, type, placement, wantEdges, wantNormals, preserveOrder, }); this._computeChordTolerance = options.computeChordTolerance; this._viewIndependentOrigin = options.viewIndependentOrigin?.clone(); this._context = options.context; if (!(this._context.transientIds instanceof core_bentley_1.TransientIdSequence)) { throw new Error("Invalid WorkerGraphicDescriptionContext"); } } finish() { const description = { [Symbols_1._implementationProhibited]: undefined, type: this.type, primitives: [], }; if (this[Symbols_1._accumulator].isEmpty) { return description; } const tolerance = this._computeChordTolerance({ builder: this, computeRange: () => this[Symbols_1._accumulator].geometries.computeRange() }); const meshes = this[Symbols_1._accumulator].toMeshes(this, tolerance, this.pickable); if (meshes.length === 0) { return description; } // If the meshes contain quantized positions, they are all quantized to the same range. If that range is small relative to the distance // from the origin, quantization errors can produce display artifacts. Remove the translation from the quantization parameters and apply // it in the transform instead. // If the positions are not quantized, they have already been transformed to be relative to the center of the meshes' range. // Apply the inverse translation to put them back into model space. let transformOrigin; let meshesRangeOffset = false; for (const mesh of meshes) { const verts = mesh.points; if (!transformOrigin) { // This is the first mesh we've processed. if (verts instanceof core_common_1.QPoint3dList) { transformOrigin = verts.params.origin.clone(); verts.params.origin.setZero(); } else { // In this case we need to modify the qOrigin of the graphic that will get created later since we have translated the origin. // We can't modify it directly, but if we temporarily modify the range of the mesh used to create it the qOrigin will get created properly. // Range is shared (not cloned) by all meshes and the mesh list itself, so modifying the range of the meshlist will modify it for all meshes. // This will become the range in local coordinates of the batch, if we are creating a batch. transformOrigin = verts.range.center; if (!meshesRangeOffset) { meshes.range?.low.subtractInPlace(transformOrigin); meshes.range?.high.subtractInPlace(transformOrigin); meshesRangeOffset = true; } } } else { if (verts instanceof core_common_1.QPoint3dList) { (0, core_bentley_1.assert)(transformOrigin.isAlmostEqual(verts.params.origin)); verts.params.origin.setZero(); } else { (0, core_bentley_1.assert)(verts.range.center.isAlmostZero); } } const primitive = this.createPrimitive(mesh); if (primitive) { const origin = this._viewIndependentOrigin; if (origin) { primitive.modifier = { type: "viewIndependentOrigin", origin: { x: origin.x, y: origin.y, z: origin.z }, }; } description.primitives.push(primitive); } } this[Symbols_1._accumulator].clear(); if (transformOrigin) { description.translation = { x: transformOrigin.x, y: transformOrigin.y, z: transformOrigin.z }; } const featureTable = this.pickable && meshes.features?.anyDefined ? meshes.features : undefined; if (featureTable) { (0, core_bentley_1.assert)(undefined !== this.pickable); const features = core_common_1.PackedFeatureTable.pack(featureTable); const range = meshes.range ?? new core_geometry_1.Range3d(); description.batch = { ...this.pickable, range: range.toJSON(), modelId: this.pickable.modelId ?? this.pickable.id, featureTable: { multiModel: false, data: features.data, numFeatures: features.numFeatures, animationNodeIds: features.animationNodeIds, }, }; } return description; } createPrimitive(mesh) { const meshArgs = mesh.toMeshArgs(); if (meshArgs) { return this.createMeshPrimitive(meshArgs); } const polylineArgs = mesh.toPolylineArgs(); if (!polylineArgs) { return undefined; } return polylineArgs.flags.isDisjoint ? this.createPointStringPrimitive(polylineArgs) : this.createPolylinePrimitive(polylineArgs); } createMeshPrimitive(args) { const params = (0, VertexTableBuilder_1.createMeshParams)(args, this._context.constraints.maxTextureSize, true); let material; const mat = params.surface.material; if (mat) { (0, core_bentley_1.assert)(mat.isAtlas === false && mat.material instanceof GraphicDescriptionContextImpl_1.WorkerMaterial); material = mat.material.toImdl(); } let textureMapping; const tex = params.surface.textureMapping; if (tex) { (0, core_bentley_1.assert)(tex.texture instanceof GraphicDescriptionContextImpl_1.WorkerTexture); textureMapping = { alwaysDisplayed: false, texture: tex.texture.index.toString(10) }; } return { type: "mesh", params: { ...params, vertices: convertVertexTable(params.vertices), auxChannels: params.auxChannels?.toJSON(), edges: params.edges ? (0, ParseImdlDocument_1.edgeParamsToImdl)(params.edges) : undefined, surface: { ...params.surface, indices: params.surface.indices.data, material, textureMapping, }, }, }; } createPolylinePrimitive(args) { const params = (0, PolylineParams_1.createPolylineParams)(args, this._context.constraints.maxTextureSize); if (!params) { return undefined; } return { type: "polyline", params: { ...params, vertices: convertVertexTable(params.vertices), polyline: { indices: params.polyline.indices.data, prevIndices: params.polyline.prevIndices.data, nextIndicesAndParams: params.polyline.nextIndicesAndParams, }, }, }; } createPointStringPrimitive(args) { const params = (0, PointStringParams_1.createPointStringParams)(args, this._context.constraints.maxTextureSize); if (!params) { return undefined; } return { type: "point", params: { indices: params.indices.data, vertices: convertVertexTable(params.vertices), weight: params.weight, }, }; } resolveGradient(gradient) { return this._context.createGradientTexture(gradient); } } exports.GraphicDescriptionBuilderImpl = GraphicDescriptionBuilderImpl; function convertVertexTable(src) { return { ...src, qparams: src.qparams.toJSON(), uvParams: src.uvParams?.toJSON(), uniformColor: src.uniformColor?.toJSON(), }; } function isGraphicDescription(description) { const descr = description; return "object" === typeof descr && Array.isArray(descr.primitives) && "number" === typeof descr.type; } function collectGraphicDescriptionTransferables(xfers, description) { if (!isGraphicDescription(description)) { throw new Error("Invalid GraphicDescription"); } for (const primitive of description.primitives) { (0, ImdlModel_1.addPrimitiveTransferables)(xfers, primitive); } } //# sourceMappingURL=GraphicDescriptionBuilderImpl.js.map