6

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?

1 Answer 1

5

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.

2
  • Hi @tomacco, is it enough to transfer the arrayBuffer of the vertices in order to create a new BufferGeometry back in the main thread? Commented Dec 9, 2018 at 21:56
  • I answer myself: yes it is if one is handling colors and indices separately. On the main thread, one's ought to code: const vertexBuffer = new THREE.Float32BufferAttribute(myVertexData, 3); let geometry = new THREE.BufferGeometry(); geometry.addAttribute('position', vertexBuffer); Hope it helps! Commented Dec 10, 2018 at 10:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.