UNPKG

@itwin/core-frontend

Version:
225 lines • 10.1 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 Views */ Object.defineProperty(exports, "__esModule", { value: true }); exports.EnvironmentDecorations = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const core_geometry_1 = require("@itwin/core-geometry"); const ImageUtil_1 = require("./common/ImageUtil"); const IModelApp_1 = require("./IModelApp"); const GraphicType_1 = require("./common/render/GraphicType"); /** @internal */ class EnvironmentDecorations { _view; _onLoaded; _onDispose; _environment; _ground; _sky; constructor(view, onLoaded, onDispose) { this._environment = view.displayStyle.environment; this._view = view; this._onLoaded = onLoaded; this._onDispose = onDispose; this._sky = {}; this.loadSkyBox(); if (this._environment.displayGround) this.loadGround(); } [Symbol.dispose]() { this._ground = undefined; this._sky.params = this._sky.promise = undefined; this._onDispose(); } setEnvironment(env) { const prev = this._environment; if (prev === env) return; this._environment = env; // Update ground plane if (!env.displayGround || env.ground !== prev.ground) this._ground = undefined; if (env.displayGround && !this._ground) this.loadGround(); // Update sky box if (env.sky !== prev.sky) this.loadSkyBox(); } decorate(context) { const env = this._environment; let sky; if (env.displayAtmosphere) { sky = IModelApp_1.IModelApp.renderSystem.createSkyBox(this.createSkyGradientParams()); } else if (env.displaySky && this._sky.params) { sky = IModelApp_1.IModelApp.renderSystem.createSkyBox(this._sky.params); } if (sky) context.setSkyBox(sky); if (!env.displayGround || !this._ground) return; const extents = this._view.getGroundExtents(context.viewport); if (extents.isNull) return; const points = [extents.low.clone(), extents.low.clone(), extents.high.clone(), extents.high.clone()]; points[1].x = extents.high.x; points[3].x = extents.low.x; const aboveGround = this._view.isEyePointAbove(extents.low.z); const params = aboveGround ? this._ground.aboveParams : this._ground.belowParams; const builder = context.createGraphicBuilder(GraphicType_1.GraphicType.WorldDecoration); builder.activateGraphicParams(params); const strokeOptions = new core_geometry_1.StrokeOptions(); strokeOptions.needParams = true; const polyfaceBuilder = core_geometry_1.PolyfaceBuilder.create(strokeOptions); polyfaceBuilder.toggleReversedFacetFlag(); const uvParams = [core_geometry_1.Point2d.create(0, 0), core_geometry_1.Point2d.create(1, 0), core_geometry_1.Point2d.create(1, 1), core_geometry_1.Point2d.create(0, 1)]; polyfaceBuilder.addQuadFacet(points, uvParams); const polyface = polyfaceBuilder.claimPolyface(false); builder.addPolyface(polyface, true); context.addDecorationFromBuilder(builder); } loadGround() { (0, core_bentley_1.assert)(undefined === this._ground); const aboveParams = this.createGroundParams(true); const belowParams = this.createGroundParams(false); if (aboveParams && belowParams) this._ground = { aboveParams, belowParams }; } createGroundParams(above) { // Create a gradient texture. const ground = this._environment.ground; const values = [0, 0.25, 0.5]; const color = above ? ground.aboveColor : ground.belowColor; const alpha = above ? 0x80 : 0x85; const groundColors = [color.withTransparency(0xff), color, color]; groundColors[1] = groundColors[2] = color.withTransparency(alpha); const gradient = new core_common_1.Gradient.Symb(); gradient.mode = core_common_1.Gradient.Mode.Spherical; gradient.keys = [{ color: groundColors[0], value: values[0] }, { color: groundColors[1], value: values[1] }, { color: groundColors[2], value: values[2] }]; const texture = IModelApp_1.IModelApp.renderSystem.getGradientTexture(gradient, this._view.iModel); if (!texture) return undefined; // Create a material using the gradient texture const material = IModelApp_1.IModelApp.renderSystem.createRenderMaterial({ diffuse: { color: core_common_1.ColorDef.white, weight: 0 }, textureMapping: { texture, transform: new core_common_1.TextureMapping.Trans2x3(0, 1, 0, 1, 0, 0), }, }); if (!material) return undefined; // Create GraphicParams using the material. const params = new core_common_1.GraphicParams(); params.lineColor = gradient.keys[0].color; params.fillColor = core_common_1.ColorDef.white; // Fill should be set to opaque white for gradient texture... params.material = material; return params; } loadSkyBox() { const loader = this.loadSkyBoxParams(); if (undefined === loader.preload) { this.setSky(loader.load()); return; } const promise = loader.preload; this._sky.promise = promise; loader.preload.then((loaded) => { if (promise === this._sky.promise) this.setSky(loaded ? loader.load() : undefined); }).catch(() => { if (promise === this._sky.promise) this.setSky(undefined); }); } setSky(params) { this._sky.promise = undefined; this._sky.params = params ?? this.createSkyGradientParams(); this._onLoaded(); } loadSkyBoxParams() { let load; let preload; const sky = this._environment.sky; if (sky instanceof core_common_1.SkyCube) { const key = this.createCubeImageKey(sky); load = () => { const texture = IModelApp_1.IModelApp.renderSystem.findTexture(key, this._view.iModel); return texture ? { type: "cube", texture } : undefined; }; if (!IModelApp_1.IModelApp.renderSystem.findTexture(key, this._view.iModel)) { // Some faces may use the same image. Only request each image once. const promises = []; const specs = new Set([sky.images.front, sky.images.back, sky.images.left, sky.images.right, sky.images.top, sky.images.bottom]); for (const spec of specs) promises.push(this.imageFromSpec(spec)); preload = Promise.all(promises).then((images) => { const idToImage = new Map(); let index = 0; for (const spec of specs) { const image = images[index++]; if (!image) return false; else idToImage.set(spec, image); } const params = new core_common_1.RenderTextureParams(key, core_common_1.RenderTexture.Type.SkyBox); const txImgs = [ idToImage.get(sky.images.front), idToImage.get(sky.images.back), idToImage.get(sky.images.top), idToImage.get(sky.images.bottom), idToImage.get(sky.images.right), idToImage.get(sky.images.left), ]; return undefined !== IModelApp_1.IModelApp.renderSystem.createTextureFromCubeImages(txImgs[0], txImgs[1], txImgs[2], txImgs[3], txImgs[4], txImgs[5], this._view.iModel, params); }); } } else if (sky instanceof core_common_1.SkySphere) { load = () => { const texture = IModelApp_1.IModelApp.renderSystem.findTexture(sky.image, this._view.iModel); return texture ? { type: "sphere", texture, rotation: 0, zOffset: this._view.iModel.globalOrigin.z, } : undefined; }; if (!IModelApp_1.IModelApp.renderSystem.findTexture(sky.image, this._view.iModel)) { preload = this.imageFromSpec(sky.image).then((image) => { if (!image) return false; return undefined !== IModelApp_1.IModelApp.renderSystem.createTexture({ image: { source: image }, ownership: { iModel: this._view.iModel, key: sky.image }, }); }); } } else { load = () => this.createSkyGradientParams(); } return { load, preload }; } createCubeImageKey(sky) { const i = sky.images; return `skycube:${i.front}:${i.back}:${i.left}:${i.right}:${i.top}:${i.bottom}`; } createSkyGradientParams() { return { type: "gradient", gradient: this._environment.sky.gradient, zOffset: this._view.iModel.globalOrigin.z, }; } async imageFromSpec(spec) { if (core_bentley_1.Id64.isValidId64(spec)) return (await IModelApp_1.IModelApp.renderSystem.loadTextureImage(spec, this._view.iModel))?.image; return (0, ImageUtil_1.tryImageElementFromUrl)(spec); } } exports.EnvironmentDecorations = EnvironmentDecorations; //# sourceMappingURL=EnvironmentDecorations.js.map