【问题标题】:How to access the BufferGeometry of IFC items in web-ifc-threeweb-ifc-three中如何访问IFC项目的BufferGeometry
【发布时间】:2022-11-13 01:15:22
【问题描述】:
我正在尝试获取元素的几何形状
即与我拥有的 expressId 对应的 BufferGeometry 对象(不是通过拾取)。
基本上我在问如何遍历 IFC 模型并将每个对象导出为单独的 OBJ。
我会注意到我已经对某些版本的包进行了逆向工程代码来实现这一点,但是它使用了未记录的功能,因此它自然会在以后的版本中中断(代码还根据材料的颜色为几何图形着色,所以我不需要一个mtl):
不要复制此代码,它将不起作用
Object.values(bimModel.ifcManager.state.models[bimModel.modelID].items).forEach(type => {
Object.entries(type.geometries).forEach(([id, geometry]) => {
const properties = bimModel.getItemProperties(Number(id))
const numVertices = geometry.getAttribute('position').count
const color = type.material.color.toArray().map(x => x * 255)
const vertexColors = new Uint8Array(Array.from({ length: numVertices }, () => color).flat())
geometry.setAttribute('color', new BufferAttribute(vertexColors, 3, true))
})
})
【问题讨论】:
标签:
three.js
ifc
buffer-geometry
【解决方案1】:
这正是我们对export models to glTF 所做的。基本工作流程是:
- 确定要导出的 IFC 类别。
- 获取每个类别的所有项目。
- 为每个项目重建网格。
- 使用您选择的 Three.js 导出器导出网格。
让我们看一个从墙上获取所有网格的基本示例。这个过程并不像将每个 IFC 项目作为一个单独的网格那样简单,但这是让绘制调用最少的代价(否则,浏览器甚至无法支持中等大小的 IFC 文件):
import { IFCWALLSTANDARDCASE } from 'web-ifc';
async function getAllWallMeshes() {
// Get all the IDs of the walls
const wallsIDs = manager.getAllItemsOfType(0, IFCWALL, false);
const meshes = [];
const customID = 'temp-gltf-subset';
for (const wallID of wallsIDs) {
const coordinates = [];
const expressIDs = [];
const newIndices = [];
const alreadySaved = new Map();
// Get the subset for the wall
const subset = viewer.IFC.loader.ifcManager.createSubset({
ids: [wallID],
modelID,
removePrevious: true,
customID
});
// Subsets have their own index, but share the BufferAttributes
// with the original geometry, so we need to rebuild a new
// geometry with this index
const positionAttr = subset.geometry.attributes.position;
const expressIDAttr = subset.geometry.attributes.expressID;
const newGroups = subset.geometry.groups
.filter((group) => group.count !== 0);
const newMaterials = [];
const prevMaterials = subset.material;
let newMaterialIndex = 0;
newGroups.forEach((group) => {
newMaterials.push(prevMaterials[group.materialIndex]);
group.materialIndex = newMaterialIndex++;
});
let newIndex = 0;
for (let i = 0; i < subset.geometry.index.count; i++) {
const index = subset.geometry.index.array[i];
if (!alreadySaved.has(index)) {
coordinates.push(positionAttr.array[3 * index]);
coordinates.push(positionAttr.array[3 * index + 1]);
coordinates.push(positionAttr.array[3 * index + 2]);
expressIDs.push(expressIDAttr.getX(index));
alreadySaved.set(index, newIndex++);
}
const saved = alreadySaved.get(index);
newIndices.push(saved);
}
const geometryToExport = new BufferGeometry();
const newVerticesAttr = new BufferAttribute(Float32Array.from(coordinates), 3);
const newExpressIDAttr = new BufferAttribute(Uint32Array.from(expressIDs), 1);
geometryToExport.setAttribute('position', newVerticesAttr);
geometryToExport.setAttribute('expressID', newExpressIDAttr);
geometryToExport.setIndex(newIndices);
geometryToExport.groups = newGroups;
geometryToExport.computeVertexNormals();
const mesh = new Mesh(geometryToExport, newMaterials);
meshes.push(mesh);
}
viewer.IFC.loader.ifcManager.removeSubset(modelID, undefined, customID);
return meshes;
}