Can you help us customise the Speckle Viewer?

Hi Jonathon,
We are working on a 3D viewer and would like to use Speckle, but need some custom tools developed sectioning methods, and selection and highlighting methods. Things like that. Where can I find some developers that can help with this? Or do you think I can just ask for freelancers in the Help board?
Thanks,
~Scott

If you can line up developers familiar with your intended stack, by and large, the Speckle Viewer is a freely available package which has an API. We can work with them to help direct to the correct resources.

The Viewer API already covers sectioning, filtering & colouring under your control; unclear how much customising you are planning beyond current capabilities.

ThreeJS knowledge wouldn’t hurt as something they are familiar with. Still, reviewing the Speckle code or simply the Viewer API and reverse engineer is theoretically possible if you want to customise it heavily.

Point any potential hires at our code and say - here, use this.

And there’s another way to go about it: could you describe some of those features? We could see if we could enable them, or point you towards enabling them yourself :slight_smile:

1 Like

We want to cut through floors and create 2D plans(top down isometric views. But we dont want to cut the equipment.

1 Like

Hi @GreenBIM

We’re always happy to hear from users who want to build their own applications on top of speckle!

The viewer currently supports sectioning, as you probably already know, there is nothing in the explicit viewer API that will let you exclude from sectioning objects based on any criteria.
However, using the same current viewer API, one can enable such functionality with a bit of code on top.
The gif below shows how a group of objects which had their category set to “Furniture” are excluded from sectioning


I also colored them red so they stand out and are more visible

In order to do this, we’ve used a DebugViewer instance instead of a regular Viewer instance. This is available in the API and we’re using it for out sandbox application. The DebugViewer currently offers a little bit of extra access to the viewer internals. For reference, here is the code used in the video above.

const batchMap: { [id: string]: Array<BatchObject> } = {}
// Walking the tree and finding 'Furniture' objects
this.viewer.getWorldTree().walk((node: TreeNode) => {
  if (node.model.raw.category === 'Furniture') {
    /** We get their coresponding batch objects and map them according to the batchId 
     *  they belong to
    */
    const batchObjects = this.viewer.getObjects(node.model.id)
    for (let k = 0; k < batchObjects.length; k++) {
      if (!batchMap[batchObjects[k].renderView.batchId]) {
        batchMap[batchObjects[k].renderView.batchId] = []
      }
      batchMap[batchObjects[k].renderView.batchId].push(batchObjects[k])
    }
  }
  return true
})
/** We begin a filtering phase */
this.viewer.getRenderer().clearFilter()
this.viewer.getRenderer().beginFilter()
for (const k in batchMap) {
  const speckleMesh = this.viewer
    .getRenderer()
    .scene.getObjectByProperty('uuid', k)
  const material = speckleMesh.getBatchObjectMaterial(batchMap[k][0])
  /** We clone the original material. You can edit it at will */
  const materialClone = material.clone()
  materialClone.color.set(0xff0000)
  /** We apply a user-defined material to all "Furniture" objects 
   *  This will allow the user to directly control the material
  */
  this.viewer.getRenderer().applyMaterial(
    batchMap[k].map((value) => value.renderView),
    materialClone
  )
}
this.viewer.getRenderer().endFilter()

/** Whenever the section box has changed */
this.viewer.on(ViewerEvent.SectionBoxUpdated, () => {
  for (const k in batchMap) {
    const speckleMesh = this.viewer
      .getRenderer()
      .scene.getObjectByProperty('uuid', k)
    /** We get the mateiral being used by the batch object (render view) */
    const material = speckleMesh.getBatchObjectMaterial(batchMap[k][0])
    /** We just reset it's clipping planes. It will no longer be sectioned */
    material.clippingPlanes = []
  }
})

This uses the concept of BatchObject which is briefly present in the viewer API but it’s not yet documented since we’re still working that part of the API. I realize this isn’t very straightforward, but at the very least makes selective sectioning possible.

Use cases like this help us a lot in designing a better API for the viewer, so that as many people can extend and develop their own applications on top of it. We do have the intention of widening the viewer API in the future and thus giving the users more granular control over it’s features.

Cheers

4 Likes

. :eyes: :heart_eyes: :speckle:

3 Likes