拾取模型的原理及其在THREE.JS中的代码实现

时间:2022-08-28 21:22:48

1. Three.js中的拾取 

1.1. 从模型转到屏幕上的过程说开

由于图形显示的基本单位是三角形,那就先从一个三角形从世界坐标转到屏幕坐标说起,例如三角形abc

拾取模型的原理及其在THREE.JS中的代码实现

乘以模型视图矩阵就进入了视点坐标系,其实就是相机所在的坐标系,如下图:

拾取模型的原理及其在THREE.JS中的代码实现

进入视点坐标系后,再乘以投影矩阵,就会变换到一个立方体内,如下图:

拾取模型的原理及其在THREE.JS中的代码实现

这个时候整个三角形就位于中心位于坐标系原点,边长为2的立方体内,在这个立方体内,三角形要计算光照,要裁剪,然后乘以视口矩阵,最后转到屏幕上。

拾取模型的原理及其在THREE.JS中的代码实现

转到屏幕上后,三角形的所有点的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就可以形成一个射线,此射线和模型再求交,就能选中模型。如下图是在视点坐标系中的情形。注意,求交可以在视点坐标系或者世界坐标系计算都可以,但一般会在世界坐标坐标系中计算。

拾取模型的原理及其在THREE.JS中的代码实现

1.3. 拾取的优化,射线和AABB包围盒求交

如果射线和所有的模型求交,显然不是一个好办法,一般情况下会进行一些优化,比如先和模型的包围盒求交,如果和模型的包围盒不相交的话,就放过去,否则就接着往下进行,和模型的所有三角面片求交。

那么什么是包围盒呢?在计算机图形学与计算几何领域,一组物体的包围体就是将物体组合完全包容起来的一个封闭空间。将复杂物体封装在简单的包围体中,就可以提高几何运算的效率。通常简单的物体比较容易检查相互之间的重叠。其中有一种包围盒叫做AABB, AABB的全称是axis aligned bounding box,就是我们常常提到轴向包围盒,这个盒子的边是平行于x/y/z轴的。 所有的2d和3d物体都是由点组成的,所以只要找出这些物体的最大值点和最小值点,那么就可以使用这两个点表示该物体的AABB包围盒了。
       检测碰撞的时候我们只需要检测这些物体的AABB(即他们的最大值点和最小值点)是否相交,就可以判断是否碰撞了。

拾取模型的原理及其在THREE.JS中的代码实现

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中的代码实现的更多相关文章

  1. paip.编程语言方法重载实现的原理及python,php,js中实现方法重载

    paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...

  2. 【JavaScript】JS中没有代码块的概念

    <script> var m = "roboce"; if(m === "roboce"){ var k = "haha"; } ...

  3. js中深拷贝代码实现

    function copy(original,o){ if(typeof original != 'object') return original; var o = o || (Array.isAr ...

  4. WebGL射线拾取模型——八叉树优化

    经过前面2篇WebGL射线拾取模型的文章,相信大家对射线和模型面片相交的原理已经有所了解,那么今天我们再深入探究关于射线拾取的一个问题,那就是遍历场景中的所有与射线相交的模型的优化问题.首先我们来复习 ...

  5. 在 Node&period;js 中引入模块:你所需要知道的一切都在这里

    本文作者:Jacob Beltran 编译:胡子大哈 翻译原文:http://huziketang.com/blog/posts/detail?postId=58eaf471a58c240ae35bb ...

  6. JS中window&period;document对象

    小知识点注:外面双引号,里面的双引号改为单引号:                  在div里面行高设置和整个外面高度一样,才能用竖直居中,居中是行居中                  文本框取出来 ...

  7. js中匿名函数

    今天碰到一道题,里面既包含了匿名函数的知识,也包含了预编译,函数的传参(形参),感觉迷迷糊糊的,所以想着做个总结. var foo={n:1}; (function(foo){ console.log ...

  8. JS中同步显示并分割输入的数字字符串

    题目比较晦涩,来张图来说明要表达的效果: 第一张图的效果就是,用户输入一个数字,上面就显示一个大层,然后显示输入的数字,并把数字用空格按照每四位分割出来.好像在建行的网上银行上面就有这种效果.第二个图 ...

  9. JS基础&lowbar;代码块

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. jdk 环境变量配置

    环境变量:Path %JAVA_HOME%\bin;%JAVA_HOME%\jre\binCLASSPATH .;%JAVA_HOME%\lib;JAVA_HOME D:\java\jdk1.5.0_ ...

  2. struts 异常机制

    1.try-catch 在Action中通过try-catch捕获异常,在catch中返回字符串, 通过返回的字符串在Action的result元素中进行匹配,最终返回响应的页面 2. 局部异常映射 ...

  3. &period;NET使用Com组件的一点点教训笔记~

    中控IFACE系列的产品,二次开发包 zkemkeeper.dll 在system32 ,SySWoW64都注册了,就是他妈的用不了. 最后,在 system32 ,SySWoW64 注册了,然后把需 ...

  4. Fortran向C传递NULL值

    在很多C或C++的头文件定义中,NULL被指定定义为0,这里不再具体展开 gfortran的手册关于iso c binding的章节,定义NULL如下 Moreover, the following ...

  5. Struts2返回JSON对象的方法总结

    如果是作为客户端的HTTP+JSON接口工程,没有JSP等view视图的情况下,使用Jersery框架开发绝对是第一选择.而在基于Spring3 MVC的架构下,对HTTP+JSON的返回类型也有很好 ...

  6. 选择问题&lpar;选出第i个最小元素&rpar;

    通过分治法解决的分析(还有其他方法解决选择问题如使用 堆) 1 同快速排序一样,对输入的数组进行递归分解 不同的是:快速排序会递归处理分解的两边,而选择问题只处理需要的一边 2 选择问题的期望时间代价 ...

  7. 严重&colon; The web application &lbrack;&rsqb; registered the JDBC driver 错误

    近日发现启动tomcat的时候报如下警告: -- :: org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc 严重: The ...

  8. go语言的安装和配置,以及包引用

    1.下载和安装 首先大家可以去官网下载 http://golang.org/dl/ 如果官网你看不懂的话,可以到这里下载: http://golangtc.com/download ,这里也提供了百度 ...

  9. Objective-C探究alloc方法的实现

    OS X,iOS中的大部分作为开源软件公开在 Apple Open Source 上.虽然想让大家参考NSObject类的源代码,但是很遗憾,包含NSObject类的Foundation框架没有公开. ...

  10. hihocoder 1015题

    代码 #include <iostream> #include <string> #include <typeinfo> #include <vector&g ...