基础概念
坐标系
屏幕是二维的,但是展示物体的世界是三维的,当我们在构建一个物体的时候我们是以一个三维世界既是世界坐标来构建,而转化为屏幕坐标展示在我们眼前,则需要经历多道矩阵变化。
- 世界坐标系
在webGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。
- 屏幕坐标系
webGL的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。
坐标转化
可以查阅一下web项目中的HSApp.View.T3d.Util类(web/app/view/t3d/util.js),里面有对于的实现,这次也对细节做了调整,保持坐标之间的转化是一一对应的。思路基本是下面图所示。
Raycaster
通过射线的方式,找到3D场景中的模型
/*
* @param {*} origin 射线的起点向量。
* @param {*} direction 射线的方向向量,应该归一标准化。
* @param {*} near 所有返回的结果应该比 near 远。Near不能为负,默认值为0。
* @param {*} far 所有返回的结果应该比 far 近。Far 不能小于 near,默认值为无穷大。
*/
Raycaster(origin: Vector3, direction: Vector3, near: Float, far: Float)
找到点击物品
鼠标在屏幕上点击的时候,得到二维坐标p(x, y),再加上深度坐标的范围(0, 1), 就可以形成两个三位坐标A(x1, y1, 0), B(x2, y2, 1), 由于它们的Z轴坐标是0和1,则转变到投影坐标系的话,一定分别是前剪切平面上的点和后剪切平面上的点,也就是说,在投影坐标系中,A点一定在能看见的所有模型的最前面,B点一定在能看见的所有的模型的最后边,将AB点连成线,AB线穿过的物体就是被点击的物体。而 Three.js提供一个射线类Raycasting来拾取场景里面的物体。更方便的使用鼠标来操作3D场景。
(不过在实际代码中我们组成射线的两个点是摄像机所在视点与屏幕上点击的点连接而成的射线)。