Android AR Sceneform. Moving 3D model along with Camera moving. 3D model should be align to the bottom

871 views Asked by At

I'm a newbie in AR for Android, and I wanna achieve the following behavior. I'm using Sceneform.

implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.15.0'

I have a 3D model (simple cuboid). Here is the method to create cuboid.

  private ModelRenderable 3dModel;

  private void createModel(AnchorNode anchorNode) {
  TransformableNode cartoonPersonNodeThree = new TransformableNode(arFragment.getTransformationSystem());
      cartoonPersonNodeThree.getScaleController()
          .setEnabled(false); // Disable scaling
      cartoonPersonNodeThree.getTranslationController()
          .setEnabled(false); // Disable moving
      cartoonPersonNodeThree.setParent(anchorNode);
      cartoonPersonNodeThree.setRenderable(3dModel);
      cartoonPersonNodeThree.select();

}

I need this model to be displayed in front of user when Surface is detected, and it should be moved along with camera moving.

The code below does it. 3D model is displayed in the center and 1m in front of the camera.

arFragment.getArSceneView()
    .getScene()
    .addOnUpdateListener(frameTime -> {
      Frame frame = arFragment.getArSceneView()
          .getArFrame();
      if (frame == null) {
        return;
      }

      if (frame.getCamera()
          .getTrackingState() != TrackingState.TRACKING) {
        return;
      }

      if (isModelAlreadyInPlace) {
        return;
      }

      if (isModelLocked) {
        return;
      }

      removeAnchorNode(anchorNode); // Remove previous 3D model

      // Place the anchor 1m in front of the camera.
      Session session = arFragment.getArSceneView()
          .getSession();
      Anchor newMarkAnchor = session.createAnchor(frame.getCamera()
          .getPose()
          .compose(Pose.makeTranslation(0, 0, -1f)) //This will place the anchor 1M in front of the camera
          .extractTranslation());

      AnchorNode addedAnchorNode = new AnchorNode(newMarkAnchor);
      addedAnchorNode.setRenderable(cartoonPersonThree);
      addedAnchorNode.setParent(arFragment.getArSceneView()
          .getScene());
      anchorNode = addedAnchorNode;
    });

The issue here is that 3D model is in the air, if I move my camera up to the ceiling, 3D model will be there. enter image description hereenter image description here

Is there a way to align 3 D model to the floor?

1

There are 1 answers

0
Alexandru Iachimov On

This code snippet helped me to get exact behavior I wanted. We have a HitTest which hits to the center of our screen so we can get a "HitResult" and get Anchor from it. So it's kind of pseudo tap event which we perform each frame chane.

private fun initArFragment() {
    arFragment.arSceneView.scene.addOnUpdateListener {
        arFragment.arSceneView?.let { sceneView ->
            sceneView.arFrame?.let { frame ->
                if (frame.camera.trackingState == TrackingState.TRACKING) {
                    val hitTest =
                        frame.hitTest(sceneView.width / 2f, sceneView.height / 2f)
                    val hitTestIterator = hitTest.iterator()
                    if (hitTestIterator.hasNext()) {
                        if (!placed) {
                            val hitResult = hitTestIterator.next()
                            val anchor = hitResult.createAnchor()
                            if (anchorNode == null) {
                                anchorNode = AnchorNode()
                                anchorNode?.setParent(sceneView.scene)
                                transformableNode =
                                    DragTransformableNode(arFragment.transformationSystem)
                                transformableNode?.setParent(anchorNode)
                                boxNode = createBoxNode(.4f, .6f, .4f)
                                boxNode?.setParent(transformableNode)
                            }
                            anchorNode?.anchor?.detach()
                            anchorNode?.anchor = anchor
                        }
                    }
                }
            }
        }
    }
}