I'm trying to build a simple object-viewer in React with Meteor that can import .obj and .mtl Files using the following npm modules:
- three(0.87.1)
- react(15.6.1)
- three-obj-loader(1.1.3)
- three-mtl-loader(1.0.1)
So far i have managed to display an object using the OBJLoader. But when i try to render an object after applying a texture with MTLLoader, i get this error from console:
Uncaught TypeError: Cannot read property 'toString' of undefined at WebGLPrograms.getProgramCode (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:50707) at initMaterial (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54628) at setProgram (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54820) at WebGLRenderer.renderBufferDirect (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:53883) at renderObject (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54613) at renderObjects (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54586) at WebGLRenderer.render (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:54350) at WebGlDisplay.renderScene (WebGlDisplay.jsx:86) at onClick (WebGlDisplay.jsx:90) at HTMLUnknownElement.boundFunc (modules.js?hash=eae498e3ee56e21f967b663c5bed3444c66eaef2:8794)
Cause: material.onBeforeCompile in getProgramCode is undefined
My code looks like this:
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 }}
/>
)
}
}
Does anyone have an idea why i get this error? I've tried to use different .obj- and .mtl-files, but the error remains (whenever i try to call renderScene()).
By any chance, could it be a problem with the module versions, or maybe some timing problems while loading?
Any help would be appreciated.
=>
"arrow function" and use more clear and explicit code... I don't know how this=>
precisely works, but this appear to me another false good-idea of the elastic Javascript syntax... mostly in a context where references must be consistants and reliable... I'am not a Javascript guru, but coming from C/C++, this kind of thing make to me the same effect than a match in a gunpowder magazine. – user1501157onBeforeCompile
defined on a material? Are you absolutely sure you are using 87? – pailhead