Search code examples
javascriptrecursionscenegraph

Recursive function is not being executed


I am trying to recursively load a scenegraph structure from a JSON file. My idea was to call the same function on all child nodes until the last node has no children. However when debugging the code I found that the recursive call of loadNodes inside the second loop is being ignored and instead the loop just increases the counter and starts with the next loop.

I checked my syntax and I check calling other functions inside the loop (which works)..

Does anybody have an idea on what I am doing wrong?

function loadNodes(obj, current_group_node) {
    for (let i = 0; i < obj.length; i++) {
        if (obj[i].nodetype === 'group') {
            let new_group_node = new GroupNode(new Matrix(obj[i].matrix));
            current_group_node.add(new_group_node);
            for (let j = 0; j < obj[i].children.length; j++) {
                loadNodes(obj[i].children[j], new_group_node);
            }
        } else {
           // some more logic

        }
    }
}

My function receives an array of objects with the following possible structure:

{
  "nodetype": "group",
  "name": "root",
  "matrix": [
    1,0,0,0,
    0,1,0,0,
    0,0,1,0,
    0,0,0,1
  ],
  "children": [
    {
      "nodetype": "group",
      "name": "driver-cube-group",
      "matrix": [
        1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        0,0,0,1
      ],
      "children": [
        {
          "nodetype": "aabox",
          "name": "driver-cube",
          "minpoint": {
            "x": -3,
            "y": -3,
            "z": -3,
            "w": 1
          },
          "maxpoint": {
            "x": -2,
            "y": -2,
            "z": -2,
            "w": 1
          },
          "color": {
            "x": 1,
            "y": 1,
            "z": 1,
            "w": 1
          }
        }
      ]
    }
  ]
}

Solution

  • loadNodes expects the first argument to be an array of objects, not a single object. You don't need to call it in a loop on each child object, just call it once, passing the child array as the argument. It does its own looping over the array.

    So replace this:

            for (let j = 0; j < obj[i].children.length; j++) {
                loadNodes(obj[i].children[j], new_group_node);
            }
    

    with:

            loadNodes(obj[i].children, new_group_node);
    

    It might be helpful to rename the first argument from obj to arr, to make it clear that it expects an array, not a single object.