Files
coins/src/components/scene/coin.tsx
T
2023-09-13 02:47:04 +01:00

111 lines
2.5 KiB
TypeScript

import * as THREE from "three";
import { useLoader } from "@react-three/fiber";
import { CoinProps } from "@/types/coin";
import { Suspense, useEffect, useMemo } from "react";
const SafeEdgeMaterial = ({
color,
edge,
}: Pick<CoinProps, "edge" | "color">) => {
try {
// eslint-disable-next-line react-hooks/rules-of-hooks
const edgeTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
edge.picture,
);
edgeTexture.repeat = new THREE.Vector2(2, 1);
edgeTexture.offset = new THREE.Vector2(0.5, 0);
edgeTexture.wrapS = THREE.MirroredRepeatWrapping;
edgeTexture.wrapT = THREE.MirroredRepeatWrapping;
return (
<Suspense
fallback={
<meshStandardMaterial
metalness={1}
roughness={0.5}
color={color}
attach="material-0"
/>
}
>
<meshStandardMaterial
map={edgeTexture}
metalness={1}
roughness={0.5}
attach="material-0"
/>
</Suspense>
);
} catch {
return (
<meshStandardMaterial
metalness={1}
roughness={0.5}
color={color}
attach="material-0"
/>
);
}
};
export const CoinInstance = ({
orientation,
size,
thickness,
color,
obverse,
shape,
reverse,
edge,
}: CoinProps) => {
const sides = useMemo(() => {
return 32;
const parsed = Number(/(\d+)/.exec(shape)?.[0]);
return Math.min(32, Math.max(4, isNaN(parsed) ? 32 : parsed));
}, [shape]);
//const edgeTexture = useLoader(THREE.TextureLoader, edge.picture);
const obverseTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
obverse.picture,
);
const reverseTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
reverse.picture,
);
useEffect(() => {
if (orientation === "medal") {
reverseTexture.center = new THREE.Vector2(0.5, 0.5);
reverseTexture.rotation = Math.PI;
}
}, [orientation, reverseTexture]);
return (
<>
<cylinderBufferGeometry
attach="geometry"
args={[
(size ?? 16) / 16,
(size ?? 16) / 16,
(thickness ?? 2) / 16,
sides,
]}
/>
<SafeEdgeMaterial color={color} edge={edge} />
<meshStandardMaterial
metalness={1}
roughness={0.5}
map={obverseTexture}
attach="material-1"
/>
<meshStandardMaterial
metalness={1}
roughness={0.5}
map={reverseTexture}
attach="material-2"
/>
</>
);
};