Changes
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
@@ -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<THREE.Group>(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<Map<THREE.Material, THREE.Color>>(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 (
|
||||
<group scale={[renderFactor, renderFactor, renderFactor]}>
|
||||
<group
|
||||
scale={[renderFactor, renderFactor, renderFactor]}
|
||||
onClick={(e) => { e.stopPropagation(); setActive(sceneModel.id); }}
|
||||
>
|
||||
<group
|
||||
ref={ref}
|
||||
position={[
|
||||
@@ -134,11 +139,29 @@ function GLBModel({ url }: { url: string }) {
|
||||
scale={[s, s, s]}
|
||||
>
|
||||
<primitive object={scene} />
|
||||
{isActive && (
|
||||
<mesh>
|
||||
<boxGeometry args={[modelInfo.size.x * 1.05, modelInfo.size.y * 1.05, modelInfo.size.z * 1.05]} />
|
||||
<meshBasicMaterial color={sceneModel.color} wireframe transparent opacity={0.25} />
|
||||
</mesh>
|
||||
)}
|
||||
</group>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
function SceneModels() {
|
||||
const models = useModelStore((s) => s.models);
|
||||
const activeId = useModelStore((s) => s.activeModelId);
|
||||
return (
|
||||
<>
|
||||
{models.map((m) => (
|
||||
<GLBModel key={m.id} sceneModel={m} isActive={m.id === activeId} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** Sphere marker at a 3D point */
|
||||
function PointMarker({ position, color = '#e8a838' }: { position: [number, number, number]; color?: string }) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user