From e10a9c433ac015512b26afcd1df52db5ae578b1f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 16:44:02 +0000 Subject: [PATCH] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 43 +++++++++++++++++++++------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index ff5aec5..a5f56e1 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -21,8 +21,10 @@ function LoadingFallback() { ); } -function GLBModel({ url }: { url: string }) { - const { scene } = useGLTF(url); +function GLBModel({ sceneModel, isActive }: { sceneModel: SceneModel; isActive: boolean }) { + const { scene: rawScene } = useGLTF(sceneModel.url); + // Clone scene per instance so multiple GLBModels with same url don't share materials/transforms + const scene = useMemo(() => rawScene.clone(true), [rawScene]); const ref = useRef(null); const opacity = useModelStore((s) => s.opacity); const renderMode = useModelStore((s) => s.renderMode); @@ -30,7 +32,8 @@ function GLBModel({ url }: { url: string }) { const wireframeThickness = useModelStore((s) => s.wireframeThickness); const edgeThresholdAngle = useModelStore((s) => s.edgeThresholdAngle); const checklist = useModelStore((s) => s.checklist); - const fineTuning = useModelStore((s) => s.fineTuning); + const setActive = useModelStore((s) => s.setActiveModel); + const fineTuning = sceneModel.fineTuning; const modelInfo = useMemo(() => { const box = new THREE.Box3().setFromObject(scene); @@ -41,7 +44,6 @@ function GLBModel({ url }: { url: string }) { return { size, center }; }, [scene]); - // Store original colors so we can restore them const originalColors = useRef>(new Map()); useEffect(() => { @@ -56,7 +58,6 @@ function GLBModel({ url }: { url: string }) { child.material = child.material.clone(); } - // Clean up previous edge lines const toRemove: THREE.Object3D[] = []; child.children.forEach(c => { if (c.userData.__edgeLine) toRemove.push(c); @@ -72,7 +73,6 @@ function GLBModel({ url }: { url: string }) { const materials = Array.isArray(child.material) ? child.material : [child.material]; materials.forEach((mat: THREE.Material) => { if (mat instanceof THREE.MeshStandardMaterial) { - // Store original color on first encounter if (!originalColors.current.has(mat)) { originalColors.current.set(mat, mat.color.clone()); } @@ -92,14 +92,14 @@ function GLBModel({ url }: { url: string }) { } else if (allApproved) { mat.color.setHSL(0.38, 0.7, 0.45); } else { - mat.color.set(0x8899aa); + // Tint with the per-model color (subtle) + mat.color.set(sceneModel.color); } } mat.needsUpdate = true; } }); - // Create edge lines for edges mode if (renderMode === 'edges' && child.geometry) { const edgesGeo = new THREE.EdgesGeometry(child.geometry, edgeThresholdAngle); const lineMat = new THREE.LineBasicMaterial({ @@ -112,7 +112,7 @@ function GLBModel({ url }: { url: string }) { } } }); - }, [scene, opacity, renderMode, checklist, wireframeColor, wireframeThickness, edgeThresholdAngle]); + }, [scene, opacity, renderMode, checklist, wireframeColor, wireframeThickness, edgeThresholdAngle, sceneModel.color]); const rotXRad = (fineTuning.rotX * Math.PI) / 180; const rotYRad = (fineTuning.rotY * Math.PI) / 180; @@ -121,8 +121,13 @@ function GLBModel({ url }: { url: string }) { const scaleRatio = useModelStore((st) => st.scaleRatio); const renderFactor = scaleRatio?.factor ?? 1; + if (!sceneModel.visible) return null; + return ( - + { e.stopPropagation(); setActive(sceneModel.id); }} + > + {isActive && ( + + + + + )} ); } +function SceneModels() { + const models = useModelStore((s) => s.models); + const activeId = useModelStore((s) => s.activeModelId); + return ( + <> + {models.map((m) => ( + + ))} + + ); +} + /** Sphere marker at a 3D point */ function PointMarker({ position, color = '#e8a838' }: { position: [number, number, number]; color?: string }) { return (