androidaugmented-realityarcoresceneformsceneview

How can I get list of all objects and their co-ordinates placed in scene in ARCore?


I'm trying to place a new object in the scene, how can I get list of objects already placed in the scene and their co-ordinates so that the new object I place wouldn't be placed over existing objects in the scene in AR Core?


Solution

  • Simple Hierarchy (linear)

    This is an example of the simplest linear node hierarchy, where each anchor is the parent of only one node with a renderable. Every Sceneform node containing renderable, every anchor with its single child and every light source are attached to the root node of the scene. Give each node a name and create a dictionary of type <String, Vector3> to populate an empty List with a collection of dictionaries (where the key is a name of a node and a value is its coordinates).

    val scene = arFragment.arSceneView.scene
    
    anchorNode.name = "anchor"      // Anchor with Model A child node
    modelNode.name = "model"        // Model B node without anchor
    lightNode.name = "light"        // Light node
    
    scene.addChild(anchorNode)
    scene.addChild(modelNode)
    scene.addChild(lightNode)
    
    var nodes = emptyList<Map<String, Vector3>>()
    
    for (i in 0..scene.children.size-1) {
        val name: String = scene.children[i].name
        val coords: Vector3 = scene.children[i].worldPosition
        val dictionary = mutableMapOf<String, Vector3>()
        dictionary.put(name, coords)
        nodes += dictionary
    
        // down the hierarchy (anchor -> modelR)
        if (scene.children[i].name == "anchor" && !scene.children[i].children.isEmpty()) {
            val nameR: String = scene.children[i].children[0].name
            val coordsR: Vector3 = scene.children[i].children[0].worldPosition
            val dictionaryR = mutableMapOf<String, Vector3>()
            dictionaryR.put(nameR, coordsR)
            nodes += dictionaryR
        }
    }
    
    Log.d("Nodes:", "$nodes")
    

    As a result, you'll get a List of four dictionaries with nodes' names and their coordinates:

    //*  [ {anchor=[x,y,z]}, {modelR=[x,y,z]}, {model=[x,y,z]}, {light=[x,y,z]} ]  *//
    


    Complex Hierarchy (cascade)

    In some situations, you will be using models that consist of cascade of nodes, or using many nodes with renderables that are attached to the same anchor. Then you cannot live without the Sceneform .callOnHierarchy(..) method with lambda, which saves you from the need to create an algorithm that traverses all the scene nodes down the hierarchy of each branch.

    scene.callOnHierarchy { eachNode ->
        val name: String = eachNode.name
        val coords: Vector3 = eachNode.worldPosition
        val dictionary = mutableMapOf<String, Vector3>()
        dictionary.put(name, coords)
        nodes += dictionary
    }
    
    Log.d("Nodes:", "$nodes")
    

    The result is the same:

    //*  [ {anchor=[x,y,z]}, {modelR=[x,y,z]}, {model=[x,y,z]}, {light=[x,y,z]} ]  *//