基础概念

坐标系

我们的手机屏幕是二维的,但是我们展示物体的世界是三维的,当我们在构建一个物体的时候我们是以一个三维世界既是世界坐标来构建,而转化为屏幕坐标展示在我们眼前,则需要经历多道矩阵变化,中间webGL替我们操作了许多事情。

  • 世界坐标系:在webGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角
    坐标为(1,1)。

  • 屏幕坐标系:
    webGL的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。

  • 视点坐标系:
    是以视点(照相机)为原点,以视线的方向为Z+轴正方向的坐标系中的方向。webGL会将世界坐标先变换到视点坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。

Raycaster

Raycaster threeJs官方文档

这个类设计用于鼠标去获取在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场景。(不过在实际代码中我们组成射线的两个点是摄像机所在视点与屏幕上点击的点连接而成的射线)

来一个Raycasting的官方实例

代码实现

  //将鼠标点击位置的屏幕坐标转成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的用法的更多相关文章

  1. Android中webView和网页的交互

     Android中webView和网页的交互 Android中webView跟网页的交互式通过JavaScript进行的.具体步骤: 1.创建JavaScript,在点击的时候调用JavaScript ...

  2. Threejs 的场景查看 - 几个交互事件库助你方便查看场景

    Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...

  3. asp.net中javascript与后台c#交互

    asp.net中javascript与后台c#交互 作者:熊猫大叔 字体:[增加 减小] 类型:转载 时间:2015-10-23我要评论,出处:http://www.jb51.net/article/ ...

  4. iOS中web与Js的交互

    问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...

  5. 转 threejs中3D视野的缩放实现

    Threejs基础部分学习知道透视相机new THREE.PerspectiveCamera(fov, aspect , near,far)中. fov视野角(拍摄距离)越大,场景中的物体越小.fov ...

  6. [转]iOS Safari 中click点击事件失效的解决办法

    iOS Safari 中click点击事件失效的解决办法 问题起因: 在微信公众号开发(微站)过程中用jquery的live方法绑定的click事件点击无效(不能执行) 问题描述 当使用委托给一个元素 ...

  7. Android中Listview点击item不变颜色以及设置listselector 无效

    Android中Listview点击item不变颜色以及设置listselector 无效 这是同一个问题,Listview中点击item是会变颜色的,因为listview设置了默认的listsele ...

  8. android ListView中button点击事件盖掉onItemClick解决办法

    ListView 1.在android应用当中,很多时候都要用到listView,但如果ListView当中添加Button后,ListView 自己的 public void onItemClick ...

  9. 微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone)

    微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone) 前言: 这是小菜博客的第三篇文章.一直认为自己可以表达的东西太过简单,难以上台面,总是吝啬地不肯写.就算是写,也不知道从何开始.在同事的 ...

随机推荐

  1. vue项目动态控制数据变动时箭头样式

    html代码 <div class="top_precent"> <span :class="{arrow:numPrecent<0}" ...

  2. mybatis实现一对多连接查询

    问题:两个对象User和Score,它们之间的关系为一对多. 底层数据库为postgresql,ORM框架为mybatis. 关键代码如下: mybatis配置文件如下: mybatis.xml文件内 ...

  3. Java模板引擎之freemarker简介

  4. C# Excel To DataTable

    原地址忘了 需引用NPOI,引用方法:项目引用那儿右键 => 管理NuGet程序包 => 游览 =>输入NPOI =>选中NPOI后安装(一般是第一个) /// <sum ...

  5. C# Excel转换为Json

    demo:https://files.cnblogs.com/files/guxingy/Excel%E8%BD%AC%E6%8D%A2%E4%B8%BAJson%E5%AF%B9%E8%B1%A1. ...

  6. 学JS的心路历程-函式(二)arguments

    参数(argument)与函式参数(parameter) 在讨论函式时,很多人都会把这两个搞混,我自己也不例外. 虽然讲错别人也听得懂,但是我们还是要搞清楚这两个的定义到底是什么! 参数是当我们呼叫函 ...

  7. u-boot 内核 启动参数

    kernel如何得到uboot启动信息: http://blog.sina.com.cn/s/blog_89d9bec60101bzen.html u-boot向linux内核传递启动参数: http ...

  8. Shell 处理文件名中包含空格的文件

    最近在学Gradle, 使用git clone 命令下载了一些资料,但是文件名含有空格,看上去不是很舒服,因此想到用shell脚本对其进行批处理,去掉文件名中的空格,注意这里是把所有的空格全去掉 gi ...

  9. linux系统上项目部署

    步骤:(特别注意:虚拟机安装的一般是32位的操作系统,jdk也必须使用32位的)查看虚拟机版本:sudo uname --m i686 //表示是32位 x86_64 // 表示是64位 查看是否已经 ...

  10. 从源码安装Node

    [从源码安装Node] Nodejs官网未并提供i686架构的bin,为了在i686架构cpu下使用Nodejs,需要从源码编译. 1../configure 2.make 3.make instal ...