模型、光源这些应该没啥问题,主要就是针对障碍物的检测。
检查信号路径是否被墙壁阻挡: 通过射线检测(Raycasting)检查从信号源到目标点的路径是否被墙壁遮挡。如果有遮挡,则衰减信号强度。可以看下下方的实现
// 1. 创建场景、相机和渲染器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);// 2. 创建地面(模拟 Wi-Fi 信号区域)const geometry = new THREE.PlaneGeometry(10, 10, 10, 10);const material = new THREE.MeshBasicMaterial({ color: 0xffffff, // 初始颜色
side: THREE.DoubleSide, vertexColors: true // 启用顶点颜色});const plane = new THREE.Mesh(geometry, material);
plane.rotation.x = Math.PI / 2;
scene.add(plane);// 3. 创建墙壁(遮挡物)const wallGeometry = new THREE.BoxGeometry(1, 5, 0.1); // 创建一面薄墙const wallMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });const wall = new THREE.Mesh(wallGeometry, wallMaterial);
wall.position.set(4, 2.5, 0); // 将墙壁放置到特定位置scene.add(wall);// 4. 定义一个简单的信号衰减模型function calculateSignalStrength(x, z, signalSource) { const distance = Math.sqrt(x * x + z * z); // 计算从信号源到目标点的距离
let signalStrength = Math.max(0, 1 - distance / 10); // 信号衰减公式
// 使用射线检测判断是否被墙壁遮挡
const raycaster = new THREE.Raycaster();
raycaster.origin.set(signalSource.x, signalSource.y, signalSource.z);
raycaster.direction.set(x - signalSource.x, 0, z - signalSource.z); // 计算目标方向
const intersects = raycaster.intersectObject(wall); // 检查射线是否与墙壁相交
if (intersects.length > 0) { // 如果射线与墙壁相交,信号受到阻挡
signalStrength *= 0.3; // 阻挡的情况下信号强度衰减
} return signalStrength;
}// 5. 更新热力图的颜色function updateHeatmap() { const vertices = geometry.attributes.position.array; for (let i = 0; i < vertices.length; i += 3) { const x = vertices[i]; const z = vertices[i + 2]; // 根据位置计算信号强度
const signalStrength = calculateSignalStrength(x, z, new THREE.Vector3(0, 0, 0)); // 信号源位置为 (0, 0, 0)
// 使用信号强度来决定颜色
const color = new THREE.Color();
color.setHSL((1 - signalStrength) / 2, 1, 0.5); // 将信号强度映射到颜色,绿色为强信号,红色为弱信号
// 将颜色应用到顶点
geometry.attributes.color.array[i] = color.r;
geometry.attributes.color.array[i + 1] = color.g;
geometry.attributes.color.array[i + 2] = color.b;
} // 通知渲染器更新颜色
geometry.attributes.color.needsUpdate = true;
}// 6. 渲染循环function animate() { requestAnimationFrame(animate); updateHeatmap(); // 更新热力图
renderer.render(scene, camera);
}
camera.position.z = 5;animate();// 为了实现动态效果,使用 orbitControlsconst controls = new THREE.OrbitControls(camera, renderer.domElement);