最近几天忙一个项目,一直没有更新,今天抽空更新一期,接着上一节我们来实现鼠标与物体的交互效果,这里我们先来思考下我们人眼看到物体的过程,比如人眼看到电脑屏幕的过程,借助光,从人眼发出一条射线照射到电脑屏幕,也就是说这条射线和电脑屏幕又交叉,这样我们才能看到屏幕。
在Threejs中,我们可以通过类似的方法获取三维空间中某一点的位置,比如从摄像机发出一条射线,照射到鼠标的坐标位置,这条射线和鼠标坐标位置交叉的物探就会被选中,这里面用到了光线投射Raycaster类,我们来认识一下这个类
光线投射Raycaster
这个类用于进行光线投射。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。
构造函数
Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float )
origin —— 光线投射的原点向量。
direction —— 向射线提供方向的方向向量,应当被标准化。
near —— 返回的所有结果比near远。near不能为负值,其默认值为0。
far —— 返回的所有结果都比far近。far不能小于near,其默认值为Infinity(正无穷。)
属性
.far : Float类型,raycaster的远距离因数(投射远点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比near属性大。
.near : Float类型,raycaster的近距离因数(投射近点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比far属性小。
.camera : Camera类型,对视图相关对象(如“精灵”之类的Billboard对象)进行光线投射时要使用的摄影机。此字段可以手动设置,也可以在调用“setFromCamera”时设置。默认为null。
.layers : Layers类型,
.params : Object类型,具体包含如下参数
{
Mesh: {},
Line: { threshold: 1 },
LOD: {},
Points: { threshold: 1 },
Sprite: {}
}
其中threshold是与对象相交时光线投射器的精度,单位为世界单位。
.ray : Ray类型,用于进行光线投射的Ray(射线)。
const raycaster = new THREE.Raycaster()
console.log(raycaster.ray)
射线具有起点和方向属性
// 设置射线起点
raycaster.ray.origin = new THREE.Vector3(-100, 0, 0)
// 设置射线方向,射线方向沿着y轴
raycaster.ray.direction = new THREE.Vector3(0, 1, 0)
方法
.set ( origin : Vector3, direction : Vector3 ) : 方法
origin —— 光线投射的原点向量。
direction —— 为光线提供方向的标准化方向向量。
使用一个新的原点和方向来更新射线。
.setFromCamera ( coords : Vector2, camera : Camera ) :
coords —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。
camera —— 射线所来源的摄像机。
使用一个新的原点和方向来更新射线。
.intersectObject ( object : Object3D, recursive : Boolean, optionalTarget : Array ) : Array
object —— 检查与射线相交的物体。
recursive —— 若为true,则同时也会检查所有的后代。否则将只会检查对象本身。默认值为true。
optionalTarget — (可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。
检测所有在射线与物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个。
该方法返回一个包含有交叉部分的数组:
[ { distance, point, face, faceIndex, object }, ... ]
distance —— 射线投射原点和相交部分之间的距离。
point —— 相交部分的点(世界坐标)
face —— 相交的面
faceIndex —— 相交的面的索引
object —— 相交的物体
uv —— 相交部分的点的UV坐标。
uv2 —— Second set of U,V coordinates at point of intersection
instanceId – The index number of the instance where the ray intersects the InstancedMesh
当计算这条射线是否和物体相交的时候,Raycaster将传入的对象委托给raycast方法。 这将可以让mesh对于光线投射的响应不同于lines和pointclouds。
请注意:对于网格来说,面必须朝向射线的原点,以便其能够被检测到。 用于交互的射线穿过面的背侧时,将不会被检测到。如果需要对物体中面的两侧进行光线投射, 需要将material中的side属性设置为THREE.DoubleSide。
.intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array
objects —— 检测和射线相交的一组物体。
recursive —— 若为true,则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分。默认值为true。
optionalTarget —— (可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。
检测所有在射线与这些物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个),相交部分和.intersectObject所返回的格式是相同的。
const raycaster = new THREE.Raycaster()
raycaster.ray.origin = ne