具有三个 CSG 的 3D 布尔运算 [英] 3D Boolean operations with Three CSG
问题描述
按照这里的例子:
http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
使用 Three.js 和 https://github.com/chandlerprall/ThreeCSG,我'正在尝试对模型中的节点进行 3D 布尔运算.例如,如果我有一堵带窗户的墙,我想对它执行 invert()
以获取窗户.
And using Three.js with https://github.com/chandlerprall/ThreeCSG, I'm trying to do 3D boolean operations on nodes from the model. Like for example if I have a wall with a window, I want to do invert()
on that to get just the window.
我有一个函数可以返回一个节点的多边形的所有顶点,这是一个没有孔的对象的顶点示例 https://pastebin.com/8dhYzPwE.
I have a function that returns all the vertices of the polygons of a node, here's an example of vertices of an object without holes https://pastebin.com/8dhYzPwE.
我像这样使用 ThreeCSG:
I'm using ThreeCSG like this:
const geometryThree = new THREE.Geometry();
geometryThree.vertices.push(
...vertices
);
const geometryCsg = new ThreeBSP(geometryThree);
但这就是我在 geometryCsg
中得到的:
But that's what I'm getting in geometryCsg
:
"{
"matrix": {
"elements": {
"0": 1,
"1": 0,
"2": 0,
"3": 0,
"4": 0,
"5": 1,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 1,
"11": 0,
"12": 0,
"13": 0,
"14": 0,
"15": 1
}
},
"tree": {
"polygons": []
}
}"
我认为这是因为 geometry.faces.length
为 0.
I think it's because the geometry.faces.length
is 0.
如何使顶点数组成为适当的 Three.Geometry
以便面不会为空?Geometry.elementsNeedsUpdate 不起作用...
How can I make the vertices array to be a proper Three.Geometry
such that the faces won't be empty? Geometry.elementsNeedsUpdate doesn't work...
是否有使用形状的多边形作为 Vector3s 数组并将其转换为 csg 的示例?
Is there an example that uses polygons of a shape as an array of Vector3s and transforms that to csg?
推荐答案
我刚刚使用三个 csg 完成了一个演示:查看器网格具有顶点索引数组,因此您不能直接从中创建 BSP.此外,我的代码使用 web worker 来处理网格,以保持 UI 对大型模型的响应,所以我需要首先将网格数据发送给 worker 并在 worker 端重建一个简单的 THREE.Mesh,代码看起来如下图:
I just worked on a demo using THREE csg: the Viewer meshes have an indexed array of vertices so you cannot create a BSP directly out of it. Also my code is using a web worker to process the meshes in order to keep the UI responsive with large models, so I need first to send the mesh data to the worker and reconstruct a simple THREE.Mesh on the worker side, the code looks like below:
// Sends component geometry to the web worker
postComponent (dbId) {
const geometry = this.getComponentGeometry(dbId)
const msg = {
boundingBox: this.getComponentBoundingBox(dbId),
matrixWorld: geometry.matrixWorld,
nbMeshes: geometry.meshes.length,
msgId: 'MSG_ID_COMPONENT',
dbId
}
geometry.meshes.forEach((mesh, idx) => {
msg['positions' + idx] = mesh.positions
msg['indices' + idx] = mesh.indices
msg['stride' + idx] = mesh.stride
})
this.worker.postMessage(msg)
}
// get geometry for all fragments in a component
getComponentGeometry (dbId) {
const fragIds = Toolkit.getLeafFragIds(
this.viewer.model, dbId)
let matrixWorld = null
const meshes = fragIds.map((fragId) => {
const renderProxy = this.viewer.impl.getRenderProxy(
this.viewer.model,
fragId)
const geometry = renderProxy.geometry
const attributes = geometry.attributes
const positions = geometry.vb
? geometry.vb
: attributes.position.array
const indices = attributes.index.array || geometry.ib
const stride = geometry.vb ? geometry.vbstride : 3
const offsets = geometry.offsets
matrixWorld = matrixWorld ||
renderProxy.matrixWorld.elements
return {
positions,
indices,
offsets,
stride
}
})
return {
matrixWorld,
meshes
}
}
// On the worker side reconstruct THREE.Mesh
// from received data and create ThreeBSP
function buildComponentMesh (data) {
const vertexArray = []
for (let idx=0; idx < data.nbMeshes; ++idx) {
const meshData = {
positions: data['positions' + idx],
indices: data['indices' + idx],
stride: data['stride' + idx]
}
getMeshGeometry (meshData, vertexArray)
}
const geometry = new THREE.Geometry()
for (var i = 0; i < vertexArray.length; i += 3) {
geometry.vertices.push(vertexArray[i])
geometry.vertices.push(vertexArray[i + 1])
geometry.vertices.push(vertexArray[i + 2])
const face = new THREE.Face3(i, i + 1, i + 2)
geometry.faces.push(face)
}
const matrixWorld = new THREE.Matrix4()
matrixWorld.fromArray(data.matrixWorld)
const mesh = new THREE.Mesh(geometry)
mesh.applyMatrix(matrixWorld)
mesh.boundingBox = data.boundingBox
mesh.bsp = new ThreeBSP(mesh)
mesh.dbId = data.dbId
return mesh
}
function getMeshGeometry (data, vertexArray) {
const offsets = [{
count: data.indices.length,
index: 0,
start: 0}
]
for (var oi = 0, ol = offsets.length; oi < ol; ++oi) {
var start = offsets[oi].start
var count = offsets[oi].count
var index = offsets[oi].index
for (var i = start, il = start + count; i < il; i += 3) {
const a = index + data.indices[i]
const b = index + data.indices[i + 1]
const c = index + data.indices[i + 2]
const vA = new THREE.Vector3()
const vB = new THREE.Vector3()
const vC = new THREE.Vector3()
vA.fromArray(data.positions, a * data.stride)
vB.fromArray(data.positions, b * data.stride)
vC.fromArray(data.positions, c * data.stride)
vertexArray.push(vA)
vertexArray.push(vB)
vertexArray.push(vC)
}
}
}
我的示例的完整代码在那里:Wall Analyzer 和现场演示 那里.
The complete code of my sample is there: Wall Analyzer and the live demo there.
这篇关于具有三个 CSG 的 3D 布尔运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!