Add tostão furado model and stage lights

This commit is contained in:
2023-09-19 16:17:50 +01:00
parent 62cbca8083
commit c4feadb4af
10 changed files with 400 additions and 23 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
import { useGLTF, useTexture } from "@react-three/drei";
import { CoinProps } from "@/types/coin";
export function TostaoFurado(coin: CoinProps) {
// @ts-expect-error property `nodes` actually exists
const { nodes } = useGLTF("/models/tostao-furado.gltf");
const texture = useTexture("/api/merge-textures/" + coin.id);
return (
<>
<primitive object={nodes.TostaoFurado.geometry} />
<meshStandardMaterial metalness={1} roughness={0.5} map={texture} />
</>
);
}
useGLTF.preload("/models/tostao-furado.gltf");
+12 -3
View File
@@ -2,9 +2,10 @@ import * as THREE from "three";
import { useLoader } from "@react-three/fiber"; import { useLoader } from "@react-three/fiber";
import { CoinProps } from "@/types/coin"; import { CoinProps } from "@/types/coin";
import { useEffect, useMemo } from "react"; import { useEffect, useMemo } from "react";
import { EuroCents20 } from "./custom-geometries/euro-cents-20"; import { EuroCents20 } from "./custom/euro-cents-20";
import { BahamasCents15 } from "./custom-geometries/bahamas-cents-15"; import { BahamasCents15 } from "./custom/bahamas-cents-15";
import { BahamasCents10 } from "./custom-geometries/bahamas-cents-10"; import { BahamasCents10 } from "./custom/bahamas-cents-10";
import { TostaoFurado } from "./custom/tostao-furado";
const SafeEdgeMaterial = ({ edge }: Pick<CoinProps, "edge">) => { const SafeEdgeMaterial = ({ edge }: Pick<CoinProps, "edge">) => {
const edgeTexture: THREE.Texture = useLoader( const edgeTexture: THREE.Texture = useLoader(
@@ -94,6 +95,14 @@ export const CoinInstance = (coin: CoinProps) => {
return <EuroCents20 {...coin} />; return <EuroCents20 {...coin} />;
} }
if (
coin.value?.numeric_value === 25 &&
coin.value?.currency?.name === "Peseta" &&
coin.min_year >= 1990
) {
return <TostaoFurado {...coin} />;
}
if ( if (
coin.value?.currency?.name === "Dollar" && coin.value?.currency?.name === "Dollar" &&
coin.issuer?.code === "bahamas" coin.issuer?.code === "bahamas"
+6 -1
View File
@@ -38,7 +38,12 @@ export const CoinInstances = (coinProps: CoinProps) => {
}, [at, count, size, thickness]); }, [at, count, size, thickness]);
return ( return (
<instancedMesh ref={ref} args={[undefined, undefined, count]}> <instancedMesh
castShadow
receiveShadow
ref={ref}
args={[undefined, undefined, count]}
>
<CoinInstance {...coinProps} /> <CoinInstance {...coinProps} />
</instancedMesh> </instancedMesh>
); );
+19 -19
View File
@@ -1,4 +1,4 @@
import { Canvas, PointLightProps } from "@react-three/fiber"; import { Canvas, SpotLightProps } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei"; import { OrbitControls } from "@react-three/drei";
import { useRef } from "react"; import { useRef } from "react";
import { CoinInstances } from "./coin-instances"; import { CoinInstances } from "./coin-instances";
@@ -6,6 +6,7 @@ import { CoinProps } from "@/types/coin";
import { PlaneProps, Physics, usePlane } from "@react-three/cannon"; import { PlaneProps, Physics, usePlane } from "@react-three/cannon";
import { Mesh } from "three"; import { Mesh } from "three";
import styles from "./index.module.css"; import styles from "./index.module.css";
import { StageLightModel } from "./stage-light-model";
type Props = { type Props = {
coins: CoinProps[]; coins: CoinProps[];
@@ -13,33 +14,28 @@ type Props = {
const Plane = (props: PlaneProps) => { const Plane = (props: PlaneProps) => {
const [ref] = usePlane(() => ({ ...props }), useRef<Mesh>(null)); const [ref] = usePlane(() => ({ ...props }), useRef<Mesh>(null));
return ( return (
<mesh ref={ref}> <mesh receiveShadow ref={ref}>
<circleGeometry args={[64]} /> <circleGeometry args={[128]} />
<meshBasicMaterial color={"black"} /> <meshStandardMaterial color={"#222"} metalness={0} roughness={1} />
</mesh> </mesh>
); );
}; };
const Lightbulb = (props: PointLightProps) => ( const StageLight = (props: SpotLightProps) => (
<> <>
<pointLight {...props} /> <spotLight {...props} castShadow penumbra={1} />
<mesh position={props.position}> <StageLightModel position={props.position} />
<sphereGeometry args={[0.25]} />
<meshBasicMaterial color="white" />
</mesh>
</> </>
); );
export const Pile = ({ coins }: Props) => ( export const Pile = ({ coins }: Props) => (
<Canvas camera={{ position: [0, 16, 16] }} className={styles.canvas}> <Canvas shadows camera={{ position: [0, 16, 16] }} className={styles.canvas}>
<ambientLight /> <StageLight position={[32, 16, 32]} />
<StageLight position={[32, 16, -32]} />
<Lightbulb position={[0, 16, 0]} /> <StageLight position={[-32, 16, 32]} />
<Lightbulb position={[16, 0, 16]} /> <StageLight position={[-32, 16, -32]} />
<Lightbulb position={[16, 0, -16]} />
<Lightbulb position={[-16, 0, 16]} />
<Lightbulb position={[-16, 0, -16]} />
<Physics gravity={[0, -20, 0]}> <Physics gravity={[0, -20, 0]}>
<Plane rotation={[-Math.PI / 2, 0, 0]} position={[0, -2, 0]} /> <Plane rotation={[-Math.PI / 2, 0, 0]} position={[0, -2, 0]} />
{coins.map((coinProps) => ( {coins.map((coinProps) => (
@@ -47,6 +43,10 @@ export const Pile = ({ coins }: Props) => (
))} ))}
</Physics> </Physics>
<OrbitControls maxPolarAngle={Math.PI / 2} enablePan={false} /> <OrbitControls
maxPolarAngle={Math.PI / 2}
enablePan={false}
minDistance={4}
/>
</Canvas> </Canvas>
); );
+36
View File
@@ -0,0 +1,36 @@
import { GroupProps } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";
import { useLayoutEffect, useRef } from "react";
import { Group } from "three";
export function StageLightModel(props: GroupProps) {
// @ts-expect-error properties `nodes` and `materials` actually exist
const { nodes, materials } = useGLTF("/models/stage-light.gltf");
const ref = useRef<Group>(null!);
useLayoutEffect(() => {
ref.current.lookAt(0, 0, 0);
ref.current.rotateY(-Math.PI / 2);
}, []);
return (
<group ref={ref} {...props} dispose={null}>
<mesh
position={[-2, 0, 0]}
castShadow
receiveShadow
geometry={nodes.Cube001.geometry}
material={materials.Base}
/>
<mesh
position={[-2, 0, 0]}
castShadow
receiveShadow
geometry={nodes.Cube001_1.geometry}
material={materials.Light}
/>
</group>
);
}
useGLTF.preload("/models/stage-light.gltf");