Three.js r125+从文件构建自定义BufferGeometry及设置三角面的问题
实现方案
Three.js的BufferGeometry对应旧版Geometry的faces逻辑,不需要重复存储顶点,直接用索引数组实现即可,你原有的扇形拆分逻辑几乎不需要修改,只需要把添加Face3的逻辑替换为往索引数组中推顶点索引,最后给BufferGeometry设置索引属性就行。
你第一版读取VERTICES、VERTEX NORMALS设置position、normal属性的代码可以直接保留,只需要新增下面处理FACES的代码:
// 接你第一版设置完position、normal属性之后的代码 while(pieces[0]!="FACES") { i++; pieces = jedata[i].split(" "); } cnt = parseInt(pieces[1]); while(pieces[0]!="0:") { i++; pieces = jedata[i].split(" "); } const indices = []; // 存储所有三角面的顶点索引 for(var j = 0; j < cnt; j++) { pieces = jedata[i+j].trim().split(" "); var faces = []; var vcnt = pieces[7]; for(var k=0; k<vcnt*2; k+=2) { faces.push(parseInt(pieces[k+8])); } // 扇形拆分逻辑和旧版完全一致 for(var k=1; k<faces.length-1; k++) { indices.push(faces[0], faces[k], faces[k+1]); } } // 给BufferGeometry设置索引 geo.setIndex(indices); // 如果你读取的顶点法线有误差,可以调用下面的方法重新计算平滑法线 // geo.computeVertexNormals();
临时方案的问题说明
- 顶点数据翻倍:临时方案将每个三角面的顶点都单独存储,原本可复用的顶点被重复写入了多次,而使用索引模式时顶点仅需存储一次,索引数组仅存顶点的引用,内存占用和旧版
Geometry完全一致。 - 光照异常:两个核心原因:
- 重复存储顶点时,原本共享同一个顶点的面被拆分为了多组独立顶点,顶点法线的连续性被破坏,就会出现光照接缝;
- 未使用索引时Three.js默认按顺序每3个顶点为一个面处理,很容易出现面的绕序和法线方向不匹配,导致光照计算错误。
额外注意点
如果你的自定义3D文件的顶点索引是从1开始计数的,读取后需要手动减1,Three.js的BufferGeometry索引默认从0开始计数,这是这类自定义格式解析的常见坑点。
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

