【Sceneform-EQR】(手势优化)通过手势事件实现在AR/VR等三维场景中的控制模型旋转、平移与缩放


在上一篇文档中,我们实现了通过手势控制模型节点的旋转、缩放和平移。现在本文将介绍如何优化上一篇做的手势控制器,从而实现更好的跟手效果。

相关链接:【Sceneform-EQR】(手势控制器实现)通过手势事件实现在AR/VR等三维场景中的控制模型旋转、平移与缩放


手势优化

平移手势优化

当前存在的问题

直接采用安卓提供的onScroll方法,能够获取到distanceX\Y,而不同设备的屏幕密度不一致,会导致distanceX\Y的值都会有差异。
此外,在AR场景中,不同手机平板的相机的内参(相机焦距、感光元件尺寸等)都不同,会导致相机的视场角不同。
总之,这些都会导致无法实现“指哪打哪”的效果。

优化后的效果

“指哪打哪”的效果

请添加图片描述

解决思路

  • 思路是屏幕坐标转空间坐标

需要注意的是,屏幕坐标是二维的,空间坐标是三维的。
这里通过屏幕坐标计算出一条射线,然后通过这条射线取指定距离的空间点或是求射线与指定平面的交点。(两种方式都可以很好的实现平移效果,但是实际上有些区别(与相机的距离不一样))

  • 采用指定距离

Sceneform-EQR提供了屏幕坐标转射线的方法camera.screenPointToRay(x,y),然后我们传入指定距离即可。

        //计算射线,再取得固定距离的空间点坐标.作为新的空间位置Vector3 newPosition = camera.screenPointToRay(screenPoint.x, screenPoint.y).getPoint(/*外部传入*/distance);
  • 采用线面相交

原理是,求射线与前方指定距离的平面的交点。用高中的立体几何知识,就不列举公式了,直接看下面代码。

代码如下:

//向量AB
Vector3 vectorAB = Vector3.subtract(b, a);
//向量AC
Vector3 vectorAC = Vector3.subtract(c, a);
//直线方向向量i
Vector3 i = Vector3.subtract(v1, v0);
//平面法向量n
Vector3 n = Vector3.cross(vectorAB,vectorAC);//点法式平面方程常数K(条件:代入A点坐标计算=>)
float constK = n.x * a.x + n.y * a.y + n.z * a.z;
//点向式直线方程常数M(条件:直线与平面相交=>)
float constM = (constK - n.x * v0.x - n.y * v0.y - n.z * v0.z)/(i.x * n.x + i.y * n.y + i.z * n.z);//D点坐标
Vector3 d=new Vector3(v0.x + i.x * constM,v0.y + i.y * constM,v0.z + i.z * constM);

EQR-源码定位

    private void onDoubleFingerScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {isDoubleFingerScroll = true;//计算当前Node的世界坐标系下的空间位置。Vector3 screenPoint = camera.worldToScreenPoint(target.getWorldPosition());screenPoint.x -= distanceX;screenPoint.y -= distanceY;//计算射线,再取得固定距离的空间点坐标.作为新的空间位置Vector3 newPosition = camera.screenPointToRay(screenPoint.x, screenPoint.y).getPoint(/*外部传入*/distance);target.setWorldPosition(newPosition);}

旋转手势优化

当前存在的问题

在AR/VR等三维场景中,若场景相机的位姿(位置、姿态)发生变化,原旋转轴的计算已不再适用了

旋转手势优化前
由上图,可发现,当前相机视角发生改变后,原来的旋转手势只能实现模型在它自身坐标系下旋转。

优化后的效果

优化后效果如下:

旋转手势优化后

解决思路

步骤

  • 通过屏幕坐标转空间坐标的方法(与平移优化中用到的一样)计算两个MotionEvent事件的屏幕坐标AB对应的空间坐标A、B。
  • 获取当前相机的在世界坐标系下的位置C。
  • 通过余弦定义求∠ACB,这个作为旋转角度。
  • 通过向量CA与向量CB的叉乘求旋转轴。

在这里插入图片描述
叉乘计算:

  /*** 叉乘* @return 垂直于两个矢量的矢量*/public static Vector3 cross(Vector3 lhs, Vector3 rhs) {float lhsX = lhs.x;float lhsY = lhs.y;float lhsZ = lhs.z;float rhsX = rhs.x;float rhsY = rhs.y;float rhsZ = rhs.z;return new Vector3(lhsY * rhsZ - lhsZ * rhsY, lhsZ * rhsX - lhsX * rhsZ, lhsX * rhsY - lhsY * rhsX);}
  • 通过计算得到的旋转角度与旋转轴构造四元数,以此做旋转

EQR-源码定位

Commit记录

  • 优化旋转手势
        //单指实现旋转(计算旋转轴和旋转角度)//原理://上一触摸点转为空间坐标点A,当前触摸点转为空间触摸点B。记当前场景相机的位置为点O//那么向量OA与向量OB的叉积则是旋转轴//转为空间坐标(屏幕坐标->射线->固定距离的点)Vector3 pointA = camera.screenPointToRay(currentEvent.getX() - distanceX,currentEvent.getY() - distanceY).getPoint(/*外部传入*/distance);Vector3 pointB = camera.screenPointToRay(currentEvent.getX(),currentEvent.getY()).getPoint(distance);Vector3 pointO = camera.getWorldPosition();Vector3 oa = Vector3.subtract(pointA, pointO);Vector3 ob = Vector3.subtract(pointB, pointO);float c = Vector3.subtract(pointA, pointB).length();float a = oa.length();float b = ob.length();float cosC = (a * a + b * b - c * c) / (2 * a * b);//旋转轴Vector3 cross = Vector3.cross(oa, ob).normalized();

查看示例demo请转至git。欢迎交流讨论!

Git仓库

  • Sceneform-EQR

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/448269.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全中的RCE命令执行漏洞----入门小白必看

RCE命令执行&代码执行漏洞 RCE命令执行漏洞 RCE漏洞简介 RCE(remote code/command execute) 远程代码/命令执行漏洞 RCE漏洞是两个漏洞: 代码执行漏洞 # 针对后端语言!命令执行漏洞 # 针对系统! 如何产生 在 Web应用中有时候程序员为了考虑灵活性、简洁性…

【SEO】什么是SEO?

什么是SEO(搜索引擎优化)?为什么SEO对于⼀个⽹站⾄关重要? SEO 全称是搜索引擎优化(Search Engine Optimization) 因为我们目前开发的网址,需要人看到,除了通过宣传营销的方式展现…

前端布局与响应式设计综合指南(二)

​🌈个人主页:前端青山 🔥系列专栏:Css篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Css篇专栏内容:前端布局与响应式设计综合指南(二) 目录 23、行内元素和块级元素?img算什么&…

影刀RPA实战:操作Mysql数据库

1.摘要 影刀RPA(Robotic Process Automation)是一种软件自动化工具,它可以模拟人类用户执行各种重复性任务,其中包括对数据库的操作。 我们可以使用软件自动化指令,通过获取数据库窗口对象来操作数据库,也…

《探秘数据合规官CCRC-DCO人员能力验证》

在当今竞争激烈的商业世界中,“数据合规官CCRC-DCO人员能力验证”这个词逐渐走入人们的视野。但究竟什么是数据合规官CCRC-DCO人员能力验证呢? 首先,咱们来明确一下概念。数据合规官CCRC-DCO人员能力验证,简单来说,就…

数仓范式建模和维度建模有什么不同?

在数据库设计的复杂世界中,还有一类建模方法,为范式建模,是一种旨在优化数据库结构、提高数据一致性和完整性的设计方法。本文将深入探讨范式建模的概念、原理、步骤以及与维度建模的区别。 一、什么是范式建模? 范式建模是一种…

Chromium 中window.DOMParser接口说明c++

一、DOMParser DOMParser 可以将存储在字符串中的 XML 或 HTML 源代码解析为一个 DOM Document。 备注: XMLHttpRequest 支持从 URL 可寻址资源解析 XML 和 HTML,在其response 属性中返回Document。 你可以使用XMLSerializer 接口执行相反的操作 - 将…

接口测试自动化后起之秀-YApi接口管理平台

前言 众多接口管理工具如雨后春笋,让人欣慰的是,有许多优秀作品来自国内,包含Yapi和rap,看着中文的官网,华丽的汉语,不禁让人大快朵颐,暗自称爽。当然这也就带来另一个弊端,使用基数…

nodejs的卸载和nvm安装

由于项目需求,需要多版本控制的nodejs,所以要把原来的nodejs卸载干净,然后再装nvm 常见问题 1.在安装nvm的时候没有卸载node,导致使用nvm安装完之后,node和npm都不可用。 2.在第一次使用nvm安装node后,要…

从零开始使用最新版Paddle【PaddleOCR系列】——第二部分:自建数据集 + 模型微调训练

目录 一、自建数据集 1.官方数据集格式参考 2.自建数据集txt文件编写代码 3.数据集检验 二、模型训练 1.模型配置yaml文件 2.命令行指令训练 在上一篇文章中,构建好了paddleOCR 运行必需的环境,并通过在线下载的方式,使用官方训练好的模型进…

深入理解 JDK 的 Optional 类

深入理解 JDK 的 Optional 类 深入理解 JDK 的 Optional 类1. 什么是 Optional?1.1 主要构造方法示例 2. Optional 的常用方法2.1 判断值是否存在示例2.2 获取值示例2.3 进行操作示例 3. 使用场景3.1 避免 null 值示例3.2 提高代码可读性3.3 与流结合示例 4. 注意事…

中航资本:股市融资50万一天的利息是多少?融资一般多久归还?

融资官方利率是8.35%,实际上大部分券商融资利息在6%~8%左右,详细利率因券商及投资者状况而异。少部分券商可提供低至5%,乃至更低的优惠利率。 该利息按天然日核算,融资利息融资金额融资年利率实际使用资金的天然日天数/360。 假…

基于深度学习的细粒度图像分析综述【翻译】

🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 基础信息0 摘要1 INTRODUCTION2 识别与检索 RECOGNITION VS. RETRIEVAL3 问题和…

React01 开发环境搭建

React 开发环境搭建 一、创建 React 项目二、项目精简 一、创建 React 项目 执行下述命令创建 react 项目 blu-react-basis npx create-react-app blu-react-basis项目目录结构如下: 执行下述命令启动项目 npm run start启动效果如下: 二、项目精简 …

Vue.js 错误异常: Component template should contain exactly one root element.

一、错误异常: Errors compiling template: Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead. 二、原因 组件模板应该只包含一个根元素 查看vue代码,发…

OpenCV-人脸检测

文章目录 一、人脸检测流程二、关键方法三、代码示例四、注意事项 OpenCV是一个开源的计算机视觉和机器学习软件库,它提供了多种人脸检测方法,以下是对OpenCV人脸检测的详细介绍: 一、人脸检测流程 人脸检测是识别图像中人脸位置的过程&…

【C语言】数据输出格式控制

数据的输出格式修饰 常用两种&#xff1a; 整型中&#xff0c;输出数据左对齐、右对齐、占m位、不足m位前补0。浮点型中&#xff0c;默认通过四舍五入保留小数点后6位&#xff0c;通过参数设置保留小数点后n位。 #include <stdio.h> #define PI 3.14159 /* 功能&#x…

2024怎么选择网站建设公司?2024靠谱建站公司推荐TOP3

说起怎么挑个靠谱的网站建设公司啊&#xff0c;我觉得有这么几点挺关键的&#xff0c;咱们可以聊聊&#xff1a; 首先啊&#xff0c;你得瞅瞅这公司啥背景&#xff0c;成立了多久了&#xff0c;团队大不大&#xff0c;都服务过哪些客户&#xff0c;有啥拿得出手的成功案例没。…

如何判断通风天窗的优劣

通风天窗是否优质直接决定天窗的通风采光效果&#xff0c;影响厂房的空气质量。判断通风天窗的优劣主要从天窗使用材料、防水密封性能、通风性能、安装与售后服务等多方面出发。‌ ‌通风天窗使用材料是判断通风天窗优劣的重要因素之一。优质的通风天窗应采用耐候性强、坚固耐用…

ESP32-S3无法下载且报错的原因

该文将作为ESP32-S3下载报错记录&#xff0c;将持续更新 ARDUINO-IDE: Sketch uses 289393 bytes (22%) of program storage space. Maximum is 1310720 bytes. Global variables use 18408 bytes (5%) of dynamic memory, leaving 309272 bytes for local variables. Maximu…