How to get vertices(positions) out of the scope after loading a 3D model

Hi Expert,

I tried to get the positions outside he scope of loading 3D objects (using loader.load()) . But, the error message always showed that TypeError: undefined is not an object. Even I tried using the following code, like
console.log(scene.children[0].geometry.getAttribute(‘position’));
console.log(scene.getObjectByName[‘’].geometry.getAttribute(‘position’));

Why is it easier to get positions inside the scope of loader.load()? ?
Please advise. Thanks.

Loading is asynchronous - onLoad callback will not be called until model is ready, by which time the rest of your code will already have proceeded with execution.

1 Like

I put the code in the end of the program. But, it still did not work. The 3D model is supposed to be loaded before the end of the program, right? It still could not catch the scene.children.

No, as above, the code is asynchronous, it doesn’t have beginning or the end. You could put 1 billion lines before .load and .children.length and you would still not see the value, since .load is usually postponed past the synchronous queue (ie. it’ll be executed whenever there’s time for that.)

let model;

gltfLoader.load('model.glb', (gltf) => {
  console.info(gltf.scene.children.length); // <- Will always have a value here

  model = gltf.scene;
});

console.info(model.children.length); // <- You can safely assume it will *never* have a value here

There are just 2 cases you need to handle:

a) If you need the value for to parse the model after it’s loaded, just use the callback:

const doSomeParsingToMyModel = (model) => {
  // NOTE Model will always be loaded here
};

gltfLoader.load('model.glb', (gltf) => {
  doSomeParsingToMyModel(gltf.scene);
});

b) If you need the value in a continuous rendering loop, just put it in an if conditional

let model;

gltfLoader.load('model.glb', (gltf) => {
  model = gltf.scene;
});

const doSomethingWithModel = (model) => {
  if (!model) {
    return;
  } 

  // NOTE Model will always be loaded here
};

const onFrame = () => {
  requestAnimationFrame(onFrame);

  doSomethingWithModel(model);
};

Can’t think of any other cases - all you need to do is ensure you wait with model-related code until the model is actually loaded (you don’t have power over how or when it’s loaded, but you can always check if it’s been always loaded.)

One question, I could get a scene structure by console.log(scene), but it returned “undefined” by using console.log(scene.children[0]). Why not able to get into the structure and get the position?

Not sure if my info is enough for you to check on the issue.

Thanks.

One way to overcome this problem is the following (Warning: hack ahead!) :

Since you don’t know, exactly when a certain value will be available, I have on occasion resorted to the following trick, from within the animation loop:

If (asynchronusly_provided_value) then {
//do something with that value that you've been waiting for
...
} else {

// else: do nothing with that value and check again next frame

}

You have to be patient to wait for an unknown and unpredictable amount of time, and stand the “pain” associated with a possibly incomplete scene etc. for the duration of the waiting time.

1 Like

You’re right!

I just got the position data returned when I put the code, console.log(scene.getObjectById()), inside the animation function.

Thanks for your sharing.