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

React-Planner集成Three.js加载MTL/OBJ文件时出现TypeError报错

React中使用react-planner加载OBJ/MTL模型报错解决

在React项目中使用react-planner包,SRC目录存储了包含MTL、OBJ和纹理文件的3D模型资源,切换至3D视图时加载报错:

Uncaught (in promise) TypeError: url.lastIndexOf is not a function

报错指向load-obj.js文件中的loadObjWithMaterial函数。

相关代码

load-obj.js中的加载函数

import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';

export function loadObjWithMaterial(mtlFile, objFile, imgPath) {
  let mtlLoader = new MTLLoader();
  mtlLoader.setResourcePath(imgPath);
  let url = mtlFile;
  return new Promise((resolve, reject) => {

    mtlLoader.load(url, materials => {
      materials.preload();
      let objLoader = new OBJLoader();
      objLoader.setMaterials(materials);
      objLoader.load(objFile, object => resolve(object));

    });
  });
}

调用加载函数的代码

let mtl = require('./door.mtl');
let obj = require('./door.obj');
let img = require('./texture.jpg');

return loadObjWithMaterial(mtl, obj, img)
  .then(object => {
    cached3DDoor = object;
    return onLoadItem(cached3DDoor.clone())
  })

执行console.log(url)后,控制台输出:

Object { default: "/static/media/door.3052bdbf.mtl", … }

该路径对应的文件可正常访问。

曾尝试将let url = mtlFile;替换为let url = window.URL.createObjectURL(new Blob([mtlFile]));,但出现新报错:

Uncaught Error: THREE.OBJLoader: Unexpected line: "<!DOCTYPE html>"

问题原因与解决方法

问题根源

用require()加载MTL/OBJ文件时,webpack返回的是包含default属性的模块对象,而非直接的文件路径字符串,而MTLLoader.load()需要传入字符串格式的URL,因此触发url.lastIndexOf is not a function错误。

解决步骤

  1. 修正文件路径取值
    调用函数时,传入模块对象的default属性值(即实际文件URL):

    let mtl = require('./door.mtl').default;
    let obj = require('./door.obj').default;
    let img = require('./texture.jpg').default;
    
    return loadObjWithMaterial(mtl, obj, img)
      .then(object => {
        cached3DDoor = object;
        return onLoadItem(cached3DDoor.clone())
      })
    

    若使用ES6 import语法,可直接获取路径:

    import mtl from './door.mtl';
    import obj from './door.obj';
    import img from './texture.jpg';
    
  2. 修正纹理路径处理
    MTLLoader.setResourcePath()需要的是纹理文件所在的目录路径,而非完整的纹理文件URL,需从纹理URL中提取目录部分:

    export function loadObjWithMaterial(mtlFile, objFile, imgUrl) {
      let mtlLoader = new MTLLoader();
      // 提取纹理文件的目录路径
      const imgPath = imgUrl.substring(0, imgUrl.lastIndexOf('/') + 1);
      mtlLoader.setResourcePath(imgPath);
      return new Promise((resolve, reject) => {
        mtlLoader.load(mtlFile, materials => {
          materials.preload();
          let objLoader = new OBJLoader();
          objLoader.setMaterials(materials);
          objLoader.load(objFile, object => resolve(object), undefined, reject);
        }, undefined, reject);
      });
    }
    
  3. 添加错误回调
    在load方法中加入错误回调,便于排查后续加载问题,如上述代码中的undefined, reject参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:25:35