问题
Yesterday I asked this question (Uncaught TypeError: THREE.MTLLoader is not a constructor 2.0), which I thought that I had finally gotten to work, but now new questions have instead emerged:
I have installed 'three-mtl-loader' using npm, but now it seems that the object isn't visible, eventhough I can console.log
my way into seeing that the object exists.
For some reason it now spits out the following error, and I guess that that is why it is not visible:
THREE.MeshPhongMaterial: .shading has been removed. Use the boolean .flatShading instead.
get @ three.js:43339
WebGLPrograms.getParameters @ three.js:17838
initMaterial @ three.js:21734
setProgram @ three.js:21929
WebGLRenderer.renderBufferDirect @ three.js:20964
renderObject @ three.js:21722
renderObjects @ three.js:21695
WebGLRenderer.render @ three.js:21463
render @ main.ts:163
requestAnimationFrame (async)
render @ main.ts:162
requestAnimationFrame (async)
render @ main.ts:162
requestAnimationFrame (async)
...
The code as I have it now looks like this:
import * as THREE from 'three'
import * as OBJLoader from 'three-obj-loader'
OBJLoader(THREE)
import * as MTLLoader from 'three-mtl-loader'
//create global variables such that we can work with models outside of loader:
var model1, model2;
var mtlLoader = new MTLLoader();
mtlLoader.setPath( 'http://blabla/objects/' );
mtlLoader.load( 'bla.obj.mtl', function(materials){
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'http://blabla/objects/' );
objLoader.load( 'bla.obj', function (object){
var object1 = object.clone();
model1 = object; //save in global variables and add those to the scene
model2 = object1;
scene.add(model1);
scene.add(model2)
});
});
I am not quite sure whether it is a problem similar to this one: https://github.com/sohamkamani/three-object-loader/issues/9, because if I e.g. insert:
let child;
for(let i = 0; i < object.children.length; i++) {
child = object.children[i];
scene.add(new THREE.Mesh(child.geometry, new THREE.MeshPhongMaterial({ })));
}
A white mesh is inserted - but I wouldn't know how to insert the mtl-file as color, because in the example they use getHex()
. And it also seems like something that would take a long time, if I would have to do it for each mesh individually (I am cloning the model because I need two). Or could I in some way use object.traverse - I don't want to manually change the loader.
Any help is very appreciated :D
EDIT I have now tried many different approaches, with non of them working just yet, so I will sum up the issues here, hoping that someone can see what it wrong:
The approach mentioned above, and it is explained why it doesn't work in the comments. I updated to the newest version of three, and now I get the same error but only as a warning, and the objects are still not visible. The error seems to come from something else now. If I change it to flatshading in the OBJloader the warning disappear but the objects are still not visible - and I really don't want to change the files.
THREE.MeshPhongMaterial: .shading has been removed. Use the boolean .flatShading instead set @ three.js:43344 parse @ index.js:628 (anonymous) @ index.js:58 (anonymous) @ three.js:30483 XMLHttpRequest.send (async) load @ three.js:30563 load @ index.js:56 (anonymous) @ main.ts:117 (anonymous) @ index.js:36 (anonymous) @ three.js:30090 XMLHttpRequest.send (async) load @ three.js:30146 load @ index.js:34 s @ _prelude.js:1 e @ _prelude.js:1 (anonymous) @ _prelude.js:1
Only using the three-obj-loader works fine (as described here : Uncaught TypeError: THREE.MTLLoader is not a constructor)
Copying the OBJLoader and MTLLoader (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js and https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/MTLLoader.js) and putting them in the folder three/src/loaders and then including the following in the three.js:
export { MTLLoader} from './loaders/MTLLoader.js' export { OBJoader} from './loaders/OBJLoader.js'
And then trying to load them like this:
import {MTLLoader} from 'three'
import {OBJLoader} from 'three'
and using them in the same way as above results in a Uncaught TypeError: THREE.MTLLoader is not a constructor
and when trying to console.log(MTLLoader)
or console.log(OBJLoader)
they are both undefined. So I am not sure whether they are loaded correctly into the framework, as I can only find examples of loading them in html (<script src="js/loaders/OBJLoader.js"></script>
).I am pretty new to typescript, so I am not sure if I should create a reference path, or how one would come about this.
The same problem occurs if I try to use OBJLoader2.
- The final thing I have tried to do, was to load the obj and mtl loader that is actually in three under examples, where I reference to it in the three.js file:
export { OBJLoader } from '../examples/js/loaders/OBJLoader.js'
but that gives the same 'not a constructor' error `
回答1:
A little late to the party but you can work around the need for alternative three.js loader npm packages by leveraging imports loader with webpack.
// I'm not positive that we even need to declare this `const` but I haven't tested
const THREE = require('three');
import {
OBJLoader,
MTLLoader
} from 'three';
require('imports-loader?THREE=three!three/examples/js/loaders/OBJLoader.js');
require('imports-loader?THREE=three!three/examples/js/loaders/MTLLoader.js');
The gist of this is that we import
to satisfy TypeScript, but we require
the loaders explicitly so we have an opportunity to feed them the global THREE
that they need. If you run into a dependency that requires two imports, like FBXLoader
, you can separate them with commas before the !path-to-file.js
.
It's a little goofy but it lets us work without having to rely on custom packages that might not match your current version of three. I'm successfully using this with both MTLLoader and OBJLoader in a React app built with TypeScript 2.9.2.
来源:https://stackoverflow.com/questions/47753533/three-mtl-loader-error-three-meshphongmaterial-shading-has-been-removed-ob