Android 使用Arcore 實現多點測距

Android 使用Arcore 實現多點測距

主要使用了Anchor(錨點),Pose (姿勢/姿態),Node(節點),Vector3(三維向量)

預覽1

預覽2

github源碼 點這裏 <==

1.準備

  • 一臺支持Arcore的手機
  • 依賴arcore和sceneform
    implementation 'com.google.ar:core:1.4.0'
    implementation 'com.google.ar.sceneform:core:1.4.0'
    implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.4.0'

-佈局文件使用sceneform提供的fragment

      <fragment
        android:id="@+id/UI_ArSceneView"
        android:name="com.gj.arcoredraw.MyArFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
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
            }
}

UI這裏有點複雜,主要難點在Vector3(空間向量)這裏.用的是數學知識了.
1.先用兩個Anchor 獲得 世界座標(worldPosition)
2.使用向量計算兩點空間差
3.使用起始Anchor ,生成一個Node.附加到arSceneView上
4.使用MaterialFactory 創建一個Material.再創建一個 Node使用剛纔的材質,附加到之前的Node上.


github源碼 點這裏 <==

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章