arcoresceneform

ARCORE: remove a specific renderable by clicking on this renderable


I'm working on a project using Sceneform from ARCore. I develop it base on HelloSceneform example provided by ARCore. What I wanna do is adding a renderable object by a hit and then delete it when I click on the specific renderable on the screen. I've tried method AnchorNode.setOnTapListener as following, but it didn't work(no response):

anchorNode.setOnTapListener(new Node.OnTapListener() {
                      @Override
                      public void onTap(HitTestResult hitTestResult, MotionEvent motionEvent) {
                          if(anchorNode.getAnchor()!=null){
                              arFragment.getArSceneView().getScene().removeChild(anchorNode);
                              anchorNode.getAnchor().detach();
                              anchorNode.setParent(null);
                          }
                      }
                  });

I also tried the following method, which causes unexpected close:

      Scene scene = arFragment.getArSceneView().getScene();
      scene.addOnPeekTouchListener(new Scene.OnPeekTouchListener() {
          @Override
          public void onPeekTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
              Node node = hitTestResult.getNode();
              node.setParent(null);
          }
      });

Is there any method could achieve this feature?


Solution

  • The code below should detect the touch and delete the node.

    If you want to have a separate button to delete a selected node you can add a regular button and listener and just use the 'touch' event to select the node you want to delete.

    private void handleOnTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
            Log.d(TAG,"handleOnTouch");
            // First call ArFragment's listener to handle TransformableNodes.
            arFragment.onPeekTouch(hitTestResult, motionEvent);
    
            //We are only interested in the ACTION_UP events - anything else just return
            if (motionEvent.getAction() != MotionEvent.ACTION_UP) {
                return;
            }
    
            // Check for touching a Sceneform node
            if (hitTestResult.getNode() != null) {
                Log.d(TAG,"handleOnTouch hitTestResult.getNode() != null");
                Node hitNode = hitTestResult.getNode();
    
                if (hitNode.getRenderable() == andyRenderable) {
                    Toast.makeText(LineViewMainActivity.this, "We've hit Andy!!", Toast.LENGTH_SHORT).show();
                    arFragment.getArSceneView().getScene().removeChild(hitNode);
                    AnchorNode hitNodeAnchor = (AnchorNode) hitNode;
                    if (hitNodeAnchor != null) {
                         hitNode.getAnchor().detach();
                    }
                    hitNode.setParent(null);
                    hitNode = null;
                 }
            }
    

    }

    The above is extracted from various parts of a VR test application and combined here for a concise example - the full working application source is available here: https://github.com/mickod/LineView

    Update - Kotlin version (tested April 2020):

        private fun removeAnchorNode(nodeToRemove: AnchorNode) {
            //Remove an Anchor node
            arFragment.getArSceneView().getScene().removeChild(nodeToRemove);
            nodeToRemove.getAnchor()?.detach();
            nodeToRemove.setParent(null);
            nodeToRemove.renderable = null
        }