Uncaught TypeError: Cannot read property 'elements' of undefined
at Matrix3.copy (three.module.js?0371:3277)
at refreshUniformsCommon (three.module.js?0371:23180)
at setProgram (three.module.js?0371:22963)
at WebGLRenderer.renderBufferDirect (three.module.js?0371:21822)
at renderObject (three.module.js?0371:22575)
at renderObjects (three.module.js?0371:22548)
at WebGLRenderer.render (three.module.js?0371:22312)
at Object3D.draw (Object3D.js?2363:160)`
I have a 3D model (.obj) using three from npm. This is an ES6 project using Webpack.
I am using these dependencies:
import * as THREE from 'three';
import OBJLoader from 'three-obj-loader';
import MTLLoader from 'three-mtl-loader';
import OrbitControls from 'three-orbitcontrols';
The model is resolved and loaded. Texture files are resolved and loaded - the .mtl and the single .png
If I call:
mtlLoader.load(materialUrl, ( materials ) => {
materials.preload();
objLoader.setMaterials( materials );
The app crashes on the error listed above. On objLoader.setMaterials.
If I comment that out the App works.
NVIDIA GTX 970 in Sli. Asus motherboard. Output over HDMI 2.0. Doesn't seem to be related to either hardware, or OS.
Can you please provide a live example for debugging? Or maybe a reduced test case in a zip file? At least, share your OBJ
and MTL
file with all respective textures. Otherwise it will be hard to investigate this issue.
Sorry, but the assets are under NDA. I can provide the mtl file. I have also investigated the issue a bit:
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 05.10.2016 13:42:24
newmtl Material__3337
Ns 10.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.5880 0.5880 0.5880
Kd 0.5880 0.5880 0.5880
Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000
map_Ka <removed>_2048_Diff.png
map_Kd <removed>_2048_Diff.png
The issue is with the Kd map, which, I believe, is the diffuse map. Kindly note that the mtl file has multiple textures (even if technically using the same bitmap).
To get the material and texture applied, I had to bind them manually.
mtlLoader.load(materialUrl, ( materials ) => {
materials.preload();
// Load object after materials
// loadingManager.onLoad = function(){
// objLoader.setMaterials( materials );
objLoader.load(
modelUrl,
// called when resource is loaded
( object ) => {
const bbox = new THREE.Box3().setFromObject(object);
const cameraPos = new THREE.Vector3( );
materials.materials['Material__3337'].map = texture;
object.traverse(function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = materials.materials['Material__3337'];
}
});
scene.add( object );
I tried waiting until all assets were loaded (loadingManager.onload); no go. No loading error, but the material was not applied. I was able to get rid of the initial error, and get the texture applied when loading it manually.
See snippet above.
I should add: in this setup, we use webpack's file-loader to load obj, mtl, and all image types.
Hence, when loading assets at runtime, we use require(assetPath)
and webpack-dev-server
emits a valid url for the asset.
So: in any case I had to properly "prepare" the asset, by ensuring its url was emitted (require..
).
But even with that: the material AND texture were only applied when I bound them explicitly.
Hard to help fixing this one without access to the problematic assets...
I understand. Unfortunately, the assets themselves are truly locked down.
As far as I understand the issue, it seems to have something to do with multi-materials.
Again, if I load and set objects and textures individually, it works. In this case for both the diffuse and normal maps.
Somehow, we'll have to get to the bottom of this. By improving the webpack config (and not using file-loader
), and/or by finding the issue, or (more likely) by working around the MTLLoader itself. I'll make sure to update this thread if I actually track the root cause.
UV (not set) on multi/normal maps, but why.
In essence:
uvScaleMap.matrix is undefined
The loader loads the diffuse and normal maps, and seems to extrapolate a uvScaleMap based on that. But it doesn't have a matrix associated.
I eventually managed to work around this issue; I had to enable my webpack config to pass static assets through (as well as load them internally, on-demand, using import
or require syntax
).
After that, I was able to dynamically reload textures, based on the information "salvaged" from the MTLLoader, and reapply them to their respective slot.
This is sufficient for us, but - it might be worth giving the uvScaleMap reasonable defaults in case something otherworldly happens. uvScaleMap.matrix
in our case remained undefined until I sideloaded the textures, and reapplied them.
Hi everyone, I meet the very similar problem with @maurocolella, with almost the same TypeError and similar code.
In my case, the .mtl file have only one image (a Kd map). The object file in my project is not managed by webpack. The program crashes when calling renderer.render.
So there might be something happening around uvScaleMap.matrix
I think. The only usage of uvScaleMap
is in src/renderers/WebGLRenderer.js from line 1991. and goes into line 1995, finally crashes on line 2051.
In MTLLoader.js, I notice that the matrix.map is edited at function setMapForType( mapType, value )
with mapType = "map". Then the loadTexture
function.
I noticed that there is a texture = loader.load( url, onLoad, onProgress, onError );
call, (onLoad, onProgress, onError are null), the texture.matrix is mission from here. So I suspect something wrong in this loader, and expose it to document.xloader
. Then I got these information in console:
> (new THREE.TextureLoader).load(url).matrix
Matrix3 {elements: Array(9)}
> document.xloader.load(url).matrix
undefined
So I go into node_modules/three_mtl_loader and update its THREE to 0.88. The error disappears.
However. My model still invisible... Once I try to check it in Three.js Inspector, it crashes in this function InspectedWin3js.getThreeJSClassName
and then reset the model. After everything works will with Three.js Inspector.
Quiet strange. Waiting for more information.
Hi @maurocolella , I figured out my problem and it might work for you.
This warning message "Uncaught TypeError: Cannot read property 'elements' of undefined" is produced because of the "three-mtl-loader" from npm uses a old THREE version and its TextureLoader won't add matrix parameter after loading.
The solution is ask the maintainer of this package update it's package.json. Temporary solution is enter node_modules/.1.0.2@three-mtl-loader
and run npm install three@latest --save
to update it.
Thank you so much @eastpiger. I ended up working around this, as mentioned, by reloading textures explicitly.
@mrdoob , is there any way you could please help unify the distributions on npm?
.obj
files are easy to produce, easy to maintain/export materials for, so I think it's quite likely that (commercial) users would turn to them as a quick way to get some 3d displayed.
Unfortunately, at this time, objloader
and mtlloader
are not part of the main threejs
release on npm.
Perhaps a modular release on npm?
@eastpiger boss. Thank you this was driving me crazy.
In case someone else lands here from google: there is a new combined OBJ/MTLloader npm package that has solved this problem for me: https://www.npmjs.com/package/three-obj-mtl-loader
Most helpful comment
In case someone else lands here from google: there is a new combined OBJ/MTLloader npm package that has solved this problem for me: https://www.npmjs.com/package/three-obj-mtl-loader