光线投射Raycaster
这个类用于进行raycasting(光线投射)。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。
Raycaster构造器:
Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float ) {
origin —— 光线投射的原点向量。
direction —— 向射线提供方向的方向向量,应当被标准化。
near —— 投射近点,用来限定返回的所有结果比near远。near不能为负值,其默认值为0。
far —— 投射远点,用来限定返回的所有结果都比far近。far不能小于near,其默认值为Infinity(正无穷。)
偷来的图片
由于浏览器是一个2D视口,而three.js的内容是3D场景,所以需要将2D视口的x和y坐标转换成three.js场景中的3D坐标。设置三维场景的显示区域,指明当前显示的2D坐标给THREE.Raycaster,它将生成一条从显示的起点到终点的一条射线。也就是说,再屏幕上获取了一个点,在three.js里面获取的则是一条直线。
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1到 +1)
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function render() {
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera( mouse, camera );
// 计算物体和射线的焦点
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
intersects[ i ].object.material.color.set( 0xff0000 );
}
renderer.render( scene, camera );
}
window.addEventListener( 'mousemove', onMouseMove, false );
window.requestAnimationFrame(render);
属性
.far : float
raycaster的远距离因数(投射远点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比near属性大。
.linePrecision : float
raycaster与Line(线)物体相交时的精度因数。
.near : float
raycaster的近距离因数(投射近点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比near属性小。
.params : Object
具有以下属性的物体:
{
Mesh: {},
Line: {},
LOD: {},
Points: { threshold: 1 },
Sprite: {}
}
.ray : Ray
用于进行光线投射的Ray(射线)。
方法
①.set ( origin : Vector3, direction : Vector3 ) : null
origin —— 光线投射的原点向量。
direction —— 为光线提供方向的标准化方向向量。
使用一个新的原点和方向来更新射线。
②.setFromCamera ( coords : Vector2, camera : Camera ) : null
coords —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。
camera —— 射线所来源的摄像机。
使用一个新的原点和方向来更新射线。
③.intersectObject ( object : Object3D, recursive : Boolean, optionalTarget : Array ) : Array
object —— 检查与射线相交的物体。
recursive —— 若为true,则同时也会检查所有的后代。否则将只会检查对象本身。默认值为false。
optionalTarget — (可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。
检测所有在射线与物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个)。
该方法返回一个包含有交叉部分的数组:
[ { distance, point, face, faceIndex, object }, … ]
distance —— 射线投射原点和相交部分之间的距离。
point —— 相交部分的点(世界坐标)
face —— 相交的面
faceIndex —— 相交的面的索引
object —— 相交的物体
uv —— 相交部分的点的UV坐标。
当计算这条射线是否和物体相交的时候,Raycaster将传入的对象委托给raycast方法。 这将可以让mesh对于光线投射的响应不同于lines和pointclouds。
④.intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array
objects —— 检测和射线相交的一组物体。
recursive —— 若为true,则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分。默认值为false。
optionalTarget —— (可选)(可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。
检测所有在射线与这些物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个),相交部分和.intersectObject所返回的格式是相同的。
intersectObject和intersectObjects的唯一区别就是,intersectObject第一个参数需要传入一个3d对象,而intersectObjects需要传入一个3d对象组成的数组。
**请注意:**对于网格来说,面必须朝向射线的原点,以便其能够被检测到。 用于交互的射线穿过面的背侧时,将不会被检测到。如果需要对物体中面的两侧进行光线投射, 你需要将material中的side属性设置为THREE.DoubleSide。
当一个网孔(Mesh)对象和一个缓存几何模型(BufferGeometry)相交时,faceIndex 将是 undefined,并且 indices 将被设置; 而当一个网孔(Mesh)对象和一个几何模型(Geometry)相交时,indices 将是 undefined。