React和Three.js MTLLoader" material.onBeforeCompile未定义"

时间:2017-10-17 09:43:21

标签: reactjs three.js

我试图在React with Meteor中构建一个简单的对象查看器,它可以使用以下npm模块导入.obj和.mtl文件:

  • 3(0.87.1)
  • 反应(15.6.1)
  • 三OBJ-加载程序(1.1.3)
  • 三MTL-加载程序(1.0.1)

到目前为止,我已设法使用OBJLoader显示对象。 但是当我尝试使用MTLLoader应用纹理后渲染对象时,我从控制台收到此错误:

  

未捕获的TypeError:无法读取属性' toString'未定义的       在WebGLPrograms.getProgramCode(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:50707)       在initMaterial(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:54628)       at setProgram(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:54820)       在WebGLRenderer.renderBufferDirect(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:53883)       在renderObject(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:54613)       在renderObjects(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:54586)       在WebGLRenderer.render(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:54350)       在WebGlDisplay.renderScene(WebGlDisplay.jsx:86)       at onClick(WebGlDisplay.jsx:90)       在HTMLUnknownElement.boundFunc(modules.js?hash = eae498e3ee56e21f967b663c5bed3444c66eaef2:8794)

原因: getProgramCode 中的 material.onBeforeCompile 未定义

我的代码如下所示:

import React, { Component } from 'react'
import THREE from 'three'
const MTLLoader = require('three-mtl-loader');
const OBJLoader = require('three-obj-loader')(THREE);

export default class WebGlDisplay extends Component {
  constructor(props) {
    super(props)
  }

      //init canvas
   init(){
    const width = this.mount.clientWidth;
    const height = this.mount.clientHeight;
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setClearColor('#000000', 0.2);
    renderer.setSize(width, height);
    camera.position.set(3,4,6);
    camera.lookAt(new THREE.Vector3());
    this.scene = scene;
    this.camera = camera;
    this.renderer = renderer;
    this.mount.appendChild(this.renderer.domElement);
  }

  //load & render object
  drawOBJ(){
    const mtlLoader = new MTLLoader();
    let onProgress = function(e){console.log("rendering:" + e)};
    let onError = function(e){console.log("error:" + e)};
    mtlLoader.load("eagle.mtl", materials => {
        materials.preload();
        // OBJ Loader
        const objLoader = new THREE.OBJLoader();
        this.materials = materials;
        objLoader.setMaterials(materials);
        objLoader.load("eagle.obj", object => {
              this.object = object;
            this.scene.add(object);
        }, onProgress, onError);
    }, onProgress,onError);
    this.renderScene();
  }

  componentDidMount() {
    this.init();
    this.drawOBJ();
  }

  renderScene() {
    this.renderer.render(this.scene, this.camera)
  }

  render() {
    return (
      <div onClick={(e) => this.renderScene()}
        style={{ width: '800px', height: '600px' }}
        ref={(mount) => { this.mount = mount }}
      />
    )
  }
}

有谁知道我为什么会收到此错误? 我尝试使用不同的.obj-和.mtl文件,但错误仍然存​​在(每当我尝试调用 renderScene()时)。

无论如何,这可能是模块版本的问题,还是加载时的一些时序问题?

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:2)

问题似乎是三mtl-loader NPM包在它的package.json中引用了一个过时的three.js版本,所以即使你使用的是最新版本的三个,插件也不是! / p>

显然这不是一个可行的长期修复,但是我将node_modules/three-mtl-loader/package.json中的三个版本更改为0.87.1并删除了目录node_modules/three-mtl-loader/node_modules以获得良好的衡量标准并运行了我的示例直接工作,纹理和所有。

显然,插件需要更新。我还看到了插件中的源和三个示例文件夹(case语句中的'Tr'与'tr')之间至少有一个功能差异,并且它不遵循与其他加载器插件相同的初始化行为(具体而言)它没有通过调用require("three-mtl-loader")(THREE))来初始化,因此有一些工作可以使它成为船形。

或者,似乎作者已将其版本号更新为其回购中的0.86.0(足够高),但尚未对NPM进行部署。所以,如果你觉得很勇敢,你可以改变你的package.json来获得行

"dependencies": { ... "three-mtl-loader": "git+https://git@github.com/nascherman/three-mtl-loader.git", ... }

答案 1 :(得分:0)

作为一种解决方法,我最终做的是获取最新MTLLoader Version的本地副本并略微修改它,因为它似乎是@ user1691694指出的problem with the version。 如果有人在这里需要这个我导入它的方式:

在MTLLoader文件中,在顶部添加以下行:

import THREE from 'three';

在底部:

module.exports.default =  THREE.MTLLoader

question post中的drawOBJ函数一样使用它,并将其导入目标文件中,如下所示:

import MTLLoader from './MTLLoader.js';