How to set default camera position directly over .glb model with react-three-fiber

Viewed 274

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:

Correct perspective

However, this is the perspective that gets set by default:

Incorrect perspective

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.

1 Answers

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, nor is the exported position of the object respected.

Nonetheless, the behavior 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;
Related