Minor improvements

This commit is contained in:
2023-09-15 20:54:30 +01:00
parent e88f403a08
commit 8a8e39cd39
9 changed files with 89 additions and 77 deletions
+1 -1
View File
@@ -95,5 +95,5 @@
"name": "Algiers"
}
],
"color": "rgb(196,172,76)"
"color": "rgb(100,100,100)"
}
+1 -1
View File
@@ -82,5 +82,5 @@
"name": "Fábrica de Moneda de Ibagué"
}
],
"color": "rgb(153,134.05714285714288,102)"
"color": "rgb(45, 30, 20)"
}
+34 -50
View File
@@ -1,52 +1,26 @@
import * as THREE from "three";
import { useLoader } from "@react-three/fiber";
import { CoinProps } from "@/types/coin";
import { Suspense, useEffect, useMemo } from "react";
import { 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;
const SafeEdgeMaterial = ({ edge }: Pick<CoinProps, "edge">) => {
const edgeTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
edge.picture,
);
edgeTexture.repeat = new THREE.Vector2(4, 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"
/>
);
}
return (
<meshStandardMaterial
map={edgeTexture}
metalness={1}
roughness={0.5}
attach="material-0"
/>
);
};
export const CoinInstance = ({
@@ -55,16 +29,14 @@ export const CoinInstance = ({
thickness,
color,
obverse,
shape,
reverse,
edge,
}: CoinProps) => {
const sides = useMemo(() => {
//const parsed = Number(/(\d+)/.exec(shape)?.[0]);
//return Math.min(32, Math.max(4, isNaN(parsed) ? 32 : parsed));
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,
@@ -92,13 +64,25 @@ export const CoinInstance = ({
sides,
]}
/>
<SafeEdgeMaterial color={color} edge={edge} />
{edge?.picture ? (
<SafeEdgeMaterial edge={edge} />
) : (
<meshStandardMaterial
metalness={1}
roughness={0.5}
color={color}
attach="material-0"
/>
)}
<meshStandardMaterial
metalness={1}
roughness={0.5}
map={obverseTexture}
attach="material-1"
/>
<meshStandardMaterial
metalness={1}
roughness={0.5}
+6 -7
View File
@@ -5,6 +5,7 @@ import { InstancedMesh } from "three";
import { useCylinder } from "@react-three/cannon";
export const CoinInstances = (coinProps: CoinProps) => {
const didInit = useRef(false);
const { count = 1, size = 16, thickness = 2, weight = 4 } = coinProps;
const [ref, { at }] = useCylinder(
@@ -17,7 +18,10 @@ export const CoinInstances = (coinProps: CoinProps) => {
);
useEffect(() => {
console.log("resetting");
if (didInit.current) {
return;
}
didInit.current = true;
Array.from({ length: count }).forEach((_, index) => {
at(index).position.set(
8 * (Math.random() * 2 - 1),
@@ -33,12 +37,7 @@ export const CoinInstances = (coinProps: CoinProps) => {
}, [at, count]);
return (
<instancedMesh
receiveShadow
castShadow
ref={ref}
args={[undefined, undefined, count]}
>
<instancedMesh ref={ref} args={[undefined, undefined, count]}>
<CoinInstance {...coinProps} />
</instancedMesh>
);
+18 -4
View File
@@ -1,4 +1,4 @@
import { Canvas } from "@react-three/fiber";
import { Canvas, PointLightProps } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { useRef } from "react";
import { CoinInstances } from "./coin-instances";
@@ -13,19 +13,33 @@ type Props = {
const Plane = (props: PlaneProps) => {
const [ref] = usePlane(() => ({ ...props }), useRef<Mesh>(null));
return (
<mesh ref={ref} receiveShadow>
<mesh ref={ref}>
<circleGeometry args={[64]} />
<meshBasicMaterial color={"black"} />
</mesh>
);
};
const Lightbulb = (props: PointLightProps) => (
<>
<pointLight {...props} />
<mesh position={props.position}>
<sphereGeometry args={[0.25]} />
<meshBasicMaterial color="white" />
</mesh>
</>
);
export const Pile = ({ coins }: Props) => (
<Canvas shadows camera={{ position: [0, 16, 16] }}>
<Canvas camera={{ position: [0, 16, 16] }}>
<color attach="background" args={["#111"]} />
<ambientLight />
<directionalLight castShadow position={[0, 1, 0]} />
<Lightbulb position={[0, 16, 0]} />
<Lightbulb position={[16, 0, 16]} />
<Lightbulb position={[16, 0, -16]} />
<Lightbulb position={[-16, 0, 16]} />
<Lightbulb position={[-16, 0, -16]} />
<Physics gravity={[0, -20, 0]}>
<Plane rotation={[-Math.PI / 2, 0, 0]} position={[0, -2, 0]} />
{coins.map((coinProps) => (
+18 -5
View File
@@ -1,9 +1,8 @@
import { CoinProps } from "@/types/coin";
import { Canvas, MeshProps, useFrame } from "@react-three/fiber";
import { Suspense, useRef, useState } from "react";
import { Suspense, useEffect, useRef, useState } from "react";
import { CoinInstance } from "@/components/coin";
import { Mesh } from "three";
import { OrbitControls } from "@react-three/drei";
import { BanknoteInstance } from "@/components/banknote";
import { InfoBox } from "./info-box";
@@ -78,7 +77,7 @@ const Row = ({
{types.map(
(type, index) =>
Math.abs(index - selectedIndex) <= 1 && (
<Suspense key={type.id} fallback={"loading..."}>
<Suspense key={type.id} fallback={null}>
<SpinninType
category={category}
isSelected={selectedIndex === index}
@@ -96,14 +95,28 @@ const Row = ({
export const Showcase = (props: Props) => {
const [selectedIndex, selectIndex] = useState(0);
useEffect(() => {
const onKeyDown = ({ key }: KeyboardEvent) => {
switch (key) {
case "ArrowLeft":
return selectIndex((value) => Math.max(value - 1, 0));
case "ArrowRight":
return selectIndex((value) =>
Math.min(value + 1, props.types.length - 1),
);
}
};
document.addEventListener("keydown", onKeyDown);
return () => document.removeEventListener("keydown", onKeyDown);
}, [props.types.length]);
return (
<>
<Canvas shadows>
<Canvas>
<color attach="background" args={["#111"]} />
<ambientLight />
<directionalLight position={[0, 0.125, 1]} />
<Row {...props} selectedIndex={selectedIndex} />
<OrbitControls />
</Canvas>
<InfoBox
+10 -4
View File
@@ -40,13 +40,17 @@ export const InfoBox = ({
>
<small>{type.issuer.name}</small>
<h1 style={{ textAlign: "center" }}>{type.title}</h1>
<p>{type.min_year + " - " + type.max_year}</p>
<p>
{type.min_year !== type.max_year
? type.min_year + " - " + type.max_year
: type.min_year}
</p>
<small>{(type.count ?? 1) + " in collection"}</small>
{category === "coins" && (
<>
<p>{type.weight + "g"}</p>
<p>{type.size + "mm"}</p>
<p>{type.thickness + "mm"}</p>
{type.weight && <p>{type.weight + "g"}</p>}
{type.size && <p>{type.size + "mm"}</p>}
{type.thickness && <p>{type.thickness + "mm"}</p>}
</>
)}
</div>
@@ -66,6 +70,8 @@ export const InfoBox = ({
{"<-"}
</button>
<span>{selectedIndex + 1 + "/" + (maxIndex + 1)}</span>
<button
disabled={selectedIndex >= maxIndex}
style={{ flex: 1 }}
-2
View File
@@ -44,8 +44,6 @@ export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const coins = await getCountryCoins(params.country);
const banknotes = await getCountryBanknotes(params.country);
console.log({ coins, banknotes });
return {
props: {
country: params.country,
+1 -3
View File
@@ -8,10 +8,8 @@ html,
body {
max-width: 100vw;
overflow-x: hidden;
}
#scene-root {
background-color: #111;
color: white;
}
#scene-root > div:first-child {