You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Three Fiber中GLTFLoader加载的3D模型过小问题

解决React Three Fiber中3D模型过小且自动适配视图的问题

针对你遇到的模型显示极小的问题,完全可以通过自动计算模型包围盒来实现居中适配,无需手动调整缩放和相机位置。以下是修改后的代码和关键逻辑说明:

核心解决方案:基于包围盒自动居中与缩放

在模型加载完成后,利用Three.js的Box3计算模型的整体包围盒,然后:

  1. 将模型平移到场景原点实现居中
  2. 根据包围盒尺寸计算合适的缩放比例,让模型刚好适配相机视野

修改后的完整代码

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";

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

  useEffect(() => {
    if (!gltf?.scene) return;

    // 1. 计算模型整体包围盒
    const box = new THREE.Box3().setFromObject(gltf.scene);
    // 获取包围盒的中心坐标与尺寸
    box.getCenter(center);
    box.getSize(size);

    // 2. 计算适配相机视野的缩放比例
    const maxDim = Math.max(size.x, size.y, size.z);
    // 5是基于相机z轴位置(4)的适配值,可根据需求微调
    const scale = 5 / maxDim;

    // 3. 应用居中与缩放设置
    modelRef.current.position.set(-center.x, -center.y, -center.z);
    modelRef.current.scale.setScalar(scale);

    // 初始化动画播放器
    if (gltf.animations.length > 0) {
      mixer.current = new THREE.AnimationMixer(gltf.scene);
      gltf.animations.forEach(clip => {
        const action = mixer.current.clipAction(clip);
        action.play();
      });
    }
  }, [gltf]);

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

  return (
    <primitive 
      ref={modelRef}
      object={gltf.scene}
      rotation={[0, Math.PI / 4, 0]}
    />
  );
}

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>
  );
}

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;

关键逻辑说明

  • 包围盒计算:Box3().setFromObject(gltf.scene)会遍历模型所有子网格,计算出覆盖整个模型的最小包围盒,确保包含所有可见元素
  • 居中处理:将模型位置设置为包围盒中心的负值,让模型的几何中心与场景原点重合,实现自动居中
  • 缩放计算:通过模型最大边长与相机视野的比例(5 / maxDim),确保模型不会超出相机可见范围,这个数值可以根据你想要的显示大小微调
  • 动画兼容:包围盒计算在动画初始化前完成,避免动画帧干扰尺寸计算

内容的提问来源于stack exchange,提问作者Sithil Sandinu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:06:09