0

Currently trying to get to grips with Threebox.js and I'm run into an issue trying to create a wind turbine for each point on a layer. My code is as follows:

function AddTurbineLayer()
{
    console.log("AddTurbineLayer");
    if(!renderedModels)
    {
        console.log("AddTurbineLayer - renderedModels");
        renderedModels = true;


        var options = {
            obj: './assets/Models/WindTurbineGLB-Blender.glb',
            type: 'glb',
            scale: 10,
            units: 'meters',
            rotation: { x: 90, y: 180, z: 0 }, //default rotation
        }

        app.map.addLayer({
            id: 'threebox-test-models',
            type: 'custom',
            renderingMode: '3d',
            layout: {
                visibility: 'none'
            },
            onAdd: function (m, mbxContext) {

                var source = app.map.queryRenderedFeatures({layers: ['buffer_images']});
                console.log(source);
                let promises = [];

                for(var i = 0; i < source.length; i++) {
                    var feature = source[i];
                    options.rotation = { x: 90, y: i * 10, z: 0 };

                    promises.push(new Promise((resolve) => { 
                      tb.loadObj(options, function (model) {
                          var turbine = model.setCoords(feature.geometry.coordinates);
                          tb.add(turbine);
                          resolve(true);
                      });
                    }));
                }

                Promise.all(promises).then(function () {
                  console.log("All models loaded");

                  app.map.repaint = true;
                });
            },
            render: function (gl, matrix) {
                tb.update(); //update Threebox scene
            }
        });
    }
}

The method runs 5 seconds after the map has loaded or when the map is idle, whichever is first. What I'm expecting, since there are 4 points on the map corresponding to the 4 icons on the map, there should be 4 turbines next to each icon which it doesn't do.

Then to try and figure out how many it was creating I decided to set the Y rotation to be based on the index of the array, when doing this I was expecting 4 turbines rotating around the last point in the array. This didn't happen either and only rendered 2, I get the following result:

enter image description here

My question is, what am I missing to make this behaviour and why is it only rendering 2 turbines and not 4?

Edit 18/10: Here's the console log, it contains all the four points on the map enter image description here

Edit 19/10: One thing I noticed when trying to use the Threebox example for rendering multiple models at once but changing it from using random coordinates to the ones from my layer. enter image description here

Despite the fact that the variable j is defined in the same way as source it comes back as undefined. Is there something I'm missing with how JavaScript uses scopes? I've had a look at the types of scope and this should work

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Adam_R
  • 37
  • 2
  • 12
  • 1
    What does `console.log(source);` say? – M - Oct 17 '22 at 16:19
  • I've attached an image – Adam_R Oct 18 '22 at 07:54
  • @Adam_R You need to change `for (var i=0;` into `for (let i=0;`. – hackape Nov 10 '22 at 06:56
  • Explanation [here](https://stackoverflow.com/a/30479554/3617380). TL;DR: `for (let i` creates new `i` for each loop iteration, while `for (var i` share the same `i` across all iteration. It makes no diff in iteration logic per se, UNTILL you pass the i into some closure/function, which is exactly what you did. For `var i` case, by the time your `tb.loadObj(cb)` callbacks actually get called, they all find `i == 4` because that's what `i++` ends up when the for-loop breaks. – hackape Nov 10 '22 at 07:03
  • I'm the owner of Threebox repo you are using. Can you log in the console `feature.geometry.coordinates` of the four objects? – jscastro Nov 24 '22 at 17:19

0 Answers0