@sequent-org/ifc-viewer 1.2.4-ci.49.0 → 1.2.4-ci.51.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/README.md +1 -0
- package/package.json +3 -2
- package/scripts/copy-rhino3dm.mjs +90 -0
- package/scripts/patch-three-3dm-loader.mjs +60 -0
- package/src/IfcViewer.js +9 -1
- package/src/index.js +1 -0
- package/src/main.js +13 -4
- package/src/model-loading/loaders/ThreeDmModelLoader.js +147 -0
- package/src/styles-local.css +75 -0
- package/src/ui/CardPlacementController.js +774 -0
- package/src/viewer/Viewer.js +35 -4
package/src/viewer/Viewer.js
CHANGED
|
@@ -1373,6 +1373,10 @@ export class Viewer {
|
|
|
1373
1373
|
this.activeModel = object3D;
|
|
1374
1374
|
this.scene.add(object3D);
|
|
1375
1375
|
|
|
1376
|
+
// Сброс MMB-pan (viewOffset) при загрузке новой модели:
|
|
1377
|
+
// иначе экранный сдвиг может "унести" модель из кадра даже при корректном кадрировании по bbox.
|
|
1378
|
+
try { this._mmbPan?.controller?.reset?.(); } catch (_) {}
|
|
1379
|
+
|
|
1376
1380
|
// Пересчитать плоскость под моделью (3x по площади bbox по X/Z)
|
|
1377
1381
|
this.#updateShadowReceiverFromModel(object3D);
|
|
1378
1382
|
|
|
@@ -1627,13 +1631,40 @@ export class Viewer {
|
|
|
1627
1631
|
const center = box.getCenter(new THREE.Vector3());
|
|
1628
1632
|
const minY = box.min.y;
|
|
1629
1633
|
|
|
1630
|
-
//
|
|
1634
|
+
// Базовая плоскость: площадь = 3x площади объекта (bbox по X/Z).
|
|
1631
1635
|
// => множитель по размерам = sqrt(3).
|
|
1632
1636
|
const areaMultiplier = 3;
|
|
1633
1637
|
const dimMul = Math.sqrt(areaMultiplier);
|
|
1634
1638
|
|
|
1639
|
+
// Доп. запас по X/Z из-за длины тени: высокая модель при наклонном солнце
|
|
1640
|
+
// может давать тень далеко за bbox по X/Z.
|
|
1641
|
+
// Оценка смещения тени по земле: displacementXZ ≈ height * |dirXZ| / |dirY|
|
|
1642
|
+
// где dir = (target - lightPos) нормализованный.
|
|
1643
|
+
let extraX = 0;
|
|
1644
|
+
let extraZ = 0;
|
|
1645
|
+
try {
|
|
1646
|
+
const sun = this.sunLight;
|
|
1647
|
+
if (sun) {
|
|
1648
|
+
const targetPos = (sun.target?.position?.clone?.() || center.clone());
|
|
1649
|
+
const dir = targetPos.sub(sun.position).normalize();
|
|
1650
|
+
const ay = Math.max(1e-3, Math.abs(dir.y));
|
|
1651
|
+
extraX = Math.abs(dir.x) * (Math.max(0, size.y) / ay);
|
|
1652
|
+
extraZ = Math.abs(dir.z) * (Math.max(0, size.y) / ay);
|
|
1653
|
+
// небольшой коэффициент запаса, чтобы не ловить «пограничные» обрезания
|
|
1654
|
+
const pad = 1.05;
|
|
1655
|
+
extraX *= pad;
|
|
1656
|
+
extraZ *= pad;
|
|
1657
|
+
}
|
|
1658
|
+
} catch (_) {
|
|
1659
|
+
extraX = 0;
|
|
1660
|
+
extraZ = 0;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1635
1663
|
this.shadowReceiver.position.set(center.x, minY + 0.001, center.z);
|
|
1636
|
-
|
|
1664
|
+
// receiver.scale: X->world X, Y->world Z (PlaneGeometry is X/Y in local, rotated -90° around X)
|
|
1665
|
+
const receiverX = Math.max(0.001, (size.x * dimMul) + extraX * 2);
|
|
1666
|
+
const receiverZ = Math.max(0.001, (size.z * dimMul) + extraZ * 2);
|
|
1667
|
+
this.shadowReceiver.scale.set(receiverX, receiverZ, 1);
|
|
1637
1668
|
this.shadowReceiver.updateMatrixWorld();
|
|
1638
1669
|
|
|
1639
1670
|
// Обновим bbox здания для градиента тени (в XZ)
|
|
@@ -1647,8 +1678,8 @@ export class Viewer {
|
|
|
1647
1678
|
// чтобы при включении теней они не "обрезались" слишком маленькой областью.
|
|
1648
1679
|
if (this.sunLight) {
|
|
1649
1680
|
const cam = this.sunLight.shadow.camera;
|
|
1650
|
-
const halfX =
|
|
1651
|
-
const halfZ =
|
|
1681
|
+
const halfX = receiverX / 2;
|
|
1682
|
+
const halfZ = receiverZ / 2;
|
|
1652
1683
|
cam.left = -halfX;
|
|
1653
1684
|
cam.right = halfX;
|
|
1654
1685
|
cam.top = halfZ;
|