ARCore中根据屏幕坐标计算射线的算法

ARCore中提供了根据屏幕坐标、视口大小及view、 project矩阵计算从屏幕坐标发射一条射线的方法,此方法用于3D拾取。

 1 class Ray {
 2 
 3     public final Vector3f origin;//射线起点
 4     public final Vector3f direction;//射线方向
 5 
 6     public Ray(Vector3f origin, Vector3f direction) {
 7         this.origin = origin;
 8         this.direction = direction;
 9     }
10 
11     //根据屏幕坐标计算射线——3D拾取
12     public static Ray screenPointToRay(Vector2f point, Vector2f viewportSize, float[] viewProjMtx) {
13         point.y = viewportSize.y - point.y;//转化为左下角为原点
14         float x = point.x * 2.0F / viewportSize.x - 1.0F;//转换到[-1,1]
15         float y = point.y * 2.0F / viewportSize.y - 1.0F;//转换到[-1,1]
16 
17         float[] farScreenPoint = new float[]{x, y, 1.0F, 1.0F};//远平面上的坐标透视除法之后的值
18         float[] nearScreenPoint = new float[]{x, y, -1.0F, 1.0F};//近平面上的坐标透视除法之后的值
19 
20         float[] nearPlanePoint = new float[4];//用于记录世界坐标系下,近平面上的点
21         float[] farPlanePoint = new float[4];//用于记录世界坐标系下,远平面上的点
22 
23         float[] invertedProjectionMatrix = new float[16];
24         Matrix.setIdentityM(invertedProjectionMatrix, 0);
25         Matrix.invertM(invertedProjectionMatrix, 0, viewProjMtx, 0);//计算逆矩阵
26 
27         Matrix.multiplyMV(nearPlanePoint, 0, invertedProjectionMatrix, 0, nearScreenPoint, 0);//计算世界坐标系中,对应到近平面的坐标
28         Matrix.multiplyMV(farPlanePoint, 0, invertedProjectionMatrix, 0, farScreenPoint, 0);
29 
30         Vector3f direction = new Vector3f(farPlanePoint[0] / farPlanePoint[3], farPlanePoint[1] / farPlanePoint[3], farPlanePoint[2] / farPlanePoint[3]);
31         Vector3f origin = new Vector3f(new Vector3f(nearPlanePoint[0] / nearPlanePoint[3], nearPlanePoint[1] / nearPlanePoint[3], nearPlanePoint[2] / nearPlanePoint[3]));
32         direction.sub(origin);
33         direction.normalize();
34         return new Ray(origin, direction);
35     }   
36 }

 

原理:

一、世界坐标系的点P1转化到投影空间得到点P2的公式是:P2 = P1 * viewMatrix * projectMatrix = P1 * viewProjMatrix;

在渲染管线中,投影空间的点还需要经过透视除法,转化到x , y , z值均为[-1,1]区间内,是一个单位立方体。公式是:point_clip = P2/P2.w;

 

那么将点从单位立方体坐标系转化到世界坐标系的公式跟上述情况是逆过程,公式:

P2 = point_clip * wValue;
P1 = P2 * viewProjMatrix_invert;

其中wValue代表给定的w值,在ARCore中此值为1,所以并未体现在代码中。

 

二、上面代码片段,是将屏幕上的点的x,y坐标值均转化到[-1,1],给定近裁剪平面的点的z为-1,远裁剪平面上的点的z为1,其w值均为1,这种方法得到透视除法后单位立方体中的坐标。

因为wValue为1,所以此时farScreenPoint和nearScreenPoint就代表投影空间中的坐标点。

然后根据(一)中的结论即可得到对应到世界坐标系的坐标点,根据两个点可得到射线方法,最终即可得到射线的起点和方向。

posted on 2017-09-07 12:03 bky2016 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/calence/p/7489019.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值