@itwin/core-frontend
Version:
iTwin.js frontend components
187 lines • 9.51 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* 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.PrimitiveBuilder = void 0;
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const GraphicBuilder_1 = require("../../render/GraphicBuilder");
const GraphicBranch_1 = require("../../render/GraphicBranch");
const core_bentley_1 = require("@itwin/core-bentley");
const Symbols_1 = require("../../common/internal/Symbols");
const GraphicTemplateImpl_1 = require("../../internal/render/GraphicTemplateImpl");
class PrimitiveBuilder extends GraphicBuilder_1.GraphicBuilder {
[Symbols_1._implementationProhibited] = undefined;
system;
primitives = [];
_options;
_viewIndependentOrigin;
constructor(system, options) {
super(options);
this.system = system;
this._options = options;
this._viewIndependentOrigin = options.viewIndependentOrigin?.clone();
}
finish() {
const template = this.toTemplate(false);
const graphic = this.system.createGraphicFromTemplate({ template });
return graphic ?? this.system.createGraphicList([]);
}
finishTemplate() {
return this.toTemplate(true);
}
toTemplate(noDispose) {
const accum = this[Symbols_1._accumulator];
const tolerance = this.computeTolerance(accum);
const result = this.saveToTemplate(this, tolerance, this.pickable, noDispose);
accum.clear();
return result ?? (0, GraphicTemplateImpl_1.createGraphicTemplate)({ nodes: [], noDispose });
}
computeTolerance(accum) {
return this._computeChordTolerance({
graphic: this,
computeRange: () => accum.geometries.computeRange(),
});
}
resolveGradient(gradient) {
return this.system.getGradientTexture(gradient, this.iModel);
}
/**
* Populate a list of Graphic objects from the accumulated Geometry objects.
* removed ViewContext
*/
saveToGraphicList(graphics, options, tolerance, pickable) {
const meshes = this[Symbols_1._accumulator].toMeshes(options, tolerance, pickable);
if (0 === meshes.length)
return undefined;
// 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.
const branch = new GraphicBranch_1.GraphicBranch(true);
let transformOrigin;
let meshesRangeOffset = false;
for (const mesh of meshes) {
const verts = mesh.points;
if (branch.isEmpty) {
if (verts instanceof core_common_1.QPoint3dList) {
transformOrigin = verts.params.origin.clone();
verts.params.origin.setZero();
}
else {
transformOrigin = verts.range.center;
// 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.
// We will then later add this offset back to the range once all of the graphics have been created because it is needed unmodified for locate.
if (!meshesRangeOffset) {
meshes.range?.low.subtractInPlace(transformOrigin);
meshes.range?.high.subtractInPlace(transformOrigin);
meshesRangeOffset = true;
}
}
}
else {
(0, core_bentley_1.assert)(undefined !== transformOrigin);
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 graphic = this.system.createMeshGraphics(mesh, this._viewIndependentOrigin);
if (graphic)
branch.add(graphic);
}
if (!branch.isEmpty) {
(0, core_bentley_1.assert)(undefined !== transformOrigin);
const transform = core_geometry_1.Transform.createTranslation(transformOrigin);
graphics.push(this.system.createBranch(branch, transform));
if (meshesRangeOffset) { // restore the meshes range that we modified earlier.
meshes.range?.low.addInPlace(transformOrigin);
meshes.range?.high.addInPlace(transformOrigin);
}
}
return meshes;
}
saveToTemplate(options, tolerance, pickable, noDispose) {
const meshes = this[Symbols_1._accumulator].toMeshes(options, tolerance, pickable);
if (0 === meshes.length)
return undefined;
// 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;
const geometry = [];
for (const mesh of meshes) {
const verts = mesh.points;
if (!transformOrigin) {
if (verts instanceof core_common_1.QPoint3dList) {
transformOrigin = verts.params.origin.clone();
verts.params.origin.setZero();
}
else {
transformOrigin = verts.range.center;
// 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.
// We will then later add this offset back to the range once all of the graphics have been created because it is needed unmodified for locate.
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 geom = this.system.createGeometryFromMesh(mesh, this._viewIndependentOrigin);
if (geom) {
geometry.push(geom);
}
}
let transform;
if (transformOrigin) {
transform = core_geometry_1.Transform.createTranslation(transformOrigin);
if (meshesRangeOffset) { // restore the meshes range that we modified earlier.
meshes.range?.low.addInPlace(transformOrigin);
meshes.range?.high.addInPlace(transformOrigin);
}
}
let batch;
if (meshes.features?.anyDefined) {
batch = {
featureTable: core_common_1.PackedFeatureTable.pack(meshes.features),
range: meshes.range ?? new core_geometry_1.Range3d(),
options: this._options.pickable,
};
}
return (0, GraphicTemplateImpl_1.createGraphicTemplate)({
batch,
nodes: [{ geometry, transform }],
noDispose,
});
}
}
exports.PrimitiveBuilder = PrimitiveBuilder;
//# sourceMappingURL=PrimitiveBuilder.js.map