Jump to content

Multi-threading BABYLON.SceneLoader.ImportMesh


Hagop
 Share

Recommended Posts

Let me start by stating that I have thousands of meshes to import into a scene.

Since the following  loop will not work because i is incremented before the callback function of ImportMesh is complete

for (var i:=0; i< max;i++)

{

BABYLON.SceneLoader.ImportMesh("", "products/", productBabylonName, scene, function (newMeshes) {});

newMeshes.position = new BABYLON.Vector3(x,y,z)

}

I solved the problem by creating a recursive loop. Here  is my code

productLocationData (JSON format) & productCount  are retrieved from database using a AJAX-PHP-MySQL call

var Pindex=0;

populateRack ( productLocationData , productCount,Pindex );

var populateRack = function(productLocationData,productCount,Pindex)
            {
                var popRackProdPositionX = parseFloat(productLocationData.products[Pindex].positionX);
                var popRackProdPositionY = parseFloat(productLocationData.products[Pindex].positionY);
                var popRackProdPositionZ = parseFloat(productLocationData.products[Pindex].positionZ);
                var productBabylonName   = productLocationData.products[Pindex].productBabylonName;
                                                                                
                                        BABYLON.SceneLoader.ImportMesh("", "productshr/", productBabylonName, scene, function (newMeshes) {
                                                     newMeshes[0].position = new BABYLON.Vector3(popRackProdPositionX,popRackProdPositionY,popRackProdPositionZ);
                                                                     
                                        });//end import
                         
                Pindex +=1;
                if (Pindex < productCount)
                {
                populateRack(productLocationData,productCount,Pindex);    
                }

            }

Everything works fine. However, if there is a simpler way please advise.

HOWEVER my MAIN question is the following. Can I run many instances of the above code in parallel ? Reason being of course to have everything load faster. I know that javascript is a sinle-threaded language. Could HTML5 web workers be of help here? Or any other plug-in such as parallel.js ? Has anybody applied parallel processing to BABYLON.SceneLoader.ImportMesh. I am aware that Web Workers has been applied to collisions. Does anybody have an example?

 

 

Link to comment
Share on other sites

JS is indeed single-threaded, so the only way to parse multiple things in parallel would be workers. Workers don't share memory with the main thread though, so this would only be beneficial if parsing took significantly longer than copying the memory for the results back into the main thread. Have you measured where the time is being spent currently? If most of the time is being spent waiting for the files to load, then I'd expect the browser already does those in parallel, so code changes might not help much.

Incidentally, you can fix your initial loop with closures:

for (var i=0; i<max; i++) {
    var callback = makeHandler(i)
    BABYLON.SceneLoader.ImportMesh("", somePath, someName, scene, callback)
}

function makeHandler(i) {
    return function() {
        console.log('Value of i: ', i)
    }
}

 

Link to comment
Share on other sites

Thanks Fenomas. Indeed most of the "time" is spent, waiting for one mesh to load before the other. So if i could run multiple  Import Meshes in parallel, then I would save precious time. I would segment my database so that each ImportMesh command accesses  a different chunk of data. I will test the loop closure trick.

Link to comment
Share on other sites

On 9/22/2016 at 1:11 PM, Hagop said:

Let me start by stating that I have thousands of meshes to import into a scene

Are you really importing thousands of models in a single scene ? Because that is beyond imaginable, I can't imagine a web browser handling such a tedious task.

If I were you, I would have included all the models in a single .babylon scene and loaded it using the SceneLoader.

Link to comment
Share on other sites

X3MC2, yes indeed, thousands. I am thinking as a workaround as you mentioned to group them is babylon files, store in a database and load them with SceneLoader using the data: command. I will check if Web Worker could be helpful in this scenario as XMLHTTP is supported in Worker.

Adam, how would the webworker-preload example be applied BABYLON.SceneLoader.ImportMesh callback function, which is the main reason for delay?

Link to comment
Share on other sites

You would just use the webworker to load the file and then serlialize it to pass to the main thread. If your not familiar with webworkers then it might be tough. Also you could do a recursive function to load.  JavaScript is single thread so you would have to fake it or use webworkers.

Link to comment
Share on other sites

7 hours ago, Pryme8 said:

You would just use the webworker to load the file and then serlialize it to pass to the main thread.

It doesn't appear that you have to do that.  Once the webworker loads the file, it is available from cache.  So as long as you go to access it after the webworker has loaded it, you are good.

 

Link to comment
Share on other sites

Ok, I agree with Adam that textures & audio are just as important as geometry.  If coming from Blender, you can in-line (base64) textures.  Assuming you have gzip on your server, only a slight increase in total transfer.

As far as using JIT (Tower of Babel in-line source code) as opposed to JSON (babylon file), I am not sure if dynamically added script files in a worker are going to be visible in main thread.  Might even vary by browser. 

I have a tool to generate in-line (base64) audio, but have not committed it.  It is Javascript source code.

 

Link to comment
Share on other sites

The way I was handeling passing objects with webworkers is always Serialize them @adam, I have a recursive loop function that checks the the objects keys and then that's keys keys and so on an so forth until it's completely a string then you can pass what ever.   A lot of the confusion I had initally with web workers was what data actually needs to be passed back and forth, if you just have the web worker grab the file and stringify it then pass that over to the main thread to an array for a file loading stack you should be good to go and get async loading of objects.

 

and I guess you won't see any performance increase really using webworkers to load a file because that's not really considered a intensive operation.

Link to comment
Share on other sites

I'm lost. Generally the point of webworker is to do things without blocking the UI thread. Loading assets doesn't block the UI thread, so what's the benefit of doing it in a worker?

I mean - the browser has a network stack running underneath the JS VM that knows how to async load multiple assets in parallel. When you load assets from a webworker, the requests go to the same network stack, don't they? All it does is add overhead for copying memory back and forth. Am I missing something?

(Of course if you parsed the results in a worker, that might have some benefit, but that's not what's under discussion here, right?)

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...