将材质应用于 gltf 对象时出现未定义错误

Posted

技术标签:

【中文标题】将材质应用于 gltf 对象时出现未定义错误【英文标题】:Undefined Error when applying materials to gltf object 【发布时间】:2021-11-24 04:25:30 【问题描述】:

我创建了一个 Three.js 场景,它在 RGBELoader 中加载了一个 GLtf 对象 (.glb)(用于 hdr 环境纹理照明)

然后,我为这个 GLtf 对象内的每个 Mesh 赋予一个新材质。像这样:

              gltfObject.traverse((ChildGLTF) => 

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

现在奇怪的是,我得到一个错误,同时材料按照我想要的方式应用。所以它确实有效。

我仍然想摆脱这个错误,或者至少了解导致它的原因。

这是错误:

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

所以我最好的猜测是,有不止一个 .material 属性?但是我怎么能指定,我只想要可变的材料..

或者,'gltfObject.traverse((ChildGLTF)' 以 ChildGLTF 作为数组运行不止一次?如果是这样,“console.log( ChildGLTF[0] );”给出“未定义”..

这是控制台日志

              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])

!网格uuid:'3BE5076C-A90D-47B4-BE40-D1E77E4F4DEC',名称:'Cube',类型:'Mesh',父级:组,子级:Array(0),... 动画:[] 投射阴影:假 孩子们: [] frustumCulled:真 几何:BufferGeometry uuid:'EC8A35A7-1942-4556-9D93-6C3E25F4C77A',名称:'',类型:'BufferGeometry',索引:BufferAttribute,属性:...,... 层:层掩码:1 材料:MeshStandardMaterial uuid:'ACA40D34-B763-42DA-A956-3ABBAC901D37',名称:'',类型:'MeshStandardMaterial',雾:真,混合:1,... 矩阵:Matrix4 元素:数组(16) 矩阵自动更新:真 矩阵世界:Matrix4 元素:数组(16) 矩阵世界需要更新:假 名称:“立方体” 父:组uuid:'27EE9C8E-3B31-4483-8058-CA2DA42070FC',名称:'场景',类型:'组',父:场景,子:数组(3),... 位置:Vector3 x:0,y:0,z:0 四元数:四元数_x:0,_y:0,_z:0,_w:1,_onChangeCallback:ƒ 接收阴影:假 渲染顺序:0 旋转:欧拉_x:0,_y:0,_z:0,_order:'XYZ',_onChangeCallback:ƒ 比例:Vector3 x:1,y:1,z:1 类型:“网格” 向上:Vector3 x:0,y:1,z:0 用户数据:名称:'Cube' uuid:“3BE5076C-A90D-47B4-BE40-D1E77E4F4DEC” 可见:真 绘制模式:(...) eulerOrder: (...) 编号:40 modelViewMatrix:Matrix4 元素:数组(16) normalMatrix:Matrix3 元素:数组(9) 使用四元数:(...) [[原型]]:Object3D

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

! MeshStandardMaterial uuid:'FBA72EAB-93C3-4F92-B141-1BA011BB81FD',名称:'CubeMaterial',类型:'MeshStandardMaterial',雾:true,混合:1,... 阿尔法地图:空 阿尔法测试:0 地图:空 地图强度:1 混合目标:205 blendDstAlpha:空 混合方程:100 blendEquationAlpha:空 混合源:204 blendSrcAlpha:空 混合:1 凹凸图:空 凹凸比例:1 剪辑交集:假 剪辑阴影:假 剪裁平面:空 颜色:颜色r:0.011123105883598328,g:0.004119289573282003,b:0.8000000715255737 颜色写:真 定义:标准:'' 深度函数:3 深度测试:真 深度写入:真 位移偏差:0 置换贴图:空 位移比例:1 抖动:假 发射:颜色r:0,g:0,b:0 发射强度:1 发射地图:空 环境地图:空 环境映射强度:1 平面阴影:假 雾:真 光照贴图:空 光照贴图强度:1 地图:空 金属度:0 金属度图:空 morphNormals:假 变形目标:假 名称:“立方体材料” 法线贴图:空 正常地图类型:0 normalScale: Vector2 x: 1, y: 1 不透明度:1 多边形偏移:假 多边形偏移因子:0 多边形偏移单位:0 精度:空 预乘Alpha:假 折射比:0.98 粗糙度:0.5 粗糙度贴图:空 阴影面:空 侧面:2 剥皮:假 模板失败:7680 模板功能:519 模板功能掩码:255 模板参考:0 模板写入:假 模板写入掩码:255 模板失败:7680 模板ZPass:7680 色调映射:真 透明:假 类型:“MeshStandardMaterial” 用户数据: uuid:“FBA72EAB-93C3-4F92-B141-1BA011BB81FD” 版本:0 顶点颜色:假 顶点切线:假 可见:真 线框:假 线框线帽:“圆形” 线框线连接:“圆形” 线框线宽:1 编号:7 透支:(...) 阴影:(...) 模板面具:(...) 环绕:(...) 包装RGB:(...) [[原型]]:材质

【问题讨论】:

【参考方案1】:

.traverse(...) 将为模型中的每个对象运行该回调,并且您的代码假定每个对象恰好具有三个子对象。这是不可能的,因为模型必须无限深,当你最终到达一个没有子对象的对象时,.children[0].material 会抛出这些错误。

您需要检查ChildGLTF是什么,并且在循环期间修改那个对象。

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 
    // ...
  
);

【讨论】:

以上是关于将材质应用于 gltf 对象时出现未定义错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Xcode 4 下构建 PhoneGap 时出现未定义符号错误?

Angular2:尝试使用 @ViewChild 注释将焦点设置到输入字段时出现未定义的错误

将 Firebase 与 Google Toolbox for Mac 一起使用时出现未定义符号 Xcode 错误

使用c ++实现EAST文本检测时出现未定义的cv :: dnn :: experimental_dnn错误

注册时出现未定义的方法错误

运行生成脚手架命令时出现未定义的方法“组”错误