@sequent-org/ifc-viewer 1.2.4-ci.42.0 → 1.2.4-ci.43.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/viewer/Viewer.js +116 -67
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sequent-org/ifc-viewer",
3
3
  "private": false,
4
- "version": "1.2.4-ci.42.0",
4
+ "version": "1.2.4-ci.43.0",
5
5
  "type": "module",
6
6
  "description": "IFC 3D model viewer component for web applications - fully self-contained with local IFCLoader",
7
7
  "main": "src/index.js",
@@ -148,10 +148,10 @@ export class Viewer {
148
148
  this._sectionClippingActive = false;
149
149
  /** @type {WeakMap<THREE.Mesh, any>} */
150
150
  this._sectionOriginalMaterial = new WeakMap();
151
- // +50% яркости при активном сечении (комнаты светлее)
152
- this._sectionLightBoost = { mul: 1.5, snapshot: null };
153
- // При активном сечении: AO выключаем (убирает "сетку"), а контраст возвращаем лёгкой цветокоррекцией
154
- this._sectionPostBoost = { snapshot: null, brightness: 0.03, contrast: 0.15 };
151
+ // Локальная подсветка "внутри": без теней, с малой дальностью (чтобы не пересвечивать фасад/внешнюю тень)
152
+ this._interiorAssist = { light: null, box: null, enabled: false, lastBoxAt: 0 };
153
+ // Пост-эффекты только "внутри": AO OFF (убирает "сетку"), чуть контраста (без глобального пересвета)
154
+ this._interiorPost = { snapshot: null, contrast: 0.12 };
155
155
 
156
156
  // Snapshot начального состояния для Home
157
157
  this._home = {
@@ -628,6 +628,9 @@ export class Viewer {
628
628
  this.setSunHeight(5.9);
629
629
  this.setShadowsEnabled(this.shadowsEnabled);
630
630
 
631
+ // Локальная подсветка "внутри" (по умолчанию скрыта)
632
+ this.#ensureInteriorAssistLight();
633
+
631
634
  // Демонстрационный куб отключён для чистого прелоадера
632
635
  // Оставим сцену пустой до загрузки модели
633
636
  // Добавим метод фокусировки объекта
@@ -755,6 +758,8 @@ export class Viewer {
755
758
  }
756
759
 
757
760
  if (this.controls) this.controls.update();
761
+ // "Внутренняя" подсветка/пост-эффекты: включаются только когда камера внутри модели
762
+ this.#updateInteriorAssist();
758
763
  this._notifyZoomIfChanged();
759
764
  if (this.renderer && this.camera && this.scene) {
760
765
  // Применим ТОЛЬКО активные (конечные) плоскости отсечения
@@ -1960,69 +1965,9 @@ export class Viewer {
1960
1965
  if (next === this._sectionClippingActive) return;
1961
1966
  this._sectionClippingActive = next;
1962
1967
 
1963
- // 0) Светлее при сечении (+50%)
1964
- try {
1965
- if (this._sectionClippingActive) {
1966
- if (!this._sectionLightBoost.snapshot) {
1967
- this._sectionLightBoost.snapshot = {
1968
- sunIntensity: this.sunLight?.intensity ?? null,
1969
- ambientIntensity: this.ambientLight?.intensity ?? null,
1970
- };
1971
- }
1972
- if (this.sunLight && Number.isFinite(this._sectionLightBoost.snapshot.sunIntensity)) {
1973
- this.sunLight.intensity = this._sectionLightBoost.snapshot.sunIntensity * this._sectionLightBoost.mul;
1974
- }
1975
- if (this.ambientLight && Number.isFinite(this._sectionLightBoost.snapshot.ambientIntensity)) {
1976
- this.ambientLight.intensity = this._sectionLightBoost.snapshot.ambientIntensity * this._sectionLightBoost.mul;
1977
- }
1978
- } else {
1979
- const snap = this._sectionLightBoost.snapshot;
1980
- if (snap) {
1981
- if (this.sunLight && Number.isFinite(snap.sunIntensity)) this.sunLight.intensity = snap.sunIntensity;
1982
- if (this.ambientLight && Number.isFinite(snap.ambientIntensity)) this.ambientLight.intensity = snap.ambientIntensity;
1983
- }
1984
- this._sectionLightBoost.snapshot = null;
1985
- }
1986
- } catch (_) {}
1987
-
1988
- // 0.5) Пост-эффекты: AO OFF + лёгкий контраст (только при сечении)
1989
- try {
1990
- if (this._sectionClippingActive) {
1991
- if (!this._sectionPostBoost.snapshot) {
1992
- this._sectionPostBoost.snapshot = {
1993
- ao: { ...this.visual.ao },
1994
- color: { ...this.visual.color },
1995
- };
1996
- }
1997
- // AO OFF
1998
- this.setAOEnabled(false);
1999
- // Color correction ON (без изменения hue/saturation)
2000
- this.setColorCorrectionEnabled(true);
2001
- this.setColorBrightness(this._sectionPostBoost.brightness);
2002
- this.setColorContrast(this._sectionPostBoost.contrast);
2003
- } else {
2004
- const snap = this._sectionPostBoost.snapshot;
2005
- if (snap) {
2006
- // Restore AO
2007
- this.setAOEnabled(!!snap.ao?.enabled);
2008
- if (typeof snap.ao?.intensity === 'number') this.setAOIntensity(snap.ao.intensity);
2009
- if (typeof snap.ao?.radius === 'number') this.setAORadius(snap.ao.radius);
2010
- if (typeof snap.ao?.minDistance === 'number') this.visual.ao.minDistance = snap.ao.minDistance;
2011
- if (typeof snap.ao?.maxDistance === 'number') this.visual.ao.maxDistance = snap.ao.maxDistance;
2012
- if (this._ssaoPass) {
2013
- this._ssaoPass.minDistance = this.visual.ao.minDistance;
2014
- this._ssaoPass.maxDistance = this.visual.ao.maxDistance;
2015
- }
2016
- // Restore color correction
2017
- this.setColorCorrectionEnabled(!!snap.color?.enabled);
2018
- if (typeof snap.color?.hue === 'number') this.setColorHue(snap.color.hue);
2019
- if (typeof snap.color?.saturation === 'number') this.setColorSaturation(snap.color.saturation);
2020
- if (typeof snap.color?.brightness === 'number') this.setColorBrightness(snap.color.brightness);
2021
- if (typeof snap.color?.contrast === 'number') this.setColorContrast(snap.color.contrast);
2022
- }
2023
- this._sectionPostBoost.snapshot = null;
2024
- }
2025
- } catch (_) {}
1968
+ // Важно: никаких глобальных усилений света/яркости на само включение сечения.
1969
+ // Подсветка делается локально и только когда камера "внутри".
1970
+ try { this.#updateInteriorAssist(true); } catch (_) {}
2026
1971
 
2027
1972
  // 1) self-shadowing (комнаты/стены)
2028
1973
  if (this.activeModel) {
@@ -2043,6 +1988,110 @@ export class Viewer {
2043
1988
  try { if (this.renderer?.shadowMap) this.renderer.shadowMap.needsUpdate = true; } catch (_) {}
2044
1989
  }
2045
1990
 
1991
+ #ensureInteriorAssistLight() {
1992
+ if (!this.scene) return;
1993
+ if (this._interiorAssist.light) return;
1994
+ try {
1995
+ // Небольшой "fill light" около камеры. Без теней, чтобы не ломать внешнюю тень.
1996
+ const light = new THREE.PointLight(0xffffff, 0.9, 6.5, 2.0);
1997
+ light.castShadow = false;
1998
+ light.visible = false;
1999
+ light.name = 'interior-assist-light';
2000
+ this.scene.add(light);
2001
+ this._interiorAssist.light = light;
2002
+ } catch (_) {
2003
+ this._interiorAssist.light = null;
2004
+ }
2005
+ }
2006
+
2007
+ #isCameraInsideModelBox() {
2008
+ const model = this.activeModel;
2009
+ if (!model || !this.camera) return false;
2010
+ const now = performance?.now?.() ?? Date.now();
2011
+ // Обновляем bbox не чаще ~4 раза/сек (достаточно; модель обычно статична)
2012
+ if (!this._interiorAssist.box || (now - (this._interiorAssist.lastBoxAt || 0)) > 250) {
2013
+ try {
2014
+ this._interiorAssist.box = new THREE.Box3().setFromObject(model);
2015
+ this._interiorAssist.lastBoxAt = now;
2016
+ } catch (_) {
2017
+ this._interiorAssist.box = null;
2018
+ }
2019
+ }
2020
+ const box = this._interiorAssist.box;
2021
+ if (!box) return false;
2022
+ const p = this.camera.position;
2023
+ const eps = 0.05;
2024
+ return (
2025
+ p.x > (box.min.x + eps) && p.x < (box.max.x - eps) &&
2026
+ p.y > (box.min.y + eps) && p.y < (box.max.y - eps) &&
2027
+ p.z > (box.min.z + eps) && p.z < (box.max.z - eps)
2028
+ );
2029
+ }
2030
+
2031
+ #updateInteriorAssist(force = false) {
2032
+ if (!this._sectionClippingActive) {
2033
+ if (this._interiorAssist.enabled || force) {
2034
+ this._interiorAssist.enabled = false;
2035
+ if (this._interiorAssist.light) this._interiorAssist.light.visible = false;
2036
+ this.#restoreInteriorPost();
2037
+ }
2038
+ return;
2039
+ }
2040
+
2041
+ this.#ensureInteriorAssistLight();
2042
+ const inside = this.#isCameraInsideModelBox();
2043
+ if (inside !== this._interiorAssist.enabled || force) {
2044
+ this._interiorAssist.enabled = inside;
2045
+ if (this._interiorAssist.light) this._interiorAssist.light.visible = inside;
2046
+ if (inside) this.#applyInteriorPost();
2047
+ else this.#restoreInteriorPost();
2048
+ }
2049
+ // Следуем за камерой, если активны
2050
+ if (inside && this._interiorAssist.light) {
2051
+ try { this._interiorAssist.light.position.copy(this.camera.position); } catch (_) {}
2052
+ }
2053
+ }
2054
+
2055
+ #applyInteriorPost() {
2056
+ // AO OFF + лёгкий контраст только "внутри"
2057
+ if (!this._interiorPost.snapshot) {
2058
+ this._interiorPost.snapshot = {
2059
+ ao: { ...this.visual.ao },
2060
+ color: { ...this.visual.color },
2061
+ };
2062
+ }
2063
+ try { this.setAOEnabled(false); } catch (_) {}
2064
+ try {
2065
+ this.setColorCorrectionEnabled(true);
2066
+ this.setColorContrast(this._interiorPost.contrast);
2067
+ // brightness не трогаем, чтобы не пересвечивать
2068
+ } catch (_) {}
2069
+ }
2070
+
2071
+ #restoreInteriorPost() {
2072
+ const snap = this._interiorPost.snapshot;
2073
+ if (!snap) return;
2074
+ try {
2075
+ this.setAOEnabled(!!snap.ao?.enabled);
2076
+ if (typeof snap.ao?.intensity === 'number') this.setAOIntensity(snap.ao.intensity);
2077
+ if (typeof snap.ao?.radius === 'number') this.setAORadius(snap.ao.radius);
2078
+ if (typeof snap.ao?.minDistance === 'number') this.visual.ao.minDistance = snap.ao.minDistance;
2079
+ if (typeof snap.ao?.maxDistance === 'number') this.visual.ao.maxDistance = snap.ao.maxDistance;
2080
+ if (this._ssaoPass) {
2081
+ this._ssaoPass.minDistance = this.visual.ao.minDistance;
2082
+ this._ssaoPass.maxDistance = this.visual.ao.maxDistance;
2083
+ }
2084
+ } catch (_) {}
2085
+ try {
2086
+ this.setColorCorrectionEnabled(!!snap.color?.enabled);
2087
+ if (typeof snap.color?.hue === 'number') this.setColorHue(snap.color.hue);
2088
+ if (typeof snap.color?.saturation === 'number') this.setColorSaturation(snap.color.saturation);
2089
+ if (typeof snap.color?.brightness === 'number') this.setColorBrightness(snap.color.brightness);
2090
+ if (typeof snap.color?.contrast === 'number') this.setColorContrast(snap.color.contrast);
2091
+ } catch (_) {}
2092
+ this._interiorPost.snapshot = null;
2093
+ }
2094
+
2046
2095
  /**
2047
2096
  * Дамп текущих параметров тест-пресета в консоль.
2048
2097
  */