Android 使用Arcore 实现多点测距

Android 使用Arcore 实现多点测距

已更新第二版,详情见github链接github源码 点这里 <==
主要使用了Anchor(锚点),Pose (姿势/姿态),Node(节点),Vector3(三维向量)
Android 使用Arcore 实现多点测距_第1张图片
Android 使用Arcore 实现多点测距_第2张图片
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.pose
val endPose = startAnchor.pose
val 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 = [email protected]
            val direction = Vector3.subtract(cameraPosition, nodePosition)
            [email protected] = Quaternion.lookRotation(direction, Vector3.up())
        }
    }

UI这里有点复杂,主要难点在Vector3(空间向量)这里.用的是数学知识了.
1.先用两个Anchor 获得 世界坐标(worldPosition)
2.使用向量计算两点空间差
3.使用起始Anchor ,生成一个Node.附加到arSceneView上
4.使用MaterialFactory 创建一个Material.再创建一个 Node使用刚才的材质,附加到之前的Node上.


github源码 点这里 <==

你可能感兴趣的:(arcore)