getBoundingSphere() {
    // Get the geometry's current bounding sphere
    let geomSphere = this._getGeometryBoundingSphere()
    if (!geomSphere) return null

    // Ensure world matrix is up to date
    this.updateMatrices()

    // Lazily create our Sphere
    let sphere = this._boundingSphere
    if (!sphere) {
      sphere = this._boundingSphere = new Sphere()
    }

    // If the geometry, the geometry's bounding sphere, or this object's world matrix changed,
    // update our bounding sphere to match them.
    if (sphere._geometrySphereVersion !== geomSphere.version || sphere._worldMatrixVersion !== this._worldMatrixVersion) {
      sphere.copy(geomSphere)
      sphere.applyMatrix4(this.threeObject.matrixWorld)
      sphere._worldMatrixVersion = this._worldMatrixVersion
      sphere._geometrySphereVersion = geomSphere.version
    }

    return sphere
  }
Return a {@link Sphere} encompassing the bounds of this object in worldspace, or `null` if
it has no physical bounds. This is used for optimized raycasting.

The default implementation attempts to be as efficient as possible, only updating the sphere
when necessary, and assumes the threeObject has a geometry that accurately describes its bounds.
Override this method to provide custom bounds calculation logic, for example when additional meshes
need to be checked or a vertex shader manipulates the geometry; you'll probably also need to override
{@link #raycast} to match.

TODO: this needs to be easier to override without having to reimplement large chunks of logic