computeBoundingSphere method

void computeBoundingSphere()
inherited

Computes the bounding sphere of the geometry, and updates the boundingSphere attribute.

The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling. You may need to recompute the bounding sphere if the geometry vertices are modified.

Implementation

void computeBoundingSphere() {
  boundingSphere ??= BoundingSphere();

  final position = attributes["position"];
  final morphAttributesPosition = morphAttributes["position"];

  if (position != null && position is GLBufferAttribute) {
    boundingSphere!.set(Vector3.zero(), 99999999999);

    return;
  }

  if (position != null) {
    // first, find the center of the bounding sphere

    final center = boundingSphere!.center;

    _bufferGeometrybox.setFromBuffer(position);

    // process morph attributes if present

    if (morphAttributesPosition != null) {
      for (int i = 0, il = morphAttributesPosition.length; i < il; i++) {
        final morphAttribute = morphAttributesPosition[i];
        _bufferGeometryboxMorphTargets.setFromBuffer(morphAttribute);

        if (morphTargetsRelative) {
          _bufferGeometryvector.add2(_bufferGeometrybox.min, _bufferGeometryboxMorphTargets.min);
          _bufferGeometrybox.expandByPoint(_bufferGeometryvector);

          _bufferGeometryvector.add2(_bufferGeometrybox.max, _bufferGeometryboxMorphTargets.max);
          _bufferGeometrybox.expandByPoint(_bufferGeometryvector);
        } else {
          _bufferGeometrybox.expandByPoint(_bufferGeometryboxMorphTargets.min);
          _bufferGeometrybox.expandByPoint(_bufferGeometryboxMorphTargets.max);
        }
      }
    }

    _bufferGeometrybox.getCenter(center);

    // second, try to find a boundingSphere with a radius smaller than the
    // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
    double maxRadiusSq = 0;
    for (int i = 0, il = position.count; i < il; i++) {
      _bufferGeometryvector.fromBuffer(position, i);
      maxRadiusSq = math.max(
        maxRadiusSq,
        center.distanceToSquared(_bufferGeometryvector),
      );
    }

    // process morph attributes if present

    if (morphAttributesPosition != null) {
      for (int i = 0, il = morphAttributesPosition.length; i < il; i++) {
        final morphAttribute = morphAttributesPosition[i];
        final morphTargetsRelative = this.morphTargetsRelative;

        for (int j = 0, jl = morphAttribute.count; j < jl; j++) {
          _bufferGeometryvector.fromBuffer(morphAttribute, j);

          if (morphTargetsRelative) {
            _bufferGeometryoffset.fromBuffer(position, j);
            _bufferGeometryvector.add(_bufferGeometryoffset);
          }

          maxRadiusSq = math.max(
            maxRadiusSq,
            center.distanceToSquared(_bufferGeometryvector),
          );
        }
      }
    }

    boundingSphere!.radius = math.sqrt(maxRadiusSq);

    if (boundingSphere?.radius == null) {
      console.warning('BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values. $this');
    }
  }
}