UNPKG

@itwin/core-frontend

Version:
305 lines • 12.4 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.MeshList = exports.Mesh = exports.MeshArgsEdges = void 0; exports.createPolylineArgs = createPolylineArgs; exports.createMeshArgs = createMeshArgs; 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 ColorMap_1 = require("./ColorMap"); const DisplayParams_1 = require("./DisplayParams"); const MeshPrimitive_1 = require("./MeshPrimitive"); const Primitives_1 = require("./Primitives"); function createPolylineArgs(mesh) { if (!mesh.polylines || mesh.polylines.length === 0) return undefined; const polylines = []; for (const polyline of mesh.polylines) if (polyline.indices.length > 0) polylines.push(polyline.indices); if (polylines.length === 0) return undefined; const flags = { is2d: mesh.is2d, isPlanar: mesh.isPlanar, isDisjoint: mesh.type === MeshPrimitive_1.MeshPrimitiveType.Point, }; if (mesh.displayParams.regionEdgeType === DisplayParams_1.DisplayParams.RegionEdgeType.Outline) { // This polyline is behaving as the edges of a region surface. if (!mesh.displayParams.gradient || mesh.displayParams.gradient.isOutlined) flags.type = core_common_1.PolylineTypeFlags.Edge; else flags.type = core_common_1.PolylineTypeFlags.Outline; // edges only displayed if fill undisplayed } const colors = new core_common_1.ColorIndex(); mesh.colorMap.toColorIndex(colors, mesh.colors); const features = new core_common_1.FeatureIndex(); mesh.toFeatureIndex(features); return { width: mesh.displayParams.width, linePixels: mesh.displayParams.linePixels, flags, polylines, points: mesh.points, colors, features, }; } /** The vertices of the edges are shared with those of the surface. */ class MeshArgsEdges { edges = new core_common_1.EdgeArgs(); silhouettes = new core_common_1.SilhouetteEdgeArgs(); polylines = new core_common_1.PolylineEdgeArgs(); width = 0; linePixels = core_common_1.LinePixels.Solid; color; clear() { this.edges.clear(); this.silhouettes.clear(); this.polylines.clear(); this.width = 0; this.linePixels = core_common_1.LinePixels.Solid; } get isValid() { return this.edges.isValid || this.silhouettes.isValid || this.polylines.isValid; } } exports.MeshArgsEdges = MeshArgsEdges; function createMeshArgs(mesh) { if (!mesh.triangles || mesh.triangles.isEmpty || mesh.points.length === 0) return undefined; const texture = mesh.displayParams.textureMapping?.texture; const textureMapping = texture && mesh.uvParams.length > 0 ? { texture, uvParams: mesh.uvParams } : undefined; const colors = new core_common_1.ColorIndex(); mesh.colorMap.toColorIndex(colors, mesh.colors); const features = new core_common_1.FeatureIndex(); mesh.toFeatureIndex(features); let edges; if (mesh.edges) { edges = new MeshArgsEdges(); edges.width = mesh.edges.appearance?.width ?? mesh.displayParams.width; edges.linePixels = mesh.edges.appearance?.linePixels ?? mesh.displayParams.linePixels; edges.edges.init(mesh.edges); edges.silhouettes.init(mesh.edges); edges.color = mesh.edges.appearance?.color; edges.polylines.init(mesh.edges.polylineGroups); } return { vertIndices: mesh.triangles.indices, points: mesh.points, normals: !mesh.displayParams.ignoreLighting && mesh.normals.length > 0 ? mesh.normals : undefined, textureMapping, colors, features, material: mesh.displayParams.material, fillFlags: mesh.displayParams.fillFlags, isPlanar: mesh.isPlanar, is2d: mesh.is2d, hasBakedLighting: true === mesh.hasBakedLighting, isVolumeClassifier: true === mesh.isVolumeClassifier, edges, auxChannels: mesh.auxChannels, }; } class Mesh { _data; points; normals = []; uvParams = []; colorMap = new ColorMap_1.ColorMap(); // used to be called ColorTable colors = []; edges; features; type; is2d; isPlanar; hasBakedLighting; isVolumeClassifier; displayParams; _auxChannels; constructor(props) { const { displayParams, features, type, range, is2d, isPlanar } = props; this._data = MeshPrimitive_1.MeshPrimitiveType.Mesh === type ? new Primitives_1.TriangleList() : []; this.displayParams = displayParams; this.features = features ? new Mesh.Features(features) : undefined; this.type = type; this.is2d = is2d; this.isPlanar = isPlanar; this.hasBakedLighting = (true === props.hasBakedLighting); this.isVolumeClassifier = (true === props.isVolumeClassifier); if (props.quantizePositions) { this.points = new core_common_1.QPoint3dList(core_common_1.QParams3d.fromRange(range)); } else { const points = []; points.range = range; const center = range.center; points.add = (pt) => { // assert(range.containsPoint(pt)); rounding error triggers this sometimes... points.push(pt.minus(center)); }; this.points = points; } } static create(props) { return new Mesh(props); } get triangles() { return MeshPrimitive_1.MeshPrimitiveType.Mesh === this.type ? this._data : undefined; } get polylines() { return MeshPrimitive_1.MeshPrimitiveType.Mesh !== this.type ? this._data : undefined; } get auxChannels() { return this._auxChannels; } addAuxChannels(channels, srcIndex) { // The native version of this function appears to assume that all polyfaces added to the Mesh will have // the same number + type of aux channels. // ###TODO We should really produce a separate Mesh for each unique combination. For now just bail on mismatch. if (this._auxChannels) { if (this._auxChannels.length !== channels.length) return; for (let i = 0; i < channels.length; i++) { const src = channels[i]; const dst = this._auxChannels[i]; if (src.dataType !== dst.dataType || src.name !== dst.name || src.inputName !== dst.inputName) return; } } if (!this._auxChannels) { // Copy the channels, leaving each AuxData's values array empty. this._auxChannels = channels.map((x) => new core_geometry_1.AuxChannel(x.data.map((y) => new core_geometry_1.AuxChannelData(y.input, [])), x.dataType, x.name, x.inputName)); } // Append the value at srcIndex from each source channel's data to our channels. for (let channelIndex = 0; channelIndex < channels.length; channelIndex++) { const srcChannel = channels[channelIndex]; const dstChannel = this._auxChannels[channelIndex]; const dstIndex = dstChannel.valueCount; for (let dataIndex = 0; dataIndex < srcChannel.data.length; dataIndex++) { const dstData = dstChannel.data[dataIndex]; dstData.copyValues(srcChannel.data[dataIndex], dstIndex, srcIndex, dstChannel.entriesPerValue); } } } toFeatureIndex(index) { if (undefined !== this.features) this.features.toFeatureIndex(index); } toMeshArgs() { return createMeshArgs(this); } toPolylineArgs() { return createPolylineArgs(this); } addPolyline(poly) { const { type, polylines } = this; (0, core_bentley_1.assert)(MeshPrimitive_1.MeshPrimitiveType.Polyline === type || MeshPrimitive_1.MeshPrimitiveType.Point === type); (0, core_bentley_1.assert)(undefined !== polylines); if (MeshPrimitive_1.MeshPrimitiveType.Polyline === type && poly.indices.length < 2) return; if (undefined !== polylines) polylines.push(poly); } addTriangle(triangle) { const { triangles, type } = this; (0, core_bentley_1.assert)(MeshPrimitive_1.MeshPrimitiveType.Mesh === type); (0, core_bentley_1.assert)(undefined !== triangles); if (undefined !== triangles) triangles.addTriangle(triangle); } addVertex(props) { const { feature, position, normal, uvParam, fillColor } = props; this.points.add(position); if (undefined !== normal) this.normals.push(normal); if (undefined !== uvParam) this.uvParams.push(uvParam); if (feature) { (0, core_bentley_1.assert)(undefined !== this.features); this.features.add(feature, this.points.length); } // Don't allocate color indices until we have non-uniform colors if (0 === this.colorMap.length) { this.colorMap.insert(fillColor); (0, core_bentley_1.assert)(this.colorMap.isUniform); (0, core_bentley_1.assert)(0 === this.colorMap.indexOf(fillColor)); } else if (!this.colorMap.isUniform || !this.colorMap.hasColor(fillColor)) { // Back-fill uniform value (index=0) for existing vertices if previously uniform if (0 === this.colors.length) this.colors.length = this.points.length - 1; this.colors.push(this.colorMap.insert(fillColor)); (0, core_bentley_1.assert)(!this.colorMap.isUniform); } return this.points.length - 1; } } exports.Mesh = Mesh; (function (Mesh) { class Features { table; indices = []; uniform = 0; initialized = false; constructor(table) { this.table = table; } add(feat, numVerts) { const index = this.table.insert(feat); if (!this.initialized) { // First feature - uniform. this.uniform = index; this.initialized = true; } else if (0 < this.indices.length) { // Already non-uniform this.indices.push(index); } else { // Second feature - back-fill uniform for existing verts while (this.indices.length < numVerts - 1) this.indices.push(this.uniform); this.indices.push(index); } } setIndices(indices) { this.indices.length = 0; this.uniform = 0; this.initialized = 0 < indices.length; (0, core_bentley_1.assert)(0 < indices.length); if (1 === indices.length) this.uniform = indices[0]; else if (1 < indices.length) this.indices = indices; } toFeatureIndex(output) { const index = output ?? new core_common_1.FeatureIndex(); if (!this.initialized) { index.type = core_common_1.FeatureIndexType.Empty; } else if (this.indices.length === 0) { index.type = core_common_1.FeatureIndexType.Uniform; index.featureID = this.uniform; } else { index.type = core_common_1.FeatureIndexType.NonUniform; index.featureIDs = new Uint32Array(this.indices); } return index; } } Mesh.Features = Features; })(Mesh || (exports.Mesh = Mesh = {})); class MeshList extends Array { features; range; constructor(features, range) { super(); this.features = features; this.range = range; } } exports.MeshList = MeshList; //# sourceMappingURL=MeshPrimitives.js.map