在 3D 场景开发中,计算两个物体之间的距离是常见需求。无论是实现碰撞检测、AI 行为逻辑,还是创建视觉特效,距离计算都是基础且关键的功能。本文将详细介绍在 Three.js 中如何计算两个物体之间的距离。
基本概念
在 Three.js 中,物体之间的距离通常指的是它们位置 (position) 之间的欧几里得距离。每个 Three.js 对象都有一个 position 属性,它是一个 Vector3 实例,表示该对象在 3D 空间中的坐标 (x, y, z)。
计算距离的方法
Three.js 的 Vector3 类提供了多种计算距离的方法:
- distanceTo () - 计算当前向量到另一个向量的距离
- distanceToSquared () - 计算距离的平方 (性能更好,适用于比较距离大小的场景)
下面是一个简单的示例,展示如何使用这些方法:
// 假设我们有两个Three.js对象
const object1 = new THREE.Mesh(geometry, material);
const object2 = new THREE.Mesh(geometry, material);
// 设置它们的位置
object1.position.set(10, 5, 0);
object2.position.set(4, 1, 0);
// 计算它们之间的距离
const distance = object1.position.distanceTo(object2.position);
console.log('两个物体之间的距离是:', distance); // 输出约为7.21
// 如果只需要比较距离大小,可以使用distanceToSquared()
const distanceSquared = object1.position.distanceToSquared(object2.position);
console.log('距离的平方是:', distanceSquared); // 输出约为52
应用示例:距离检测系统
下面是一个完整的示例,展示如何实现一个简单的距离检测系统。当两个物体之间的距离小于某个阈值时,我们会改变它们的颜色。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 距离检测示例</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
</head>
<body>
<script>
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建两个立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 物体1 - 红色立方体
const material1 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const object1 = new THREE.Mesh(geometry, material1);
object1.position.set(-3, 0, 0);
scene.add(object1);
// 物体2 - 蓝色立方体
const material2 = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const object2 = new THREE.Mesh(geometry, material2);
object2.position.set(3, 0, 0);
scene.add(object2);
// 添加坐标轴辅助
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 设置相机位置
camera.position.z = 5;
// 距离阈值
const distanceThreshold = 4;
// 创建一个标签显示距离
const distanceLabel = document.createElement('div');
distanceLabel.style.position = 'absolute';
distanceLabel.style.top = '10px';
distanceLabel.style.left = '10px';
distanceLabel.style.color = 'white';
distanceLabel.style.fontFamily = 'Arial';
distanceLabel.style.fontSize = '16px';
document.body.appendChild(distanceLabel);
// 动画循环
function animate() {
requestAnimationFrame(animate);
// 让物体2向物体1移动
object2.position.x -= 0.01;
// 如果物体2移动到左边太远,则重置位置
if (object2.position.x < -5) {
object2.position.x = 3;
}
// 计算两个物体之间的距离
const distance = object1.position.distanceTo(object2.position);
// 更新标签显示
distanceLabel.textContent = `距离: ${distance.toFixed(2)} (阈值: ${distanceThreshold})`;
// 当距离小于阈值时,改变颜色
if (distance < distanceThreshold) {
object1.material.color.set(0x00ff00);
object2.material.color.set(0x00ff00);
} else {
object1.material.color.set(0xff0000);
object2.material.color.set(0x0000ff);
}
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
在这个示例中,我们创建了两个立方体,一个红色一个蓝色。蓝色立方体会自动向红色立方体移动,我们实时计算它们之间的距离并显示出来。当距离小于设定的阈值时,两个立方体都会变成绿色。
性能优化
在处理大量对象的场景中,计算每个对象之间的距离可能会影响性能。以下是一些优化建议:
- 使用 distanceToSquared () 代替 distanceTo (),避免开平方运算
- 实现空间分区算法 (如八叉树) 来减少需要计算距离的对象数量
- 限制距离计算的频率,不必每帧都计算
更复杂的距离计算
在某些情况下,你可能需要计算更复杂的距离,比如:
- 从一个点到一个物体表面的距离
- 两个物体边界框之间的距离
- 两个物体碰撞体之间的最小距离
对于这些情况,Three.js 提供了 Box3、Sphere 等类,它们也有类似的 distanceTo 方法。你还可以使用 Raycaster 来计算点到物体表面的距离。
通过掌握这些技术,你可以在 Three.js 中实现各种复杂的交互和效果,从简单的距离提示到高级的物理模拟。