经纬志
首页 / three.js / 使用示例

地形拾取

鼠标划过起伏的地表,左下角实时显示命中的经纬平面坐标与海拔。 点击会在地面立一根标柱,用来验证屏幕坐标到世界坐标的换算是否可靠。

three.js 0.160.0 · 更新 2026-10-28
源码与运行效果
运行效果

三步完成一次拾取

先把鼠标位置换算成归一化设备坐标:横向 0 → 2x-1,纵向取反。 再用 raycaster.setFromCamera(pointer, camera) 生成射线, 最后 intersectObject(terrain) 拿到命中数组,取第一个交点的 point。

求交的对象必须是地形 Mesh 本身,而不是它所在的 Group。 传 true 作为第二个参数会递归遍历子对象,场景大了之后每次移动都要遍历整棵树, 在 pointermove 里会明显拖慢。

步骤代码注意点
坐标归一化(x/w)*2-1要用 canvas 的 getBoundingClientRect(),不能用窗口尺寸
生成射线setFromCamera相机矩阵必须是最新的
求交intersectObject返回按距离升序排列

精度与性能

拾取精度取决于网格密度。示例用 120 × 120 段,单个三角形约 0.25 单位, 读数与真实高程函数之间的偏差在这个量级以内。 如果数据是规则 DEM,更快的做法是跳过射线求交, 直接用射线与水平面的交点坐标去采样高程栅格,一次查表就能得到结果。

pointermove 触发频率很高,真要做实时拾取时建议在事件里只记录坐标, 把求交放进渲染循环,每帧最多算一次,避免事件堆积。

拾取结果是世界坐标。如果地形整体做过平移或缩放,命中点已经包含这些变换。 要把结果转成业务坐标,得先 worldToLocal 回到几何体空间, 再套用「场景单位 → 米」的比例与原点偏移。