如何获取Three.js中InstancedMesh各实例的顶点位置?
获取Three.js InstancedMesh单个实例的顶点世界坐标
问题场景
已通过以下代码创建InstancedMesh及对应的dummy Object3D数组,实现了单个实例的独立操控,但无法像普通Mesh那样获取每个实例的顶点信息:
const parentGeometry = new THREE.BoxBufferGeometry( 10, 10, 10, 1, 1, 1 ); const instancedGeometry = new THREE.InstancedBufferGeometry(); const material = new THREE.MeshPhongMaterial( { color: 0xFF0000 } ) THREE.BufferGeometry.prototype.copy.call( instancedGeometry, parentGeometry ); var defaultTransform = new THREE.Matrix4().multiply( new THREE.Matrix4().makeScale( 1, 1, 1 ) ) instancedGeometry.applyMatrix4( defaultTransform ); instancedMeshes = new THREE.InstancedMesh( instancedGeometry, material, instanceCount ); instancedMeshes.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // 创建dummy数组用于单独控制每个实例 for ( let i = 0; i < instanceCount; i ++ ) { let dummy = new THREE.Object3D(); dummyArray.push( dummy ); dummyArray[i].position.copy( new THREE.Vector3( i*15-100,0,-100 ) ); dummyArray[i].updateMatrix(); instancedMeshes.setMatrixAt( i, dummyArray[i].matrix ); instancedMeshes.instanceMatrix.needsUpdate = true; } scene.add( instancedMeshes );
普通Mesh的顶点获取代码对InstancedMesh无效(因每个实例无独立geometry属性):
// 普通Mesh可用,但InstancedMesh实例不适用 let meshVertices = meshArray[i].geometry.attributes["position"].array; meshArray[i].updateMatrixWorld(); let mesh_top_left_vertices = meshArray[i].localToWorld( new THREE.Vector3( meshVertices[15], meshVertices[15 + 1], meshVertices[15 + 2] ) )
解决方案
InstancedMesh的所有实例共享同一个基础几何体,每个实例的变换信息存储在对应的dummy对象中。只需将基础几何体的局部顶点,通过对应实例的世界变换矩阵转换,即可得到该实例顶点的世界坐标:
实现步骤
- 获取基础几何体的顶点数据:可直接使用创建InstancedMesh时的
parentGeometry,或从instancedMeshes.geometry中读取(两者顶点数据一致)。 - 更新实例的世界矩阵:确保dummy对象的变换是最新的。
- 转换顶点坐标:用实例的世界矩阵将基础几何体的局部顶点转换为世界坐标。
代码示例
// 获取基础几何体的顶点数组 const baseVertices = instancedMeshes.geometry.attributes.position.array; // 处理第i个实例 const targetIndex = i; // 替换为你需要查询的实例索引 const dummy = dummyArray[targetIndex]; // 更新dummy的世界矩阵(确保包含父节点变换) dummy.updateMatrixWorld(); // 取出基础几何体中目标局部顶点 const localVertex = new THREE.Vector3( baseVertices[15], baseVertices[16], baseVertices[17] ); // 用实例的世界矩阵转换为世界坐标 const worldVertex = localVertex.applyMatrix4(dummy.matrixWorld); console.log(`第${targetIndex}个实例的目标顶点世界坐标:`, worldVertex);
关键说明
- InstancedMesh的核心优势是共享几何体与材质,减少Draw Call,因此每个实例没有独立的
geometry属性,所有实例共用同一套顶点数据。 - dummy对象的
matrixWorld包含了该实例的所有变换(位置、旋转、缩放),是转换顶点坐标的关键。
内容的提问来源于stack exchange,提问作者Toki
相关产品推荐
相关产品推荐

