expandByObject扩张包围盒
expandByObject与setFromObject的区别:

-
作用:把当前
Box3扩大,直到能包住传入object(以及它所有子节点)的世界空间范围。 -
签名:
box.expandByObject(object: THREE.Object3D): this -
特点:是累加(并集),不是覆盖。多次调用会逐步扩大
box。 -
返回:仍是这个
box本身,方便链式调用。
对比:
setFromObject(object)会直接覆盖,把box设置为该对象的范围;而expandByObject是在原有box基础上扩张。
使用要点(易踩坑)
-
先更新矩阵:
object.updateMatrixWorld(true),否则拿到旧的包围盒。 -
重算 vs 扩张:
expandByObject只会变大不会变小;若场景变化需要“收缩”,先box.makeEmpty()再重新 expand。 -
几何的 boundingBox:Three 会在需要时计算,但自定义/动态几何建议手动:
geometry.computeBoundingBox()。 -
可见性/图层:它不关心
visible或layers,纯几何范围计算。 -
InstancedMesh:实例很多时,
expandByObject可能成本较高;确保实例矩阵已更新(instanceMatrix.needsUpdate=false之后)。
常用示例
1) 计算整个场景(或若干组)的全局高度
// 1) 创建空盒子
const globalBox = new THREE.Box3().makeEmpty();
// 2) 累加若干 group 的范围(或直接传 scene)
for (const group of [...this.initModelGroup, ...this.pglModelGroup]) {
group.updateMatrixWorld(true);
globalBox.expandByObject(group);
}
// 3) 取最高点 + 安全余量
this.defaultHeight = globalBox.max.y + 1000;
2) 向下发射射线(基于全局最高点)
const origin = new THREE.Vector3(x, this.defaultHeight, z);
const dir = new THREE.Vector3(0, -1, 0); // 向下
raycaster.set(origin, dir);
// 注意传入 { recursive: true } 或第二参数 true
const targets = [...this.initModelGroup, ...this.pglModelGroup];
const hits = raycaster.intersectObjects(targets, true);
3) 只算一个组的范围(比如一栋楼)
const box = new THREE.Box3().makeEmpty();
buildingGroup.updateMatrixWorld(true);
box.expandByObject(buildingGroup);
const size = new THREE.Vector3();
box.getSize(size); // 楼的宽高深
const center = new THREE.Vector3();
box.getCenter(center); // 楼的中心点(世界坐标)
4) 相机自适应取景(frame object)
function frameBox(camera, controls, box, fitOffset = 1.2) {
const size = new THREE.Vector3(); box.getSize(size);
const center = new THREE.Vector3(); box.getCenter(center);
const maxSize = Math.max(size.x, size.y, size.z);
const fov = THREE.MathUtils.degToRad(camera.fov);
const dist = (maxSize / 2) / Math.tan(fov / 2) * fitOffset;
const dir = new THREE.Vector3()
.subVectors(camera.position, controls.target)
.normalize();
camera.position.copy(center).addScaledVector(dir, dist);
camera.near = dist / 100;
camera.far = dist * 100;
camera.updateProjectionMatrix();
controls.target.copy(center);
controls.update();
}
// 用法:
const box = new THREE.Box3().makeEmpty();
scene.updateMatrixWorld(true);
box.expandByObject(scene);
frameBox(camera, controls, box);
5) 动态场景的“重算”套路
// 每次需要精确更新全局盒子时:
globalBox.makeEmpty();
for (const group of groups) {
group.updateMatrixWorld(true);
globalBox.expandByObject(group);
}
什么时候选它
-
你要的是多个对象的总体边界(全场景/若干组的包围盒)——用
expandByObject。 -
你只关心单个对象当前范围——用
setFromObject更直接。

浙公网安备 33010602011771号