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

 class Ray {

     public final Vector3f origin;//射线起点
public final Vector3f direction;//射线方向 public Ray(Vector3f origin, Vector3f direction) {
this.origin = origin;
this.direction = direction;
} //根据屏幕坐标计算射线——3D拾取
public static Ray screenPointToRay(Vector2f point, Vector2f viewportSize, float[] viewProjMtx) {
point.y = viewportSize.y - point.y;//转化为左下角为原点
float x = point.x * 2.0F / viewportSize.x - 1.0F;//转换到[-1,1]
float y = point.y * 2.0F / viewportSize.y - 1.0F;//转换到[-1,1] float[] farScreenPoint = new float[]{x, y, 1.0F, 1.0F};//远平面上的坐标透视除法之后的值
float[] nearScreenPoint = new float[]{x, y, -1.0F, 1.0F};//近平面上的坐标透视除法之后的值 float[] nearPlanePoint = new float[4];//用于记录世界坐标系下,近平面上的点
float[] farPlanePoint = new float[4];//用于记录世界坐标系下,远平面上的点 float[] invertedProjectionMatrix = new float[16];
Matrix.setIdentityM(invertedProjectionMatrix, 0);
Matrix.invertM(invertedProjectionMatrix, 0, viewProjMtx, 0);//计算逆矩阵 Matrix.multiplyMV(nearPlanePoint, 0, invertedProjectionMatrix, 0, nearScreenPoint, 0);//计算世界坐标系中,对应到近平面的坐标
Matrix.multiplyMV(farPlanePoint, 0, invertedProjectionMatrix, 0, farScreenPoint, 0); Vector3f direction = new Vector3f(farPlanePoint[0] / farPlanePoint[3], farPlanePoint[1] / farPlanePoint[3], farPlanePoint[2] / farPlanePoint[3]);
Vector3f origin = new Vector3f(new Vector3f(nearPlanePoint[0] / nearPlanePoint[3], nearPlanePoint[1] / nearPlanePoint[3], nearPlanePoint[2] / nearPlanePoint[3]));
direction.sub(origin);
direction.normalize();
return new Ray(origin, direction);
}
}

原理:

一、世界坐标系的点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就代表投影空间中的坐标点。

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

ARCore中根据屏幕坐标计算射线的算法的更多相关文章

  1. ARCore中Pose类变换点的算法实现

    ARCore中Pose类变换点的算法实现,主要分为两步,分别是平移和旋转. 1. 旋转向量:通过四元数计算旋转后的向量 参数列表:q表示四元数, v是长度为4的float数组,表示待旋转的向量,   ...

  2. EIGRP-11-弥散更新算法-EIGRP中的本地计算和弥散计算

    至此,我们已经了解了诸多概念: RD (报告距离). CD (计算距离). FD (可行距 离)和FC (可行性条件) ,在此基础上继续了解EIGRP对于拓扑变化的应对方法想必是轻松愉快的.能够导致拓 ...

  3. 三角函数计算,Cordic 算法入门

    [-] 三角函数计算Cordic 算法入门 从二分查找法说起 减少乘法运算 消除乘法运算 三角函数计算,Cordic 算法入门 三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来 ...

  4. (转)三角函数计算,Cordic 算法入门

    由于最近要使用atan2函数,但是时间上消耗比较多,因而网上搜了一下简化的算法. 原帖地址:http://blog.csdn.net/liyuanbhu/article/details/8458769 ...

  5. ARCore中四元数的插值算法实现

    ARCore中四元数差值算法: 其中t的取值范围为[0, 1],当 t = 0 时,结果为a:当t = 1 时,结果为b. public static Quaternion makeInterpola ...

  6. SVD在推荐系统中的应用详解以及算法推导

    SVD在推荐系统中的应用详解以及算法推导     出处http://blog.csdn.net/zhongkejingwang/article/details/43083603 前面文章SVD原理及推 ...

  7. DDos攻击,使用深度学习中 栈式自编码的算法

    转自:http://www.airghc.top/2016/11/10/Dection-DDos/ 最近研究了一篇论文,关于检测DDos攻击,使用了深度学习中 栈式自编码的算法,现在简要介绍一下内容论 ...

  8. 【微信小程序】 小程序中的递归运算/二分查找算法/Maximum call stack size exceeded

    摘要: 小程序中的递归运算/二分查找算法/Maximum call stack size exceeded 场景:最近做一个车贷计算器, 其中存在一个公式如下: /**** 总金额 * 月利率 * ( ...

  9. --关于null在oracle数据库中是否参与计算,进行验证,

    --关于null在oracle数据库中是否参与计算,进行验证,with td as (select null id,1 name from dual ),td1 as ( select null id ...

随机推荐

  1. springboot+thymeleaf+springbootJPA实现一个简单的增删改查

    1.springboot是什么,给我们带来了什么方便? 通过阅读springboot的书籍发现springboot最便利的是为我们自动配置了很多的东西,几乎可以实现无xml,甚至简单的无sql,为我们 ...

  2. .NET并行计算和并发5:多线程编程一般指导性原则

    使用多线程时要考虑以下准则: 不要使用 Thread.Abort 终止其他线程. 对另一个线程调用 Abort 无异于引发该线程的异常,也不知道该线程已处理到哪个位置. 不要使用 Thread.Sus ...

  3. 前端-URL到页面显示的全过程

    大概有以下几步: DNS解析(浏览器缓存→系统缓存→路由器缓存→ISP DNS缓存→从根域名服务器递归搜索) 建立TCP链接(TCP的三次握手) 浏览器向服务器发送HTTP请求 服务器返回结果给浏览器 ...

  4. C# 之TripleDESCryptoServiceProvider类加密/解密程序

    这篇博文的编写基于以下博客地址提供的知识: TripleDESCryptoServiceProvider 加密解密 基于该博客,我的毕业设计中密码存储加密字符串这一问题得到解决.

  5. Using Dispatcher

    he following code example shows how you might attempt to update the UI from your task logic. // The ...

  6. 在MySQL中快速的插入大量测试数据

    很多时候为了测试数据库设计是否恰当,优化SQL语句,需要在表中插入大量的数据,怎么插入大量的数据就是个问题了. 最开始想到的办法就是写一个程序通过一个很大的循环来不停的插入,比如这样: int i = ...

  7. Google - Find Most People in Chat Log

    1. 给你一个chatting log file,format大概是这样的: A: bla B: bla bla C: bla bla bla 要你找出说话最多(看word number) 的K个人 ...

  8. PythonStudy——Python 内存池机制 (Memory pool mechanism) Pymalloc

    Python是如何进行内存管理-内存池机制 Pymalloc Python引用了一个内存池(memory pool)机制,即Pymalloc机制(malloc:n.分配内存),用于对小块内存的申请和释 ...

  9. kvm创建新虚拟机

    安装图形化管理界面yum install virt-manager -y 安装好之后 新建虚拟机,我使用的方法是使用ISO镜像文件安装 选择镜像 设置内存 如此,一步一步走下去即可,不再截图 创建好之 ...

  10. Keepalived+LVS实现高可用负载均衡双主模式

    LVS是一种集群(Cluster)技术:采用IP负载均衡技术和基于内容请求分发技术.调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一 ...