frontend/src/3dModels/Shapes/BaseMesh.tsx

99 lines
No EOL
2.9 KiB
TypeScript

import { Euler, Vector3, BufferGeometry, MaterialParameters, Side } from "three";
import { ThreeEvent } from "@react-three/fiber";
export interface BaseMeshProps {
geometry: BufferGeometry;
position?: Vector3;
rotation?: Euler;
colour?: string;
opacity?: number;
metalness?: number;
roughness?: number;
wireframe?: boolean;
frameColour?: string;
materialType?: "standard" | "basic";
materialProps?: Partial<MaterialParameters>;
materialOverride?: React.ReactNode;
side?: Side;
depthWrite?: boolean;
depthTest?: boolean;
renderOrder?: number;
onClick?: (event: ThreeEvent<MouseEvent>) => void;
}
export default function BaseMesh(props: BaseMeshProps) {
const {
geometry,
position,
rotation,
colour = "#fff",
opacity = 1,
metalness = 0,
roughness = 1,
wireframe = false,
frameColour = "black",
materialType,
materialProps,
materialOverride,
side,
depthWrite = true,
depthTest = true,
renderOrder = 0,
onClick,
} = props;
const isTransparent = opacity < 1;
const buildMaterial = () => {
if (materialOverride) return materialOverride;
switch (materialType) {
case "basic":
return (
<meshBasicMaterial
color={colour}
transparent={isTransparent}
opacity={opacity}
depthWrite={depthWrite}
depthTest={depthTest}
side={side}
{...materialProps}
/>
);
case "standard":
default:
return (
<meshStandardMaterial
color={colour}
metalness={metalness}
roughness={roughness}
transparent={isTransparent}
opacity={opacity}
depthWrite={depthWrite}
depthTest={depthTest}
side={side}
{...materialProps}
/>
);
}
};
return (
<group position={position} rotation={rotation} renderOrder={renderOrder}>
{/* Main surface */}
<mesh geometry={geometry} onClick={onClick} renderOrder={renderOrder}>
{buildMaterial()}
</mesh>
{/* Optional wireframe overlay */}
{wireframe && (
<mesh geometry={geometry} renderOrder={renderOrder}>
<meshStandardMaterial
wireframe
color={frameColour}
/>
</mesh>
)}
</group>
);
}