当前位置: 首页 > 知识库问答 >
问题:

如何在不点击屏幕的情况下放置对象

赵灼光
2023-03-14

我正在尝试使用ARCore在屏幕上不点击的情况下显示对象。在Google提供的ARCore Sceneform的基本示例中,您需要在屏幕检测到表面后点击屏幕。

我想实现这一点,AR在不点击屏幕的情况下显示对象。

Anchor newAnchor;

    for (Plane plane : mSession.getAllTrackables(Plane.class)) {
        if (plane.getType() == Plane.Type.HORIZONTAL_UPWARD_FACING
                && plane.getTrackingState() == TrackingState.TRACKING)
        {
            newAnchor = plane.createAnchor(plane.getCenterPose());
            break;
        }
    }

我试着在不点击屏幕的情况下进行显示。

如果有人知道怎么做,请帮助我。提前感谢

共有3个答案

狄奕
2023-03-14

如果您只想放置一个对象,下面是代码段。。谢谢@clinkz

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)
}
宰父淳
2023-03-14

如果您不想使用点击测试或按钮的动作在真实环境中放置对象,例如,您可以使用相机的姿势进行自动放置(请记住,您必须在ARCamera前面,即沿Z方向添加一个Anchor、其相应的节点和一个可渲染的):

if (this.anchorNode == null) {

    Session session = arFragment.getArSceneView().getSession();

    float[] position = { 0, 0, -0.75 };       // 75 cm away from camera
    float[] rotation = { 0, 0, 0, 1 };

    Anchor anchor =  session.createAnchor(new Pose(position, rotation));

    anchorNode = new AnchorNode(anchor);
    anchorNode.setRenderable(yourModelRenderable);
    anchorNode.setParent(arFragment.getArSceneView().getScene());
}

希望这有帮助。

锺离德运
2023-03-14

虽然我建议您在用户点击时放置对象

在开始放置对象之前,您需要创建一个ModelRenderable。全局声明一个@Nullable

private var modelRenderable: ModelRenderable? = null

//Create the football renderable
ModelRenderable.builder()
                //get the context of the ARFragment and pass the name of your .sfb file
                .setSource(fragment.context, Uri.parse("FootBall.sfb"))
                .build()

                //I accepted the CompletableFuture using Async since I created my model on creation of the activity. You could simply use .thenAccept too.
                //Use the returned modelRenderable and save it to a global variable of the same name
                .thenAcceptAsync { modelRenderable -> this@MainActivity.modelRenderable = modelRenderable }

编程的主要部分必须在帧的更新方法上完成。因此,您为帧更新附加了一个侦听器,如下所示

 fragment.arSceneView.scene.addOnUpdateListener(this@MainActivity) //You can do this anywhere. I do it on activity creation post inflating the fragment

现在,您可以在侦听器上添加一个对象。

 override fun onUpdate(frameTime: FrameTime?) {
    //get the frame from the scene for shorthand
    val frame = fragment.arSceneView.arFrame
    if (frame != null) {
        //get the trackables to ensure planes are detected
        val var3 = frame.getUpdatedTrackables(Plane::class.java).iterator()
        while(var3.hasNext()) {
            val plane = var3.next() as Plane

            //If a plane has been detected & is being tracked by ARCore
            if (plane.trackingState == TrackingState.TRACKING) {

                //Hide the plane discovery helper animation
                fragment.planeDiscoveryController.hide()


                //Get all added anchors to the frame
                val iterableAnchor = frame.updatedAnchors.iterator()

                //place the first object only if no previous anchors were added
                if(!iterableAnchor.hasNext()) {
                    //Perform a hit test at the center of the screen to place an object without tapping
                    val hitTest = frame.hitTest(frame.screenCenter().x, frame.screenCenter().y)

                    //iterate through all hits
                    val hitTestIterator = hitTest.iterator()
                    while(hitTestIterator.hasNext()) {
                        val hitResult = hitTestIterator.next()

                        //Create an anchor at the plane hit
                        val modelAnchor = plane.createAnchor(hitResult.hitPose)

                        //Attach a node to this anchor with the scene as the parent
                        val anchorNode = AnchorNode(modelAnchor)
                        anchorNode.setParent(fragment.arSceneView.scene)

                        //create a new TranformableNode that will carry our object
                        val transformableNode = TransformableNode(fragment.transformationSystem)
                        transformableNode.setParent(anchorNode)
                        transformableNode.renderable = this@MainActivity.modelRenderable

                        //Alter the real world position to ensure object renders on the table top. Not somewhere inside.
                        transformableNode.worldPosition = Vector3(modelAnchor.pose.tx(),
                                modelAnchor.pose.compose(Pose.makeTranslation(0f, 0.05f, 0f)).ty(),
                                modelAnchor.pose.tz())
                    }
                }
            }
        }
    }
}

我用了一种扩展方法

//A method to find the screen center. This is used while placing objects in the scene
private fun Frame.screenCenter(): Vector3 {
    val vw = findViewById<View>(android.R.id.content)
    return Vector3(vw.width / 2f, vw.height / 2f, 0f)
}
 类似资料:
  • 问题内容: 我“d成的运行Django的服务器,我不能简单地和出来。 是否有其他摆脱困境的方法? 目前,我手动关闭本地PC上的选项卡,然后再重新打开,但这变得很烦人。 问题答案: 或 。请参阅屏幕手册#分离。

  • 如何避免图像的所有向上/向下缩放?由于Windows屏幕缩放信息,我检查的所有变体都会导致一些缩放。 动机 我有一些渲染器,它们以一定大小的文档(svg,pdf等)创建图像。当这些图像被JavaFX放大时,它们会变得模糊。我没有找到摆脱它的方法。 在 Swing 中,解决方案是使用 AbstractMultiResolutionImage。但这不适用于JavaFX。 我无法使用 ImageLoad

  • 安装应用程序时,如何默认启用屏幕覆盖权限。 现在我面临一些问题,当捕获图像询问运行时权限时,一些设备不允许它打开屏幕覆盖设置对话框的权限。在用户看来,他们不知道为什么对话框显示以及他们做了什么。 当打开覆盖设置屏幕时,一些应用程序会自动启用屏幕覆盖权限。 下面我使用代码。 此代码直接打开覆盖设置屏幕。所有应用程序的显示列表。 我的要求是显示权限特定的应用程序或启用覆盖权限而无需用户交互。 做需要.

  • 假设用户单击屏幕上的任何位置,我需要将该点,例如(500200)转换为屏幕中心的极点。抽头位置(500,200)从屏幕左上角开始测量。 因此,我必须从一个原点位于屏幕左上角的笛卡尔坐标系转换为另一个原点位于屏幕中间的笛卡尔坐标系(宽度/2,高度/2),然后再从中心原点转换为一个极点。 另一种提问方式是我需要屏幕点与屏幕中心的角度。

  • 问题内容: 我是.Net开发人员,但出于某种原因,我不知为何要用java创建一个简单的应用程序。我能够创建该应用程序,但是我的问题是启动应用程序时如何在屏幕上居中放置表单? 这是我的代码: 上面的代码工作正常,但问题是我已经看到表格从最左上角移到中间屏幕。我还尝试在事件中添加该代码,但仍显示相同的操作。有更好的方法吗?就像里面有一个。还是如果上面的代码正确,我将在哪个事件上放? 感谢您阅读本文。

  • 问题内容: 嗨,我正在使用类似于以下内容的方法来将div定位在屏幕中间: 但是,这样做的问题是它将项目放置在页面的中间而不是屏幕的中间。因此,如果页面高了几个屏幕,而我使div出现时,我就位于页面的顶部(该部分的顶部显示在屏幕上)。您必须向下滚动才能查看它。 有人可以告诉我您如何将其显示在屏幕中间吗? 问题答案: 只需添加即可,即使您向下滚动也可以看到它。