gkjohnson / three-bvh-csg

A flexible, memory compact, fast and dynamic CSG implementation on top of three-mesh-bvh
MIT License
552 stars 45 forks source link

Use WebWorkers to parralelize mesh generation issue #150

Closed RobinLasserye closed 10 months ago

RobinLasserye commented 10 months ago

Hello,

I'm currently working on a project that requires me to generate intersections. However, I'm using meshes that can be complex and I need to do this on a recurring basis. So I'm looking to use three-bvh-csg with Webworkers.

However, I'm stuck, I have the impression (after my tests) that I need to render my scene for the evaluator to work. But I can't provide my scene in a WebWorker.

So I always get a mesh with empty attributes (array(0)). Is it possible to activate the evaluator outside a render?

Here's the code for my main thread:

generateCollisions(mesh1, mesh2) {
      // let worker = new Worker('/src/scripts/collisionWorker.js');
      const worker = new Worker(new URL('/src/scripts/collisionWorker.js', import.meta.url), { type: 'module' });

      // Convertir les géométries en JSON pour les envoyer au Web Worker
      let mesh1Data = mesh1.geometry.toJSON();
      let mesh2Data = mesh2.geometry.toJSON();

      const scene = this.context.scene

      worker.postMessage({
          mesh1: mesh1Data,
          mesh2: mesh2Data
      });

      worker.onmessage = function(event) {
          let intersectionData = event.data;

          if (intersectionData) {
              // Convertir le JSON en une géométrie
              let loader = new THREE.BufferGeometryLoader();
              let geometry = loader.parse(intersectionData);

              let material = new THREE.MeshStandardMaterial({ color: 0xff0000 });
              let intersectionMesh = new THREE.Mesh(geometry, material);
              intersectionMesh.name = "intersection_" + mesh1.name + "_" + mesh2.name
              console.log(intersectionMesh.geometry.attributes)
              scene.add(intersectionMesh)
          }
      };
  }

And here the code of my WebWorker script:

import { INTERSECTION, Brush, Evaluator } from 'three-bvh-csg';
import { BufferGeometryLoader, BufferGeometry, MeshStandardMaterial, Mesh, Scene } from 'three';
import * as THREE from 'three';

function convertJSONToBufferGeometry(jsonData) {
    const loader = new THREE.BufferGeometryLoader();
    return loader.parse(jsonData);
}

// Création d'une "fausse" scène juste pour le calcul
// const fakeScene = new Scene();

// Evaluator qui calculera la différence entre les deux maillages
const csgEvaluator = new Evaluator();
// csgEvaluator.scene = scene;
csgEvaluator.attributes = ['position', 'normal', 'color'];

self.onmessage = function(event) {
    const { mesh1, mesh2 } = event.data;

    const geometry1 = convertJSONToBufferGeometry(mesh1);
    const geometry2 = convertJSONToBufferGeometry(mesh2);
    const scene = new THREE.Scene();

    const brush1 = new Brush(geometry1);
    const brush2 = new Brush(geometry2);

    // Ajouter les brosses à la "fausse" scène
    scene.add(brush1);
    scene.add(brush2);

    csgEvaluator.scene = scene;

    // Utilisation du même évaluateur pour effectuer l'intersection
    const resultObject = new Mesh(new BufferGeometry(), new MeshStandardMaterial({
        flatShading: false,
        polygonOffset: true,
        polygonOffsetUnits: 0.1,
        polygonOffsetFactor: 0.1,
        color: "#008000",
    }));

    const result = csgEvaluator.evaluate(brush1, brush2, INTERSECTION, resultObject);

    // Récupérez les données de géométrie du résultat et envoyez-les de nouveau au thread principal
    postMessage(result.geometry.toJSON());
};
gkjohnson commented 10 months ago

I have the impression (after my tests) that I need to render my scene for the evaluator to work.

There's no need to render in order to perform a CSG evaluation. It can be performed without a scene, renderer, or anything. It is just important that the Brush matrixWorld matrices be updated before performing an operation.

So I always get a mesh with empty attributes (array(0)).

Without providing a working example it won't be possible to tell what might be happening here. Make sure you transfer the world matrices to the worker, as well, and that the operations are working without the WebWorker.