THREE.js中如何从BoxGeometry立方体上选中指定的面?
Three.js立方体指定面选取与面球碰撞检测实现方案
1. 立方体指定面选取方法
你创建的立方体用的是BoxGeometry,可以通过以下两种方式精准定位目标面:
方案一:通过固定面索引直接获取
Three.js的BoxGeometry生成的三角面有固定的索引规则,每个立方体共12个三角面(每个矩形面由2个三角面组成),索引对应关系如下:
- 正X面:索引0、1
- 负X面:索引2、3
- 正Y面:索引4、5
- 负Y面:索引6、7
- 正Z面:索引8、9
- 负Z面:索引10、11
你可以直接通过索引提取目标面的顶点数据,示例代码如下:
// 你原有的创建立方体代码 const hand1geo = new THREE.BoxGeometry(2, 0.01, 0.2); const material_sidehand = new THREE.MeshBasicMaterial({ color: 0x3cc1b7 }); const sidehand = new THREE.Mesh(hand1geo, material_sidehand); // 获取几何体顶点属性 const positionAttr = hand1geo.getAttribute('position'); // 示例:选取正Y面对应的两个三角面索引 const targetTriIndices = [4,5]; const faceVertices = []; // 提取目标面顶点并转换为世界坐标 targetTriIndices.forEach(triIdx => { for(let i = 0; i < 3; i++) { const vertexIdx = triIdx * 3 + i; const vec = new THREE.Vector3( positionAttr.getX(vertexIdx), positionAttr.getY(vertexIdx), positionAttr.getZ(vertexIdx) ); vec.applyMatrix4(sidehand.matrixWorld); faceVertices.push(vec); } }); // 生成目标面对应的无限平面对象,用于后续碰撞检测 const targetPlane = new THREE.Plane().setFromCoplanarPoints(faceVertices[0], faceVertices[1], faceVertices[2]);
方案二:多材质标记目标面
如果需要可视化区分目标面,或者需要灵活切换目标面,可以给立方体6个面分配独立材质,通过材质索引定位目标面:
// 材质顺序对应:正X、负X、正Y、负Y、正Z、负Z const cubeMaterials = [ new THREE.MeshBasicMaterial({color: 0x3cc1b7}), new THREE.MeshBasicMaterial({color: 0x3cc1b7}), new THREE.MeshBasicMaterial({color: 0xff0000}), // 给目标面(正Y面)设置特殊颜色标记 new THREE.MeshBasicMaterial({color: 0x3cc1b7}), new THREE.MeshBasicMaterial({color: 0x3cc1b7}), new THREE.MeshBasicMaterial({color: 0x3cc1b7}), ]; const sidehand = new THREE.Mesh(hand1geo, cubeMaterials);
2. 面与球体碰撞检测实现
拿到目标面对应的Plane对象后,结合Three.js内置的碰撞检测方法即可实现需求:
// 构造球体的碰撞体,需传入球体世界坐标下的球心和半径 const sphereCollider = new THREE.Sphere(sphereMesh.position, sphereRadius); // 第一步:检测球体是否和目标面对应的无限平面相交 const isPlaneIntersect = sphereCollider.intersectsPlane(targetPlane); if (isPlaneIntersect) { // 第二步:判断交点是否在立方体目标面的有限范围内,排除平面其他位置的误判 const collisionPoint = new THREE.Vector3(); targetPlane.projectPoint(sphereCollider.center, collisionPoint); // 碰撞点转换到立方体局部坐标 collisionPoint.applyMatrix4(sidehand.matrixWorld.clone().invert()); // 以正Y面为例,判断交点是否在面的矩形范围内(你的立方体参数x范围±1,z范围±0.1) if (Math.abs(collisionPoint.x) <= 1 && Math.abs(collisionPoint.z) <= 0.1) { // 此处写碰撞触发后的逻辑 console.log('目标面与球体发生碰撞'); } }
面与球体示意
内容的提问来源于stack exchange,提问作者hellooooo
相关产品推荐
相关产品推荐

