From c6bd96dfb340a3c42a886f783c7238f04b5aff79 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 11:35:53 +0000 Subject: [PATCH] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 38 +++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index 046c96c..2a97659 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -454,10 +454,11 @@ function MeasureClickHandler() { function GridLayer() { const showGrid = useModelStore((s) => s.showGrid); + const gridY = useModelStore((s) => s.gridY); if (!showGrid) return null; return ( s.models); + const { scene } = useThree(); + useEffect(() => { + const auto = useModelStore.getState().gridAutoFollow; + if (!auto) return; + // Defer to next tick so models have rendered/positioned + const id = setTimeout(() => { + if (!useModelStore.getState().gridAutoFollow) return; + const box = new THREE.Box3(); + let has = false; + scene.traverse((obj) => { + if (obj instanceof THREE.Mesh && obj.geometry) { + // Skip helpers (markers, rings) + if (obj.geometry instanceof THREE.SphereGeometry) return; + if (obj.geometry instanceof THREE.RingGeometry) return; + if (obj.userData.__edgeLine) return; + obj.updateWorldMatrix(true, false); + const b = new THREE.Box3().setFromObject(obj); + if (isFinite(b.min.y)) { + if (!has) { box.copy(b); has = true; } + else box.union(b); + } + } + }); + if (has) { + useModelStore.setState({ gridY: box.min.y - 0.005 }); + } + }, 100); + return () => clearTimeout(id); + }, [models, scene]); + return null; +} + export function ModelViewerCanvas({ url }: ModelViewerProps) { return (