buildSphere method
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;
}