web-dev-qa-db-ja.com

画面をタップせずにオブジェクトを配置する方法

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;
        }
    }

画面をタップせずに表示してみました。

誰かがこれを行う方法を知っている場合は、私を助けてください。前もって感謝します

9
Akash Mishra

ユーザーが画面をタップした場所とタップした場所にオブジェクトを配置することをお勧めしますが、求めていることはこのようにして実現できます。 (この例はKotlinにあります)

オブジェクトを配置する前に、ModelRenderableを作成する必要があります。 1つを宣言@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 -> [email protected] = modelRenderable }

プログラミングの主要な部分は、フレームのonUpdateメソッドで行う必要があります。だからあなたはそのようなフレーム更新のためのリスナーをアタッチします

 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 = [email protected]

                        //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())
                    }
                }
            }
        }
    }
}

1つの拡張メソッドを使用しました

//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)
}

これが最終結果です enter image description here

7
Clinkz

実際の環境にオブジェクトを配置するためにhit-testingまたはbutton's actionメソッドを使用したくない場合は、たとえば、カメラのポーズを自動配置に使用できます(追加する必要があります) ARAnchor、それに対応するNode、およびARCameraの前にあるRenderable、つまり-Z方向に沿って):

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());
}

お役に立てれば。

0
Andy

オブジェクトを1つだけ配置する場合のコードスニペットを次に示します。ありがとう@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 = [email protected]

                                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)
}
0
GokulaKrishnanM