【问题标题】:React and Three.js MTLLoader "material.onBeforeCompile is undefined"React 和 Three.js MTLLoader “material.onBeforeCompile 未定义”
【发布时间】:2018-03-28 23:15:54
【问题描述】:

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

  • 三个(0.87.1)
  • 反应(15.6.1)
  • 三个obj-loader(1.1.3)
  • 三-mtl-loader(1.0.1)

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

未捕获的类型错误:无法读取未定义的属性“toString” 在 WebGLPrograms.getProgramCode (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:50707) 在 initMaterial (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54628) 在 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) 在 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() 时)。

有没有可能是模块版本的问题,或者加载时的一些时间问题?

任何帮助将不胜感激。

【问题讨论】:

  • 尽量避免这个=&gt;“箭头函数”并使用更清晰和明确的代码......我不知道这个=&gt;是如何工作的,但这在我看来是另一个错误的好- 弹性Javascript语法的想法......主要是在引用必须一致且可靠的上下文中......我不是Javascript大师,但来自C / C ++,这种事情对我的影响与火药杂志上的火柴。
  • 嗯,你能看看这三个的来源,看看它是否在材质上定义了onBeforeCompile?你确定你使用的是 87 吗?
  • 您是否有机会发布此代码,以便我们追踪它并查看发生了什么?这看起来像一个错误,但没有什么比这更明显。
  • 箭头函数现在是完全正常的 JavaScript。 @Sedenion 我建议你学习它们。他们不会消失。他们绝对没有错。它们是在现代 JavaScript 中做很多事情的推荐方式。
  • 是的,版本肯定是 87 @pailhead。到目前为止,我还不能真正理解这三个来源。我没有找到 onBeforeCompile 的任何直接定义,除了 Material.js 中 Object.assign 中的一个空函数(我什至不明白它是否在某处被调用)。对不起,我在这里似乎不是很有帮助。有没有一种方法可以在不自己托管的情况下将该节点/反应的东西放到网上? (我不知道合适的方法,但无论如何我对这一切都很陌生)

标签: reactjs three.js


【解决方案1】:

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

显然,这不是一个可行的长期解决方案,但我将node_modules/three-mtl-loader/package.json 中的三个版本更改为 0.87.1 并删除了目录node_modules/three-mtl-loader/node_modules 并运行了我的示例,它立即工作,纹理和所有。

显然插件需要更新。我还看到插件中的源代码和三个示例文件夹(案例语句中的“Tr”与“tr”)之间至少有一个功能差异,并且它不遵循与其他加载器插件相同的初始化行为(特别是它不是通过调用require("three-mtl-loader")(THREE)) 来初始化的,因此需要做一些工作才能使其成型。

另外,作者似乎在他们的 repo 中将版本号更新为 0.86.0(这已经足够高了),只是还没有部署到 NPM。所以,如果你觉得勇敢,你可以把你的 package.json 改成一行

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

【讨论】:

  • 准确!我自己的依赖与消耗我依赖的我自己的应用程序的 Three.js 版本不同。
【解决方案2】:

作为一种解决方法,我最终做的是获取最新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';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-24
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 2016-02-20
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多