buildSphere method

Future<SphereImage?> buildSphere(
  1. double maxWidth,
  2. double maxHeight
)

Implementation

Future<SphereImage?> buildSphere(double maxWidth, double maxHeight) async {
  if (widget.controller.surface == null ||
      widget.controller.surfaceProcessed == null) {
    return Future.value(null);
  }

  final r = convertedRadius().roundToDouble();
  final minX = math.max(-r, -maxWidth / 2);
  final minY = math.max(-r, -maxHeight / 2);
  final maxX = math.min(r, maxWidth / 2);
  final maxY = math.min(r, maxHeight / 2);
  final width = maxX - minX;
  final height = maxY - minY;

  final surfaceWidth = widget.controller.surface?.width.toDouble();
  final surfaceHeight = widget.controller.surface?.height.toDouble();

  final spherePixels = Uint32List(width.toInt() * height.toInt());

  // Prepare rotation matrices
  final rotationMatrixX = Matrix3.rotationX(math.pi / 2 - rotationX);
  // final rotationMatrixY = Matrix3.rotationY(math.pi / 2 - rotationY);
  final rotationMatrixZ = Matrix3.rotationZ(rotationZ + math.pi / 2);

  final surfaceXRate = (surfaceWidth! - 1) / (2.0 * math.pi);
  final surfaceYRate = (surfaceHeight! - 1) / math.pi;

  for (var y = minY; y < maxY; y++) {
    final sphereY = (height - y + minY - 1).toInt() * width;
    for (var x = minX; x < maxX; x++) {
      var zSquared = r * r - x * x - y * y;
      if (zSquared > 0) {
        var z = math.sqrt(zSquared);
        var vector = Vector3(x, y, z);

        // Apply rotations
        vector = rotationMatrixX.transform(vector);
        // vector = rotationMatrixY.transform(vector);
        vector = rotationMatrixZ.transform(vector);

        final lat = math.asin(vector.z / r);
        final lon = math.atan2(vector.y, vector.x);

        final x0 = (lon + math.pi) * surfaceXRate;
        final y0 = (math.pi / 2 - lat) * surfaceYRate;

        final color = widget.controller.surfaceProcessed![
            (y0.toInt() * surfaceWidth + x0.toInt()).toInt()];
        spherePixels[(sphereY + x - minX).toInt()] = color;
      }
    }
  }

  final completer = Completer<SphereImage>();
  ui.decodeImageFromPixels(spherePixels.buffer.asUint8List(), width.toInt(),
      height.toInt(), ui.PixelFormat.rgba8888, (image) {
    final sphereImage = SphereImage(
      image: image,
      radius: r,
      origin: Offset(-minX, -minY),
      offset: Offset(maxWidth / 2, maxHeight / 2),
    );
    completer.complete(sphereImage);
  });
  return completer.future;
}