web-dev-qa-db-fra.com

Comment placer un objet sans taper sur l'écran

J'essaie de montrer un objet sans taper sur l'écran en utilisant ARCore. Dans l'exemple de base d'ARCore Sceneform fourni par Google, vous devez appuyer sur l'écran après qu'il ait détecté la surface.

Je veux implémenter cela, AR montre l'objet sans taper sur l'écran.

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

J'ai essayé cela pour afficher sans taper sur l'écran.

si quelqu'un sait comment le faire, veuillez m'aider. Merci d'avance

9
Akash Mishra

Bien que je vous suggère de placer l'objet lorsqu'un utilisateur tape et où il tape sur l'écran, ce que vous demandez peut être réalisé de la sorte. (cet exemple est dans Kotlin)

Avant de commencer à placer un objet, vous devez créer un ModelRenderable. Déclarez un @Nullable globalement.

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 }

La majeure partie de la programmation doit être effectuée sur la méthode onUpdate du cadre. Vous attachez donc un écouteur pour les mises à jour de trames comme ça

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

vous gérez maintenant l'ajout d'un objet sur l'écouteur.

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

J'ai utilisé une méthode d'extension

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

Ceci est le résultat final enter image description here

7
Clinkz

Si vous ne souhaitez pas utiliser hit-testing ou button's action méthodes pour placer un objet dans un environnement réel, vous pouvez utiliser, par exemple, la pose d'une caméra pour le placement automatique (rappelez-vous, vous devez ajouter un ARAnchor, son Node correspondant et un Renderable devant l'ARCamera c'est-à-dire le long de -Z direction):

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

J'espère que cela t'aides.

0
Andy

Voici l'extrait de code si vous souhaitez placer un seul objet. Merci @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