<h5 dir="auto">Description of the problem</h5>
<p dir="auto">ThreeJs ThreeMF loader is blocking the UI while upzipping the 3MF file.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="try {
	zip = new JSZip( data ); // eslint-disable-line no-undef
} catch ( e ) {
	if ( e instanceof ReferenceError ) {
		console.error( 'THREE.3MFLoader: jszip missing and file is compressed.' );
		return null;
	}
}"><pre class="notranslate"><span class="pl-k">try</span> <span class="pl-kos">{</span>
	<span class="pl-s1">zip</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">JSZip</span><span class="pl-kos">(</span> <span class="pl-s1">data</span> <span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// eslint-disable-line no-undef</span>
<span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span> <span class="pl-s1">e</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
	<span class="pl-k">if</span> <span class="pl-kos">(</span> <span class="pl-s1">e</span> <span class="pl-k">instanceof</span> <span class="pl-v">ReferenceError</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">'THREE.3MFLoader: jszip missing and file is compressed.'</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">return</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
	<span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">According the the <a href="https://stuk.github.io/jszip/documentation/howto/read_zip.html" rel="nofollow">JSZip documenation</a> I assume it would be better to unzip the container asynchronously not to block the UI.</p>
<h5 dir="auto">Three.js version</h5>
<ul class="contains-task-list">
<li>[x ] Dev</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> r120</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> ...</li>
</ul>
<h5 dir="auto">Browser</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Chrome</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Firefox</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Internet Explorer</li>
</ul>
<h5 dir="auto">OS</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Windows</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> macOS</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Linux</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Android</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> iOS</li>
</ul>
<h5 dir="auto">Hardware Requirements (graphics card, VR Device, ...)</h5>
<p dir="auto">As discussed in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="227275148" data-permission-text="Title is private" data-url="https://github.com/mrdoob/three.js/issues/11301" data-hovercard-type="issue" data-hovercard-url="/mrdoob/three.js/issues/11301/hovercard" href="https://github.com/mrdoob/three.js/issues/11301">#11301</a> one of the main problems that we have in WebVR, although is annoying in non-VR experiences too, is blocking the main thread while loading assets.</p>
<p dir="auto">With the recent implementation on <a href="https://blog.mozvr.com/link-traversal/" rel="nofollow">link traversal</a> in the browser non-blocking loading is a must to ensure a satisfying user experience. If you jump from one page to another and the target page start to load assets blocking the mainthread, it will block the render function so no frames will be submitted to the headset and after a small period of grace the browser will kick us out from VR and it will require the user to take out the headset, click enter VR again (user gesture required to do so) and go back to the experience.</p>
<p dir="auto">Currently we can see two implementations of non-blocking loading of OBJ files:</p>
<ul dir="auto">
<li>
<p dir="auto">(1) Using webworkers to parse the obj file and then return the data back to the main thread <a href="https://threejs.org/docs/index.html#examples/loaders/WWOBJLoader2" rel="nofollow">WWOBJLoader</a>:<br>
Here the parsing is done concurrently and you could have several workers at the same time. The main drawback is that once you've loaded the data you need to send the payload back to the mainthread to reconstruct the THREE objects instances and that part could block the main thread:<br>
<a href="https://github.com/kaisalmen/WWOBJLoader/blob/master/src/loaders/WWOBJLoader2.js#L312-L423">https://github.com/kaisalmen/WWOBJLoader/blob/master/src/loaders/WWOBJLoader2.js#L312-L423</a></p>
</li>
<li>
<p dir="auto">(2) Mainthread promise with deferred parsing using setTimeOut:<a href="https://github.com/facebook/react-vr/tree/master/ReactVR/js/Loaders/WavefrontOBJ">Oculus ReactVR</a>: This loader keeps reading lines using small time slots to prevent blocking the main thread by calling setTimeout: <a href="https://github.com/facebook/react-vr/blob/master/ReactVR/js/Loaders/WavefrontOBJ/OBJParser.js#L281-L298">https://github.com/facebook/react-vr/blob/master/ReactVR/js/Loaders/WavefrontOBJ/OBJParser.js#L281-L298</a><br>
With this approach the loading will be slower as we're just parsing some lines on each time slot, but the advantage is that once the parsing is completed, we'll have the THREE objects ready to use without any additional overhead.</p>
</li>
</ul>
<p dir="auto">Both has their pros and cons and I'm honestly not an expert of webworkers to evalute that implementation but It's an interesting discussion that ideally would lead to a generic module that could be used to port the loaders to a non-blocking version.</p>
<p dir="auto">Any suggestions?</p>
<p dir="auto">/cc <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/mikearmstrong001/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/mikearmstrong001">@mikearmstrong001</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/kaisalmen/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/kaisalmen">@kaisalmen</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/delapuente/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/delapuente">@delapuente</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/spite/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/spite">@spite</a></p>