Once I kicked the react-three-fiber tires it was time to start learning how to render 3D models in the project I started this week. I wanted to use a free submarine model I got from Turbo Squid. I just downloaded the .blend file and opened it in Blender, then File > Export > gITF 2.0. glTF is a file format for 3D models using the JSON standard.
Loading the submarine.gltf model
First I needed to create a new component for the model.
import React, { useLayoutEffect }from 'react';
import { useGLTF } from '@react-three/drei';
import * as THREE from 'three';
export const Submarine = ({currentColor}) => {
const { scene, nodes, materials } = useGLTF('./models/submarine.gltf');
useLayoutEffect(() => {
Object.assign(materials.Material, {
roughness: 0,
metalness: 0.25,
emissive: new THREE.Color(0x000000),
color: currentColor,
envMapIntensity: 0.5 })
}, [scene, nodes, materials, currentColor]);
return <primitive object={scene} />
};
I’m importing useGLTF
from @react-three/drei
(A collection of abstractions for react-three-fiber.) and pulling out the some variables to use with React’s useLayoutEffect
hook. I’ll be using the currentColor
state to change the color of the submarine.
Changing the submarine color
Now I needed to update the App.js file to store some colors and refactor the handleColorChange
function:
...
const orange = new THREE.Color(0xffa500);
const crimson = new THREE.Color(0xdc143c);
const teal = new THREE.Color(0x008080);
const steelblue = new THREE.Color(0x4682b4);
const [currentColor, setCurrentColor] = useState(orange);
const handleColorChange = (event, color) => {
event.preventDefault();
if (color === 'crimson') {
setCurrentColor(crimson);
} else if (color === 'teal') {
setCurrentColor(teal);
} else if (color === 'steelblue') {
setCurrentColor(steelblue);
} else {
setCurrentColor(orange);
}
};
...
Moving the scene with mouse
Last thing to do was use the <OrbitControls>
component from @react-three/drei
so I could make the submarine rotate and respond to mouse events.
...
<OrbitControls autoRotate enableZoom={false} enablePan={false} minPolarAngle={Math.PI / 2.8} maxPolarAngle={Math.PI / 2.8} />
...
I have a branch with this code and here’s what the project looks like so far: