I have a codesandbox setup here to demonstrate and troubleshoot.
I exported a simple 3d model using blender. My goal is to import the model into my React app with react-three-fiber, and have the camera perspective looking directly over the model's face at initial render. However, the imported model defaults to a side-view.
Here is the default perspective I would like:
However, this is the perspective that gets set by default:
Using blender, I set the correct camera position, and exported the .glb file with the camera. However, I'm not sure how to use the exported camera, or if that's even possible.
My goal is to either use the exported camera, or utilize react-three-fiber to setup the camera and perspective I want.
Thanks in advance for any help, I'm new to three.js and 3d modeling in general.
Okay, it seems that three.js defaults to creating it's own perspective camera for our imported models, which gives the funky angle. Apparently cameras from blender are not imported.
This is only part of my issue. In blender, I had my model sitting flat on the x and y plane, instead of upright. The default camera created by three.js is positioned as if it were a person standing on the plane, looking toward the center of the x and y axis. That's why my model is being seen from a side-on view.
So I have two options:
In reality, a mixture of the two options would usually be needed for accurate positioning. However, we'll stick with option two alone for this solution.
The three.js default camera positioning can be overwritten by accessing the threejs camera using using the useThree hook.
The camera object gives us access to the position
properties and the lookAt
method.
In the case of my model, setting the y property to 50 gives a straight on view. So, if I set it at 30, then call the lookAt(0,0,0)
method to re-center the camera, I can achieve the desired result.
Here's an update of my model component reflecting these changes. I updated the sandbox as well for those looking to get a visual:
import React, { useRef } from "react";
import { useLoader, useFrame, useThree } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
const GltfModel = ({ modelPath, position = [0, 0, 0] }) => {
const ref = useRef();
const gltf = useLoader(GLTFLoader, modelPath);
// Subscribe this component to the render-loop, rotate the mesh every frame
useFrame(() => (ref.current.rotation.y += 0.001));
// Here, we can access the camera via the useThree hook
useThree(({camera}) => {
camera.position.y = 8;
camera.lookAt(0, 0, 0);
});
return (
<>
<primitive
ref={ref}
object={gltf.scene}
scale={"6"}
/>
</>
);
};
export default GltfModel;