Android(安卓)使用Arcore 实现多点测距
16lz
2022-06-19
Android 使用Arcore 实现多点测距
已更新第二版,详情见github链接github源码 点这里 <==
主要使用了Anchor(锚点),Pose (姿势/姿态),Node(节点),Vector3(三维向量)
github源码 点这里 <==
1.准备
- 一台支持Arcore的手机
- 依赖arcore和sceneform
implementation 'com.google.ar:core:1.5.0' implementation 'com.google.ar.sceneform:core:1.5.0' implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.5.0'
-布局文件使用sceneform提供的fragment
import com.blankj.utilcode.util.ToastUtils;import com.google.ar.core.exceptions.UnavailableApkTooOldException;import com.google.ar.core.exceptions.UnavailableArcoreNotInstalledException;import com.google.ar.core.exceptions.UnavailableDeviceNotCompatibleException;import com.google.ar.core.exceptions.UnavailableException;import com.google.ar.core.exceptions.UnavailableSdkTooOldException;import com.google.ar.sceneform.ux.ArFragment;//可以直接使用ArFragment 我这里为了中文提示public class MyArFragment extends ArFragment { @Override protected void handleSessionException(UnavailableException sessionException) { String message; if (sessionException instanceof UnavailableArcoreNotInstalledException) { message = "请安装ARCore"; } else if (sessionException instanceof UnavailableApkTooOldException) { message = "请升级ARCore"; } else if (sessionException instanceof UnavailableSdkTooOldException) { message = "请升级app"; } else if (sessionException instanceof UnavailableDeviceNotCompatibleException) { message = "当前设备部不支持AR"; } else { message = "未能创建AR会话,请查看机型适配,arcore版本与系统版本"; String var3 = String.valueOf(sessionException); } ToastUtils.showLong(message); }}
2.监听点击 生成锚点
- **设置ArFragment的Tap监听 **
(UI_ArSceneView as MyArFragment).setOnTapArPlaneListener { hitResult, plane, motionEvent -> val currentAnchor=hitResult.createAnchor() }
3.计算两个锚点之间的距离
val startPose = endAnchor.poseval endPose = startAnchor.poseval dx = startPose.tx() - endPose.tx()val dy = startPose.ty() - endPose.ty()val dz = startPose.tz() - endPose.tz()val length = Math.sqrt((dx * dx + dy * dy + dz * dz).toDouble())anchorInfoBean.dataText = "距离为${decimalFormat.format(length)}m"
4.UI 划线 (两个锚点在ui上连接划线)
private fun drawLine(firstAnchor: Anchor, secondAnchor: Anchor) { val firstAnchorNode = AnchorNode(firstAnchor) val secondAnchorNode = AnchorNode(secondAnchor) firstAnchorNode.setParent((UI_ArSceneView as MyArFragment).arSceneView.scene) val firstWorldPosition = firstAnchorNode.worldPosition val secondWorldPosition = secondAnchorNode.worldPosition val difference = Vector3.subtract(firstWorldPosition, secondWorldPosition) val directionFromTopToBottom = difference.normalized() val rotationFromAToB = Quaternion.lookRotation(directionFromTopToBottom, Vector3.up()) MaterialFactory.makeOpaqueWithColor(this@MainActivity, com.google.ar.sceneform.rendering.Color(0f, 191f, 255f)) .thenAccept { material -> val lineMode = ShapeFactory.makeCube(Vector3(0.01f, 0.01f, difference.length()), Vector3.zero(), material) val lineNode = Node() lineNode.setParent(firstAnchorNode) lineNode.renderable = lineMode lineNode.worldPosition = Vector3.add(firstWorldPosition, secondWorldPosition).scaled(0.5f) lineNode.worldRotation = rotationFromAToB }}
5.自定义Node 始终面向相机
override fun onUpdate(p0: FrameTime?) { scene?.let { scene -> val cameraPosition = scene.camera.worldPosition val nodePosition = this@FaceToCameraNode.worldPosition val direction = Vector3.subtract(cameraPosition, nodePosition) this@FaceToCameraNode.worldRotation = Quaternion.lookRotation(direction, Vector3.up()) } }
UI这里有点复杂,主要难点在Vector3(空间向量)这里.用的是数学知识了.
1.先用两个Anchor 获得 世界坐标(worldPosition)
2.使用向量计算两点空间差
3.使用起始Anchor ,生成一个Node.附加到arSceneView上
4.使用MaterialFactory 创建一个Material.再创建一个 Node使用刚才的材质,附加到之前的Node上.
github源码 点这里 <==
更多相关文章
- Android(安卓)studio 使用问题
- Android官方教程翻译(1)——创建第一个Android应用
- Android(安卓)调用相机和调用图库
- android 使用include 调用内部组件
- Android(安卓)SQLite数据库解析并使用两种方法实现增删改查
- Calling startActivity() from outside of an Activity context
- 箭头函数的基础使用
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用