Three.js从boxGeometry中更新网格的位置属性



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

我想通过更新缓冲区几何对象上的位置属性来实现这一点,或者重新创建网格,或者只是设置needsUpdate标志,让它更新自己。这两种选择对我都不起作用。我的最新尝试如下。

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/手册/en/介绍/How-to-update-things

任何帮助或建议将不胜感激!编辑:根据下面的评论,我正在仔细检查我的…属性位置。并注意到它看起来像每个面列出了它的所有顶点,所以我不能像上面那样访问它们(或设置它们)。有什么建议我应该去看的吗?有更简单的方法吗?

所以根据@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

…这让我回答了自己的问题!

最简单的方法是:

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

更新position属性的有效模式是:

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

注意,上面的循环并没有在位置中选择合适的元素。数组if只是展示了如何更新如果这是你需要做的

谢谢!

最新更新