rayzee 11.6.0 → 11.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +13 -14
  2. package/dist/{ArchiveImporter-iofnC8zB.js → ArchiveImporter-DYcRXeKE.js} +2 -2
  3. package/dist/{BidirectionalIntegrator-CqAilt2I.js → BidirectionalIntegrator-BvjRpbTP.js} +2 -2
  4. package/dist/{NeuralRetouch-DFI4pOjO.js → NeuralRetouch-ClaMiKYg.js} +1 -1
  5. package/dist/{NeuralSuperRes-ChCiiilS.js → NeuralSuperRes-WNEXun9s.js} +1 -1
  6. package/dist/{PathTracer-BX4sJLx7.js → PathTracer-B9wZPPVL.js} +6 -8
  7. package/dist/{PhysicalSky-Biv39eTA.js → PhysicalSky-DcjItqKi.js} +1 -1
  8. package/dist/{RayzeeRenderer-D8XRKU3A.js → RayzeeRenderer-p-NeE6E2.js} +2 -3
  9. package/dist/addons/archives.es.js +1 -1
  10. package/dist/addons/bidirectional.es.js +1 -1
  11. package/dist/addons/physical-sky.es.js +1 -1
  12. package/dist/rayzee-core.es.js +3 -3
  13. package/dist/rayzee.es.js +865 -1591
  14. package/dist/rayzee.umd.js +87 -134
  15. package/dist/{sceneCachePolicy-W5PLbzuR.js → sceneCachePolicy-B9w3BnaP.js} +1 -1
  16. package/package.json +1 -1
  17. package/src/Passes/OIDNDenoiser.js +9 -11
  18. package/src/PathTracerApp.js +6 -17
  19. package/src/Pipeline/BindingAudit.js +2 -3
  20. package/src/Pipeline/PipelineContext.js +0 -1
  21. package/src/Pipeline/RenderPipeline.js +1 -2
  22. package/src/Pipeline/RenderStage.js +1 -1
  23. package/src/Processor/PackedRayBuffer.js +2 -2
  24. package/src/Processor/StorageTexturePool.js +1 -1
  25. package/src/RayzeeRenderer.js +1 -1
  26. package/src/Stages/DenoiserSettings.js +5 -81
  27. package/src/Stages/MotionVector.js +21 -215
  28. package/src/Stages/NormalDepth.js +5 -5
  29. package/src/Stages/PathTracer.js +1 -1
  30. package/src/Stages/PathTracerStage.js +4 -17
  31. package/src/TSL/FinalWriteKernel.js +2 -2
  32. package/src/TSL/ShadeKernel.js +3 -3
  33. package/src/index.js +1 -1
  34. package/src/managers/DenoisingManager.js +78 -187
  35. package/src/Stages/ASVGF.js +0 -932
  36. package/src/Stages/BilateralFilter.js +0 -486
  37. package/src/Stages/EdgeFilter.js +0 -545
  38. package/src/Stages/Variance.js +0 -443
@@ -11,7 +11,7 @@ import { createLogger } from '../utils/Logger.js';
11
11
  const neuralLog = createLogger( 'neural' );
12
12
  import { CAMERA_PROJECTION_IDS } from '../EngineDefaults.js';
13
13
  import {
14
- DENOISER_DEFAULTS, ASVGF_QUALITY_PRESETS, NRD_DEFAULTS, NRD_QUALITY_PRESETS, NRD_PRESET_KEYS,
14
+ DENOISER_DEFAULTS, DENOISER_STRATEGIES, NRD_DEFAULTS, NRD_QUALITY_PRESETS, NRD_PRESET_KEYS,
15
15
  } from '../Stages/DenoiserSettings.js';
16
16
 
17
17
  // A refresh slower than this is a slideshow, not a live view, so the cadence swaps to a cheaper
@@ -85,7 +85,7 @@ const historyFade = ( samples ) => Math.max( 0, 1 - samples / HISTORY_HANDOFF_SA
85
85
 
86
86
  /**
87
87
  * Orchestrates all denoising, post-processing, and AI upscaling:
88
- * - Real-time denoiser strategy switching (ASVGF / NRD / EdgeAware / None)
88
+ * - Real-time denoiser strategy switching (OIDN / NRD / None)
89
89
  * - OIDN (offline denoise on render completion)
90
90
  * - AI Upscaler
91
91
  * - Auto-exposure coordination
@@ -118,7 +118,7 @@ export class DenoisingManager extends EventDispatcher {
118
118
  this.pipeline = pipeline;
119
119
 
120
120
  // Stage references — only used internally for orchestration
121
- this._stages = stages; // { pathTracer, asvgf, nrd, variance, bilateralFilter, edgeFilter, autoExposure, compositor }
121
+ this._stages = stages; // { pathTracer, normalDepth, motionVector, nrd, autoExposure, compositor }
122
122
 
123
123
  this._getExposure = getExposure;
124
124
  this._getSaturation = getSaturation;
@@ -349,7 +349,9 @@ export class DenoisingManager extends EventDispatcher {
349
349
  this.dispatchEvent( { type: EngineEvents.DENOISING_START, continuous: !! e.continuous } );
350
350
  this._denoiserEndHandler = e => {
351
351
 
352
- if ( this.denoiser?.hasOutput ) this._publishOutput();
352
+ // A refresh that lands after the live view stopped wanting one would cover what replaced it.
353
+ const current = ! e.continuous || ( this.continuousDenoise && ! this._cadenceSuspended );
354
+ if ( this.denoiser?.hasOutput && current ) this._publishOutput();
353
355
  this.dispatchEvent( { type: EngineEvents.DENOISING_END, continuous: !! e.continuous } );
354
356
 
355
357
  };
@@ -447,9 +449,8 @@ export class DenoisingManager extends EventDispatcher {
447
449
  // ── Denoiser Strategy ─────────────────────────────────────────
448
450
 
449
451
  /**
450
- * Active real-time denoiser, derived from stage state so it can't drift from
451
- * setDenoiserStrategy / setASVGFEnabled.
452
- * @returns {'asvgf'|'nrd'|'edgeaware'|'none'}
452
+ * Active real-time denoiser, derived from stage state so it can't drift from setDenoiserStrategy.
453
+ * @returns {'none'|'nrd'|'oidn'}
453
454
  */
454
455
  get denoiserStrategy() {
455
456
 
@@ -457,105 +458,55 @@ export class DenoisingManager extends EventDispatcher {
457
458
  // belongs in the same one-of-N choice. Two of these running at once would mean paying for
458
459
  // a per-frame denoise whose result the OIDN overlay then covers.
459
460
  if ( this.continuousDenoise ) return 'oidn';
460
- if ( this._stages.asvgf?.enabled ) return 'asvgf';
461
461
  if ( this._stages.nrd?.enabled ) return 'nrd';
462
- if ( this._stages.edgeFilter?.enabled ) return 'edgeaware';
463
462
  return 'none';
464
463
 
465
464
  }
466
465
 
467
466
  /**
468
467
  * Switches the real-time denoiser strategy.
469
- * @param {string} strategy - 'none' | 'asvgf' | 'nrd' | 'edgeaware'
470
- * @param {string} [preset] - quality preset for 'asvgf' (ASVGF_QUALITY_PRESETS) or 'nrd' (NRD_QUALITY_PRESETS)
468
+ * @param {string} strategy - one of DENOISER_STRATEGIES; any other name is recorded and runs 'none'
469
+ * @param {string} [preset] - NRD quality preset (NRD_QUALITY_PRESETS)
471
470
  */
472
471
  setDenoiserStrategy( strategy, preset ) {
473
472
 
474
473
  const s = this._stages;
475
474
 
476
- // Disable all real-time denoisers first
477
- if ( s.asvgf ) s.asvgf.enabled = false;
478
- if ( s.nrd ) s.nrd.enabled = false;
479
- if ( s.variance ) s.variance.enabled = false;
480
- if ( s.bilateralFilter ) s.bilateralFilter.enabled = false;
481
- if ( s.edgeFilter ) s.edgeFilter.setFilteringEnabled( false );
475
+ if ( ! DENOISER_STRATEGIES.includes( strategy ) ) {
482
476
 
483
- this._clearDenoiserTextures();
484
-
485
- // Which denoiser owns the live view. Deliberately says nothing about the finished image:
486
- // wanting OIDN on the viewport is not the same as opting into a final pass.
487
- this.setContinuousDenoise( strategy === 'oidn' );
488
-
489
- switch ( strategy ) {
490
-
491
- case 'asvgf':
492
- s.asvgf.enabled = true;
493
- if ( s.variance ) s.variance.enabled = true;
494
- if ( s.bilateralFilter ) s.bilateralFilter.enabled = true;
495
- s.asvgf.setTemporalEnabled?.( true );
496
- this._applyASVGFPreset( preset || 'medium' );
497
- break;
477
+ this._issues?.record(
478
+ ISSUE_CODES.DENOISER_UNAVAILABLE,
479
+ `'${strategy}' is not a live denoiser (${DENOISER_STRATEGIES.join( ', ' )}) — none is used`,
480
+ { strategy }
481
+ );
482
+ strategy = 'none';
498
483
 
499
- case 'nrd':
500
- if ( s.nrd ) {
501
-
502
- s.nrd.enabled = true;
503
- // Stale history from the last time it ran describes another view.
504
- s.nrd.resetHistory?.();
505
- this._applyNRDPreset( preset || 'medium' );
506
-
507
- }
484
+ }
508
485
 
509
- break;
486
+ // NRD reprojects through motion vectors, which mean nothing once every pixel is its own direction.
487
+ if ( strategy === 'nrd' && this._isPanorama() ) {
510
488
 
511
- case 'edgeaware':
512
- // EdgeAware is a spatial-only SVGF à-trous — it consumes the Variance
513
- // stage's per-pixel variance to drive its luminance edge-stop.
514
- if ( s.variance ) s.variance.enabled = true;
515
- if ( s.edgeFilter ) s.edgeFilter.setFilteringEnabled( true );
516
- break;
489
+ this._issues?.record( ISSUE_CODES.DENOISER_UNAVAILABLE, 'NRD cannot run in a panorama — oidn is used', { strategy } );
490
+ strategy = 'oidn';
517
491
 
518
492
  }
519
493
 
520
- this._syncGBufferStages();
521
-
522
- }
523
-
524
- /**
525
- * Enables/disables ASVGF denoising with coordination of related stages.
526
- * @param {boolean} enabled
527
- * @param {string} [qualityPreset]
528
- */
529
- setASVGFEnabled( enabled, qualityPreset ) {
494
+ this._clearDenoiserTextures();
530
495
 
531
- const s = this._stages;
532
- if ( s.asvgf ) s.asvgf.enabled = enabled;
533
- if ( s.variance ) s.variance.enabled = enabled;
534
- if ( s.bilateralFilter ) s.bilateralFilter.enabled = enabled;
496
+ if ( s.nrd ) s.nrd.enabled = strategy === 'nrd';
535
497
 
536
- if ( enabled ) {
498
+ if ( s.nrd?.enabled ) {
537
499
 
538
- // One real-time denoiser at a time.
539
- if ( s.nrd ) s.nrd.enabled = false;
540
- s.asvgf?.setTemporalEnabled?.( true );
541
- this._applyASVGFPreset( qualityPreset || 'medium' );
500
+ // Stale history from the last time it ran describes another view.
501
+ s.nrd.resetHistory?.();
502
+ this._applyNRDPreset( preset || 'medium' );
542
503
 
543
504
  }
544
505
 
545
- // Coordinate with EdgeAware filtering
546
- if ( s.edgeFilter ) s.edgeFilter.setFilteringEnabled( ! enabled );
547
-
548
- this._syncGBufferStages();
549
-
550
- }
551
-
552
- /**
553
- * Applies an ASVGF quality preset.
554
- * @param {string} presetName - 'low' | 'medium' | 'high'
555
- */
556
- applyASVGFPreset( presetName ) {
557
-
558
- this._applyASVGFPreset( presetName );
506
+ // Which denoiser owns the live view. Deliberately says nothing about the finished image:
507
+ // wanting OIDN on the viewport is not the same as opting into a final pass. Also re-syncs
508
+ // the G-buffer stages, so NRD must already be set.
509
+ this.setContinuousDenoise( strategy === 'oidn' );
559
510
 
560
511
  }
561
512
 
@@ -569,6 +520,13 @@ export class DenoisingManager extends EventDispatcher {
569
520
 
570
521
  }
571
522
 
523
+ /** True while a strategy that reprojects through motion vectors is active. */
524
+ get requiresMotionVectors() {
525
+
526
+ return !! this._stages.nrd?.enabled;
527
+
528
+ }
529
+
572
530
  /**
573
531
  * Gate the G-buffer stages (NormalDepth, MotionVector) on demand: they only
574
532
  * need to run when a real-time denoiser consumes their output. Idling them
@@ -576,17 +534,10 @@ export class DenoisingManager extends EventDispatcher {
576
534
  * navigation and frees their textures. Call after any consumer toggle.
577
535
  *
578
536
  * MotionVector requires NormalDepth (reads pathtracer:normalDepth) and its
579
- * consumers (ASVGF, NRD) are a subset of NormalDepth's, so NormalDepth is
580
- * always enabled whenever MotionVector is. Adaptive sampling / Variance / OIDN
581
- * do NOT read these signals, so they don't keep the G-buffer alive.
537
+ * consumer (NRD) also reads NormalDepth, so NormalDepth is always enabled
538
+ * whenever MotionVector is. Adaptive sampling and OIDN's own pass do NOT read
539
+ * these signals; only OIDN's motion history keeps NormalDepth alive.
582
540
  */
583
- /** True while a strategy that reprojects through motion vectors is active. */
584
- get requiresMotionVectors() {
585
-
586
- return !! ( this._stages.asvgf?.enabled || this._stages.nrd?.enabled );
587
-
588
- }
589
-
590
541
  _syncGBufferStages() {
591
542
 
592
543
  const s = this._stages;
@@ -594,8 +545,8 @@ export class DenoisingManager extends EventDispatcher {
594
545
  const mv = s.motionVector;
595
546
 
596
547
  const motionNeeded = this.requiresMotionVectors;
597
- // pathtracer:normalDepth consumed by ASVGF, NRD, EdgeFilter, BilateralFilter, the OIDN history
598
- const normalNeeded = motionNeeded || this.historyWanted || !! ( s.edgeFilter?.enabled || s.bilateralFilter?.enabled );
548
+ // pathtracer:normalDepth consumed by NRD and the OIDN history
549
+ const normalNeeded = motionNeeded || this.historyWanted;
599
550
  if ( ! this.historyWanted ) this._releaseHistory();
600
551
 
601
552
  if ( nd ) {
@@ -612,21 +563,14 @@ export class DenoisingManager extends EventDispatcher {
612
563
 
613
564
  // On re-enable, force a camera-history reseed (matricesInitialized survives
614
565
  // normal resets) so the first frame reports zero motion, not a spike.
615
- if ( motionNeeded && ! mv.enabled ) {
616
-
617
- mv.matricesInitialized = false;
618
- mv.isFirstFrame = true;
619
- mv.frameCount = 0;
620
-
621
- }
566
+ if ( motionNeeded && ! mv.enabled ) mv.matricesInitialized = false;
622
567
 
623
568
  mv.enabled = motionNeeded;
624
569
 
625
570
  }
626
571
 
627
- // PathTracer's aux MRT (normalDepth + albedo) is consumed by the real-time denoisers (ASVGF/
628
- // BilateralFilter read albedo; ASVGF/EdgeFilter read normalDepth) and by OIDN (reads the
629
- // MRT read-targets directly). When none are active the wavefront skips those writes entirely.
572
+ // PathTracer's aux MRT (normalDepth + albedo) is consumed by NRD (albedo, hit distance) and by
573
+ // OIDN (reads the MRT read-targets directly). When neither is active the wavefront skips those writes.
630
574
  s.pathTracer?.setAuxGBufferEnabled?.( normalNeeded || !! this.denoiser?.enabled );
631
575
 
632
576
  // Clean-aux normal: temporally accumulate the aux normal only for OIDN clean-aux models
@@ -641,7 +585,7 @@ export class DenoisingManager extends EventDispatcher {
641
585
  // disabled (lazily re-created on the next dispatch after re-enable). Every strategy/denoiser
642
586
  // toggle funnels through here after the enabled flags above are settled, so this is the one
643
587
  // choke point. dispose() is idempotent, so re-running it for an already-released stage is a no-op.
644
- for ( const stage of [ s.asvgf, s.nrd, s.variance, s.bilateralFilter, s.edgeFilter, nd, mv ] ) {
588
+ for ( const stage of [ s.nrd, nd, mv ] ) {
645
589
 
646
590
  if ( stage && ! stage.enabled ) stage.releaseGPUMemory?.();
647
591
 
@@ -849,21 +793,29 @@ export class DenoisingManager extends EventDispatcher {
849
793
 
850
794
  this._cadenceSuspended = !! suspended;
851
795
  this._historyDirty = true;
852
- if ( ! this._cadenceSuspended ) return;
853
796
 
854
- // The accumulation is what a final render shows; a held preview frame would otherwise sit
855
- // over it until the render finished.
856
- this.denoiser?.abort();
857
- this._unpublishOutput();
797
+ if ( this._cadenceSuspended ) {
798
+
799
+ // The accumulation is what a final render shows; a held preview frame would otherwise sit
800
+ // over it until the render finished.
801
+ this.denoiser?.abort();
802
+ this._unpublishOutput();
803
+
804
+ }
805
+
806
+ this._syncGBufferStages();
858
807
 
859
808
  }
860
809
 
861
810
  setContinuousDenoise( enabled ) {
862
811
 
812
+ // Once nothing else uses OIDN it turns off, and a disabled denoiser can no longer be aborted.
813
+ if ( ! enabled && ! this.finalDenoise ) this.denoiser?.abort();
863
814
  this.continuousDenoise = !! enabled;
864
815
  this._syncOIDNInUse();
865
816
  this._lastCadenceAt = - Infinity;
866
817
  this._resetCadence();
818
+ this._syncGBufferStages();
867
819
 
868
820
  }
869
821
 
@@ -895,19 +847,24 @@ export class DenoisingManager extends EventDispatcher {
895
847
 
896
848
  }
897
849
 
898
- // Not at a size proven too slow to denoise while moving: the raw render owns the view there.
850
+ // Not at a size proven too slow to denoise while moving (the raw render owns the view there), nor
851
+ // through a final render or a panorama, which never reproject it.
899
852
  get historyWanted() {
900
853
 
901
- return this.temporalHistory && this.continuousDenoise && !! this.denoiser?.enabled && ! this._movingHopeless;
854
+ return this.temporalHistory && this.continuousDenoise && !! this.denoiser?.enabled && ! this._movingHopeless
855
+ && ! this._cadenceSuspended && ! this._isPanorama();
902
856
 
903
857
  }
904
858
 
905
859
  get historyActive() {
906
860
 
907
- const pt = this._stages.pathTracer;
908
- return this.historyWanted && ! this._cadenceSuspended && !! this._stages.normalDepth?.enabled
909
- && pt?.uniforms?.get( 'cameraProjection' )?.value !== CAMERA_PROJECTION_IDS.equirectangular
910
- && ! ( pt?.visMode?.value > 0 );
861
+ return this.historyWanted && !! this._stages.normalDepth?.enabled && ! ( this._stages.pathTracer?.visMode?.value > 0 );
862
+
863
+ }
864
+
865
+ _isPanorama() {
866
+
867
+ return this._stages.pathTracer?.uniforms?.get( 'cameraProjection' )?.value === CAMERA_PROJECTION_IDS.equirectangular;
911
868
 
912
869
  }
913
870
 
@@ -1443,7 +1400,9 @@ export class DenoisingManager extends EventDispatcher {
1443
1400
  // What closes the render, if anything. A full pass at the chosen tier when that switch is
1444
1401
  // on; otherwise, if OIDN owns the live view, one last cheap refresh — the cadence's last
1445
1402
  // tick lands a few samples short, and the picture should match the render that finished.
1446
- const closing = this.finalDenoise ? 'final' : this.continuousDenoise ? 'refresh' : null;
1403
+ // A final render has no live view to match, so with the switch off it stays undenoised.
1404
+ const live = this.continuousDenoise && ! this._cadenceSuspended;
1405
+ const closing = this.finalDenoise ? 'final' : live ? 'refresh' : null;
1447
1406
 
1448
1407
  // Registered only once the closing denoise has been launched, so the next 'end' is
1449
1408
  // unambiguously that one — a cadence run's end can look identical otherwise.
@@ -1686,53 +1645,6 @@ export class DenoisingManager extends EventDispatcher {
1686
1645
  // These methods match the DenoisingAPI surface so call sites need
1687
1646
  // zero or minimal changes after facade removal.
1688
1647
 
1689
- /** Updates ASVGF stage parameters. */
1690
- setASVGFParams( params ) {
1691
-
1692
- this._stages.asvgf?.updateParameters( params );
1693
-
1694
- }
1695
-
1696
- /**
1697
- * Toggle the ASVGF heatmap compute pass. When enabled, the stage writes
1698
- * the heatmap to its public `heatmapTarget` RenderTarget — the host is
1699
- * responsible for rendering it.
1700
- */
1701
- toggleASVGFHeatmap( enabled ) {
1702
-
1703
- this._stages.asvgf?.setHeatmapEnabled?.( enabled );
1704
-
1705
- }
1706
-
1707
- /**
1708
- * Configures ASVGF for a specific render mode (multi-stage coordination).
1709
- * @param {Object} config - { enabled, temporalAlpha, atrousIterations, ... }
1710
- */
1711
- configureASVGFForMode( config ) {
1712
-
1713
- if ( ! this._stages.asvgf ) return;
1714
-
1715
- this._stages.asvgf.enabled = config.enabled;
1716
- if ( this._stages.variance ) this._stages.variance.enabled = config.enabled;
1717
- if ( this._stages.bilateralFilter ) this._stages.bilateralFilter.enabled = config.enabled;
1718
-
1719
- if ( config.enabled ) {
1720
-
1721
- this._stages.asvgf.updateParameters( config );
1722
-
1723
- }
1724
-
1725
- this._syncGBufferStages();
1726
-
1727
- }
1728
-
1729
- /** Updates edge-aware filtering parameters. */
1730
- setEdgeAwareParams( params ) {
1731
-
1732
- this._stages.edgeFilter?.updateUniforms( params );
1733
-
1734
- }
1735
-
1736
1648
  /** Updates auto-exposure stage parameters. */
1737
1649
  setAutoExposureParams( params ) {
1738
1650
 
@@ -1850,7 +1762,7 @@ export class DenoisingManager extends EventDispatcher {
1850
1762
 
1851
1763
  /**
1852
1764
  * Switches strategy with automatic reset (convenience wrapper).
1853
- * @param {'none'|'asvgf'|'nrd'|'edgeaware'} strategy
1765
+ * @param {'none'|'nrd'|'oidn'} strategy
1854
1766
  * @param {string} [preset]
1855
1767
  */
1856
1768
  setStrategy( strategy, preset ) {
@@ -1919,12 +1831,8 @@ export class DenoisingManager extends EventDispatcher {
1919
1831
  const ctx = this.pipeline?.context;
1920
1832
  if ( ! ctx ) return;
1921
1833
 
1922
- const keys = [
1923
- 'asvgf:output', 'asvgf:demodulated', 'asvgf:gradient',
1924
- 'variance:output', 'bilateralFiltering:output',
1925
- 'edgeFiltering:output', 'nrd:output', 'oidn:output',
1926
- ];
1927
- keys.forEach( k => ctx.removeTexture( k ) );
1834
+ ctx.removeTexture( 'nrd:output' );
1835
+ ctx.removeTexture( 'oidn:output' );
1928
1836
 
1929
1837
  }
1930
1838
 
@@ -1939,21 +1847,4 @@ export class DenoisingManager extends EventDispatcher {
1939
1847
 
1940
1848
  }
1941
1849
 
1942
- _applyASVGFPreset( presetName ) {
1943
-
1944
- const preset = ASVGF_QUALITY_PRESETS[ presetName ];
1945
- if ( ! preset ) return;
1946
- // ASVGF consumes temporalAlpha / gradientStrength / maxAccumFrames.
1947
- // BilateralFilter consumes phi* edge-stopping params and atrousIterations.
1948
- // Variance consumes varianceBoost. Each stage cherry-picks what it needs.
1949
- this._stages.asvgf?.updateParameters( preset );
1950
- this._stages.bilateralFilter?.updateParameters( preset );
1951
- if ( this._stages.variance && preset.varianceBoost !== undefined ) {
1952
-
1953
- this._stages.variance.varianceBoost.value = preset.varianceBoost;
1954
-
1955
- }
1956
-
1957
- }
1958
-
1959
1850
  }