Three.js的物体点击选中拾取原理剖析
Hello, 大家好,今天来说一下three.js的物体拾取原理!
声明:本文介绍的是three.js全屏模式下的原理,如果涉及到three.js渲染在网页的一部分,请自行推导。
第一节 介绍Three.js的坐标系
先来粗浅的介绍一下Three的拾取原理,我们先介绍一下Three.js的坐标系,我们知道Three.js是右手坐标系。
我用最浅显的一句话介绍就是,Z轴指向屏幕前的自己时就是右手坐标系。
第二节 介绍Three.js物体点击选中拾取原理
选中物体的原理就是如果点A在物体内,那么点A如果发出一条射线指向当前的摄像机,那么这条射线一定与该物体相交。
以物体的中心点为为起点,向物体外发射射线,检测射线是否与A点相交,如果存在相交就检查最近一个交点与射线起点的距离,如果这个距离比物体中心到物体顶点的距离都要小,则点A在物体里面。
和平面几何中判断一个点在不在圆内是一样的道理,只是这里推广到空间立体几何了。大家明白这个意思就行。
更多解释
第三节 介绍Raycaster基础概念
我们的手机屏幕是二维的,但是我们展示物体的世界是三维的,当我们在构建一个物体的时候我们
是以一个三维世界既是世界坐标来构建,而转化为屏幕坐标展示在我们眼前,则需要经历多道矩阵
变化,中间webGL替我们操作了许多事情。
世界坐标系
在webGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏幕,
你的右边是x正轴,
上面是y正轴,
屏幕指向你的为z正轴。
长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。
屏幕坐标系
屏幕坐标系的原点是左上角。
webGL的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。
因此这里就涉及到一个屏幕坐标转换为世界坐标的公式。如图
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
推导过程
设A点为屏幕点击点(x1,y1), x1=e.clintX, y1=e.clientY;
设A点在世界坐标中的坐标值为A'(x2,y2);
由于A点的坐标值的原点是以屏幕左上角为(0,0);
我们可以计算可得以屏幕中心为原点的值A'
x2' = x1 - innerWidth/2
y2' = innerHeight/2 - y1
又由于在世界坐标的范围是[-1,1],要得到正确的B值我们必须要将坐标标准化
x2 = (x1 - innerWidth/2)/(innerwidth/2) = (x1/innerWidth)*2 - 1
y2 = -(y1 / innerHeight)*2 +1
第四节 实施拾取操作
Raycaster 用于鼠标去获取在3D世界被鼠标选中的一些物体;
Raycaster( origin, direction, near, far )
origin — 射线的起点向量。
direction — 射线的方向向量,应该归一标准化。
near — 所有返回的结果应该比 near 远。Near不能为负,默认值为0。
far — 所有返回的结果应该比 far 近。Far 不能小于 near,默认值为无穷大。
代码实现
//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
//射线和模型求交,选中一系列直线
var intersects = raycaster.intersectObjects(objects);
console.log('imtersrcts=' + intersects)
if (intersects.length > 0) {
//选中第一个射线相交的物体
SELECTED = intersects[0].object;
var intersected = intersects[0].object;
console.log(intersects[0].object)
}
}
更多推荐
所有评论(0)