资讯专栏INFORMATION COLUMN

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

elina / 2359人阅读

摘要:选择对象的本质是从点击位置发射光线,但屏幕坐标系与坐标系是不同的,而把屏幕的二维坐标转化为三维坐标就是关键,做一步换算后交由的方法即可。

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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100202.html

相关文章

  • WebVR开发教程——交互事件(三)Cardboard与注视

    摘要:开发传送门开发教程交互事件一头显与手柄开发教程交互事件二使用开发教程深度剖析关于的开发调试方案以及原理机制开发教程标准入门使用开发场景的入门教程 showImg(https://segmentfault.com/img/remote/1460000011814846?w=1240&h=587); Cardboard可以说是手机VR头显的元老了,狭义上指的是Google推出的一个带有双凸...

    Allen 评论0 收藏0
  • SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

    摘要:在文末,我会附上一个可加载的模型方便学习中文艺术字渲染用原生可以很容易地绘制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 Web...

    objc94 评论0 收藏0
  • three.js 入门详解(一)

    摘要:一般说来,对于制图建模软通常使正交投影,这样不会因为投影而改变物体比例而对于其他大多数应用,通常使用透视投影,因为这更接近人眼的观察效果。 showImg(https://segmentfault.com/img/remote/1460000012581680?w=1920&h=1080); 1. 概述 1.1 什么是WebGL? WebGL是在浏览器中实现三维效果的一套规范 想要使用...

    Jacendfeng 评论0 收藏0
  • three.js学习笔记】渲染器

    摘要:使用将能够利用硬件加速从而提高渲染性能。这个渲染器比渲染器有更好的性能。声明构造器是一个可选对象,包含用来定义渲染器行为的属性。所用的渲染上下文对象。设置背景色和背景色透明度渲染器渲染器不使用来绘制场景,而使用相对较慢的。 渲染器api WebGL渲染器(WebGLRenderer) WebGL渲染器使用WebGL来绘制您的场景,如果您的设备支持的话。使用WebGL将能够利用GPU硬...

    刘玉平 评论0 收藏0

发表评论

0条评论

elina

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<