Search code examples
androidarcoresceneform

ARCore Sceneform ViewRenderable rotates the image by random angle


I am placing a 2D image on vertical wall like a painting hanging on wall. But the rendered image is rotating by random angle. Its not properly aligned. I have integrated following code:

 @RequiresApi(api = Build.VERSION_CODES.N)
    private void createViewRenderable(WeakReference<ARRoomViewActivity> weakActivity) {
        imageViewRenderable = new ImageView(this);
        Picasso.get().load(paintingImageUrl)
                    .networkPolicy(NetworkPolicy.OFFLINE)
                    .into(imageViewRenderable);

        ViewRenderable.builder()
                .setView(this, imageViewRenderable)
                .build()
                .thenAccept(renderable -> {
                    ARRoomViewActivity activity = weakActivity.get();
                    if (activity != null) {
                        activity.renderable = renderable;
                    }
                })
                .exceptionally(
                        throwable -> {
                            return null;
                        });
    }



 private void addToScene(HitResult hitResult) {
        if (renderable == null) {
            return;
        }
        Anchor anchor = hitResult.createAnchor();
        anchorNode = new AnchorNode(anchor);
        anchorNode.setParent(arFragment.getArSceneView().getScene());

        node = new Node();
        node.setRenderable(renderable);

        transformableNode = new TransformableNode(arFragment.getTransformationSystem());
        node.setLocalRotation(Quaternion.axisAngle(new Vector3(-1f, 0, 0), -90f));
        node.setLookDirection(new Vector3(0, 10f, 0));
        transformableNode.setParent(anchorNode);
        node.setParent(transformableNode);
        transformableNode.select();
    }

I am using following Sceneform version and also tried latest 1.17.0 but could not succeed

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

Solution

  • The orientation of anchors by default is such that one of the axes points somewhat towards the camera. This results in models placed on the floor to be "looking at" the user. However, models on the wall end up rotating arbitrarily. This can be fixed by setting the look direction of the node.

    In your addToScene method, you can introduce an intermediate node that fixes the orientation relative to the anchor node. Children of the intermediate node will then be oriented correctly.

    // Create an anchor node that will stay attached to the wall
    Anchor anchor = hitResult.createAnchor();
    anchorNode = new AnchorNode(anchor);
    anchorNode.setParent(arFragment.getArSceneView().getScene());
    
    // Create an intermediate node and orient it to be level by fixing look direction.
    // This is needed specifically for nodes on walls.
    Node intermediateNode = new Node();
    intermediateNode.setParent(anchorNode);
    Vector3 anchorUp = anchorNode.getUp();
    intermediateNode.setLookDirection(Vector3.up(), anchorUp);
    

    Note: the last two lines in the code sample above are the key to getting the orientation correct.