具有三个CSG的3D布尔运算 [英] 3D Boolean operations with Three CSG

查看:520
本文介绍了具有三个CSG的3D布尔运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下为示例:

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进行了演示:Viewer网格具有一个索引的顶点数组,因此您不能直接从中创建BSP.我的代码还使用Web Worker处理网格,以使UI对大型模型保持响应,因此我需要首先将Mesh数据发送给Worker并重建一个简单的THREE.Mesh在Worker方面,代码看起来如下所示:

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)
    }
  }
}

示例的完整代码在这里:.

The complete code of my sample is there: Wall Analyzer and the live demo there.

这篇关于具有三个CSG的3D布尔运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆