ThreeJS中的点击与交互——Raycaster的用法
基础概念
坐标系
我们的手机屏幕是二维的,但是我们展示物体的世界是三维的,当我们在构建一个物体的时候我们是以一个三维世界既是世界坐标来构建,而转化为屏幕坐标展示在我们眼前,则需要经历多道矩阵变化,中间webGL替我们操作了许多事情。
世界坐标系:在webGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角
坐标为(1,1)。屏幕坐标系:
webGL的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。视点坐标系:
是以视点(照相机)为原点,以视线的方向为Z+轴正方向的坐标系中的方向。webGL会将世界坐标先变换到视点坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。
Raycaster
这个类设计用于鼠标去获取在3D世界被鼠标选中的一些物体
Raycaster( origin, direction, near, far ) origin — 射线的起点向量。
direction — 射线的方向向量,应该归一标准化。
near — 所有返回的结果应该比 near 远。Near不能为负,默认值为0。
far — 所有返回的结果应该比 far 近。Far 不能小于 near,默认值为无穷大。
找到点击物体的大致思路
鼠标在屏幕上点击的时候,得到二维坐标p(x, y),再加上深度坐标的范围(0, 1), 就可以形成两个三位坐标A(x1, y1, 0), B(x2, y, 1), 由于它们的Z轴坐标是0和1,则转变到投影坐标系的话,一定分别是前剪切平面上的点和后剪切平面上的点,也就是说,在投影坐标系中,A点一定在能看见的所有模型的最前面,B点一定在能看见的所有的模型的最后边,将AB点连成线,AB线穿过的物体就是被点击的物体。而 Three.js提供一个射线类Raycasting来拾取场景里面的物体。更方便的使用鼠标来操作3D场景。(不过在实际代码中我们组成射线的两个点是摄像机所在视点与屏幕上点击的点连接而成的射线)
代码实现
//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
//新建一个三维单位向量 假设z方向就是0.5
//根据照相机,把这个向量转换到视点坐标系
var vector = new THREE.Vector3(mouse.x, mouse.y,0.5).unproject(camera); //在视点坐标系中形成射线,射线的起点向量是照相机, 射线的方向向量是照相机到点击的点,这个向量应该归一标准化。
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); //射线和模型求交,选中一系列直线
var intersects = raycaster.intersectObjects(objects);
console.log('imtersrcts=' + intersects) if (intersects.length > 0) {
//选中第一个射线相交的物体
SELECTED = intersects[0].object;
var intersected = intersects[0].object;
console.log(intersects[0].object)
} }
代码释义
//得到
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1; 推导过程:
设A点为点击点(x1,y1),x1=e.clintX, y1=e.clientY
设A点在世界坐标中的坐标值为B(x2,y2); 由于A点的坐标值的原点是以屏幕左上角为(0,0);
我们可以计算可得以屏幕中心为原点的B'值
x2' = x1 - innerWidth/2
y2' = innerHeight/2 - y1
又由于在世界坐标的范围是[-1,1],要得到正确的B值我们必须要将坐标标准化
x2 = (x1 -innerWidth/2)/(innerwidth/2) = (x1/innerWidth)*2-1
同理得 y2 = -(y1/innerHeight)*2 +1
参考资料
Three.js中的拾取
OpenGL中各种坐标系的理解
threejs对象拾取
《计算机图形学》
前端填坑指南
ThreeJS中的点击与交互——Raycaster的用法的更多相关文章
- Android中webView和网页的交互
Android中webView和网页的交互 Android中webView跟网页的交互式通过JavaScript进行的.具体步骤: 1.创建JavaScript,在点击的时候调用JavaScript ...
- Threejs 的场景查看 - 几个交互事件库助你方便查看场景
Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- asp.net中javascript与后台c#交互
asp.net中javascript与后台c#交互 作者:熊猫大叔 字体:[增加 减小] 类型:转载 时间:2015-10-23我要评论,出处:http://www.jb51.net/article/ ...
- iOS中web与Js的交互
问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...
- 转 threejs中3D视野的缩放实现
Threejs基础部分学习知道透视相机new THREE.PerspectiveCamera(fov, aspect , near,far)中. fov视野角(拍摄距离)越大,场景中的物体越小.fov ...
- [转]iOS Safari 中click点击事件失效的解决办法
iOS Safari 中click点击事件失效的解决办法 问题起因: 在微信公众号开发(微站)过程中用jquery的live方法绑定的click事件点击无效(不能执行) 问题描述 当使用委托给一个元素 ...
- Android中Listview点击item不变颜色以及设置listselector 无效
Android中Listview点击item不变颜色以及设置listselector 无效 这是同一个问题,Listview中点击item是会变颜色的,因为listview设置了默认的listsele ...
- android ListView中button点击事件盖掉onItemClick解决办法
ListView 1.在android应用当中,很多时候都要用到listView,但如果ListView当中添加Button后,ListView 自己的 public void onItemClick ...
- 微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone)
微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone) 前言: 这是小菜博客的第三篇文章.一直认为自己可以表达的东西太过简单,难以上台面,总是吝啬地不肯写.就算是写,也不知道从何开始.在同事的 ...
随机推荐
- [ SHELL编程 ] 编程常用的ORACLE相关命令
本文主要描述shell编程中常用的Oracle相关命令. 1.sqlplus -L/-S参数 sqlplus -L user/password #-L参数表示用户只尝试登录一次, 而不是在出错时再次提 ...
- Linux IP和网关配置
操作环境 SuSE11/SuSE10 配置方法一<永久有效,重启不失效> 通过修改/etc/sysconfig/network/ifcfg-eth*文件直接配置,服务器重启不失效,建议使用 ...
- scala case类
case类 case class Person(name:String) case 类有如下特点: 1. 构造参数默认是 val 的. 2. case 类实例化对象的时候,不需要 new 关键字.因为 ...
- easyui中的几个问题
easyui中的tree,采用url参数读取json,无法显示.有可能是vs的IIS不支持,$.ajax 原因待测试,有知道的朋友也可以贴代码,我解决的一个办法是 $(function () { $. ...
- WPF 中关于 DataTemplateSelector 类的应用
MSDN的解释: 提供一种根据数据对象和与该数据绑定的元素来选择数据模板 DataTemplate 的方法. 示例代码: <Window x:Class="WpfApplication ...
- swift和OC中frame的小差异
//1.0 OC中 CGRect .CGPoint.CGSize 的结构如下: struct CGRect { CGPoint origin; CGSize size; }; struct CGPoi ...
- 吴裕雄 python神经网络 花朵图片识别(9)
import osimport numpy as npimport matplotlib.pyplot as pltfrom PIL import Image, ImageChopsfrom skim ...
- JAVA语言 第四周
oh my god! 说实话,上周的目标没有完成. 这一周过的太随便了,比刚放假时候的热情减少的太多了. 具体干了啥,就不说了吧.好像什么完整的事都没有干~~~~~ 不过一直在完善代码,已经能实现部分 ...
- ABAP 自定义排序的思想(不用系统标准的SORT语句)
不用ABAP的标准SORT语句,你能将下面这个数组按从小到大(或从大到小)的顺序重新排列,并计算其算法复杂度吗? 现在假设有一个数组:A = [10,66,52,102,-65,85,99,1,56, ...
- getHibernateTemplate()的用法 (转)
在spring 中获得由spring所配置的hibernate的操作对象,然后利用此对象进行,保存,修改和删除等操作, 此方法是在配置了spring以后,hibernate由spring接管,不直接使 ...