first commit
This commit is contained in:
commit
0e854110d3
49 files changed
+2292
No files matched your search
@@ -0,0 +1,52 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import * as THREE from "three";
|
||||
import type { ThreeEvent } from "@react-three/fiber";
|
||||
import { modelUrl } from "../../lib/api.js";
|
||||
|
||||
interface Props {
|
||||
modelFile: string;
|
||||
selectedSlug: string | null;
|
||||
onSelect: (slug: string) => void;
|
||||
clippingPlanes: THREE.Plane[];
|
||||
}
|
||||
|
||||
const HIGHLIGHT = new THREE.Color("#22d3ee");
|
||||
|
||||
export function SystemModel({ modelFile, selectedSlug, onSelect, clippingPlanes }: Props) {
|
||||
const { scene } = useGLTF(modelUrl(modelFile));
|
||||
const clonedRef = useRef<THREE.Group>();
|
||||
|
||||
if (!clonedRef.current) {
|
||||
const clone = scene.clone(true);
|
||||
clone.traverse((obj) => {
|
||||
const mesh = obj as THREE.Mesh;
|
||||
if (mesh.isMesh && mesh.material) {
|
||||
mesh.material = (mesh.material as THREE.MeshStandardMaterial).clone();
|
||||
}
|
||||
});
|
||||
clonedRef.current = clone;
|
||||
}
|
||||
const root = clonedRef.current!;
|
||||
|
||||
useEffect(() => {
|
||||
root.traverse((obj) => {
|
||||
const mesh = obj as THREE.Mesh;
|
||||
if (!mesh.isMesh) return;
|
||||
const mat = mesh.material as THREE.MeshStandardMaterial;
|
||||
mat.clippingPlanes = clippingPlanes;
|
||||
mat.clipShadows = true;
|
||||
const isSelected = mesh.name === selectedSlug;
|
||||
mat.emissive = isSelected ? HIGHLIGHT : new THREE.Color(0x000000);
|
||||
mat.emissiveIntensity = isSelected ? 0.6 : 0;
|
||||
});
|
||||
}, [root, selectedSlug, clippingPlanes]);
|
||||
|
||||
const handleClick = (e: ThreeEvent<MouseEvent>) => {
|
||||
e.stopPropagation();
|
||||
const name = e.object.name;
|
||||
if (name) onSelect(name);
|
||||
};
|
||||
|
||||
return <primitive object={root} onClick={handleClick} />;
|
||||
}
|
||||
Reference in new issue
Block a user