【问题标题】:Dynamically place object in front of the user with ArCore使用 ArCore 将对象动态放置在用户面前
【发布时间】:2020-04-26 20:01:05
【问题描述】:

我正在使用 ArCore 为 Android(Java 语言)构建一个简单的导航应用程序。我开始在 Google (https://github.com/google-ar/sceneform-android-sdk/tree/master/samples/hellosceneform) 的 Sceneform 演示上构建我的应用程序。

目前,该应用正在扫描环境中的锚点。用户可以通过点击它们将对象放置在锚点上。是否可以使用这些找到的锚点自动在用户面前放置例如导航箭头?箭头应该在用户前方 3m-5m 处,如果用户靠近则移动。

我知道如何查看锚点并始终删除最后一个锚点。但我不确定如何将下一个对象自动放在用户面前。有没有办法做到这一点?

编辑: 有没有办法做到这一点?也许从锚点读出位置并寻找所需的距离?

【问题讨论】:

  • 我最终没有找到解决方案,只是使用用户输入来放置对象。用户必须点击他想要放置对象的位置。

标签: java android android-studio arcore


【解决方案1】:

我希望这是您正在寻找的。一旦 AR 场景开始跟踪特征点,这将在手机前面渲染箭头。

//添加一个布尔值以确保只呈现1个箭头。

 boolean placed = false;

//在 onCreate 函数中添加一个更新监听器,因为应用程序需要一两秒才能获取相机的 Pose,如果您尝试从空 Pose 制作锚点,应用程序可能会崩溃。

arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);

//可以在更新函数中获取相机的位姿,在相机前做一个相应的锚点。

private void onUpdateFrame(FrameTime frameTime) {

    Frame frame = arFragment.getArSceneView().getArFrame();

    // If there is no frame, just return.
    if (frame == null) {
        return;
    }

  //Making sure ARCore is tracking some feature points, makes the augmentation little stable. 
  if(frame.getCamera().getTrackingState()==TrackingState.TRACKING && !placed) {

      Pose pos = frame.getCamera().getPose().compose(Pose.makeTranslation(0, 0, -0.3f));
      Anchor anchor = arFragment.getArSceneView().getSession().createAnchor(pos);
      AnchorNode anchorNode = new AnchorNode(anchor);
      anchorNode.setParent(arFragment.getArSceneView().getScene());

  // Create the arrow node and add it to the anchor.
  Node arrow = new Node();
  arrow.setParent(anchorNode);
  arrow.setRenderable(arrowRenderable);
  placed = true; //to place the arrow just once.

  }

}

您必须对箭头的变换进行更改,以将其准确地设置在相机前方的中心和正确的方向。 我希望这能让你开始。干杯!

【讨论】:

  • 嗯,这将使用相机作为锚点。不过,我想将它定位在现实世界中的锚点上。对于我的第一个实现,我已经将箭头放在屏幕的一角。虽然走应用程序已经检测到现实世界中可能的锚点,但我只需要一种方法将其放置在这些找到的锚点之一上。我想我不确定如何在距相机一定距离的地方选择正确的锚点。
【解决方案2】:

这里是代码 sn-p 将对象放置在屏幕中心

    override fun onUpdate(frameTime: FrameTime?) {
    arFragment?.let { fragment ->
        fragment.arSceneView?.let { sceneView ->
            sceneView.arFrame?.let { frame ->
                if (!placed) {
                    val trackable = frame.getUpdatedTrackables(Plane::class.java).iterator()
                    if (trackable.hasNext()) {
                        val plane = trackable.next() as Plane
                        if (plane.trackingState == TrackingState.TRACKING) {
                            fragment.planeDiscoveryController?.hide()
                            val hitTest =
                                frame.hitTest(frame.screenCenter().x, frame.screenCenter().y)
                            val hitTestIterator = hitTest.iterator()
                            if (hitTestIterator.hasNext()) {
                                val hitResult = hitTestIterator.next()
                                val modelAnchor = plane.createAnchor(hitResult.hitPose)
                                val anchorNode = AnchorNode(modelAnchor)
                                anchorNode.setParent(sceneView.scene)

                                val transformableNode =
                                    TransformableNode(fragment.transformationSystem)
                                transformableNode.setParent(anchorNode)
                                transformableNode.renderable = this@ARActivity.modelRenderable

                                transformableNode.worldPosition = Vector3(
                                    modelAnchor.pose.tx(),
                                    modelAnchor.pose.compose(
                                        Pose.makeTranslation(
                                            0f,
                                            0.05f,
                                            0f
                                        )
                                    ).ty(),
                                    modelAnchor.pose.tz()
                                )
                                placed = true
                            }
                        }
                    }
                }
            }
        }
    }
}

private fun Frame.screenCenter(): Vector3 {
    val vw = findViewById<View>(android.R.id.content)
    return Vector3(vw.width / 2f, vw.height / 2f, 0f)
}

【讨论】:

    猜你喜欢
    • 2020-10-12
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多