@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.
- package/package.json +1 -1
- 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.
|
|
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",
|
package/src/viewer/Viewer.js
CHANGED
|
@@ -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
|
-
//
|
|
152
|
-
this.
|
|
153
|
-
//
|
|
154
|
-
this.
|
|
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
|
-
//
|
|
1964
|
-
|
|
1965
|
-
|
|
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
|
*/
|