首页 / three.js / 使用示例
地形拾取
鼠标划过起伏的地表,左下角实时显示命中的经纬平面坐标与海拔。 点击会在地面立一根标柱,用来验证屏幕坐标到世界坐标的换算是否可靠。
源码与运行效果
三步完成一次拾取
先把鼠标位置换算成归一化设备坐标:横向 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 回到几何体空间,
再套用「场景单位 → 米」的比例与原点偏移。