Three.js 选择拾取对象学习总结

9次阅读

共计 1845 个字符,预计需要花费 5 分钟才能阅读完成。

Three.js 选择对象的本质是从点击位置发射光线,但屏幕坐标系与 webgl 坐标系是不同的,而把屏幕的二维坐标转化为三维坐标就是关键,做一步换算后交由 Raycaster 的 setFromCamera 方法即可。所以思路如下:1. 获取屏幕坐标 (x, y)2. 换算至 webgl 坐标中的(x2,y2),此时长度仍为像素单位下的长度 3. 由于 webgl 坐标轴的范围为(-1,1),做个比值,称为标准化 4.Raycaster.setFromCamera(mouse, camera) 发射射线 5.Raycaster.intersectObjects 获取射得的所有对象, 再按需要操作
先对比下各坐标轴,再按代码分析步骤
代码中使用了我封装的方法,threeConf 对象包含 three.js 的基本组件,但不影响拾取对象的逻辑,拾取的代码于此
一、坐标轴
1. 屏幕坐标轴
即我们的屏幕的二维坐标,矩形为我们的屏幕,左上角就是(0, 0),长度即是以 px 为单位

2. 世界坐标系
即 webgl 中的坐标系,屏幕中心为(0, 0, z),第三个坐标为从屏幕指向我们的 z 轴。三个坐标的大小范围为(-1,1),如图

这里其实还有个相机坐标系,因为还没有学习 webgl 或者 opengl 怕胡说八道,我觉得一篇很棒的 blog 贴于文末但是我们实现选择拾取功能时,但单纯从 three.js 角度来看可以不需要相关知识
二、代码思路
全部代码请看上方地址
1. 坐标标准化
//1. 获取屏幕坐标(x, y)
//2. 换算至 webgl 坐标中的(x2,y2),此时长度单位仍为像素
//3. 由于 webgl 坐标轴的范围为(-1,1),做个比值,称为标准化
// 这三步后化简的式子如下,这里我们 three.js 的窗口为整个浏览器
let rayRaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
function onMouseMove(event) {
mouse.x = (event.clientX/window.innerWidth) * 2 – 1;
mouse.y = 1 -(event.clientY/window.innerHeight) * 2 ;
}
window.addEventListener(‘mousemove’, onMouseMove, false);
x1 = event.clientX,y1 = event.clientY,即点击位置,换算过程如下(这里默认画布宽高为浏览器宽高)根据式子带入 x1 与 y1 即可得到代码中相同的式子
2. 发射射线,获取对象
这里截取射线代码
function render() {
// 射线射出
rayRaster.setFromCamera(mouse, threeConf.camera);
// 射线上的物体
let intersects = rayRaster.intersectObjects(threeConf.scene.children);
// 选中另一物体的情况,仍为同一物体则不更新,这里我们只拿第一个物体
if(selectedObj !== intersects[0]){
selectedObj && selectedObj.object.material.color.set(0x87CEEB); // 复原
intersects.length && intersects[0].object.material.color.set(0xff0000);
selectedObj = intersects[0];
document.body.style.cursor = “pointer”;
}
// 未选中物体情况
if(intersects[0] === undefined){
document.body.style.cursor = “auto”;
}
threeConf.stats.update();
threeConf.renderer.render(threeConf.scene, threeConf.camera);
requestAnimationFrame(render);
}
即可
三、参考资料
OpenGL. 坐标系统的介绍与坐标变换的实现(此篇 blog 包含相机坐标轴)https://blog.csdn.net/stringN…
ThreeJS 中的点击与交互——Raycaster 的用法 https://segmentfault.com/a/11…
Three.js Raycaster 官方文档 https://threejs.org/docs/#api…

正文完
 0