Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using webworker and IndexedDB for loader of Three js

I want to use dracoLoader of threeJS in multi-threads, then I selected Webworker and IndexedDB. I have gotten the correct Geometry in webworker, however, when I pass data to main thread using IndexedDB, the geometry will be changed to a normal JS object instead of a ThreeJS Geometry. The geometry lost its functions and some information.

webworker.js

self.saveDrcToIndexedDB = function (drcfinal) {

  var db;
  var request = indexedDB.open("drcDB");

  drcfinal.indexName = self.randomStr();

  request.onupgradeneeded = function(event) {

    console.log('successfully upgraded db');  

    db = event.target.result;
    var objectStore = db.createObjectStore("drcfinal", { keyPath: "indexName"});
  };

  request.onsuccess = function(event) {

    console.log('successfully opened db');

    db = event.target.result;
    var transaction = db.transaction(["drcfinal"], "readwrite");

    var objectStore = transaction.objectStore("drcfinal");
    objectStore.add(drcfinal).onsuccess = function(event) {
      self.postMessage(drcfinal.indexName);
    };
  } 
}

main.js

var worker = new Worker('webworker.js');

worker.addEventListener('message', function(e) {

  indexedDB.open("drcDB").onsuccess = function(event) {

    let db = event.target.result;   
    let objectStore = db.transaction(["drcfinal"]).objectStore("drcfinal");

    objectStore.get(e.data).onsuccess = function(event) {
      console.log(event.target.result);
    };
  }

}, false);

worker.postMessage(somedata);

Can I transfer a correct geometry to main thread? Or using other tools instead of IndexedDB? Or using other multi-threading tools instead of webworker?

like image 355
ClaireWang Avatar asked Feb 02 '18 03:02

ClaireWang


1 Answers

A mechanism called Structured Cloning is used when storing data in IndexedDB. Same applies to sending messages to and from WebWorkers via postMessage. It is not possible with this approach to duplicate functions. Thus you cannot transfer complete objects including their methods. Simply put, it is a better JSON.stringify/parse approach since Structured Cloning can e.g. handle cyclic dependencies.

AFAIK all web-browser available multi threading mechanisms such as WebWorker, SharedWorker and ServiceWorker use this actor based message sending approach.

However, you could use a Transferable object to transfer data from a WebWorker to the main thread using Worker.postMessage. This way, you could send THREE.Geometry's vertex array as a Transferable. E.g. when using a THREE.BufferGeometry within WebWorker.

const myVertexData = bufferGeometry.getAttribute('position').array.buffer;
self.postMessage({myVertices: myVertexData}, [myVertexData]);

This is quite fast since the data is not copied but only its ownership is changed.

like image 185
tomacco Avatar answered Oct 19 '22 23:10

tomacco