Three.js 从 boxGeometry 更新网格的位置属性
Three.js update position attribute of mesh from 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/#manual/en/introduction/How-to-update-things
如有任何帮助或建议,我们将不胜感激!
编辑:根据下面的评论,我正在仔细查看我的 ...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
...这让我回答了我自己的问题!
最简单的方法是:
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
请注意,上面的循环没有 select positions.array 中的正确元素 if 只是显示如何更新,如果这是你需要做的。
谢谢!
我正在实现一个通过单击 + 拖动立方体的面来调整立方体大小的界面。
我想通过更新缓冲区几何对象的位置属性来实现这一点,然后重新创建网格或只设置 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/#manual/en/introduction/How-to-update-things
如有任何帮助或建议,我们将不胜感激!
编辑:根据下面的评论,我正在仔细查看我的 ...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
...这让我回答了我自己的问题!
最简单的方法是:
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
请注意,上面的循环没有 select positions.array 中的正确元素 if 只是显示如何更新,如果这是你需要做的。
谢谢!