使用Three.js BufferGeometryLoader加载JSON几何体时出现‘Cannot read property 'index' of undefined’错误原因
这个错误的核心原因非常明确:你用错了加载器!
你当前使用的是THREE.BufferGeometryLoader(),但你提供的JSON文件是旧版的Geometry格式(从JSON里的metadata.type: "Geometry"可以直接看出来),而非BufferGeometry格式。BufferGeometryLoader专门用来加载BufferGeometry结构的JSON,它会尝试读取index这类BufferGeometry特有的属性,但你的JSON里根本没有这些字段,自然就会抛出"Cannot read property 'index' of undefined"的错误。
下面帮你梳理具体问题和可行的解决方案:
问题细节补充
你的JSON文件是传统Geometry格式,包含vertices、faces、normals这些字段,但BufferGeometry的JSON结构完全不同——它会包含attributes(比如position、normal)、index等专属字段,这两种格式完全不兼容。另外你的JSON末尾还缺失了一个闭合的},不过这是次要问题,优先解决加载器不匹配的核心问题。
解决方案
有两种靠谱的处理方式:
方式一:改用适配旧格式的加载器
如果你想继续使用这个旧的Geometry格式的JSON,需要换成对应的加载器:
- 若你使用的是较旧版本的Three.js,可以直接用
THREE.JSONLoader() - 若你使用的是r125+的新版本Three.js,
JSONLoader已被整合到THREE.ObjectLoader中,直接用后者即可
修改后的代码示例:
// 旧版本Three.js写法 var loader = new THREE.JSONLoader(); loader.load('models/box2.json', function (geometry) { // 建议把Geometry转成BufferGeometry(当前Three.js更推荐使用BufferGeometry) var bufferGeo = new THREE.BufferGeometry().fromGeometry(geometry); var material = new THREE.MeshBasicMaterial({ color: 0xF5F5F5 }); var object = new THREE.Mesh(bufferGeo, material); mesheto = object; scene.add(object); GameLoop(); }); // 新版本Three.js写法 var loader = new THREE.ObjectLoader(); loader.load('models/box2.json', function (geometry) { var bufferGeo = new THREE.BufferGeometry().fromGeometry(geometry); var material = new THREE.MeshBasicMaterial({ color: 0xF5F5F5 }); var object = new THREE.Mesh(bufferGeo, material); mesheto = object; scene.add(object); GameLoop(); });
方式二:将JSON转换为BufferGeometry格式
如果你想继续使用BufferGeometryLoader,可以先把现有Geometry转成BufferGeometry再导出新的JSON:
// 用于转换格式的示例代码 var loader = new THREE.JSONLoader(); loader.load('models/box2.json', function (geometry) { var bufferGeo = new THREE.BufferGeometry().fromGeometry(geometry); // 导出BufferGeometry格式的JSON var json = bufferGeo.toJSON(); // 把控制台输出的json内容保存为新文件,比如box2-buffer.json console.log(json); });
之后用BufferGeometryLoader加载这个新生成的JSON文件就不会报错了。
最后别忘了补全你原JSON文件末尾缺失的},否则会先出现JSON解析错误。
内容的提问来源于stack exchange,提问作者appzone_oto

