HighlightLayer for imported GLB meshes

I wanted to use the HighlightLayer to highlight meshes and encountered an issue where meshes imported from GLB files were not highlighted. Simple meshes created with MeshBuilder like Sphere or Box were highlighted, but more complex objects didn’t work with HighlightLayer. The issue was that HighlightLayer doesn’t affect SubMeshes. I wrote this class for myself, and it might be useful for you too.

Highlighter.ts

import { AbstractMesh, Color3, HighlightLayer, Mesh, Scene } from 'babylonjs'

class Highlighter {
  get color(): Color3 {
    return this._color
  }

  set color(value: Color3) {
    this._color = value
  }
  get glow(): boolean {
    return this._glow
  }

  set glow(value: boolean) {
    this._glow = value
  }

  readonly highlightLayer: HighlightLayer
  mesh: Mesh | undefined
  private _color: Color3 = new Color3(1, 1, 0)
  private _glow: boolean = false

  constructor(scene?: Scene) {
    this.highlightLayer = new HighlightLayer('highlightLayer', scene,
      { mainTextureRatio: 1,
        blurTextureSizeRatio: 1,
        blurVerticalSize: 0.5,
        blurHorizontalSize: 0.5,
        isStroke: false
      })
  }

  add(mesh: Mesh) {
      this.mesh = mesh
      this.highlightSubMeshes(mesh, true)
      return mesh
  }

  replace(mesh: Mesh) {
    if (this.mesh !== mesh) {
      if (this.mesh) this.remove(this.mesh)
      return this.add(mesh)
    }
  }

  remove(mesh: Mesh) {
    if (mesh && this.highlightLayer.hasMesh(mesh)) {
      const childMeshes = mesh.getChildMeshes()
      for (let i = 0; i < childMeshes.length; i++) {
        const childMesh = childMeshes[i]
        this.highlightLayer.removeMesh(childMesh as Mesh)
      }
      this.highlightLayer.removeMesh(mesh)
      this.mesh = undefined
    }
  }

  clear() {
    if (this.mesh && this.highlightLayer.hasMesh(this.mesh)) {
      this.highlightLayer.removeAllMeshes()
      this.mesh = undefined
    }
  }

  private highlightSubMeshes(mesh: AbstractMesh, enabled: boolean = false) {
    this.highlightLayer.addMesh(mesh as Mesh, this._color, this._glow)
    const childMeshes = mesh.getChildMeshes()
    for (let i = 0; i < childMeshes.length; i++) {
      const childMesh = childMeshes[i]
      if (enabled) {
        this.highlightLayer.addMesh(childMesh as Mesh, this._color, this._glow)
      } else {
        this.highlightLayer.removeMesh(childMesh as Mesh)
      }
    }
  }

}

export default Highlighter

Usage:

const highlight = new Highlighter()
highlight.glow = true
highlight.color = new Color3(1,1,1)

Cheers. :handshake:

3 Likes

Highlight layer works at the mesh level so yes, you need to add all the meshes from one hierarchy to import the full glb

Feel free to PR a addHierachy function highlighting all the meshes under a node if you want.

1 Like

Do you mean add flag withRelatives into parametrs for addMesh() and removeMesh() in this file: Babylon.js/packages/dev/core/src/Layers/highlightLayer.ts at master · BabylonJS/Babylon.js · GitHub ?

you could do it this way but it would prevent to add a hierarchy starting with a transformNode in this case. This is why I was thinking of a separate addHierarachy/removeHierachy pair of functions. I am stupid with name so feel free to chose a better one :slight_smile: