<p dir="auto">Hi,</p>
<p dir="auto">For my project I need to load/unload various models avoiding main JS thread to get blocked (models are a little heavy in MB) So I tried this approach:</p>
<p dir="auto"><strong>Worker code</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="importScripts( &quot;lib/dev.three.js/build/Three.js&quot; );

function privateComponentLoaded( geometry ) {
    postMessage( geometry );
    self.close();
}

self.onmessage = function(event) {
    var componentLoader = new THREE.JSONLoader();
    componentLoader.load( event.data, self.privateComponentLoaded );
};"><pre class="notranslate"><span class="pl-en">importScripts</span><span class="pl-kos">(</span> <span class="pl-s">"lib/dev.three.js/build/Three.js"</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">function</span> <span class="pl-en">privateComponentLoaded</span><span class="pl-kos">(</span> <span class="pl-s1">geometry</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-en">postMessage</span><span class="pl-kos">(</span> <span class="pl-s1">geometry</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-en">close</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-en">onmessage</span> <span class="pl-c1">=</span> <span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">componentLoader</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-c1">THREE</span><span class="pl-kos">.</span><span class="pl-c1">JSONLoader</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-s1">componentLoader</span><span class="pl-kos">.</span><span class="pl-en">load</span><span class="pl-kos">(</span> <span class="pl-s1">event</span><span class="pl-kos">.</span><span class="pl-c1">data</span><span class="pl-kos">,</span> <span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-c1">privateComponentLoaded</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Main code</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var _self = this;

var worker = new Worker( &quot;ComponentLoaderWorker.js&quot; );
 worker.onmessage = function(event) {
    _self.createComponent( event.data );
  };
worker.onerror = function(error) { console.error( &quot;Worker error: Error al cargar&quot; ) };
worker.postMessage( myURL );

this.createComponent = function ( geometry ) {

    myMesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );

    myObj.add( myMesh );
};"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">_self</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">worker</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Worker</span><span class="pl-kos">(</span> <span class="pl-s">"ComponentLoaderWorker.js"</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
 <span class="pl-s1">worker</span><span class="pl-kos">.</span><span class="pl-en">onmessage</span> <span class="pl-c1">=</span> <span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">_self</span><span class="pl-kos">.</span><span class="pl-en">createComponent</span><span class="pl-kos">(</span> <span class="pl-s1">event</span><span class="pl-kos">.</span><span class="pl-c1">data</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-s1">worker</span><span class="pl-kos">.</span><span class="pl-en">onerror</span> <span class="pl-c1">=</span> <span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">error</span><span class="pl-kos">(</span> <span class="pl-s">"Worker error: Error al cargar"</span> <span class="pl-kos">)</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-s1">worker</span><span class="pl-kos">.</span><span class="pl-en">postMessage</span><span class="pl-kos">(</span> <span class="pl-s1">myURL</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">createComponent</span> <span class="pl-c1">=</span> <span class="pl-k">function</span> <span class="pl-kos">(</span> <span class="pl-s1">geometry</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>

    <span class="pl-s1">myMesh</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-c1">THREE</span><span class="pl-kos">.</span><span class="pl-c1">Mesh</span><span class="pl-kos">(</span> <span class="pl-s1">geometry</span><span class="pl-kos">,</span> <span class="pl-k">new</span> <span class="pl-c1">THREE</span><span class="pl-kos">.</span><span class="pl-c1">MeshFaceMaterial</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-s1">myObj</span><span class="pl-kos">.</span><span class="pl-en">add</span><span class="pl-kos">(</span> <span class="pl-s1">myMesh</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Error given by chrome for previous code</strong></p>
<p dir="auto"><code class="notranslate">Uncaught TypeError: Object has no method 'computeBoundingSphere'    Three.js:133</code></p>
<p dir="auto">I checked that line and what crashed was this:</p>
<p dir="auto"><code class="notranslate">this.geometry.computeBoundingSphere()</code></p>
<p dir="auto">So I came up to the conclusion that geometry was not a ThreeJS geometry due to JSON communication parsing from Worker to main thread.</p>
<p dir="auto">So I think Worker support has to be implemented inside JSONLoader directly. However, maybe the geometry can be recovered somehow or maybe I'm missing something important.</p>
<p dir="auto"><strong>What I think needs to be done</strong></p>
<p dir="auto">The worker has to just do the <code class="notranslate">XMLHttpRequest</code> Then, the main thread has to call createModel so geometry object gets created. What do you think?</p>
<p dir="auto">I think if we also put the createModel function inside worker we will come to the same problem I have here (although it could be desirable to have this inside worker too in the name of performance for main thread)</p>
<p dir="auto">I think I can try to do this changes in JSONLoader.</p>
<p dir="auto">Currently (<a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/mrdoob/three.js/commit/0b340e7e5edc78872901d34eef04b12151e2ff85/hovercard" href="https://github.com/mrdoob/three.js/commit/0b340e7e5edc78872901d34eef04b12151e2ff85"><tt>0b340e7</tt></a>) the GLTFExporter generates new meshes, buffer views and accessors, referencing buffers full of duplicated data even if the geometry / attribute is reused in the scene.</p>
<p dir="auto"><strong>Steps to reproduce</strong>:</p>
<ol dir="auto">
<li>Create a single <code class="notranslate">BoxBufferGeometry</code> is and attach to three different meshes.</li>
<li>Add the meshes to a scene.</li>
<li>Export the scene using the <code class="notranslate">GLTFExporter.parse()</code>-method.</li>
</ol>
<p dir="auto">Fiddle that recreates this problem: <a href="https://jsfiddle.net/jxg9b67a/3/" rel="nofollow">https://jsfiddle.net/jxg9b67a/3/</a></p>
<p dir="auto">The resulting GLTF object has three different <code class="notranslate">nodes</code> (as expected), but also three different <code class="notranslate">meshes</code>. Additionally each mesh references unique accessors with unique bufferviews referencing a single buffer but at different offsets (meaning that the all the data is duplicated to multiple positions).</p>
<p dir="auto"><strong>Expected behaviour</strong> according to the <a href="https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#instantiation">GLTF spec</a> would be that the GLTF object has three <code class="notranslate">nodes</code>, all referencing a single mesh.</p>
<p dir="auto">Note that if the meshes use different materials, different objects will have to be created; but they could still reference the same accessors for attributes and index.</p>