拾取模型的原理及其在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> ...
随机推荐
- vs2010取消显示所有文件 崩溃
这属于vs2010的bug,以下是微软官方对些问题的回应: i am still investigating the problem, but looks like the issue is caus ...
- GreenDao关系建表
关系 在greenDAO,实体涉及使用一对一或一对多的关系.例如,如果要模拟一个1:greenDAOñ关系,你将有一个一对一和一对多的关系.但是,请注意,一对一和一对多的关系不是相互连接,所以你必须同 ...
- 第七章 Hibernate性能优化
一对一关联 实体类关系 一对多 多对多 一对一 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方 ...
- xcode8+iOS10问题
.xcode升级到8.0后打印的问题 ()xcode8会打印一些莫名其妙的log 解决方法:Scheme里面添加OS_ACTIVITY_MODE = disable ()xcode8打印log不完整 ...
- SQL Server 取日期时间部分
在本文中,GetDate()获得的日期由两部分组成,分别是今天的日期和当时的时间: Select GetDate() 用DateName()就可以获得相应的年.月.日,然后再把它们连接起来就可以了: ...
- centos6.6_64位操作系统安装时候出现kernel panic - not syncing: Attempted to kill init 解决办法
最近在VM上安装centos时候经常被这个问题虐,后来进入单用户模式在 kernel /vmlinuz-XXXXro root=/dev/vogroup00/logvol00 rhgb quie ...
- python之初级学习
一.python安装 1.下载安装包(本人使用python3.5.1) https://www.python.org/downloads/ 2.安装python-3.5.1.exe 本人下载的是pyt ...
- [OC]UILabel 文字长的截断方式
Tip: 参考文档:http://blog.csdn.net/reylen/article/details/21012859 @property(nonatomic) NSLineBreakMode ...
- PHP: 深入pack/unpack
https://my.oschina.net/goal/blog/195749 PHP作为一门为web而生的服务器端开发语言,被越来越多的公司所采用.其中不乏大公司,如腾迅.盛大.淘米.新浪等.在对性 ...
- php 5.3新增的闭包语法介绍function() use() {}
* 下面提到的代码在PHP5.3以上版本运行通过. */function callback($callback) { $callback();}//输出: This is a anonymous fu ...