diff --git a/viewer/index.html b/viewer/index.html
index 5f8216b..ef5b0b4 100644
--- a/viewer/index.html
+++ b/viewer/index.html
@@ -28,6 +28,11 @@ html,body{margin:0;height:100%;background:var(--bg);color:var(--fg);font-family:
대산2터널 본선 3D 모델
측점 4+745 ~ 5+480 · 단위 m
+ 구간 보기 (측점)
+
+
+ 4+745
+
지보패턴 (라이닝·굴착 여유대)
굴착 여유대
@@ -107,11 +112,11 @@ Promise.all([
const c = META_BY_ID[o.name];
o.userData = { id: o.name, group: c ? c.group : '', pattern: c && c.pattern ? c.pattern : null,
from: c ? c.from_sta : null, to: c ? c.to_sta : null, label: c ? c.label : o.name };
- o.geometry.computeVertexNormals(); // GLB normals from the exporter are not reliable for shading
+ o.geometry = o.geometry.toNonIndexed(); // flat shading: one normal per triangle, no smoothing
+ o.geometry.computeVertexNormals();
const rgb = c && c.color ? c.color : [200, 200, 200];
o.material = new THREE.MeshStandardMaterial({ color: new THREE.Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255),
- roughness: 0.75, metalness: 0.0, side: THREE.DoubleSide });
- if (o.userData.group === '굴착면') { o.material.transparent = true; o.material.opacity = 0.55; o.material.depthWrite = false; }
+ roughness: 0.8, metalness: 0.0, side: THREE.DoubleSide, flatShading: true });
meshes.push(o);
});
const box = new THREE.Box3().setFromObject(root);
@@ -126,14 +131,23 @@ Promise.all([
};
const overview = () => viewFrom(c, d * 0.75);
const focusStation = (sta) => {
+ sta = Math.max(4745, Math.min(5480, sta));
const bb = new THREE.Box3(); let any = false;
for (const m of meshes) {
- if (m.userData.group === '라이닝' && m.userData.from <= sta && sta < m.userData.to) { bb.union(new THREE.Box3().setFromObject(m)); any = true; }
+ const u = m.userData;
+ if (!m.visible || u.from == null) continue;
+ if (u.to < sta - 15 || u.from > sta + 15) continue;
+ bb.union(new THREE.Box3().setFromObject(m)); any = true;
}
if (!any) return;
const cc = bb.getCenter(new THREE.Vector3()), ss = bb.getSize(new THREE.Vector3());
- viewFrom(cc, Math.max(ss.x, ss.y, ss.z) * 2.2 + 12);
+ viewFrom(cc, Math.max(ss.x, ss.y, ss.z) * 0.9 + 25);
+ staEl.value = String(sta); staLabel.textContent = fmtSta(sta);
};
+ const staEl = document.getElementById('sta'), staLabel = document.getElementById('staLabel');
+ staEl.addEventListener('input', () => focusStation(Number(staEl.value)));
+ document.getElementById('prev').addEventListener('click', () => focusStation(Number(staEl.value) - 5));
+ document.getElementById('next').addEventListener('click', () => focusStation(Number(staEl.value) + 5));
document.getElementById('viewAll').addEventListener('click', overview);
document.getElementById('viewStart').addEventListener('click', () => focusStation(4745));
overview();