Add 3D object viewers with r3f stack
Add per-class 3D viewers for tiles, tokens, cards, and custom models using React Three Fiber, drei, and postprocessing. Viewers are lazy-loaded and registered through the existing viewer registry, with a shared scene wrapper for lighting, orbit controls, and subtle effects. Add a CORS-safe /asset proxy route so three.js loaders can fetch Workshop-hosted textures and models, and extend TTSObject with the CustomMesh and CustomTile/CustomToken fields the viewers read.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { Suspense, type ReactNode } from 'react';
|
||||
import { Canvas } from '@react-three/fiber';
|
||||
import { ContactShadows, OrbitControls } from '@react-three/drei';
|
||||
import { Bloom, EffectComposer, Vignette } from '@react-three/postprocessing';
|
||||
|
||||
/**
|
||||
* Shared 3D scene wrapper for object viewers. Provides a consistent camera,
|
||||
* lighting, orbit controls, a soft contact shadow, and subtle post-processing
|
||||
* (bloom + vignette). Children are wrapped in a Suspense boundary so loading
|
||||
* assets (textures, models) can suspend without blanking the page.
|
||||
*/
|
||||
export default function Scene({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="h-80 w-full overflow-hidden rounded-lg bg-linear-to-b from-zinc-900 to-zinc-950">
|
||||
<Canvas
|
||||
camera={{ position: [2.2, 1.8, 2.6], fov: 40 }}
|
||||
dpr={[1, 2]}
|
||||
gl={{ antialias: true }}
|
||||
>
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[4, 6, 3]} intensity={1.4} />
|
||||
<directionalLight position={[-4, 2, -3]} intensity={0.4} color="#b3c7ff" />
|
||||
<pointLight position={[0, 3, 0]} intensity={0.3} />
|
||||
|
||||
<Suspense fallback={null}>{children}</Suspense>
|
||||
|
||||
<ContactShadows
|
||||
position={[0, -0.5, 0]}
|
||||
opacity={0.55}
|
||||
scale={8}
|
||||
blur={2.4}
|
||||
far={3}
|
||||
resolution={256}
|
||||
/>
|
||||
<OrbitControls
|
||||
enablePan={false}
|
||||
minDistance={1}
|
||||
maxDistance={8}
|
||||
autoRotate
|
||||
autoRotateSpeed={1.2}
|
||||
/>
|
||||
|
||||
<EffectComposer>
|
||||
<Bloom intensity={0.25} luminanceThreshold={0.85} mipmapBlur />
|
||||
<Vignette eskil={false} offset={0.25} darkness={0.6} />
|
||||
</EffectComposer>
|
||||
</Canvas>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user