0

I'm using React Three Fiber to display a 3D model with the GLTFLoader. However, the model appears extremely small — barely visible, like a speck of dust.It is downloaded from sketchfab (https://skfb.ly/ooJLu). I've tried adjusting the scale and camera position, but the model still remains tiny.I want it to display in normal size How can I dynamically resize the model to fit the view perfectly regardless of its original size? Is there a method to automatically center and scale the model based on its bounding box?

    import React, { Suspense, useRef, useEffect } from "react";
import { Canvas, useFrame, useLoader, useThree } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls, Environment, Html } from "@react-three/drei";
import * as THREE from "three";

// Model component that loads and plays the animation from the 3D model
function Model() {
  const gltf = useLoader(GLTFLoader, "/traveler.glb");
  const modelRef = useRef();
  const mixer = useRef();
  const { scene, clock } = useThree();

  // Set up the animation mixer once the model is loaded
  useEffect(() => {
    if (gltf && gltf.animations && gltf.animations.length) {
      mixer.current = new THREE.AnimationMixer(gltf.scene);
      
      // Play all animations in the model
      gltf.animations.forEach(clip => {
        const action = mixer.current.clipAction(clip);
        action.play();
      });
    }
  }, [gltf]);

  // Update the animation on each frame
  useFrame((state, delta) => {
    if (mixer.current) {
      mixer.current.update(delta);
    }
  });

  return (
    <primitive 
      ref={modelRef}
      object={gltf.scene}
      scale={2.0}
      position={[0, -1, 0]}
      rotation={[0, Math.PI / 4, 0]} // Rotate slightly for better view
    />
  );
}

// Loader component for displaying during model loading
function Loader() {
  return (
    <Html center>
      <div style={{ color: "white", display: "flex", flexDirection: "column", alignItems: "center" }}>
        <div className="loader"></div>
        <p>Loading 3D model...</p>
      </div>
    </Html>
  );
}

// Main component
const HeroModel3D = () => {
  return (
    <div className="hero-model-3d">
      <Canvas
        camera={{ position: [0, 0, 4], fov: 45 }}
        style={{ background: "grey" }}
      >
        <ambientLight intensity={0.7} />
        <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} intensity={1.2} castShadow />
        <directionalLight position={[-5, 5, -5]} intensity={0.5} />
        <Suspense fallback={<Loader />}>
          <Model />
          <Environment preset="city" />
          <OrbitControls 
            enableZoom={false}
            enablePan={false}
            minPolarAngle={Math.PI / 3}
            maxPolarAngle={Math.PI / 2}
            autoRotate={false}
            rotateSpeed={0.5}
          />
        </Suspense>
      </Canvas>
    </div>
  );
};

export default HeroModel3D;

2
  • Any chance for sandbox with model? Commented Mar 4 at 20:06
  • You’re asking two separate questions. But you’re saying if you increase scale to a larger number, like 200, it’s still small? Is your canvas full height and width? Commented Mar 5 at 0:22

1 Answer 1

0

try to replace your Model function with this one

function Model() {
  const gltf = useLoader(GLTFLoader, "/traveler.glb");
  const modelRef = useRef();
  const mixer = useRef();
  const { camera } = useThree();

  useEffect(() => {
    if (!gltf || !modelRef.current) return;

    // Setup animation mixer
    if (gltf.animations.length) {
      mixer.current = new THREE.AnimationMixer(gltf.scene);
      gltf.animations.forEach((clip) => {
        mixer.current.clipAction(clip).play();
      });
    }

    // Auto-scale and center model
    const box = new THREE.Box3().setFromObject(modelRef.current);
    const center = box.getCenter(new THREE.Vector3());
    const size = box.getSize(new THREE.Vector3());

    const maxDim = Math.max(size.x, size.y, size.z);
    const fov = camera.fov * (Math.PI / 180);
    const distance = Math.abs(maxDim / Math.sin(fov / 2));

    camera.position.set(center.x, center.y, distance * 1.5);
    camera.lookAt(center);

    const scaleFactor = 2 / maxDim;
    modelRef.current.scale.setScalar(scaleFactor);
    modelRef.current.position.set(-center.x, -center.y, -center.z);
  }, [gltf]);

  useFrame((_, delta) => {
    if (mixer.current) mixer.current.update(delta);
  });

  return <primitive ref={modelRef} object={gltf.scene} />;
}

hope it can auto centering and auto scaling your gltf model

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.