@sequent-org/ifc-viewer 1.2.4-ci.41.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 -26
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.41.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,8 +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 };
151
+ // Локальная подсветка "внутри": без теней, с малой дальностью (чтобы не пересвечивать фасад/внешнюю тень)
152
+ this._interiorAssist = { light: null, box: null, enabled: false, lastBoxAt: 0 };
153
+ // Пост-эффекты только "внутри": AO OFF (убирает "сетку"), чуть контраста (без глобального пересвета)
154
+ this._interiorPost = { snapshot: null, contrast: 0.12 };
153
155
 
154
156
  // Snapshot начального состояния для Home
155
157
  this._home = {
@@ -626,6 +628,9 @@ export class Viewer {
626
628
  this.setSunHeight(5.9);
627
629
  this.setShadowsEnabled(this.shadowsEnabled);
628
630
 
631
+ // Локальная подсветка "внутри" (по умолчанию скрыта)
632
+ this.#ensureInteriorAssistLight();
633
+
629
634
  // Демонстрационный куб отключён для чистого прелоадера
630
635
  // Оставим сцену пустой до загрузки модели
631
636
  // Добавим метод фокусировки объекта
@@ -753,6 +758,8 @@ export class Viewer {
753
758
  }
754
759
 
755
760
  if (this.controls) this.controls.update();
761
+ // "Внутренняя" подсветка/пост-эффекты: включаются только когда камера внутри модели
762
+ this.#updateInteriorAssist();
756
763
  this._notifyZoomIfChanged();
757
764
  if (this.renderer && this.camera && this.scene) {
758
765
  // Применим ТОЛЬКО активные (конечные) плоскости отсечения
@@ -1958,30 +1965,9 @@ export class Viewer {
1958
1965
  if (next === this._sectionClippingActive) return;
1959
1966
  this._sectionClippingActive = next;
1960
1967
 
1961
- // 0) Светлее при сечении (+50%)
1962
- try {
1963
- if (this._sectionClippingActive) {
1964
- if (!this._sectionLightBoost.snapshot) {
1965
- this._sectionLightBoost.snapshot = {
1966
- sunIntensity: this.sunLight?.intensity ?? null,
1967
- ambientIntensity: this.ambientLight?.intensity ?? null,
1968
- };
1969
- }
1970
- if (this.sunLight && Number.isFinite(this._sectionLightBoost.snapshot.sunIntensity)) {
1971
- this.sunLight.intensity = this._sectionLightBoost.snapshot.sunIntensity * this._sectionLightBoost.mul;
1972
- }
1973
- if (this.ambientLight && Number.isFinite(this._sectionLightBoost.snapshot.ambientIntensity)) {
1974
- this.ambientLight.intensity = this._sectionLightBoost.snapshot.ambientIntensity * this._sectionLightBoost.mul;
1975
- }
1976
- } else {
1977
- const snap = this._sectionLightBoost.snapshot;
1978
- if (snap) {
1979
- if (this.sunLight && Number.isFinite(snap.sunIntensity)) this.sunLight.intensity = snap.sunIntensity;
1980
- if (this.ambientLight && Number.isFinite(snap.ambientIntensity)) this.ambientLight.intensity = snap.ambientIntensity;
1981
- }
1982
- this._sectionLightBoost.snapshot = null;
1983
- }
1984
- } catch (_) {}
1968
+ // Важно: никаких глобальных усилений света/яркости на само включение сечения.
1969
+ // Подсветка делается локально и только когда камера "внутри".
1970
+ try { this.#updateInteriorAssist(true); } catch (_) {}
1985
1971
 
1986
1972
  // 1) self-shadowing (комнаты/стены)
1987
1973
  if (this.activeModel) {
@@ -2002,6 +1988,110 @@ export class Viewer {
2002
1988
  try { if (this.renderer?.shadowMap) this.renderer.shadowMap.needsUpdate = true; } catch (_) {}
2003
1989
  }
2004
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
+
2005
2095
  /**
2006
2096
  * Дамп текущих параметров тест-пресета в консоль.
2007
2097
  */