Search code examples
javascriptthree.jsmesh3d-modelling

How to change material of indivudal objects in THREE.js without the use of separate Meshes?


We have created a PCB Viewer in THREE.js and now we are looking to add some selection functionality to it. This is not a difficult task and I already have this functionality working though I am facing some performance issues. As we want all features of the PCB Layers (shapes) to be individually clickable and selectable (the colors change when selected) I figured each shape need their own THREE.js Mesh, so that we can control their Materials individually. Sure enough, it works as expected but of course it has massive performance issues as now, instead of having one combined mesh for all shapes on a PCB layer we have THOUSANDS.

I understand that having a lot of Meshes will degrade the performance. This is obviously true. Does anyone have any tips on how this could be done in a more performance efficient manner? For now it is enough for us to just change the colors of the indivudal shapes when they are clicked. Before my code changes we had all shapes in the same geometry on the same THREE Mesh. Can I somehow, in any way, keep this more simple structure but still manipulate inidivudal shapes/objects separately? To me it sounds far fetched but I am not too experienced in THREE


Solution

  • So I ended up with the following solution:

    • I render "simple" meshes to my real scene, where a lot of objects are in the same geometries (objects sharing the same Material mostly)
    • I keep a "virtual scene" which I never render, on which I perform raycasting and check for intersections. In the virtual scene I have actual separate meshes for the individual objects.
    • When I find an intersection in the virtual scene, I clone that mesh object and add it to the real scene with the "selection material". I also apply a small offset to it so that it is slightly bigger than the original, to prevent z-fighting
    • When objects are deselected, I remove the selection objects from the real scene. I use user attributes to identify which ones they are. Each selection object also has a "back link" to the mesh from where it was cloned in the virtual scene. This way I can also check if I already have a selection of a certain object.
    • To know "Where" to the real scene to add my object (to which group - we have quite an advanced tree structure...) I also keep a user attribute in the virtual scene that "points to" (by id) the parent in the real world, to which I would add the selection object IF it is selected.

    Hope this makes sense and that it will help someone else too