@itwin/core-frontend
Version:
iTwin.js frontend components
305 lines • 12.4 kB
JavaScript
"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