Stop overloading your web browser with those 3D models

Álvaro Casado
Sep 6, 2018 · 3 min read

A quick (and really basic) guide on WebWorkers + three.js

Some months ago I was working on a web application built with three.js. The application goal was to let the user visualize objects that were 3D scanned previously, and then stored in PLY format files. These files are around 200 megabytes each — and there were about 10–12 of them on display in some cases.

As you may be wondering, the loading time was absurdly slow. In most cases it took around 1.5 - 2 minutes to load the application with a 5Mbps internet connection. During this time interval the whole application was totally blocked and didn’t respond to any user interaction. After we implemented web workers, our application loading time got reduced to around 20–30 seconds (and users were able to start interacting with the models as soon as they were loaded individually).

A casual user trying to visualize a pair of objects with the app.

Blocking user interaction can make them feel unconfortable, close our web application tab or even smash their brand new smartphone onto the table — trust me, we don’t want that to happen.

So, how do we get rid of this annoying blocking behaviour? The answer to this question is WebWorkers, which let you run JavaScript processes in background threads. Also, communication between a worker and the main thread is possible by posting messages to an event handler.

Think of JavaScript threads loading 3D models as bees that are collecting pollen from a collection of flowers. If there was only a queen bee, she would have to pick up pollen from every single flower in the garden. If, instead, there was a swarm of bees — which play the role of our web workers — this process would take up significantly less time because all of our workers will load a model at the same time. This way, our queen bee — aka our main thread, which is responsible of user interaction — can continue performing her usual tasks without being overwhelmed by the loading process.


Implementing web workers in three.js

That’s enough explanation for now, so let’s get down to the code! As you can see, we have two different scripts:

  • main.js: code of our three.js application. Spawns a web worker for each model file and tells them which one to load by using the postMessage method of the HTML WebWorkers API.
  • worker.js: code that loads a PLY model file and stores it’s mesh information as a BufferGeometry, then sends it back to the main thread by posting a message to the event handler again.

When the main thread get’s a worker’s response, it creates and appends to the scene a new three.js Mesh whith the BufferGeometry loaded from the message data.

Okay, so now we are able to load a 3D model into our scene without blocking the main thread, but how do we set up it’s position? We can do this quickly by applying a transformation matrix to it before appending the object to the scene in our main thread:

child.geometry.applyMatrix(transformationMatrix);child.geometry.verticesNeedUpdate = true;

NOTE: This method is not suitable for all applications, if you are loading really small 3D models you can get worse results when you use workers compared than when you just use a main thread. This is due to the communication overhead that comes from every web worker sending the BufferGeometry back to the main thread. So be careful and choose wisely. We don’t want more smashed smartphones.

For more information on WebWorkers check out these links:

Álvaro Casado

Written by

Mostly focused on data science + graphics + organizing @infusionvlc

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade