2. Raycaster(射线拾取模型)
# Raycaster(射线拾取模型)
上节课给大家介绍过射线Ray
,下面给大家介绍另一个和射线相关的API射线投射器Raycaster
。
# 准备三个mesh用于射线拾取
const geometry = new THREE.SphereGeometry(25, 50, 50);
const material = new THREE.MeshLambertMaterial({
color: 0x009999,
});
const mesh1 = new THREE.Mesh(geometry, material);
const mesh2 = mesh1.clone();
mesh2.position.y = 100;
const mesh3 = mesh1.clone();
mesh3.position.x = 100;
const model = new THREE.Group();
// 三个网格模型mesh1,mesh2,mesh3用于射线拾取测试
model.add(mesh1, mesh2, mesh3);
model.updateMatrixWorld(true);
# 射线投射器Raycaster
射线投射器Raycaster
具有一个射线属性.ray
,该属性的值就是上节课讲解的射线对象Ray
。
const raycaster = new THREE.Raycaster();
console.log('射线属性',raycaster.ray);
// 设置射线起点
raycaster.ray.origin = new THREE.Vector3(-100, 0, 0);
// 设置射线方向射线方向沿着x轴
raycaster.ray.direction = new THREE.Vector3(1, 0, 0);
# 射线交叉计算(.intersectObjects()
方法)
射线投射器Raycaster
通过.intersectObjects()
方法可以计算出来与自身射线.ray
相交的网格模型。
.intersectObjects([mesh1, mesh2, mesh3])
对参数中的网格模型对象进行射线交叉计算,未选中对象返回空数组[],选中一个对象,数组1个元素,选中多个对象,数组多个元素,如果选中多个对象,对象在数组中按照先后排序。
const raycaster = new THREE.Raycaster();
raycaster.ray.origin = new THREE.Vector3(-100, 0, 0);
raycaster.ray.direction = new THREE.Vector3(1, 0, 0);
// 射线发射拾取模型对象
const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh3]);
console.log("射线器返回的对象", intersects);
# .intersectObjects()
射线拾取返回信息
射线拾取返回的intersects里面的元素包含多种信息,你可以通过threejs文档查看,或者在浏览器控制台打印查看。
.intersectObjects()
和.intersectObject()
功能相同,只是具体语法不同,.intersectObjects()
返回数组元素包含的信息,可以参考文档关于.intersectObject()
的介绍。
console.log("射线器返回的对象", intersects);
// intersects.length大于0说明,说明选中了模型
if (intersects.length > 0) {
console.log("交叉点坐标", intersects[0].point);
console.log("交叉对象",intersects[0].object);
console.log("射线原点和交叉点距离",intersects[0].distance);
}
# 射线选中的模型对象改变材质颜色
const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh3]);
if (intersects.length > 0) {
// 选中模型的第一个模型,设置为红色
intersects[0].object.material.color.set(0xff0000);
}
# 提醒
注意射线拾取的时候,mesh1, mesh2, mesh3位置要确保更新的情况下,执行射线计算,threejs一般是渲染器执行一次.render()
之后,你设置的mesh.position或者mesh父对象的position才会真实生效。
...
// 注意更新下模型的世界矩阵,你设置的mesh.position生效,再进行射线拾取计算
model.updateMatrixWorld(true);
...
const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh3]);
mesh2.position.y = 100;
mesh3.position.x = 100;
const model = new THREE.Group();
// 三个网格模型mesh1,mesh2,mesh3用于射线拾取测试
model.add(mesh1, mesh2, mesh3);
//注意更新下模型的世界矩阵,你设置的position生效,再进行射线拾取计算
model.updateMatrixWorld(true);
const raycaster = new THREE.Raycaster();
raycaster.ray.origin = new THREE.Vector3(-100, 0, 0);
raycaster.ray.direction = new THREE.Vector3(1, 0, 0);
const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh3]);