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

如何使用expo-three在Expo React Native应用中加载渲染本地.obj格式3D模型

问题排查与修复方案

现存问题梳理

  • 缺失GLView组件引入,该组件是Expo下3D渲染的核心依赖,需从expo-gl包导入
  • 未配置Expo打包规则,默认不会识别.obj后缀的静态资源,会导致资源加载失败
  • 未给模型设置可见材质,OBJLoader加载的模型默认材质在当前弱光环境下几乎不可见
  • timeout变量未声明,运行时会抛出未定义错误
  • 无加载异常捕获逻辑,无法定位是资源加载失败还是渲染逻辑问题

修复步骤

1. 安装缺失依赖

执行命令安装必要包:
npm install expo-gl expo-three three expo-asset

2. 配置app.json支持.obj资源

在项目根目录的app.json中,给expo字段添加如下配置,让打包工具识别.obj格式资源:

{
  "expo": {
    "packagerOpts": {
      "assetExts": ["obj", "mtl", "png", "jpg"]
    },
    "assetBundlePatterns": [
      "**/*"
    ]
  }
}

如果你的模型附带.mtl材质文件和纹理图,也需要把对应后缀加到assetExts中。

3. 修正代码逻辑

下面是可直接运行的完整代码:

import { Renderer } from 'expo-three';
import * as React from 'react';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import {
  AmbientLight,
  Fog,
  GridHelper,
  PerspectiveCamera,
  PointLight,
  Scene,
  SpotLight,
  MeshStandardMaterial
} from 'three';
import { Asset } from 'expo-asset';
import { GLView } from 'expo-gl';

export default function ThreeDPhytosaur() {
  let timeout = null;

  React.useEffect(() => {
    return () => {
      if (timeout) cancelAnimationFrame(timeout);
    }
  }, []);

  return (
    <GLView
      style={{ flex: 1 }}
      onContextCreate={async (gl) => {
        try {
          const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
          const sceneColor = 0x6ad6f0;

          const renderer = new Renderer({ gl });
          renderer.setSize(width, height);
          renderer.setClearColor(sceneColor);

          const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
          camera.position.set(2, 5, 5);

          const scene = new Scene();
          scene.fog = new Fog(sceneColor, 1, 10000);
          scene.add(new GridHelper(10, 10));

          // 调高环境光亮度,确保模型可见
          const ambientLight = new AmbientLight(0xffffff, 1.2);
          scene.add(ambientLight);

          const pointLight = new PointLight(0xffffff, 2, 1000, 1);
          pointLight.position.set(0, 200, 200);
          scene.add(pointLight);

          const spotLight = new SpotLight(0xffffff, 0.5);
          spotLight.position.set(0, 500, 100);
          spotLight.lookAt(scene.position);
          scene.add(spotLight);

          const asset = Asset.fromModule(model['phytosaur']);
          await asset.downloadAsync();

          const objectLoader = new OBJLoader();
          const object = await objectLoader.loadAsync(asset.uri);

          // 给所有网格加测试材质,方便确认是否渲染成功
          object.traverse((child) => {
            if (child.isMesh) {
              child.material = new MeshStandardMaterial({ color: 0x2196F3, roughness: 0.5 });
            }
          });

          // 根据你的模型尺寸调整缩放,太小可以改大到0.1、1测试
          object.scale.set(0.025, 0.025, 0.025);
          object.position.set(0, 0, 0);
          scene.add(object);
          camera.lookAt(object.position);

          const render = () => {
            timeout = requestAnimationFrame(render);
            // 加个缓慢旋转动画,确认模型在正常渲染
            object.rotation.y += 0.01;
            renderer.render(scene, camera);
            gl.endFrameEXP();
          };
          render();
        } catch (e) {
          console.log('加载错误:', e);
        }
      }}
    />
  );
}

const model = {
  'phytosaur': require('../assets/phytosaur.obj'),
};

4. 调试提示

如果还是看不到模型,按以下顺序排查:

  • 看控制台有没有报错,确认资源路径正确、模型文件没有损坏
  • 把模型缩放值调大,比如改成1、10,很多.obj模型本身尺寸很小,缩放过度会看不到
  • 把相机位置往后移,比如改成camera.position.set(0, 0, 20),避免模型在视锥近截面外
  • 移除GridHelper,避免网格挡住模型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 16:45:00