编写程序实现逆波兰运算_three - exp 射线实现及其原理

点选模型是在webgl技术交流群里常被问到一个问题;这里做一个总结

本文一是提供three 基本实现demo,二是从webgl底层去做射线简单实现 ,三是介绍其简单数学原理;

一、three实现

在线demo:

Exp -- rayTest​thinkia.github.io

源码地址

https://github.com/Thinkia/three-Effect/blob/master/examples/exp/ray/rayTest.html​github.com

二、 thinkgl实现

在线demo:

rayTest​thinkia.github.io

源码地址:

https://github.com/Thinkia/thinkgl/blob/master/example/tutorial/ray/rayTest.js​github.com

三、数学介绍

  1. 点击屏幕获取单位屏幕二维坐标;

let x =( event.clientX / window.innerWidth ) * 2 - 1;
let y = - ( event.clientY / window.innerHeight ) * 2 + 1;
let vec = [ x,y,0.5 ];

2.乘投影矩阵的逆获取单位向量

let inversePMat = ia.thinkMath.mat4.getInverse( pMat );


ia.thinkMath.vec3.applyMat4( vec,inversePMat );

前面两点是三维成像原理的逆过程,这里不细说了;

3. 三维向量与三角面是否有交点?

a.三维向量与平面关系无非是平行和相交

b.如果向量与平面的交点为d , 三角面顶点分别为a,b,c;

c.如果向量与平面有交点必然有 Sabd + Sadc + Sdbc - Sabc < 0.0001

三角形面积用海伦公式, 平面方程用待定系数法;

向量与平面交点可参考

22d5c7f879e06c1b7a3eeaacdcfb0608.png

上面过程主要使用向量运算,巧妙避开了求模运算中的开方运算,减少了很多的运算量,而且,容易步骤化,易于编程实现。

编程实现: intersectionLinePlane(origin,vec,pointA,pointB,pointC)

/** * * @param p1 射线起始点 * @param p2 射线终点 * @param pointA 三角面片 顶点A * @param pointB 三角面片 顶点B * @param pointC 三角面片 顶点C * @returns {boolean} * */
intersectionLinePlane:function ( p1,p2,pointA,pointB,pointC ) {
let pointD =[];
let p1p2 = [ p2[0]-p1[0],p2[1]-p1[1],p2[2]-p1[2] ];

// 平面方程
let PE = ia.thinkMath.vec3.planeEquation( pointA,pointB,pointC );
let num = PE.A * p1[0] + PE.B * p1[1] + PE.C * p1[2] + PE.D ;
let den = PE.A * p1p2[0] + PE.B * p1p2[1] + PE.C*p1p2[2];
// 平行 与法向量垂直
if( Math.abs(den) <1e-5 ) return false ;
let n = -num/den ;
for( let i=0;i<3;i++) pointD[i] = p1[i] + n*p1p2[i];
// ABC 面积
let s0 = ia.thinkMath.vec3.triangleArea( pointA,pointB,pointC );
// DAB 面积
let s1 = ia.thinkMath.vec3.triangleArea( pointD,pointB,pointC );
// DBC 面积
let s2 = ia.thinkMath.vec3.triangleArea( pointA,pointD,pointC );
// DCA 面积
let s3 = ia.thinkMath.vec3.triangleArea( pointA,pointB,pointD);
if( Math.abs( (s1+s2+s3 -s0)) < 1e-6 )
{
console.log(`射线交点坐标:${pointD}` ) ;
return true;
} else
return false;
},

感谢您的阅读,如有谬误或者不当之处还请指正;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值