autodesk-viewer

Autodesk DataViz API on sheet view in Forge Viewer


I want to show sprites on sheets in Forge Viewer using the same code as for 3D view. This code works perfectly inside 3D views with one or multy-model loaded. But when i open some sheet, sprites are not loaded at all.

I use these events to find elements and add sprites.

    viewerInst.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, onGeometryLoaded);
    viewerInst.addEventListener(Autodesk.Viewing.MODEL_ADDED_EVENT, onModelAdded);
    viewerInst.addEventListener(Autodesk.Viewing.MODEL_UNLOADED_EVENT, onModelUnload);

below is onGeometryLoaded callback

  const onGeometryLoaded = useCallback(
    async e => {
      const ext = await e.target.loadExtension('Autodesk.DataVisualization');
      ext.removeAllViewables();

      //remove event listeners to prevent multi event when multy-model loaded
      e.target.removeEventListener(Autodesk.DataVisualization.Core.MOUSE_HOVERING, onSpriteHover);
      e.target.removeEventListener(Autodesk.DataVisualization.Core.MOUSE_CLICK, onSpriteClick);

      //add event listeners to handle sprite click and hover event only once
      e.target.addEventListener(Autodesk.DataVisualization.Core.MOUSE_HOVERING, onSpriteHover);
      e.target.addEventListener(Autodesk.DataVisualization.Core.MOUSE_CLICK, onSpriteClick);

      addSprites(e.target, e.model, prepData.current);
    },
    [addSprites, handleSearchParams, onSpriteClick, onSpriteHover],
  );

below is onModelAdded callback

  const onModelAdded = useCallback(
    e => {
      //start theme
      e.target.setEnvMapBackground(false);
      //endtheme

      prepData.current = [];

      e.target.getAllModels().map(model => {
        model.search('Scheduler_3DMarkup', dbIDs => {
          dbIDs.map(dbId => {
            model.getProperties(dbId, res => {
              res.properties.map(el => {
                if (el.displayName === 'Scheduler - NF Number') {
                  const item = needList.find(nf => {
                    return nf.nf === Number(el.displayValue);
                  });
                  prepData.current.push({ dbId, value: item?.status, model: model });
                }
              });
            });
          });
        });
      });
    },
    [needList],
  );

below is onModelUnload callback

  const onModelUnload = useCallback(
    async e => {
      const ext = await e.target.loadExtension('Autodesk.DataVisualization');
      prepData.current = [];
      ext.removeAllViewables();

      e.target.getAllModels().map(model => {
        model.search('Scheduler_3DMarkup', dbIDs => {
          dbIDs.map(dbId => {
            model.getProperties(dbId, res => {
              res.properties.map(el => {
                if (el.displayName === 'Scheduler - NF Number') {
                  const item = needList.find(nf => {
                    return nf.nf === Number(el.displayValue);
                  });
                  prepData.current.push({ dbId, value: item?.status, model: model });
                }
              });
            });
          });
        });
      });

      setTimeout(() => {
        addSprites(e.target, e.target.model, prepData.current);
      }, 100);
    },
    [addSprites, needList],
  );

below addSprite callback and findViewables callback for creating sprites

  const addSprites = useCallback(
    async (viewer, model, dbIDs) => {
      const dataVizExtn = await viewer.getExtension('Autodesk.DataVisualization');
      const data = await findViewables(model, dbIDs);
      dataVizExtn.addViewables(data);
      const showViewables = true;
      const enableOcclusion = false;
      dataVizExtn.showHideViewables(showViewables, enableOcclusion);
      viewer.search('');
    },
    [findViewables],
  );

  const findViewables = useCallback(async (model, dbIDs) => {
    const DataVizCore = Autodesk.DataVisualization.Core;
    const viewableType = DataVizCore.ViewableType.SPRITE;
    const spriteColor = new THREE.Color(0xffffff);

    const style_default = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfDefault);
    const style_success = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfSuccess);
    const style_warning = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfWarning);
    const style_informative = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfInformative);
    const style_danger = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfDanger);

    const viewableData = new DataVizCore.ViewableData();
    viewableData.spriteSize = 40; // Sprites as points of size value pixels

    dbIDs.forEach(el => {
      el.model.getData().instanceTree.enumNodeFragments(el.dbId, async fragId => {
        const frags = el.model.getFragmentList();
        let bbox = new THREE.Box3();
        frags.getWorldBounds(fragId, bbox);

        const center = bbox.getCenter();

        const viewable_default = new DataVizCore.SpriteViewable(center, style_default, el.dbId);
        const viewable_success = new DataVizCore.SpriteViewable(center, style_success, el.dbId);
        const viewable_warning = new DataVizCore.SpriteViewable(center, style_warning, el.dbId);
        const viewable_informative = new DataVizCore.SpriteViewable(center, style_informative, el.dbId);
        const viewable_danger = new DataVizCore.SpriteViewable(center, style_danger, el.dbId);

        if (el.value === 'accepted') {
          viewableData.addViewable(viewable_success);
        } else if (el.value === 'declined') {
          viewableData.addViewable(viewable_danger);
        } else if (el.value === 'sent') {
          viewableData.addViewable(viewable_informative);
        } else if (el.value === 'submitted' || el.value === 'provided') {
          viewableData.addViewable(viewable_warning);
        } else {
          viewableData.addViewable(viewable_default);
        }
      });
    });
    await viewableData.finish();

    return viewableData;
  }, []);

I try to change let bbox = new THREE.Box3(); in find vieweable, try let bbox = new THREE.Box2();, but it change nothing.

I recheck coordinates that are received in const center = bbox.getCenter(); and there is no z coordinate (i mean it is 0), but sprites are not shown.

I don't understand the reason why sprites are not shown in sheets.


Solution

  • I had a converstation with Autodesk developer and he provided some articles and aproaches. So i read those articles and update findViewables function.

    we use different methods to find bounds in 2D and 3D views, below is updated part of findViewables

            let bbox = new THREE.Box3();
    
            const { role } = model.getDocumentNode().data;
    
            if (role === '2d') {
              let boundsCallback = new Autodesk.Viewing.Private.BoundsCallback(bbox);
              const mesh = frags.getVizmesh(fragId);
              const vbr = new Autodesk.Viewing.Private.VertexBufferReader(mesh.geometry, window.NOP_VIEWER.impl.use2dInstancing);
              vbr.enumGeomsForObject(el.dbId, boundsCallback);
            }
    
            if (role === '3d') {
              frags.getWorldBounds(fragId, bbox);
            }
    
            const center = bbox.getCenter();
    

    and now this code works well in 2d and 3d views.