拾取模型的原理及其在THREE.JS中的代码实现
1. Three.js中的拾取
1.1. 从模型转到屏幕上的过程说开
由于图形显示的基本单位是三角形,那就先从一个三角形从世界坐标转到屏幕坐标说起,例如三角形abc
乘以模型视图矩阵就进入了视点坐标系,其实就是相机所在的坐标系,如下图:
进入视点坐标系后,再乘以投影矩阵,就会变换到一个立方体内,如下图:
这个时候整个三角形就位于中心位于坐标系原点,边长为2的立方体内,在这个立方体内,三角形要计算光照,要裁剪,然后乘以视口矩阵,最后转到屏幕上。
转到屏幕上后,三角形的所有点的Z坐标就是深度坐标,一定在(0, 1)这个区间内,那么哪些点的Z坐标是0呢,在投影坐标系中,一定是投影视景体的前剪切平面上的点,而投影视景体的后剪切平面上的点的Z坐标就是1。
1.2. 思路来了
根据以上三角形转换到屏幕坐标上的过程可以分析出,鼠标在屏幕上点击的时候,可以得到二维坐标p(x, y),再加上深度坐标的范围(0, 1), 就可以形成两个三位坐标A(x, y, 0), B(x, y, 1), 由于它们的Z轴坐标是0和1,则转变到投影坐标系的话,一定分别是前剪切平面上的点和后剪切平面上的点,也就是说,在投影坐标系中,A点一定在能看见的所有模型的最前面,B点一定在能看见的所有的模型的最后边,假设视口矩阵的逆矩帧,投影矩阵的逆矩阵,模型视图矩阵的逆矩阵为M, N, P,则 P * N * M * A = A1, P * N * M * B = B1, 在世界坐标系中,点A1B1就可以形成一个射线,此射线和模型再求交,就能选中模型。如下图是在视点坐标系中的情形。注意,求交可以在视点坐标系或者世界坐标系计算都可以,但一般会在世界坐标坐标系中计算。
1.3. 拾取的优化,射线和AABB包围盒求交
如果射线和所有的模型求交,显然不是一个好办法,一般情况下会进行一些优化,比如先和模型的包围盒求交,如果和模型的包围盒不相交的话,就放过去,否则就接着往下进行,和模型的所有三角面片求交。
那么什么是包围盒呢?在计算机图形学与计算几何领域,一组物体的包围体就是将物体组合完全包容起来的一个封闭空间。将复杂物体封装在简单的包围体中,就可以提高几何运算的效率。通常简单的物体比较容易检查相互之间的重叠。其中有一种包围盒叫做AABB, AABB的全称是axis aligned bounding box,就是我们常常提到轴向包围盒,这个盒子的边是平行于x/y/z轴的。 所有的2d和3d物体都是由点组成的,所以只要找出这些物体的最大值点和最小值点,那么就可以使用这两个点表示该物体的AABB包围盒了。
检测碰撞的时候我们只需要检测这些物体的AABB(即他们的最大值点和最小值点)是否相交,就可以判断是否碰撞了。
1.4. 射线和三角形相交
判断射线和包围盒是否求交后,就轮到判断是否和三角形求交了,最先想到的是 首先判断射线是否与三角形所在的平面相交,如果相交,再判断交点是否在三角形内。判断射线是否与平面相交, 判断点是否在三角形内.
1.5. THREE.JS中求交的代码实现
three.js中的一个案例,名字叫webgl_interactive_lines.html,可以选中一根线,并显示一个小球。根据以上的思路,代码注释如下:
//鼠标点击的屏幕坐标转换到视点坐标系
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 ).unproject( camera );
//在视点坐标系中形成射线
raycaster.set( camera.position,vector.sub( camera.position ).normalize() );
//射线和模型求交,选中一系列直线
var intersects = raycaster.intersectObjects( parentTransform.children, true);
if ( intersects.length > 0 ) {
if ( currentIntersected !== undefined )
{
currentIntersected.material.linewidth = 1;
}
//第一个直线
currentIntersected = intersects[ 0 ].object;
currentIntersected.material.linewidth = 5;
//把球设为可见,并且位置移到鼠标点击的屏幕位置
sphereInter.visible = true;
sphereInter.position.copy( intersects[ 0 ].point );
}
交流图形学的一切,尤其是大型程序的设计,每天有原创文章
微信公众号: GraphicsPlatform
qq群: 559684273
qq: 1829634717
拾取模型的原理及其在THREE.JS中的代码实现的更多相关文章
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...
- 【JavaScript】JS中没有代码块的概念
<script> var m = "roboce"; if(m === "roboce"){ var k = "haha"; } ...
- js中深拷贝代码实现
function copy(original,o){ if(typeof original != 'object') return original; var o = o || (Array.isAr ...
- WebGL射线拾取模型——八叉树优化
经过前面2篇WebGL射线拾取模型的文章,相信大家对射线和模型面片相交的原理已经有所了解,那么今天我们再深入探究关于射线拾取的一个问题,那就是遍历场景中的所有与射线相交的模型的优化问题.首先我们来复习 ...
- 在 Node.js 中引入模块:你所需要知道的一切都在这里
本文作者:Jacob Beltran 编译:胡子大哈 翻译原文:http://huziketang.com/blog/posts/detail?postId=58eaf471a58c240ae35bb ...
- JS中window.document对象
小知识点注:外面双引号,里面的双引号改为单引号: 在div里面行高设置和整个外面高度一样,才能用竖直居中,居中是行居中 文本框取出来 ...
- js中匿名函数
今天碰到一道题,里面既包含了匿名函数的知识,也包含了预编译,函数的传参(形参),感觉迷迷糊糊的,所以想着做个总结. var foo={n:1}; (function(foo){ console.log ...
- JS中同步显示并分割输入的数字字符串
题目比较晦涩,来张图来说明要表达的效果: 第一张图的效果就是,用户输入一个数字,上面就显示一个大层,然后显示输入的数字,并把数字用空格按照每四位分割出来.好像在建行的网上银行上面就有这种效果.第二个图 ...
- JS基础_代码块
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- JSTL标签库之核心标签
一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...
- 学习Linux系列--安装软件环境
本系列文章记录了个人学习过程的点点滴滴. 回到目录 10.安装Lamp套件. 最简单的方式,如下 sudo tasksel install lamp-server Apache 菜鸟教程 Ubuntu ...
- Submit Text 快捷键总结
Ctrl+D : 选择单词,重复可增加选择下一个相同的单词Ctrl+F : 查找内容Ctrl+G : 跳转到指定行Ctrl+H : 替换 Ctrl+J : 合并行(已选择需要合并的多行时)Ctr ...
- CSU 1660 K-Cycle(dfs判断无向图中是否存在长度为K的环)
题意:给你一个无向图,判断是否存在长度为K的环. 思路:dfs遍历以每一个点为起点是否存在长度为k的环.dfs(now,last,step)中的now表示当前点,last表示上一个访问的 点,step ...
- 一个ubuntu phper的自我修养(ubuntu安装)
ubuntu安装篇 一.ubuntu下载 到ubuntu官网下载适合自己电脑配置的系统版本,此处不做展开. 二.制作USB启动盘 在windows下制作USB启动盘,工具是universal usb ...
- 关于sql中join
对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...
- [Machine-Learning] 熟悉 Matlab 中的 map
概述 map 的意思是映射,即将一个变量映射到另一个变量. 比如将一个字符串映射为一个数值,那个字符串就是map 的键值(key),数值就是map的数据(value). 由此可以把map理解为一个哈希 ...
- Javascript > Eclipse > 自动代码规范化
Reference: http://blog.csdn.net/jmyue/article/details/11060003 大项目往往是有很多人一起完成的,然而每个人都有自己的style,导致整个项 ...
- linux下发现可疑用户时处理办法
如果发现了linux被可疑用户远程登录了,怎么解决呢? 1.先查看最近系统的登录情况 last -10 表示最近10个用户登录的信息,如果发现有可疑账户,就是密码被破解了 [root@localhos ...
- vchar2和nvchar2
Oracle中varchar2 nvarchar2 VARCHAR2(size),可变长度的字符串,其最大长度为 size 个字节.size 的最大值是 4000,而最小值是 1.您必须指定一个 VA ...