Skip to content

Instantly share code, notes, and snippets.

@panzerstadt
Last active December 15, 2024 05:53
Show Gist options
  • Save panzerstadt/39c2a7209ae0d1337c42e1aef840cbfb to your computer and use it in GitHub Desktop.
Save panzerstadt/39c2a7209ae0d1337c42e1aef840cbfb to your computer and use it in GitHub Desktop.
react three fiber scene setup
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/
import * as THREE from "three";
import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";
import { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
import { CarbonFiber } from "../../constants/materials/CarbonFiber";
type GLTFResult = GLTF & {
nodes: {
Body2_4002: THREE.Mesh;
Body2_44_1: THREE.Mesh;
Body2_44_2: THREE.Mesh;
Body2_44_3: THREE.Mesh;
Body2_44_4: THREE.Mesh;
Body2_44_5: THREE.Mesh;
Body2_44_6: THREE.Mesh;
Body2_44_7: THREE.Mesh;
Body2_44_8: THREE.Mesh;
["STLB_ATF_81206_COLOR=�_5002"]: THREE.Mesh;
};
materials: {
["satin black.001"]: THREE.MeshStandardMaterial;
["carbon fiber"]: THREE.MeshPhysicalMaterial;
["brass fixings"]: THREE.MeshStandardMaterial;
["novelkeys cream"]: THREE.MeshStandardMaterial;
brass: THREE.MeshPhysicalMaterial;
["black plastic"]: THREE.MeshStandardMaterial;
["shiny alu"]: THREE.MeshStandardMaterial;
["white plastic"]: THREE.MeshStandardMaterial;
["case black (deprecated).001"]: THREE.MeshStandardMaterial;
["kat_keycaps.001"]: THREE.MeshStandardMaterial;
};
};
export default function Model(props: JSX.IntrinsicElements["group"]) {
const group = useRef<THREE.Group>(null);
const { nodes, materials } = useGLTF(
"/products/rotrLite/rotr-lite.gltf"
) as unknown as GLTFResult;
return (
<group ref={group} {...props} dispose={null}>
<group position={[0.0350996, 0, 0.056208]} scale={[0.001, 0.001, 0.001]}>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_4002.geometry}
material={materials["satin black.001"]}
/>
<mesh castShadow receiveShadow geometry={nodes.Body2_44_1.geometry}>
<CarbonFiber />
</mesh>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_2.geometry}
material={materials["brass fixings"]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_3.geometry}
material={materials["novelkeys cream"]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_4.geometry}
material={materials.brass}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_5.geometry}
material={materials["black plastic"]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_6.geometry}
material={materials["shiny alu"]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_7.geometry}
material={materials["white plastic"]}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Body2_44_8.geometry}
material={materials["case black (deprecated).001"]}
/>
</group>
<mesh
castShadow
receiveShadow
geometry={nodes["STLB_ATF_81206_COLOR=�_5002"].geometry}
material={materials["kat_keycaps.001"]}
position={[0.0354439, 0.0008269, -0.0623422]}
scale={[0.001, 0.001, 0.001]}
/>
</group>
);
}
import { AdaptiveDpr, Html, Stats, Stage, Environment, ContactShadows } from "@react-three/drei";
import React, { Suspense } from "react";
import { Loading } from "../../components/Homepage/Loading";
import { useDimensions } from "../../components/useDimensions";
import { Scene3D } from "../../templates/Scene3D";
import RotrLite from "./RotrLite";
export const RotrLiteScene: React.FC = () => {
const { isDesktop } = useDimensions();
return (
<Scene3D
pannable={false}
camera={{ position: [-2, 0, 3.5], zoom: isDesktop ? 1 : 0.8 }}
controls={{ limit: { down: 0.6, up: 0.2 } }}
>
{/* <Stats /> */}
<Suspense
fallback={
<Html className="w-full h-full">
<Loading />
</Html>
}
>
<RotrLite scale={[10, 10, 10]} rotation={[Math.PI * 0.4, 0, Math.PI * 0.2]} />
<ContactShadows
rotation-x={Math.PI / 2}
position={[0, -0.6, 0]}
opacity={0.25}
width={10}
height={10}
blur={1.5}
far={0.8}
/>
<Environment files="./hdri/potsdamer_platz_1k.hdr" />
</Suspense>
<AdaptiveDpr pixelated />
</Scene3D>
);
};
import { OrbitControls } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import React from "react";
interface SceneProps {
camera?: {
position?: [number, number, number];
fov?: number;
zoom?: number;
};
scene?: {
fog?: {
near?: number;
far?: number;
};
};
controls?: {
limit?: {
left?: number;
right?: number;
up?: number;
down?: number;
near?: number;
far?: number;
};
};
pannable?: boolean;
}
const getAngle = (num: number) => Math.PI * num;
const neg = (num?: number) => (num ? -num : num!);
export const Scene3D: React.FC<React.PropsWithChildren<SceneProps>> = ({
children,
camera,
pannable,
controls,
}) => {
return (
<div style={{ height: "100%", minHeight: 600, position: "relative" }}>
<Canvas
shadows
dpr={[0.5, 1]}
camera={{
position: camera?.position || [0, 0, 10],
fov: camera?.fov || 20,
zoom: camera?.zoom,
}}
>
<ambientLight intensity={0.8} />
{/* <spotLight
intensity={0.6}
angle={0.1}
penumbra={1}
position={[10, 15, 10]}
castShadow
/> */}
{children}
<OrbitControls
enablePan={pannable || false}
autoRotate
autoRotateSpeed={0.3}
maxAzimuthAngle={
controls?.limit?.right
? getAngle(controls?.limit?.right)
: undefined
} // right
minAzimuthAngle={
controls?.limit?.left
? getAngle(neg(controls!.limit!.left))
: undefined
} // left
minDistance={controls?.limit?.near || 2}
maxDistance={controls?.limit?.far || 7}
maxPolarAngle={getAngle(controls?.limit?.down || 0.4)} // down
minPolarAngle={getAngle(controls?.limit?.up || 0.4)} // up
/>
{/* <color attach="background" args={["white"]} /> */}
{/* <fog
color={"white" as unknown as THREE.Color}
attach="fog"
near={scene?.fog?.near || 8}
far={scene?.fog?.far || 30}
/> */}
</Canvas>
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment