THREE.js中基于OBB参数计算角点并绘制三维包围盒的实现方法
Three.js OBB 角点计算与外框绘制实现
核心逻辑
OBB的计算逻辑非常直接:以center为原点,沿三个互相垂直的本地轴,向正负方向延伸对应halfSize的长度,最终围成的长方体就是定向包围盒。角点的世界坐标计算分两步:
- 生成本地坐标系下的角点:三个轴的半尺寸取正负全组合,一共8个点
- 对每个本地点,通过rotation矩阵完成旋转变换后,叠加center的平移量,就是最终的世界坐标值
步骤1:计算全部8个角点
直接枚举三个轴的正负方向组合即可,不需要手动拆解旋转矩阵的元素做乘法计算——Three.js的矩阵是列主序存储,手动计算极易搞混行/列顺序导致旋转方向错误,直接复用内置向量方法就能避开这个坑。
/** * 根据OBB参数计算8个世界坐标系下的角点 * @param {THREE.Vector3} center OBB中心坐标 * @param {THREE.Vector3} halfSize OBB三个轴的半尺寸 * @param {THREE.Matrix3} rotation OBB的旋转矩阵 * @returns {THREE.Vector3[]} 8个角点的世界坐标,索引顺序固定 */ function getOBBCorners(center, halfSize, rotation) { const corners = []; // 三个轴取正负值的全排列组合 const signMap = [ [-1, -1, -1], [-1, -1, 1], [-1, 1, -1], [-1, 1, 1], [1, -1, -1], [1, -1, 1], [1, 1, -1], [1, 1, 1] ]; for (const [sx, sy, sz] of signMap) { const localPoint = new THREE.Vector3( sx * halfSize.x, sy * halfSize.y, sz * halfSize.z ); // 先旋转到世界方向,再加中心坐标平移,得到世界坐标 const worldCorner = localPoint.applyMatrix3(rotation).add(center); corners.push(worldCorner); } return corners; }
步骤2:绘制OBB外框
拿到角点数组后,按照固定的边连接关系生成12条线段,用LineSegments渲染即可——不需要依赖内置的BoxHelper,它仅支持轴对齐包围盒(AABB)的绘制。
/** * 基于计算得到的OBB角点生成外框线对象 * @param {THREE.Vector3[]} corners getOBBCorners返回的8个角点 * @returns {THREE.LineSegments} 可直接加入场景的外框对象 */ function createOBBOutline(corners) { // 角点索引与边的连接关系,和上述signMap的顺序一一对应 const edgeConnections = [ [0,1], [0,2], [0,4], [1,3], [1,5], [2,3], [2,6], [3,7], [4,5], [4,6], [5,7], [6,7] ]; // 展开为线段顶点数组 const linePointArray = []; for (const [idxA, idxB] of edgeConnections) { linePointArray.push(corners[idxA], corners[idxB]); } const geo = new THREE.BufferGeometry().setFromPoints(linePointArray); // 可自定义线颜色、透明度等材质参数 const mat = new THREE.LineBasicMaterial({ color: 0xff3333 }); return new THREE.LineSegments(geo, mat); }
参数校验方法
针对你贴的参数,当前rotation是单位矩阵(无任何旋转),计算得到的角点范围可以直接用轴对齐规则交叉验证:
- x轴范围:
4.45329 ± 0.19512 - y轴范围:
7.88595 ± 0.25958 - z轴范围:
0.48165 ± 0.34600
如果计算结果和上述范围的偏差在浮点精度允许的范围内,就说明计算逻辑是正确的。
常见踩坑提醒
- 不要手动拆解rotation的elements做矩阵乘法:Three.js的矩阵为列主序存储,手动计算极易出现顺序颠倒导致旋转错误,直接调用向量的
applyMatrix3方法即可。 - 不要混用Matrix4做旋转计算:OBB返回的rotation是纯3x3旋转矩阵,不存在平移分量,多余的平移计算会导致位置偏移。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

