Search code examples
autodesk-forgeautodesk-viewer

Forge Viewer 7.71 throws errors when removing and recreating custom meshes in ModelViewer


I have an application that adds many custom meshes to the Forge Viewer using the ModelBuilder extension. This application has worked for quite a while but ran into issues with version 7.71 of the viewer.

When graphics are updated in my application, I remove all existing meshes and then recreate them based on new data. With version 7.71 of the viewer, when I recreate the meshes I get many instances the following error in the dev tools console:

Uncaught TypeError: Cannot read properties of undefined (reading 'material')
    at FragmentList.getMaterial (FragmentList.js:760:1)
    at FragmentList.getMaterialId (FragmentList.js:754:1)
    at RenderBatch.js:222:1
    at Int32Array.sort (<anonymous>)
    at RenderBatch.sortByMaterial (RenderBatch.js:220:1)
    at RenderModel.applyVisibility (RenderModel.js:388:1)
    at RenderModel.nextBatch (RenderModel.js:360:1)
    at RenderScene.reset (RenderScene.js:387:1)
    at Array.cmdBeginPhase (Viewer3DImpl.js:1125:1)
    at RenderCommandSystem.executeCommandList (Viewer3DImpl.js:847:1)

After these errors, the new meshes are not created.

The release notes don't mention anything about any expected changes here. Looking for guidance from the Autodesk team.

Here is a repo that reproduces the issue: https://github.com/bencameron/custom-mesh-refresh


Solution

  • I'm told it will take some time to implement the fix (ticket id LMV-6757). In the meantime you could stick with v7.70 or try these workarounds a colleague suggested:

    1.) If all of the custom geometry is removed, like it is in the example app, it's probably simpler to remove the model entirely and start with a new one. Here is an (untested) snippet to do that:

    // Instead of deleting all geometries individually, simply delete the model and create a new one
    viewer.unloadModel(modelBuilder.model);
    
    // drop the reference to the model builder instance, i.e. assign a new instance
    modelBuilder = await sceneBuilder.addNewModel({});
    
    // start adding the geometry again...
    ...
    

    2.) If option #1 doesn't work, or if the user doesn't want to delete all geometries, they could also avoid the crash by running this snippet right after adding new geometries (i.e. every time they add a batch of geometries):

    const scenes = modelBuilder.model.getIterator().getGeomScenes();
    for (let i = 0; i < scenes.length; ++i) {
      scenes[i].numAdded = 0;
    }
    

    I would recommend the first option over the second one if applicable.