123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734 |
- import { EngineStore } from "../Engines/engineStore.js";
- import { Mesh } from "../Meshes/mesh.js";
- import { Observable } from "./observable.js";
- /**
- * Defines the root class used to create scene optimization to use with SceneOptimizer
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- return true;
- }
- /**
- * Creates the SceneOptimization object
- * @param priority defines the priority of this optimization (0 by default which means first in the list)
- */
- constructor(
- /**
- * Defines the priority of this optimization (0 by default which means first in the list)
- */
- priority = 0) {
- this.priority = priority;
- }
- }
- /**
- * Defines an optimization used to reduce the size of render target textures
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class TextureOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Reducing render target texture size to " + this.maximumSize;
- }
- /**
- * Creates the TextureOptimization object
- * @param priority defines the priority of this optimization (0 by default which means first in the list)
- * @param maximumSize defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
- * @param step defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
- */
- constructor(
- /**
- * Defines the priority of this optimization (0 by default which means first in the list)
- */
- priority = 0,
- /**
- * Defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
- */
- maximumSize = 1024,
- /**
- * Defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
- */
- step = 0.5) {
- super(priority);
- this.priority = priority;
- this.maximumSize = maximumSize;
- this.step = step;
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- let allDone = true;
- for (let index = 0; index < scene.textures.length; index++) {
- const texture = scene.textures[index];
- if (!texture.canRescale || texture.getContext) {
- continue;
- }
- const currentSize = texture.getSize();
- const maxDimension = Math.max(currentSize.width, currentSize.height);
- if (maxDimension > this.maximumSize) {
- texture.scale(this.step);
- allDone = false;
- }
- }
- return allDone;
- }
- }
- /**
- * Defines an optimization used to increase or decrease the rendering resolution
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class HardwareScalingOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Setting hardware scaling level to " + this._currentScale;
- }
- /**
- * Creates the HardwareScalingOptimization object
- * @param priority defines the priority of this optimization (0 by default which means first in the list)
- * @param maximumScale defines the maximum scale to use (2 by default)
- * @param step defines the step to use between two passes (0.5 by default)
- */
- constructor(
- /**
- * Defines the priority of this optimization (0 by default which means first in the list)
- */
- priority = 0,
- /**
- * Defines the maximum scale to use (2 by default)
- */
- maximumScale = 2,
- /**
- * Defines the step to use between two passes (0.5 by default)
- */
- step = 0.25) {
- super(priority);
- this.priority = priority;
- this.maximumScale = maximumScale;
- this.step = step;
- this._currentScale = -1;
- this._directionOffset = 1;
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- if (this._currentScale === -1) {
- this._currentScale = scene.getEngine().getHardwareScalingLevel();
- if (this._currentScale > this.maximumScale) {
- this._directionOffset = -1;
- }
- }
- this._currentScale += this._directionOffset * this.step;
- scene.getEngine().setHardwareScalingLevel(this._currentScale);
- return this._directionOffset === 1 ? this._currentScale >= this.maximumScale : this._currentScale <= this.maximumScale;
- }
- }
- /**
- * Defines an optimization used to remove shadows
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class ShadowsOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Turning shadows on/off";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- scene.shadowsEnabled = optimizer.isInImprovementMode;
- return true;
- }
- }
- /**
- * Defines an optimization used to turn post-processes off
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class PostProcessesOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Turning post-processes on/off";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- scene.postProcessesEnabled = optimizer.isInImprovementMode;
- return true;
- }
- }
- /**
- * Defines an optimization used to turn lens flares off
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class LensFlaresOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Turning lens flares on/off";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- scene.lensFlaresEnabled = optimizer.isInImprovementMode;
- return true;
- }
- }
- /**
- * Defines an optimization based on user defined callback.
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class CustomOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- if (this.onGetDescription) {
- return this.onGetDescription();
- }
- return "Running user defined callback";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- if (this.onApply) {
- return this.onApply(scene, optimizer);
- }
- return true;
- }
- }
- /**
- * Defines an optimization used to turn particles off
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class ParticlesOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Turning particles on/off";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- scene.particlesEnabled = optimizer.isInImprovementMode;
- return true;
- }
- }
- /**
- * Defines an optimization used to turn render targets off
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class RenderTargetsOptimization extends SceneOptimization {
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Turning render targets off";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer) {
- scene.renderTargetsEnabled = optimizer.isInImprovementMode;
- return true;
- }
- }
- /**
- * Defines an optimization used to merge meshes with compatible materials
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class MergeMeshesOptimization extends SceneOptimization {
- constructor() {
- super(...arguments);
- this._canBeMerged = (abstractMesh) => {
- if (!(abstractMesh instanceof Mesh)) {
- return false;
- }
- const mesh = abstractMesh;
- if (mesh.isDisposed()) {
- return false;
- }
- if (!mesh.isVisible || !mesh.isEnabled()) {
- return false;
- }
- if (mesh.instances.length > 0) {
- return false;
- }
- if (mesh.skeleton || mesh.hasLODLevels) {
- return false;
- }
- if (mesh.getTotalVertices() === 0) {
- return false;
- }
- return true;
- };
- }
- /**
- * Gets or sets a boolean which defines if optimization octree has to be updated
- */
- static get UpdateSelectionTree() {
- return MergeMeshesOptimization._UpdateSelectionTree;
- }
- /**
- * Gets or sets a boolean which defines if optimization octree has to be updated
- */
- static set UpdateSelectionTree(value) {
- MergeMeshesOptimization._UpdateSelectionTree = value;
- }
- /**
- * Gets a string describing the action executed by the current optimization
- * @returns description string
- */
- getDescription() {
- return "Merging similar meshes together";
- }
- /**
- * This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
- * @param scene defines the current scene where to apply this optimization
- * @param optimizer defines the current optimizer
- * @param updateSelectionTree defines that the selection octree has to be updated (false by default)
- * @returns true if everything that can be done was applied
- */
- apply(scene, optimizer, updateSelectionTree) {
- const globalPool = scene.meshes.slice(0);
- let globalLength = globalPool.length;
- for (let index = 0; index < globalLength; index++) {
- const currentPool = [];
- const current = globalPool[index];
- // Checks
- if (!this._canBeMerged(current)) {
- continue;
- }
- currentPool.push(current);
- // Find compatible meshes
- for (let subIndex = index + 1; subIndex < globalLength; subIndex++) {
- const otherMesh = globalPool[subIndex];
- if (!this._canBeMerged(otherMesh)) {
- continue;
- }
- if (otherMesh.material !== current.material) {
- continue;
- }
- if (otherMesh.checkCollisions !== current.checkCollisions) {
- continue;
- }
- currentPool.push(otherMesh);
- globalLength--;
- globalPool.splice(subIndex, 1);
- subIndex--;
- }
- if (currentPool.length < 2) {
- continue;
- }
- // Merge meshes
- Mesh.MergeMeshes(currentPool, undefined, true);
- }
- // Call the octree system optimization if it is defined.
- const sceneAsAny = scene;
- if (sceneAsAny.createOrUpdateSelectionOctree) {
- if (updateSelectionTree != undefined) {
- if (updateSelectionTree) {
- sceneAsAny.createOrUpdateSelectionOctree();
- }
- }
- else if (MergeMeshesOptimization.UpdateSelectionTree) {
- sceneAsAny.createOrUpdateSelectionOctree();
- }
- }
- return true;
- }
- }
- MergeMeshesOptimization._UpdateSelectionTree = false;
- /**
- * Defines a list of options used by SceneOptimizer
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class SceneOptimizerOptions {
- /**
- * Creates a new list of options used by SceneOptimizer
- * @param targetFrameRate defines the target frame rate to reach (60 by default)
- * @param trackerDuration defines the interval between two checks (2000ms by default)
- */
- constructor(
- /**
- * Defines the target frame rate to reach (60 by default)
- */
- targetFrameRate = 60,
- /**
- * Defines the interval between two checks (2000ms by default)
- */
- trackerDuration = 2000) {
- this.targetFrameRate = targetFrameRate;
- this.trackerDuration = trackerDuration;
- /**
- * Gets the list of optimizations to apply
- */
- this.optimizations = [];
- }
- /**
- * Add a new optimization
- * @param optimization defines the SceneOptimization to add to the list of active optimizations
- * @returns the current SceneOptimizerOptions
- */
- addOptimization(optimization) {
- this.optimizations.push(optimization);
- return this;
- }
- /**
- * Add a new custom optimization
- * @param onApply defines the callback called to apply the custom optimization (true if everything that can be done was applied)
- * @param onGetDescription defines the callback called to get the description attached with the optimization.
- * @param priority defines the priority of this optimization (0 by default which means first in the list)
- * @returns the current SceneOptimizerOptions
- */
- addCustomOptimization(onApply, onGetDescription, priority = 0) {
- const optimization = new CustomOptimization(priority);
- optimization.onApply = onApply;
- optimization.onGetDescription = onGetDescription;
- this.optimizations.push(optimization);
- return this;
- }
- /**
- * Creates a list of pre-defined optimizations aimed to reduce the visual impact on the scene
- * @param targetFrameRate defines the target frame rate (60 by default)
- * @returns a SceneOptimizerOptions object
- */
- static LowDegradationAllowed(targetFrameRate) {
- const result = new SceneOptimizerOptions(targetFrameRate);
- let priority = 0;
- result.addOptimization(new MergeMeshesOptimization(priority));
- result.addOptimization(new ShadowsOptimization(priority));
- result.addOptimization(new LensFlaresOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new PostProcessesOptimization(priority));
- result.addOptimization(new ParticlesOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new TextureOptimization(priority, 1024));
- return result;
- }
- /**
- * Creates a list of pre-defined optimizations aimed to have a moderate impact on the scene visual
- * @param targetFrameRate defines the target frame rate (60 by default)
- * @returns a SceneOptimizerOptions object
- */
- static ModerateDegradationAllowed(targetFrameRate) {
- const result = new SceneOptimizerOptions(targetFrameRate);
- let priority = 0;
- result.addOptimization(new MergeMeshesOptimization(priority));
- result.addOptimization(new ShadowsOptimization(priority));
- result.addOptimization(new LensFlaresOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new PostProcessesOptimization(priority));
- result.addOptimization(new ParticlesOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new TextureOptimization(priority, 512));
- // Next priority
- priority++;
- result.addOptimization(new RenderTargetsOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new HardwareScalingOptimization(priority, 2));
- return result;
- }
- /**
- * Creates a list of pre-defined optimizations aimed to have a big impact on the scene visual
- * @param targetFrameRate defines the target frame rate (60 by default)
- * @returns a SceneOptimizerOptions object
- */
- static HighDegradationAllowed(targetFrameRate) {
- const result = new SceneOptimizerOptions(targetFrameRate);
- let priority = 0;
- result.addOptimization(new MergeMeshesOptimization(priority));
- result.addOptimization(new ShadowsOptimization(priority));
- result.addOptimization(new LensFlaresOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new PostProcessesOptimization(priority));
- result.addOptimization(new ParticlesOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new TextureOptimization(priority, 256));
- // Next priority
- priority++;
- result.addOptimization(new RenderTargetsOptimization(priority));
- // Next priority
- priority++;
- result.addOptimization(new HardwareScalingOptimization(priority, 4));
- return result;
- }
- }
- /**
- * Class used to run optimizations in order to reach a target frame rate
- * @description More details at https://doc.babylonjs.com/features/featuresDeepDive/scene/sceneOptimizer
- */
- export class SceneOptimizer {
- /**
- * Gets or sets a boolean indicating if the optimizer is in improvement mode
- */
- get isInImprovementMode() {
- return this._improvementMode;
- }
- set isInImprovementMode(value) {
- this._improvementMode = value;
- }
- /**
- * Gets the current priority level (0 at start)
- */
- get currentPriorityLevel() {
- return this._currentPriorityLevel;
- }
- /**
- * Gets the current frame rate checked by the SceneOptimizer
- */
- get currentFrameRate() {
- return this._currentFrameRate;
- }
- /**
- * Gets or sets the current target frame rate (60 by default)
- */
- get targetFrameRate() {
- return this._targetFrameRate;
- }
- /**
- * Gets or sets the current target frame rate (60 by default)
- */
- set targetFrameRate(value) {
- this._targetFrameRate = value;
- }
- /**
- * Gets or sets the current interval between two checks (every 2000ms by default)
- */
- get trackerDuration() {
- return this._trackerDuration;
- }
- /**
- * Gets or sets the current interval between two checks (every 2000ms by default)
- */
- set trackerDuration(value) {
- this._trackerDuration = value;
- }
- /**
- * Gets the list of active optimizations
- */
- get optimizations() {
- return this._options.optimizations;
- }
- /**
- * Creates a new SceneOptimizer
- * @param scene defines the scene to work on
- * @param options defines the options to use with the SceneOptimizer
- * @param autoGeneratePriorities defines if priorities must be generated and not read from SceneOptimization property (true by default)
- * @param improvementMode defines if the scene optimizer must run the maximum optimization while staying over a target frame instead of trying to reach the target framerate (false by default)
- */
- constructor(scene, options, autoGeneratePriorities = true, improvementMode = false) {
- this._isRunning = false;
- this._currentPriorityLevel = 0;
- this._targetFrameRate = 60;
- this._trackerDuration = 2000;
- this._currentFrameRate = 0;
- this._improvementMode = false;
- /**
- * Defines an observable called when the optimizer reaches the target frame rate
- */
- this.onSuccessObservable = new Observable();
- /**
- * Defines an observable called when the optimizer enables an optimization
- */
- this.onNewOptimizationAppliedObservable = new Observable();
- /**
- * Defines an observable called when the optimizer is not able to reach the target frame rate
- */
- this.onFailureObservable = new Observable();
- if (!options) {
- this._options = new SceneOptimizerOptions();
- }
- else {
- this._options = options;
- }
- if (this._options.targetFrameRate) {
- this._targetFrameRate = this._options.targetFrameRate;
- }
- if (this._options.trackerDuration) {
- this._trackerDuration = this._options.trackerDuration;
- }
- if (autoGeneratePriorities) {
- let priority = 0;
- for (const optim of this._options.optimizations) {
- optim.priority = priority++;
- }
- }
- this._improvementMode = improvementMode;
- this._scene = scene || EngineStore.LastCreatedScene;
- this._sceneDisposeObserver = this._scene.onDisposeObservable.add(() => {
- this._sceneDisposeObserver = null;
- this.dispose();
- });
- }
- /**
- * Stops the current optimizer
- */
- stop() {
- this._isRunning = false;
- }
- /**
- * Reset the optimizer to initial step (current priority level = 0)
- */
- reset() {
- this._currentPriorityLevel = 0;
- }
- /**
- * Start the optimizer. By default it will try to reach a specific framerate
- * but if the optimizer is set with improvementMode === true then it will run all optimization while frame rate is above the target frame rate
- */
- start() {
- if (this._isRunning) {
- return;
- }
- this._isRunning = true;
- // Let's wait for the scene to be ready before running our check
- this._scene.executeWhenReady(() => {
- setTimeout(() => {
- this._checkCurrentState();
- }, this._trackerDuration);
- });
- }
- _checkCurrentState() {
- if (!this._isRunning) {
- return;
- }
- const scene = this._scene;
- const options = this._options;
- this._currentFrameRate = Math.round(scene.getEngine().getFps());
- if ((this._improvementMode && this._currentFrameRate <= this._targetFrameRate) || (!this._improvementMode && this._currentFrameRate >= this._targetFrameRate)) {
- this._isRunning = false;
- this.onSuccessObservable.notifyObservers(this);
- return;
- }
- // Apply current level of optimizations
- let allDone = true;
- let noOptimizationApplied = true;
- for (let index = 0; index < options.optimizations.length; index++) {
- const optimization = options.optimizations[index];
- if (optimization.priority === this._currentPriorityLevel) {
- noOptimizationApplied = false;
- allDone = allDone && optimization.apply(scene, this);
- this.onNewOptimizationAppliedObservable.notifyObservers(optimization);
- }
- }
- // If no optimization was applied, this is a failure :(
- if (noOptimizationApplied) {
- this._isRunning = false;
- this.onFailureObservable.notifyObservers(this);
- return;
- }
- // If all optimizations were done, move to next level
- if (allDone) {
- this._currentPriorityLevel++;
- }
- // Let's the system running for a specific amount of time before checking FPS
- scene.executeWhenReady(() => {
- setTimeout(() => {
- this._checkCurrentState();
- }, this._trackerDuration);
- });
- }
- /**
- * Release all resources
- */
- dispose() {
- this.stop();
- this.onSuccessObservable.clear();
- this.onFailureObservable.clear();
- this.onNewOptimizationAppliedObservable.clear();
- if (this._sceneDisposeObserver) {
- this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
- }
- }
- /**
- * Helper function to create a SceneOptimizer with one single line of code
- * @param scene defines the scene to work on
- * @param options defines the options to use with the SceneOptimizer
- * @param onSuccess defines a callback to call on success
- * @param onFailure defines a callback to call on failure
- * @returns the new SceneOptimizer object
- */
- static OptimizeAsync(scene, options, onSuccess, onFailure) {
- const optimizer = new SceneOptimizer(scene, options || SceneOptimizerOptions.ModerateDegradationAllowed(), false);
- if (onSuccess) {
- optimizer.onSuccessObservable.add(() => {
- onSuccess();
- });
- }
- if (onFailure) {
- optimizer.onFailureObservable.add(() => {
- onFailure();
- });
- }
- optimizer.start();
- return optimizer;
- }
- }
- //# sourceMappingURL=sceneOptimizer.js.map
|