Threejs:如何使用 GLTFExporter 导出具有绘制范围的索引几何体?
Threejs: How can one export with GLTFExporter an indexed geometry with draw range?
我有一个具体问题,我想导出一个具有绘图范围的索引几何体。
使用 GLTFExporter,在遇到打字稿集成问题(显然是已知问题)后,我很不幸地发现导出器中没有实现:
// @TODO Indexed buffer geometry with drawRange not supported yet
https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/GLTFExporter.js 第 564 行
检查提交历史显示最后一次更新是在 3 个月前,我认为这不会很快到来。
我试图删除索引缓冲区并根据我的绘制范围重写我的位置缓冲区属性数组,但我一定做错了,因为它不起作用,它只会破坏我的几何形状。
你们中的任何人都可以为我解决问题或解释如何处理我的几何图形吗?
提前谢谢你。
编辑:
我目前的解决方法是 "de-index" 我的几何图形用于导出并保留 drawRange,这种情况是由出口商处理。这并不理想,它迫使我用新的 BufferAttributes 重新创建一个全新的几何体。但由于此操作仅用于导出,我什至可以让此过程以异步方式进行。我希望有更好的方法。
关于这两个变量,这是我将在下面的 PR 中解决的问题,使其成为 WebGLUtils 的一部分并导入它。每个需要这些常量的人每次都需要重新定义它们是没有意义的。
正如我在编辑中提到的,我通过对我的几何图形进行 去索引 绕过了我的问题,这不是最好的解决方案,但因为我只需要它来导出,这是我的处理方式:
// original attributes
const vertices = geometryTmp.getAttribute("position");
const normals = geometryTmp.getAttribute("normal");
const uv = geometryTmp.getAttribute("uv");
// new buffer arrays
let verticesTmp = new Float32Array(3 * geometryTmp.index.array.length);
let normalTmp = new Float32Array(3 * geometryTmp.index.array.length);
let uvTmp = new Float32Array(2 * geometryTmp.index.array.length);
let j = 0;
for(let i = 0; i < verticesTmp.length; i += 3) {
let index = geometryTmp.index.array[j];
verticesTmp[i] = vertices.getX(index);
verticesTmp[i+1] = vertices.getY(index);
verticesTmp[i+2] = vertices.getZ(index);
normalTmp[i] = normals.getX(index);
normalTmp[i+1] = normals.getY(index);
normalTmp[i+2] = normals.getZ(index);
j++;
}
j = 0;
for(let i = 0; i < uvTmp.length; i += 2) {
let index = geometryTmp.index.array[j];
uvTmp[i] = uv.getX(index);
uvTmp[i+1] = uv.getY(index);
j++;
}
let newGeomtry = new THREE.BufferGeometry();
newGeomtry.addAttribute( 'position', new THREE.BufferAttribute( verticesTmp, 3 ) );
newGeomtry.addAttribute( 'normal', new THREE.BufferAttribute( normalTmp, 3 ) );
newGeomtry.addAttribute( 'uv', new THREE.BufferAttribute( uvTmp, 2 ) );
newGeomtry.drawRange = geometryTmp.drawRange;
mesh.geometry = newGeomtry;
// After I do that to all the meshes I need, them to a new THREE.Scene that will be given to the exporter with truncateDrawRange = true
希望对大家也有帮助。
我有一个具体问题,我想导出一个具有绘图范围的索引几何体。 使用 GLTFExporter,在遇到打字稿集成问题(显然是已知问题)后,我很不幸地发现导出器中没有实现:
// @TODO Indexed buffer geometry with drawRange not supported yet
https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/GLTFExporter.js 第 564 行
检查提交历史显示最后一次更新是在 3 个月前,我认为这不会很快到来。 我试图删除索引缓冲区并根据我的绘制范围重写我的位置缓冲区属性数组,但我一定做错了,因为它不起作用,它只会破坏我的几何形状。 你们中的任何人都可以为我解决问题或解释如何处理我的几何图形吗?
提前谢谢你。
编辑:
我目前的解决方法是 "de-index" 我的几何图形用于导出并保留 drawRange,这种情况是由出口商处理。这并不理想,它迫使我用新的 BufferAttributes 重新创建一个全新的几何体。但由于此操作仅用于导出,我什至可以让此过程以异步方式进行。我希望有更好的方法。
关于这两个变量,这是我将在下面的 PR 中解决的问题,使其成为 WebGLUtils 的一部分并导入它。每个需要这些常量的人每次都需要重新定义它们是没有意义的。
正如我在编辑中提到的,我通过对我的几何图形进行 去索引 绕过了我的问题,这不是最好的解决方案,但因为我只需要它来导出,这是我的处理方式:
// original attributes
const vertices = geometryTmp.getAttribute("position");
const normals = geometryTmp.getAttribute("normal");
const uv = geometryTmp.getAttribute("uv");
// new buffer arrays
let verticesTmp = new Float32Array(3 * geometryTmp.index.array.length);
let normalTmp = new Float32Array(3 * geometryTmp.index.array.length);
let uvTmp = new Float32Array(2 * geometryTmp.index.array.length);
let j = 0;
for(let i = 0; i < verticesTmp.length; i += 3) {
let index = geometryTmp.index.array[j];
verticesTmp[i] = vertices.getX(index);
verticesTmp[i+1] = vertices.getY(index);
verticesTmp[i+2] = vertices.getZ(index);
normalTmp[i] = normals.getX(index);
normalTmp[i+1] = normals.getY(index);
normalTmp[i+2] = normals.getZ(index);
j++;
}
j = 0;
for(let i = 0; i < uvTmp.length; i += 2) {
let index = geometryTmp.index.array[j];
uvTmp[i] = uv.getX(index);
uvTmp[i+1] = uv.getY(index);
j++;
}
let newGeomtry = new THREE.BufferGeometry();
newGeomtry.addAttribute( 'position', new THREE.BufferAttribute( verticesTmp, 3 ) );
newGeomtry.addAttribute( 'normal', new THREE.BufferAttribute( normalTmp, 3 ) );
newGeomtry.addAttribute( 'uv', new THREE.BufferAttribute( uvTmp, 2 ) );
newGeomtry.drawRange = geometryTmp.drawRange;
mesh.geometry = newGeomtry;
// After I do that to all the meshes I need, them to a new THREE.Scene that will be given to the exporter with truncateDrawRange = true
希望对大家也有帮助。