Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-15 11:35:53 +00:00
parent 9cbebdd5cb
commit c6bd96dfb3
+37 -1
View File
@@ -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 (
<Grid
position={[0, -0.09, 0]}
position={[0, gridY, 0]}
infiniteGrid
cellSize={0.01}
sectionSize={0.1}
@@ -471,6 +472,41 @@ function GridLayer() {
);
}
/** Computes min Y of all visible models and updates store gridY when auto-follow is on. */
function GridAutoFollower() {
const models = useModelStore((s) => 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 (
<Canvas