List of models loaded in Three.js

Within this block of code, my goal is to load multiple 3D models using the asynchronous .load method.

async function loadModels(lights, roomWidth, roomHeight) {
    // Initializing an empty array to store the loaded models
    models = []
    
    /* Loading the first model: "Sci-Fi Light 11" */
    const loader = new GLTFLoader(loadingManager);
    loader.load('./models/scifi_light_11.glb', function (gltf) {
        // Transforming and positioning the model in various rooms
        gltf.scene.scale.set(0.02, 0.02, 0.02)
        gltf.scene.rotateZ(-0.7 * Math.PI);
        gltf.scene.receiveShadow = true;
        gltf.scene.castShadow = true;
        // Code snippet to position the model in different rooms goes here...
        
        // Adding the loaded model to the scene and the models array
        scene.add(gltf.scene);
        models.push(gltf);
    });
    
    /* Loading the second model: "Terminal" */
    const loader1 = new GLTFLoader(loadingManager);
    // Additional description for the source of the model goes here...
    loader1.load('./models/terminal/scene.gltf', function (gltf) {
        // Similar process of transforming, positioning, and adding the model to the scene
        // Code for handling the second model goes here...
    });

    // The loading process for other models continues similarly...

}
It's evident that the current approach of populating the models list isn't effective. How can I modify this function to return a Promise containing all the loaded models?

Answer №1

To start, the first step is to create a promisified wrapper around GLTFLoader.load by following this link.

/**
 * Load a GLTF resource in a promisified manner.
 * @param {string} path The path/URL of the .gltf or .glb file.
 * @param {THREE.LoadingManager} manager The loading manager to utilize. Defaults to THREE.DefaultLoadingManager.
 * @returns {Promise<GLTF>}
 */
function loadGltf(path, manager = THREE.DefaultLoadingManager) {
  return new Promise((resolve, reject)=>{
    const loader = new GLTFLoader(manager);
    loader.load(
      path, 
      // Resolve with gltf argument from onComplete callback
      (gltf) => { resolve(gltf); },
      // Use null for onProgress as ES2015 Promises do not provide progress reporting
      null,
      // Reject with error argument from onError callback
      (err) => { reject(err); }
    );
  });
}

Now, you can create promises for each GLTF.

const p1 = loadGltf( "room1.glb" ).then( 
    /* Handle room1 operations and specify the desired result */ );
const p2 = loadGltf( "room2.glb" ).then( /* ditto */ );

Finally, initialize the array and use Promise.all to organize it.

const models = []
// Use spread operator while pushing
Promise.all([p1, p2]).then( (gltfs) => models.push( ...gltfs );

The gltfs parameter in the then function call will contain the results of p1, p2, etc., in the same order they were added to all(). You don't necessarily have to return the entire GLTF object from p1, p2, etc.; if each GLTF reduces to a single object and its children, you could pass out something like gltf.scenes[0].children[0]. Just be mindful of what is being returned from the promises when accessing them through the array.

It's important to consider that the array may not be fully populated by the time your application reaches the animate() function (or any other attempt to access the array contents). This can be addressed by either chaining another then() call before animate(), or using a guard statement like if(models.length) { ... } to handle array access.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

After zooming, are mouse coordinates pointless?

Issue with Mouse Coordinates After Zooming I am facing a problem with obtaining accurate mouse coordinates after zooming in my code. I have included a JS fiddle link to showcase the issue. I am unsure if it is a bug in three.js or if my approach to drawin ...

Guide on how to prevent Paste (Ctrl+V) and Copy (Ctrl+C) functionalities in a TextField within MaterialUI

Is there a way to restrict the Paste (Ctrl+V) and Copy (Ctrl+C) functions in a specific TextField within MaterialUI? I am currently working with ReactJs ...

Drag and Drop in Angular with Dragula - Trigger Confirmation on Drop Event

I need to implement a confirm modal dialog (UI Kit) when an element is dragged into a new bag using angular 1.4.8 and angular-dragula. If the user clicks ok, the process should continue, but if they click NO, the element should return to its original bag. ...

Is it possible to remove Sprites from a three.js scene?

Currently facing an issue where I am trying to update axis labels on a 3D plot by removing the old labels (implemented as sprites) before adding new ones. Unfortunately, I am experiencing difficulties. The previous labels seem to persist in the scene even ...

Ensure Your Forms Are Error-Free with Jquery Form Validation

Currently working on a registration form that involves the use of credit cards. I have reached the stage of form validation to ensure that users input correct data in the appropriate fields. However, this has led me to ponder whether relying on JQuery for ...

Tips for adding information to a PHP file

Previously, I used PHP to append form data to a JSON file. Currently, I am working on a PHP file instead of a JSON file with two parameters, as shown to users in the figure below. Image URL Link My Form: <form action="process.php" method="POST"> ...

Stripping out only the position attribute using jQuery

I have implemented a code with the following characteristics: The navigation items' texts are hidden behind certain Divs, which I refer to as Navigation Divs. When the mouse hovers over these pixels (navigation Divs), the text that is behind the ...

PHP displays the array returned by Ajax as "[object Object],[object Object]"

When working with Jquery, I am creating two arrays - one embedded inside the other. Here is an example of what it looks like: arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arrayTwo = [{name:'foo',value:'blah&ap ...

What is the best way to enable import and require support for npm modules?

Recently, I successfully published my debut module on npm using Javascript. Now, I am eager to ensure that it can support both import and require functions. Can someone guide me on how to achieve this? For reference, the module in question is available at ...

What is the best way to utilize the ajax factory method in order to establish a $scoped variable?

One issue I frequently encounter in my controllers is a repetitive piece of code: // Get first product from list Product.get_details( id ) .success(function ( data ) { // Setup product details $scope.active_product = data; }); To avoid this ...

Executing child processes in the Mean Stack environment involves utilizing the `child_process`

I am working on a Mean application that utilizes nodejs, angularjs and expressjs. In my setup, the server is called from the angular controller like this: Angular Controller.js $http.post('/sample', $scope.sample).then(function (response) ...

IFrame issue: Page is constantly refreshing when on iframe source

Recently, I started working with asp.net and I'm attempting to call an Iframe src within a table row using a JavaScript click event. (i.e onclick="return loadPhaseWiseChart("DGSET00025");") Here is my code snippet: <tr height="25" id="row3" oncli ...

What is the best method to retrieve JSON data from a different domain?

I am exploring the Google Images API and need to retrieve JSON data from an external domain. In the past, I have used the ajax function to fetch JSON from my own server. However, this time I will be retrieving it from: https://ajax.googleapis.com/ajax/ser ...

The error message "TypeError: dom.getElementsByTagName is not a function in Node.js" indicates

I have just started learning HTML and web development. I am trying to extract a list of tags from an HTML document but I keep receiving the error message TypeError: dom.getElementsByTagName is not a function. I am making a GET request using axios, then u ...

AngularJS factory or filter failing to update properly

I have been working on a system that manages translations in my factory. I set the language as a string and then use a filter to update the view when the language changes. Everything works fine if I define the language in the view beforehand, but when I t ...

Turn off automatic zooming for mobile device input

One common issue observed in mobile browsers is that they tend to zoom in on an input field or select drop-down when focused. After exploring various solutions, the most elegant one I came across involves setting the font-size of the input field to 16px. W ...

Uploading videos to a single YouTube channel using the YouTube Data API

I have been tasked with creating a node js app for a select group of individuals who need to upload videos. However, our budget is quite limited and we are unable to afford cloud storage services. I am curious if it would be feasible to create a key syste ...

What is the process for updating the internal TypeScript version in VS Code?

When using VS Code, I noticed it comes with its own TypeScript version: Is there a way to update this? The current version is 4.9.3. https://i.sstatic.net/vEx85.png ...

"Encountered a duplication issue while attempting to create a unique name by combining input from the textbox with the original file name using a combination of

Hey there, I'm looking to create a new name by adding the name from a text box to an original file. script.js angular.module('signin').service('fileUpload', ['$http', function ($http) { this.uploadFileToUrl = funct ...

Tips for showing only the date (excluding time) from a get operation in javascript (specifically using node js and mysql)

I recently built a CRUD application using Node.js and MySQL. However, I am facing an issue where I am unable to display the date without the time and in the correct format. { "id": 1, "name": "Rick Sanchez", "dob": & ...