前言
之前做了一期关于B站的视频,反响效果还不错。感谢各位小伙伴的支持,但是我是个追求原理的工程师, three.js 射线检测到底是怎么去实现的,我🤔还是决定用简短的时间,带大家回顾下。到底是怎么实现的,本篇文章阅读大概5分钟你就能掌握。
背景
如何知道鼠标所在位置是否存在图形,转换问题角度来看可以看做从鼠标所处位置发出一根射线,这根射线是否与三角形相交,换而言之即为「鼠标所在位置在一个三角形内是否存在投影的一点?」
投影图
思路解析
根据上述描述可知,我们的真实需求是需要判断鼠标所在位置是否在三角形内,这里我们介绍一个最快的方法,我们可以以鼠标所在点为origin,三角形a,b,c三点作为条件
步骤1
(设置前置变量,计算点origin到三角形顶点向量与三条边的向量):
image-20210811210122868
步骤2
(计算点到边与边的叉积):
image-20210811210157500
步骤3
(判断3个叉积值是否同向):若 P1,P2,P3P_1,P_2,P_3P1,P2,P3 的正负号一致,则说明射线与三角形相交
解释说明
向量的叉乘可判断向量方向,以 P1P_1P1 这个结果为例,若为0说明共线,若小于0垂直向内,若大于0说明垂直向外,一个点是否在三角形内部可以分别计算三个叉乘结果,如果在三角形内部则必定说明三个方向一定正负同号,异号则表示点在某条边的另外一侧
其他方法
- 判断某一点在三角形还有「重心坐标表示法」,该种解法是构造以鼠标为起点发出的射线,方向为正的参数方程,如果射线与三角形相交,则说明三角形内必有一点为三角形与射线的交点,需要联立射线参数方程与三角形重心坐标参数方程做等式求解,此处不另外展开说明
- 通常在求解鼠标所在位置是否存在图形时,不会采用直接求解射线与三角形是否相交的解法,因为一个复杂的几何表示可能有几千上万个三角形面片,计算量太大影响性能,通常会「采用包围盒计算方法」,虽然存在一定误差,但是能够大量的减少计算,性能十分可观