UNPKG

@itwin/core-frontend

Version:
168 lines • 8.42 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 Tiles */ Object.defineProperty(exports, "__esModule", { value: true }); exports.EllipsoidTerrainProvider = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_geometry_1 = require("@itwin/core-geometry"); const RealityMeshParams_1 = require("../../render/RealityMeshParams"); const internal_1 = require("../internal"); const scratchPoint2d = core_geometry_1.Point2d.createZero(); const scratchPoint = core_geometry_1.Point3d.createZero(); const scratchEllipsoid = core_geometry_1.Ellipsoid.create(core_geometry_1.Transform.createIdentity()); const scratchZeroRange = core_geometry_1.Range1d.createXX(0, 0); /** A terrain mesh provider that produces geometry that represents a smooth ellipsoid without any height perturbations. * The area within the project extents are represented as planar tiles and other tiles are facetted approximations * of the WGS84 ellipsoid. * This is the terrain provider used when the background map is enabled but 3d terrain is disabled. * @public */ class EllipsoidTerrainProvider extends internal_1.TerrainMeshProvider { _tilingScheme = new internal_1.WebMercatorTilingScheme(); _wantSkirts; /** Construct a new terrain provider. * @note [[TerrainMeshProviderOptions.wantNormals]] is ignored - no normals are produced. */ constructor(opts) { super(); this._wantSkirts = opts.wantSkirts; } /** Implements [[TerrainMeshProvider.maxDepth]] to return a fixed maximum depth of 22. */ get maxDepth() { return 22; } /** Implements [[TerrainMeshProvider.getChildHeightRange]] to return an empty range, because the ellipsoid is smooth. */ getChildHeightRange(_quadId, _rectangle, _parent) { return scratchZeroRange; } /** Implements [[TerrainMeshProvider.tilingScheme]]. */ get tilingScheme() { return this._tilingScheme; } createSkirtlessPlanarMesh(tile) { const projection = tile.getProjection(); const builder = new RealityMeshParams_1.RealityMeshParamsBuilder({ positionRange: projection.localRange, initialVertexCapacity: 4, initialIndexCapacity: 6, }); const uv = new core_geometry_1.Point2d(); const pos = new core_geometry_1.Point3d(); for (let v = 0; v < 2; v++) { for (let u = 0; u < 2; u++) { core_geometry_1.Point2d.create(u, 1 - v, uv); builder.addUnquantizedVertex(projection.getPoint(u, v, 0, pos), uv); } } builder.addQuad(0, 1, 2, 3); return builder.finish(); } createSkirtedPlanarMesh(tile) { const projection = tile.getProjection(); const positions = []; const uvs = []; const skirtHeight = tile.range.xLength() / 20; for (let v = 0, i = 0; v < 2; v++) { for (let u = 0; u < 2; u++) { for (let h = 0; h < 2; h++) { positions.push(projection.getPoint(u, v, h * skirtHeight)); uvs[i] = new core_geometry_1.Point2d(u, 1 - v); i++; } } } const builder = new RealityMeshParams_1.RealityMeshParamsBuilder({ initialVertexCapacity: 8, initialIndexCapacity: 30, positionRange: core_geometry_1.Range3d.createArray(positions), }); for (let i = 0; i < 8; i++) builder.addUnquantizedVertex(positions[i], uvs[i]); builder.addQuad(0, 2, 4, 6); const reorder = [0, 2, 6, 4, 0]; for (let i = 0; i < 4; i++) { const iThis = reorder[i], iNext = reorder[i + 1]; builder.addQuad(iThis, iNext, iThis + 1, iNext + 1); } return builder.finish(); } /** @internal override */ async readMesh(args) { const tile = args.tile; if (tile.isPlanar) return this._wantSkirts ? this.createSkirtedPlanarMesh(tile) : this.createSkirtlessPlanarMesh(tile); return this.createGlobeMesh(tile); } createGlobeMesh(tile) { const globeMeshDimension = 10; const projection = tile.getProjection(); const ellipsoidPatch = projection.ellipsoidPatch; (0, core_bentley_1.assert)(undefined !== ellipsoidPatch); if (!ellipsoidPatch) return undefined; const bordersSouthPole = tile.quadId.bordersSouthPole(this._tilingScheme); const bordersNorthPole = tile.quadId.bordersNorthPole(this._tilingScheme); const range = projection.localRange.clone(); const delta = 1 / (globeMeshDimension - 3); const skirtFraction = delta / 2; const dimensionM1 = globeMeshDimension - 1; const dimensionM2 = globeMeshDimension - 2; ellipsoidPatch.ellipsoid.transformRef.clone(scratchEllipsoid.transformRef); const skirtPatch = core_geometry_1.EllipsoidPatch.createCapture(scratchEllipsoid, ellipsoidPatch.longitudeSweep, ellipsoidPatch.latitudeSweep); const scaleFactor = Math.max(0.99, 1 - Math.sin(ellipsoidPatch.longitudeSweep.sweepRadians * delta)); skirtPatch.ellipsoid.transformRef.matrix.scaleColumnsInPlace(scaleFactor, scaleFactor, scaleFactor); const pointCount = globeMeshDimension * globeMeshDimension; const rowMin = (bordersNorthPole || this._wantSkirts) ? 0 : 1; const rowMax = (bordersSouthPole || this._wantSkirts) ? dimensionM1 : dimensionM2; const colMin = this._wantSkirts ? 0 : 1; const colMax = this._wantSkirts ? dimensionM1 : dimensionM2; const indexCount = 6 * (rowMax - rowMin) * (colMax - colMin); const builder = new RealityMeshParams_1.RealityMeshParamsBuilder({ positionRange: range, initialVertexCapacity: pointCount, initialIndexCapacity: indexCount, }); for (let iRow = 0, index = 0; iRow < globeMeshDimension; iRow++) { for (let iColumn = 0; iColumn < globeMeshDimension; iColumn++, index++) { let u = (iColumn ? (Math.min(dimensionM2, iColumn) - 1) : 0) * delta; let v = (iRow ? (Math.min(dimensionM2, iRow) - 1) : 0) * delta; scratchPoint2d.set(u, 1 - v); if (iRow === 0 || iRow === dimensionM1 || iColumn === 0 || iColumn === dimensionM1) { if (bordersSouthPole && iRow === dimensionM1) skirtPatch.ellipsoid.radiansToPoint(0, -core_geometry_1.Angle.piOver2Radians, scratchPoint); else if (bordersNorthPole && iRow === 0) skirtPatch.ellipsoid.radiansToPoint(0, core_geometry_1.Angle.piOver2Radians, scratchPoint); else { u += (iColumn === 0) ? -skirtFraction : (iColumn === dimensionM1 ? skirtFraction : 0); v += (iRow === 0) ? -skirtFraction : (iRow === dimensionM1 ? skirtFraction : 0); skirtPatch.uvFractionToPoint(u, v, scratchPoint); } } else { projection.getPoint(u, v, 0, scratchPoint); } builder.addUnquantizedVertex(scratchPoint, scratchPoint2d); } } for (let iRow = rowMin; iRow < rowMax; iRow++) { for (let iColumn = colMin; iColumn < colMax; iColumn++) { const base = iRow * globeMeshDimension + iColumn; const top = base + globeMeshDimension; builder.addTriangle(base, base + 1, top); builder.addTriangle(top, base + 1, top + 1); } } return builder.finish(); } /** Implements [[TerrainMeshProvider.requestMeshData]] to return an empty string because the mesh can be generated * purely from information provided by the [[MapTile]]. */ async requestMeshData() { return ""; } } exports.EllipsoidTerrainProvider = EllipsoidTerrainProvider; //# sourceMappingURL=EllipsoidTerrainProvider.js.map