【问题标题】:Three.js update position attribute of mesh from boxGeometryThree.js 从 boxGeometry 更新网格的位置属性
【发布时间】:2021-05-07 08:22:31
【问题描述】:

我正在实现一个界面,通过点击+拖动它的面来调整立方体的大小。

我想通过更新缓冲区几何对象的位置属性来实现这一点,或者重新创建网格,或者只是设置需求更新标志并让它自行更新。这些选项都没有为我工作。我最近的尝试如下。

  this.boxGeo = new THREE.BoxGeometry(2,2,2)
  this.boxMesh = new THREE.Mesh(this.boxGeo, this.boxMaterial)    

...

  // let disp = the amount we want to move the face

  // vertex indices
  let indices = this.planes[index].indices

  // new typed array for position attribute
  let positions = new Float32Array(8 * 3)

  // for each of the 8 verts
  for (let i=0; i < 8; i++) {
    if(!indices.includes(i) || disp === 0) {
      positions[i * 3]     = this.boxGeo.vertices[i].x
      positions[i * 3 + 1] = this.boxGeo.vertices[i].y
      positions[i * 3 + 2] = this.boxGeo.vertices[i].z
    } else {
      // modify verts
      let d = new THREE.Vector3(disp, disp, disp).multiply(plane.normal)
      positions[i * 3]     = this.boxGeo.vertices[i].x + d.x
      positions[i * 3 + 1] = this.boxGeo.vertices[i].y + d.y
      positions[i * 3 + 2] = this.boxGeo.vertices[i].z + d.z
    } 
  }
  // update geometry
  this.boxMesh.geometry._bufferGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))

我尝试了其他一些方法,包括更密切地遵循此处的文档: https://threejs.org/docs/#manual/en/introduction/How-to-update-things

任何帮助或建议将不胜感激!

编辑:下面的每个 cmets,我正在仔细查看我的 ...attribute.position.array 并注意到它看起来每个面都列出了它的所有顶点,所以我无法访问它们(或设置它们)如上。关于我应该阅读的文档的任何建议?有没有更简单的方法来做到这一点?

因此,根据@Murgen87 的评论,下面的代码可用于更新位置属性。看起来 BoxGeometry 基元不使用索引面,现在我认为缩放/平移框可能更容易。

let positions = 
      this.boxMesh.geometry._bufferGeometry.getAttribute('position')

 // this loop doesn't pick the right positions for my use case 
 faces.map((f, i) => {
    positions.array[f * 6 + i * 3]     += displacement.x
    positions.array[f * 6 + i * 3 + 1] += displacement.y
    positions.array[f * 6 + i * 3 + 1] += displacement.z
  })

  positions.needsUpdate = true;

我剩下的最后一个问题是为什么我不能这样做:

box.geometry.vertices.multiply(displacement)
box.geometry.verticesNeedsUpdate = true

...这只是让我回答了我自己的问题!

【问题讨论】:

  • 请不要替换现有的缓冲区属性。而是更新这些值,然后将 needsUpdate 设置为 true。另请注意,不支持更改缓冲区属性的大小。如果需要,您必须处理整个几何图形并创建一个新几何图形。
  • 嗨@Mugen87 我不想改变缓冲区属性的大小。我可以进入 this.boxMesh.geometry._bufferGeometry.attributes.position[] 并使用我发布的代码中的循环更改值吗?我也刚刚注意到 BoxGeometry 有一个 vertices 数组和一个 verticesNeedsUpdate 标志,尽管我没有看到关于它的文档。

标签: javascript three.js mesh


【解决方案1】:

最简单的方法是:

  this.boxMesh.geometry.vertices.map((v,i) => {
    if(!planeObj.indices.includes(i)) return
    this.boxMesh.geometry.vertices[i].add(displacement)
  })
  this.boxMesh.geometry.verticesNeedUpdate = true

更新位置属性的有效模式是:

  let positions = 
      this.boxMesh.geometry._bufferGeometry.getAttribute('position')
  planeObj.faces.map((f, i) => {
    positions.array[f * 6 + i * 3]     += displacement.x
    positions.array[f * 6 + i * 3 + 1] += displacement.y
    positions.array[f * 6 + i * 3 + 1] += displacement.z
  })
  positions.needsUpdate = true

请注意,上面的循环不会在 position.array 中选择正确的元素,如果只是显示如何更新,如果这是你需要做的。

谢谢!

【讨论】:

    猜你喜欢
    • 2018-11-24
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    相关资源
    最近更新 更多