GLTFLoader未填充SkinnedMesh的Geometry.bones属性,如何从骨骼恢复?
解决Three.js加载glTF后Geometry.bones未填充的问题
我清楚你从JSON格式切换到glTF2时遇到的这个骨骼属性问题——确实,glTF加载器不会自动填充Geometry.bones,但Geometry.skeleton.bones是完整的。这是因为Three.js现代版本更偏向于用Skeleton对象统一管理骨骼数据,而旧的JSON格式加载器会同时维护Geometry.bones这个相对老旧的属性。下面给你几个可行的解决办法:
1. 手动同步skeleton.bones到Geometry.bones
如果你的旧代码必须依赖Geometry.bones,可以在模型加载完成后遍历网格,手动复制骨骼数据:
// 加载glTF模型后的处理逻辑 gltfLoader.load('your-model.gltf', (gltf) => { const scene = gltf.scene; // 遍历所有网格对象 scene.traverse((mesh) => { // 只处理带骨骼的蒙皮网格 if (mesh.isSkinnedMesh && mesh.geometry.skeleton) { // 复制骨骼引用到Geometry.bones mesh.geometry.bones = Array.from(mesh.geometry.skeleton.bones); // 如果你还需要boneInverses(旧JSON格式会包含的属性),也可以同步生成 mesh.geometry.boneInverses = mesh.geometry.skeleton.bones.map(bone => { const inverse = new THREE.Matrix4(); return inverse.copy(bone.matrixWorld).invert(); }); } }); // 将模型添加到场景 scene.add(scene); });
这段代码会把skeleton里的骨骼列表完整复制到Geometry.bones中,同时生成对应的boneInverses,完全兼容旧代码对这个属性的依赖。
2. 改用Skeleton对象访问骨骼(推荐)
其实Three.js官方现在更推荐直接通过SkinnedMesh的skeleton属性来访问骨骼,比如:
// 替代mesh.geometry.bones的写法 const bones = mesh.skeleton.bones; // 或者 mesh.geometry.skeleton.bones
如果你的代码可以调整,建议优先使用这种方式,因为Geometry.bones属于较旧的API,未来可能会被逐步淘汰,依赖Skeleton更符合Three.js的当前设计规范。
补充说明
glTF作为Three.js优先支持的现代格式,加载器的设计是贴合最新架构的,所以没有保留旧JSON格式的冗余属性。上面的两种方法,第一种是临时兼容旧代码的快速方案,第二种是长期维护的最优选择,你可以根据自己的项目情况来选。
内容的提问来源于stack exchange,提问作者user2758635
相关产品推荐
相关产品推荐

