Zoom on object using setCameraView

Hi community and speckel developpers!
My development environment
I’m using codesandbox.io and API Viewer dependency : @speckle/viewer 22.18.16
Revit for publish my model with Speckle Connector to send my model
My question
When I click on a button in my tweakPane, I’d like to go to a TreeNode whose id I know
I can get the Box3 corresponding to the TreeNode I’m looking for from its Id, but when I use the setCameraView function, nothing happens…why?

I’ve tried to use setTimeout but no way…
For exemple, viewer.setLightConfiguration works, but CameraController.disableRotations not
Is there something I miss with CameraController?

If I change the projection mode, cameraEvent raise but nothing happens in viewer

cameraController.on(CameraEvent.ProjectionChanged, () => {
console.log("ProjectionChanged");
  });
viewer.setLightConfiguration({ enabled: lcParams.enabled });
cameraController.disableRotations();

Here’s part of my code, I’ll skip the createExtension loadObject, etc.

function ZoomTreeNodeById(worldNodeById) {
    const box: Box3 = new Box3();
    const rvs = viewer
      .getWorldTree()
      .getRenderTree()
      .getRenderViewsForNodeId(worldNodeById);
    
    if (rvs)
    {
      rvs.forEach((rv: NodeRenderView) => {
        box.union(rv.aabb);
      }
    }      
    return box;    
  }
folderTools
    .addButton({
      title: "Go to scene",
    })
    .on("click", () => {
      
      // Exemple d'utilisation de la fonction
      const elementIdToFind = "762e9360e79f52baf0613b55f00b9a3b"; // ID de l'élément que vous cherchez
      const boxForZoom = ZoomTreeNodeById(elementIdToFind);
      //viewer.setLightConfiguration({indirectLightIntensity:5});

      if (boxForZoom) {        
        controler.setCameraView(boxForZoom, false);        
        console.log("boxForZoom trouvée:", boxForZoom);
      } else {
        console.log("Aucun boxForZoom trouvé avec l'ID:", elementIdToFind);
      }

    });

Hi @pierrenavarra

If you already know the id or ids of the object(s) you want to focus the camera on, you can use that directly as per setCameraView documentation (where I just fixed a typo :slight_smile: ).

I’ve made a sandbox for you which shows you how to use setCameraView with both object ids and box3s. One note when building the boxes is to use the BatchObject’s aabb instead of NodeRenderView aabb, to make sure any custom or instance transformations are taken into account.

It’s super cool that your are using codesanbox.io for your tests but for a more streamlined experience, you can simply give us a link to your sandbox so we can run it ourselves. That way we can see potential issues more easily.

Cheers

Hi @alex
Sure, my sandbox is : Here

I don’t have access to it. You’ll need to share it with me or make it public or unlisted

Oups…
Tell me if it’s ok…
Thank you very much for your example.
I used this in my code…
mmm…there seems to be a problem, it selects but doesn’t want to zoom…

folderTools
    .addButton({
      title: "Do something",
    })
    .on("click", () => {
      // Exemple d'utilisation de la fonction
      /*
      if (!_treeNodeSelected) return;
      
      const treeNodeData : NodeData = _treeNodeSelected.model;
      console.log("selected speckle id is " + treeNodeData.id);      */

      const ids = [
        "4c0a6d7466d673a65e311582a26c37ab",
        "b4e8a8c8e5988db5e38a807027108f7c",
      ];

      selection.clearSelection();
      selection.selectObjects(ids);

      const box: Box3 = new Box3();
      for (const id of ids) {
        const rvs = viewer
          .getWorldTree()
          .getRenderTree()
          .getRenderViewsForNodeId(id);

        if (rvs) {
          rvs.forEach((rv: NodeRenderView) => {
            const object = viewer.getRenderer().getObject(rv);
            box.union(object.aabb);
          });
        }
      }
      console.log(box);
      cameraController.setCameraView(box, false);

      /*
      //const boxForZoom = ZoomTreeNodeById(elementIdToFind);
      //viewer.setLightConfiguration({indirectLightIntensity:5});

      if (boxForZoom) {
        
        console.log("boxForZoom trouvée:", boxForZoom);
      } else {
        console.log("Aucun boxForZoom trouvé avec l'ID:", elementIdToFind);
      }*/
    });

Right, so I found your problem. You are creating two CameraController extensions, the second one replacing the first one, since the viewer can have only one extension of a given type. This second one replaces the first one, but you were still making the setCameraView calls on the first one

const cameraController = viewer.createExtension(CameraController);
/** Add the stock camera controller extension */
/** Remove this */
viewer.createExtension(CameraController);

Here’s a forked sandbox from yours that works fine. I saw you have other duplicated extensions, which is something you might not want

Cheers

1 Like

Hello @alex
Thank you a thousand times over for your responsiveness.
I’m making good progress thanks to your precious help and the community in general.
For the moment my code isn’t very structured (I’m a C# coder and my javascript experience needs improving :slight_smile:).
I’m sure I’ll have more questions and I’ll post them on the development forum.
Perhaps my research will serve (as others’ do) to advance my project.
Cheers

2 Likes