0
votes

I created a Three.js Scene where it loads a GLtf Object (.glb) inside a RGBELoader (for hdr Enviroment Texture Lighting )

I then give each Mesh inside this GLtf Object a new Material. Like this:

              gltfObject.traverse((ChildGLTF) => {

              ChildGLTF.children[0].material = MidMaterial;
              ChildGLTF.children[1].material = TopMaterial;
              ChildGLTF.children[2].material = BotMaterial;
              
            });  

Now the strange thing is, I get an Error and at the same time the materials are applied like I want them to. So it actually works.

Still I want to get rid of that error or at least understand what is causing it.

Thats the Error:

script.js:77 Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'material')
at script.js:77
at Mesh.traverse (three.module.js:6907)
at Group.traverse (three.module.js:6913)
at script.js:72
at GLTFLoader.js:175
at GLTFLoader.js:1989

So my best guess is, that there are more than one .material Attributes? But how can i specify, that I only want the material that is changeable..

Or is it, that 'gltfObject.traverse((ChildGLTF)' runs more than one time with ChildGLTF as an array? If so, "console.log( ChildGLTF[0] );" gives "undefined" ..

Here are the console logs

              console.log( ChildGLTF[0] ); //'undefined'
              console.log( ChildGLTF.children[0] ); //works fine
              console.log( ChildGLTF.children[0].material ); //'Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'material')'

console.log( ChildGLTF.children[0] )

! Mesh {uuid: '3BE5076C-A90D-47B4-BE40-D1E77E4F4DEC', name: 'Cube', type: 'Mesh', parent: Group, children: Array(0), …} animations: [] castShadow: false children: [] frustumCulled: true geometry: BufferGeometry {uuid: 'EC8A35A7-1942-4556-9D93-6C3E25F4C77A', name: '', type: 'BufferGeometry', index: BufferAttribute, attributes: {…}, …} layers: Layers {mask: 1} material: MeshStandardMaterial {uuid: 'ACA40D34-B763-42DA-A956-3ABBAC901D37', name: '', type: 'MeshStandardMaterial', fog: true, blending: 1, …} matrix: Matrix4 {elements: Array(16)} matrixAutoUpdate: true matrixWorld: Matrix4 {elements: Array(16)} matrixWorldNeedsUpdate: false name: "Cube" parent: Group {uuid: '27EE9C8E-3B31-4483-8058-CA2DA42070FC', name: 'Scene', type: 'Group', parent: Scene, children: Array(3), …} position: Vector3 {x: 0, y: 0, z: 0} quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, _onChangeCallback: ƒ} receiveShadow: false renderOrder: 0 rotation: Euler {_x: 0, _y: 0, _z: 0, _order: 'XYZ', _onChangeCallback: ƒ} scale: Vector3 {x: 1, y: 1, z: 1} type: "Mesh" up: Vector3 {x: 0, y: 1, z: 0} userData: {name: 'Cube'} uuid: "3BE5076C-A90D-47B4-BE40-D1E77E4F4DEC" visible: true drawMode: (...) eulerOrder: (...) id: 40 modelViewMatrix: Matrix4 {elements: Array(16)} normalMatrix: Matrix3 {elements: Array(9)} useQuaternion: (...) [[Prototype]]: Object3D

console.log( ChildGLTF.children[0].material );

! MeshStandardMaterial {uuid: 'FBA72EAB-93C3-4F92-B141-1BA011BB81FD', name: 'CubeMaterial', type: 'MeshStandardMaterial', fog: true, blending: 1, …} alphaMap: null alphaTest: 0 aoMap: null aoMapIntensity: 1 blendDst: 205 blendDstAlpha: null blendEquation: 100 blendEquationAlpha: null blendSrc: 204 blendSrcAlpha: null blending: 1 bumpMap: null bumpScale: 1 clipIntersection: false clipShadows: false clippingPlanes: null color: Color {r: 0.011123105883598328, g: 0.004119289573282003, b: 0.8000000715255737} colorWrite: true defines: {STANDARD: ''} depthFunc: 3 depthTest: true depthWrite: true displacementBias: 0 displacementMap: null displacementScale: 1 dithering: false emissive: Color {r: 0, g: 0, b: 0} emissiveIntensity: 1 emissiveMap: null envMap: null envMapIntensity: 1 flatShading: false fog: true lightMap: null lightMapIntensity: 1 map: null metalness: 0 metalnessMap: null morphNormals: false morphTargets: false name: "CubeMaterial" normalMap: null normalMapType: 0 normalScale: Vector2 {x: 1, y: 1} opacity: 1 polygonOffset: false polygonOffsetFactor: 0 polygonOffsetUnits: 0 precision: null premultipliedAlpha: false refractionRatio: 0.98 roughness: 0.5 roughnessMap: null shadowSide: null side: 2 skinning: false stencilFail: 7680 stencilFunc: 519 stencilFuncMask: 255 stencilRef: 0 stencilWrite: false stencilWriteMask: 255 stencilZFail: 7680 stencilZPass: 7680 toneMapped: true transparent: false type: "MeshStandardMaterial" userData: {} uuid: "FBA72EAB-93C3-4F92-B141-1BA011BB81FD" version: 0 vertexColors: false vertexTangents: false visible: true wireframe: false wireframeLinecap: "round" wireframeLinejoin: "round" wireframeLinewidth: 1 id: 7 overdraw: (...) shading: (...) stencilMask: (...) wrapAround: (...) wrapRGB: (...) [[Prototype]]: Material

1

1 Answers

0
votes

.traverse(...) is going to run that callback for every object within the model, and your code assumes each object has exactly three children. That's not possible, because the model would have to be infinitely deep, and when you eventually reach an object that doesn't have children, doing .children[0].material will throw these errors.

You'll want to check what ChildGLTFis, and only modify that one object during the loop.

gltfObject.traverse((child) => {
  if (!child.isMesh) return;

  if (child.name === 'MyMidMeshName') { // change this name
    child.material = MidMaterial;
  } else if (child.name === 'MyTopMeshName') { // change this name
    // ...
  } else {
    // ...
  }
});