@takram/three-atmosphere
Version:
A Three.js and R3F implementation of Precomputed Atmospheric Scattering
518 lines (449 loc) • 120 kB
JavaScript
"use strict";const vn=require("postprocessing"),d=require("three"),D=require("@takram/three-geospatial"),X0=require("@takram/three-geospatial/shaders"),j0=require("./shared2.cjs"),Zt=["solarIrradiance","sunAngularRadius","bottomRadius","topRadius","rayleighScattering","mieScattering","miePhaseFunctionG","muSMin","skyRadianceToLuminance","sunRadianceToLuminance","luminousEfficiency"];function Wt(t,e){if(e!=null)for(const n of Zt){const o=e[n];o!=null&&(t[n]instanceof d.Vector3?t[n].copy(o):t[n]=o)}}const $e=class $e{constructor(e){this.solarIrradiance=new d.Vector3(1.474,1.8504,1.91198),this.sunAngularRadius=.004675,this.bottomRadius=636e4,this.topRadius=642e4,this.rayleighScattering=new d.Vector3(.005802,.013558,.0331),this.mieScattering=new d.Vector3(.003996,.003996,.003996),this.miePhaseFunctionG=.8,this.muSMin=Math.cos(D.radians(120)),this.skyRadianceToLuminance=new d.Vector3(114974.916437,71305.954816,65310.548555),this.sunRadianceToLuminance=new d.Vector3(98242.786222,69954.398112,66475.012354),this.luminousEfficiency=new d.Vector3(.2126,.7152,.0722),this.skyRadianceToRelativeLuminance=new d.Vector3,this.sunRadianceToRelativeLuminance=new d.Vector3,Wt(this,e);const n=this.luminousEfficiency.dot(this.skyRadianceToLuminance);this.skyRadianceToRelativeLuminance.copy(this.skyRadianceToLuminance).divideScalar(n),this.sunRadianceToRelativeLuminance.copy(this.sunRadianceToLuminance).divideScalar(n)}};$e.DEFAULT=new $e;let oe=$e;const Me=64,De=16,je=32,qe=128,Ke=32,Je=8,Xn=Je*Ke,Yn=qe,fn=je,Ne=256,Ue=64,ce=1/1e3,Xt=100,$n="82e00c5222d6cbc222af69abdf6d3f4fc9f63030",Yt=`https://media.githubusercontent.com/media/takram-design-engineering/three-geospatial/${$n}/packages/atmosphere/assets`,$t=`https://media.githubusercontent.com/media/takram-design-engineering/three-geospatial/${$n}/packages/atmosphere/assets/stars.bin`,jt=new d.Vector3;function Qe(t,e,n,o,a=!0){const c=n.projectOnSurface(t,jt);return c!=null?n.getOsculatingSphereCenter(!a||c.lengthSq()<t.lengthSq()?c:t,e,o):o.setScalar(0)}const qt=`precision highp sampler2DArray;
#include "core/depth"
#include "core/math"
#include "core/packing"
#include "core/transform"
#ifdef HAS_SHADOW
#include "core/raySphereIntersection"
#include "core/cascadedShadowMaps"
#include "core/interleavedGradientNoise"
#include "core/vogelDisk"
#endif // HAS_SHADOW
#include "parameters"
#include "functions"
#include "sky"
uniform sampler2D normalBuffer;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 inverseProjectionMatrix;
uniform mat4 inverseViewMatrix;
uniform float bottomRadius;
uniform vec3 ellipsoidCenter;
uniform mat4 inverseEllipsoidMatrix;
uniform vec3 sunDirection;
uniform vec3 moonDirection;
uniform float moonAngularRadius;
uniform float lunarRadianceScale;
uniform float irradianceScale;
uniform float idealSphereAlpha;
#ifdef HAS_OVERLAY
uniform sampler2D overlayBuffer;
#endif // HAS_OVERLAY
#ifdef HAS_SHADOW
uniform sampler2DArray shadowBuffer;
uniform vec2 shadowIntervals[SHADOW_CASCADE_COUNT];
uniform mat4 shadowMatrices[SHADOW_CASCADE_COUNT];
uniform mat4 inverseShadowMatrices[SHADOW_CASCADE_COUNT];
uniform float shadowFar;
uniform float shadowTopHeight;
uniform float shadowRadius;
uniform sampler3D stbnTexture;
uniform int frame;
#endif // HAS_SHADOW
#ifdef HAS_SHADOW_LENGTH
uniform sampler2D shadowLengthBuffer;
#endif // HAS_SHADOW_LENGTH
varying vec3 vCameraPosition;
varying vec3 vRayDirection;
varying vec3 vEllipsoidCenter;
varying vec3 vGeometryEllipsoidCenter;
varying vec3 vEllipsoidRadiiSquared;
vec3 readNormal(const vec2 uv) {
#ifdef OCT_ENCODED_NORMAL
return unpackVec2ToNormal(texture(normalBuffer, uv).xy);
#else // OCT_ENCODED_NORMAL
return 2.0 * texture(normalBuffer, uv).xyz - 1.0;
#endif // OCT_ENCODED_NORMAL
}
void correctGeometricError(inout vec3 positionECEF, inout vec3 normalECEF) {
// TODO: The error is pronounced at the edge of the ellipsoid due to the
// large difference between the sphere position and the unprojected position
// at the current fragment. Calculating the sphere position from the fragment
// UV may resolve this.
// Correct way is slerp, but this will be small-angle interpolation anyways.
vec3 sphereNormal = normalize(positionECEF / vEllipsoidRadiiSquared);
vec3 spherePosition = u_bottom_radius * sphereNormal;
normalECEF = mix(normalECEF, sphereNormal, idealSphereAlpha);
positionECEF = mix(positionECEF, spherePosition, idealSphereAlpha);
}
#if defined(SUN_IRRADIANCE) || defined(SKY_IRRADIANCE)
vec3 getSunSkyIrradiance(
const vec3 positionECEF,
const vec3 normal,
const vec3 inputColor,
const float sunTransmittance
) {
// Assume lambertian BRDF. If both SUN_IRRADIANCE and SKY_IRRADIANCE are not
// defined, regard the inputColor as radiance at the texel.
vec3 albedo = inputColor * irradianceScale * RECIPROCAL_PI;
vec3 skyIrradiance;
vec3 sunIrradiance = GetSunAndSkyIrradiance(positionECEF, normal, sunDirection, skyIrradiance);
#ifdef HAS_SHADOW
sunIrradiance *= sunTransmittance;
#endif // HAS_SHADOW
#if defined(SUN_IRRADIANCE) && defined(SKY_IRRADIANCE)
return albedo * (sunIrradiance + skyIrradiance);
#elif defined(SUN_IRRADIANCE)
return albedo * sunIrradiance;
#elif defined(SKY_IRRADIANCE)
return albedo * skyIrradiance;
#endif // defined(SUN_IRRADIANCE) && defined(SKY_IRRADIANCE)
}
#endif // defined(SUN_IRRADIANCE) || defined(SKY_IRRADIANCE)
#if defined(TRANSMITTANCE) || defined(INSCATTER)
void applyTransmittanceInscatter(const vec3 positionECEF, float shadowLength, inout vec3 radiance) {
vec3 transmittance;
vec3 inscatter = GetSkyRadianceToPoint(
vCameraPosition - vGeometryEllipsoidCenter,
positionECEF,
shadowLength,
sunDirection,
transmittance
);
#ifdef TRANSMITTANCE
radiance = radiance * transmittance;
#endif // TRANSMITTANCE
#ifdef INSCATTER
radiance = radiance + inscatter;
#endif // INSCATTER
}
#endif // defined(TRANSMITTANCE) || defined(INSCATTER)
#ifdef HAS_SHADOW
float getSTBN() {
ivec3 size = textureSize(stbnTexture, 0);
vec3 scale = 1.0 / vec3(size);
return texture(stbnTexture, vec3(gl_FragCoord.xy, float(frame % size.z)) * scale).r;
}
vec2 getShadowUv(const vec3 worldPosition, const int cascadeIndex) {
vec4 clip = shadowMatrices[cascadeIndex] * vec4(worldPosition, 1.0);
clip /= clip.w;
return clip.xy * 0.5 + 0.5;
}
float getDistanceToShadowTop(const vec3 positionECEF) {
// Distance to the top of the shadows along the sun direction, which matches
// the ray origin of BSM.
return raySphereSecondIntersection(
positionECEF / METER_TO_LENGTH_UNIT, // TODO: Make units consistent
sunDirection,
vec3(0.0),
bottomRadius + shadowTopHeight
);
}
float readShadowOpticalDepth(const vec2 uv, const float distanceToTop, const int cascadeIndex) {
// r: frontDepth, g: meanExtinction, b: maxOpticalDepth, a: maxOpticalDepthTail
vec4 shadow = texture(shadowBuffer, vec3(uv, float(cascadeIndex)));
// Omit adding maxOpticalDepthTail to avoid pronounced aliasing. Ground
// shadow will be attenuated by inscatter anyways.
return min(shadow.b, shadow.g * max(0.0, distanceToTop - shadow.r));
}
float sampleShadowOpticalDepthPCF(
const vec3 worldPosition,
const float distanceToTop,
const float radius,
const int cascadeIndex
) {
vec2 uv = getShadowUv(worldPosition, cascadeIndex);
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
return 0.0;
}
vec2 texelSize = vec2(1.0) / vec2(textureSize(shadowBuffer, 0).xy);
float sum = 0.0;
vec2 offset;
#pragma unroll_loop_start
for (int i = 0; i < 16; ++i) {
#if UNROLLED_LOOP_INDEX < SHADOW_SAMPLE_COUNT
offset = vogelDisk(
UNROLLED_LOOP_INDEX,
SHADOW_SAMPLE_COUNT,
interleavedGradientNoise(gl_FragCoord.xy) * PI2
);
sum += readShadowOpticalDepth(uv + offset * radius * texelSize, distanceToTop, cascadeIndex);
#endif // UNROLLED_LOOP_INDEX < SHADOW_SAMPLE_COUNT
}
#pragma unroll_loop_end
return sum / float(SHADOW_SAMPLE_COUNT);
}
float sampleShadowOpticalDepth(
const vec3 worldPosition,
const vec3 positionECEF,
const float radius,
const float jitter
) {
float distanceToTop = getDistanceToShadowTop(positionECEF);
if (distanceToTop <= 0.0) {
return 0.0;
}
int cascadeIndex = getFadedCascadeIndex(
viewMatrix,
worldPosition,
shadowIntervals,
cameraNear,
shadowFar,
jitter
);
return cascadeIndex >= 0
? sampleShadowOpticalDepthPCF(worldPosition, distanceToTop, radius, cascadeIndex)
: 0.0;
}
float getShadowRadius(const vec3 worldPosition) {
vec4 clip = shadowMatrices[0] * vec4(worldPosition, 1.0);
clip /= clip.w;
// Offset by 1px in each direction in shadow's clip coordinates.
vec2 shadowSize = vec2(textureSize(shadowBuffer, 0));
vec3 offset = vec3(2.0 / shadowSize, 0.0);
vec4 clipX = clip + offset.xzzz;
vec4 clipY = clip + offset.zyzz;
// Convert back to world space.
vec4 worldX = inverseShadowMatrices[0] * clipX;
vec4 worldY = inverseShadowMatrices[0] * clipY;
// Project into the main camera's clip space.
mat4 viewProjectionMatrix = projectionMatrix * viewMatrix;
vec4 projected = viewProjectionMatrix * vec4(worldPosition, 1.0);
vec4 projectedX = viewProjectionMatrix * worldX;
vec4 projectedY = viewProjectionMatrix * worldY;
projected /= projected.w;
projectedX /= projectedX.w;
projectedY /= projectedY.w;
// Take the mean of pixel sizes.
vec2 center = (projected.xy * 0.5 + 0.5) * resolution;
vec2 offsetX = (projectedX.xy * 0.5 + 0.5) * resolution;
vec2 offsetY = (projectedY.xy * 0.5 + 0.5) * resolution;
float size = max(length(offsetX - center), length(offsetY - center));
return remapClamped(size, 10.0, 50.0, 0.0, shadowRadius);
}
#endif // HAS_SHADOW
void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
float shadowLength = 0.0;
#ifdef HAS_SHADOW_LENGTH
shadowLength = texture(shadowLengthBuffer, uv).r;
#endif // HAS_SHADOW_LENGTH
#ifdef HAS_OVERLAY
vec4 overlay = texture(overlayBuffer, uv);
if (overlay.a == 1.0) {
outputColor = overlay;
return;
}
#endif // HAS_OVERLAY
float depth = readDepth(uv);
if (depth >= 1.0 - 1e-7) {
#ifdef SKY
vec3 rayDirection = normalize(vRayDirection);
outputColor.rgb = getSkyRadiance(
vCameraPosition - vEllipsoidCenter,
rayDirection,
shadowLength,
sunDirection,
moonDirection,
moonAngularRadius,
lunarRadianceScale
);
outputColor.a = 1.0;
#else // SKY
outputColor = inputColor;
#endif // SKY
#ifdef HAS_OVERLAY
outputColor.rgb = outputColor.rgb * (1.0 - overlay.a) + overlay.rgb;
#endif // HAS_OVERLAY
return;
}
depth = reverseLogDepth(depth, cameraNear, cameraFar);
// Reconstruct position and normal in world space.
vec3 viewPosition = screenToView(
uv,
depth,
getViewZ(depth),
projectionMatrix,
inverseProjectionMatrix
);
vec3 viewNormal;
#ifdef RECONSTRUCT_NORMAL
vec3 dx = dFdx(viewPosition);
vec3 dy = dFdy(viewPosition);
viewNormal = normalize(cross(dx, dy));
#else // RECONSTRUCT_NORMAL
viewNormal = readNormal(uv);
#endif // RECONSTRUCT_NORMAL
vec3 worldPosition = (inverseViewMatrix * vec4(viewPosition, 1.0)).xyz;
vec3 worldNormal = normalize(mat3(inverseViewMatrix) * viewNormal);
mat3 rotation = mat3(inverseEllipsoidMatrix);
vec3 positionECEF = rotation * worldPosition * METER_TO_LENGTH_UNIT - vGeometryEllipsoidCenter;
vec3 normalECEF = rotation * worldNormal;
#ifdef CORRECT_GEOMETRIC_ERROR
correctGeometricError(positionECEF, normalECEF);
#endif // CORRECT_GEOMETRIC_ERROR
#ifdef HAS_SHADOW
float stbn = getSTBN();
float radius = getShadowRadius(worldPosition);
float opticalDepth = sampleShadowOpticalDepth(worldPosition, positionECEF, radius, stbn);
float sunTransmittance = exp(-opticalDepth);
#else // HAS_SHADOW
float sunTransmittance = 1.0;
#endif // HAS_SHADOW
vec3 radiance;
#if defined(SUN_IRRADIANCE) || defined(SKY_IRRADIANCE)
radiance = getSunSkyIrradiance(positionECEF, normalECEF, inputColor.rgb, sunTransmittance);
#else // defined(SUN_IRRADIANCE) || defined(SKY_IRRADIANCE)
radiance = inputColor.rgb;
#endif // defined(SUN_IRRADIANCE) || defined(SKY_IRRADIANCE)
#if defined(TRANSMITTANCE) || defined(INSCATTER)
applyTransmittanceInscatter(positionECEF, shadowLength, radiance);
#endif // defined(TRANSMITTANCE) || defined(INSCATTER)
outputColor = vec4(radiance, inputColor.a);
#ifdef HAS_OVERLAY
outputColor.rgb = outputColor.rgb * (1.0 - overlay.a) + overlay.rgb;
#endif // HAS_OVERLAY
}
`,Kt=`uniform mat4 inverseViewMatrix;
uniform mat4 inverseProjectionMatrix;
uniform vec3 cameraPosition;
uniform vec3 ellipsoidCenter;
uniform mat4 inverseEllipsoidMatrix;
uniform vec3 altitudeCorrection;
uniform vec3 ellipsoidRadii;
uniform float idealSphereAlpha;
varying vec3 vCameraPosition;
varying vec3 vRayDirection;
varying vec3 vEllipsoidCenter;
varying vec3 vGeometryEllipsoidCenter;
varying vec3 vEllipsoidRadiiSquared;
void getCameraRay(out vec3 origin, out vec3 direction) {
bool isPerspective = inverseProjectionMatrix[2][3] != 0.0; // 4th entry in the 3rd column
if (isPerspective) {
// Calculate the camera ray for a perspective camera.
vec4 viewPosition = inverseProjectionMatrix * vec4(position, 1.0);
vec4 worldDirection = inverseViewMatrix * vec4(viewPosition.xyz, 0.0);
origin = cameraPosition;
direction = worldDirection.xyz;
} else {
// Unprojected points to calculate direction.
vec4 nearPoint = inverseProjectionMatrix * vec4(position.xy, -1.0, 1.0);
vec4 farPoint = inverseProjectionMatrix * vec4(position.xy, -0.9, 1.0);
nearPoint /= nearPoint.w;
farPoint /= farPoint.w;
// Calculate world values.
vec4 worldDirection = inverseViewMatrix * vec4(farPoint.xyz - nearPoint.xyz, 0.0);
vec4 worldOrigin = inverseViewMatrix * nearPoint;
// Outputs
direction = worldDirection.xyz;
origin = worldOrigin.xyz;
}
}
void mainSupport() {
vec3 direction, origin;
getCameraRay(origin, direction);
mat3 rotation = mat3(inverseEllipsoidMatrix);
vCameraPosition = rotation * origin.xyz * METER_TO_LENGTH_UNIT;
vRayDirection = rotation * direction.xyz;
vEllipsoidCenter = (ellipsoidCenter + altitudeCorrection) * METER_TO_LENGTH_UNIT;
#ifdef CORRECT_GEOMETRIC_ERROR
// Gradually turn off altitude correction for aerial perspective as geometric
// error correction takes effect.
// See: https://github.com/takram-design-engineering/three-geospatial/pull/23#issuecomment-2542914656
vGeometryEllipsoidCenter =
(ellipsoidCenter + mix(altitudeCorrection, vec3(0.0), idealSphereAlpha)) * METER_TO_LENGTH_UNIT;
#else
vGeometryEllipsoidCenter = vEllipsoidCenter;
#endif // CORRECT_GEOMETRIC_ERROR
vec3 radii = ellipsoidRadii * METER_TO_LENGTH_UNIT;
vEllipsoidRadiiSquared = radii * radii;
}
`,jn=`vec3 getLunarRadiance(const float moonAngularRadius) {
// Not a physical number but the order of 10^-6 relative to the sun may fit.
vec3 radiance = u_solar_irradiance * 0.000002 / (PI * moonAngularRadius * moonAngularRadius);
#ifdef PHOTOMETRIC
radiance *= SUN_SPECTRAL_RADIANCE_TO_LUMINANCE;
#endif // PHOTOMETRIC
return radiance;
}
float intersectSphere(const vec3 ray, const vec3 point, const float radius) {
vec3 P = -point;
float PoR = dot(P, ray);
float D = dot(P, P) - radius * radius;
return -PoR - sqrt(PoR * PoR - D);
}
float orenNayarDiffuse(const vec3 L, const vec3 V, const vec3 N) {
float NoL = dot(N, L);
float NoV = dot(N, V);
float s = dot(L, V) - NoL * NoV;
float t = mix(1.0, max(NoL, NoV), step(0.0, s));
return max(0.0, NoL) * (0.62406015 + 0.41284404 * s / t);
}
vec3 getSkyRadiance(
const vec3 cameraPosition,
const vec3 rayDirection,
float shadowLength,
const vec3 sunDirection,
const vec3 moonDirection,
const float moonAngularRadius,
const float lunarRadianceScale
) {
vec3 transmittance;
vec3 radiance = GetSkyRadiance(
cameraPosition,
rayDirection,
shadowLength,
sunDirection,
transmittance
);
// Rendering celestial objects without perspective doesn't make sense.
#ifdef PERSPECTIVE_CAMERA
#if defined(SUN) || defined(MOON)
vec3 ddx = dFdx(rayDirection);
vec3 ddy = dFdy(rayDirection);
float fragmentAngle = length(ddx + ddy) / length(rayDirection);
#endif // defined(SUN) || defined(MOON)
#ifdef SUN
float viewDotSun = dot(rayDirection, sunDirection);
if (viewDotSun > cos(u_sun_angular_radius)) {
float angle = acos(clamp(viewDotSun, -1.0, 1.0));
float antialias = smoothstep(u_sun_angular_radius, u_sun_angular_radius - fragmentAngle, angle);
radiance += transmittance * GetSolarRadiance() * antialias;
}
#endif // SUN
#ifdef MOON
float intersection = intersectSphere(rayDirection, moonDirection, moonAngularRadius);
if (intersection > 0.0) {
vec3 normal = normalize(moonDirection - rayDirection * intersection);
float diffuse = orenNayarDiffuse(-sunDirection, rayDirection, normal);
float viewDotMoon = dot(rayDirection, moonDirection);
float angle = acos(clamp(viewDotMoon, -1.0, 1.0));
float antialias = smoothstep(moonAngularRadius, moonAngularRadius - fragmentAngle, angle);
radiance +=
transmittance *
getLunarRadiance(moonAngularRadius) *
lunarRadianceScale *
diffuse *
antialias;
}
#endif // MOON
#endif // PERSPECTIVE_CAMERA
return radiance;
}
`;var Jt=Object.defineProperty,M0=(t,e,n,o)=>{for(var a=void 0,c=t.length-1,l;c>=0;c--)(l=t[c])&&(a=l(e,n,a)||a);return a&&Jt(e,n,a),a};const Qt=new d.Vector3,er=new d.Vector3,nr=new D.Geodetic,qn={blendFunction:vn.BlendFunction.NORMAL,octEncodedNormal:!1,reconstructNormal:!1,ellipsoid:D.Ellipsoid.WGS84,correctAltitude:!0,correctGeometricError:!0,photometric:!0,sunIrradiance:!1,skyIrradiance:!1,transmittance:!0,inscatter:!0,irradianceScale:1,sky:!1,sun:!0,moon:!0,moonAngularRadius:.0045,lunarRadianceScale:1};class g0 extends vn.Effect{constructor(e=new d.Camera,n,o=oe.DEFAULT){const{blendFunction:a,normalBuffer:c=null,octEncodedNormal:l,reconstructNormal:v,irradianceTexture:u=null,scatteringTexture:E=null,transmittanceTexture:S=null,ellipsoid:g,correctAltitude:I,correctGeometricError:N,photometric:O,sunDirection:P,sunIrradiance:H,skyIrradiance:J,transmittance:t0,inscatter:r0,irradianceScale:c0,sky:E0,sun:l0,moon:h0,moonDirection:n0,moonAngularRadius:b0,lunarRadianceScale:K0}={...qn,...n};super("AerialPerspectiveEffect",D.unrollLoops(D.resolveIncludes(qt,{core:{depth:X0.depth,packing:X0.packing,math:X0.math,transform:X0.transform,raySphereIntersection:X0.raySphereIntersection,cascadedShadowMaps:X0.cascadedShadowMaps,interleavedGradientNoise:X0.interleavedGradientNoise,vogelDisk:X0.vogelDisk},parameters:j0._parameters,functions:j0._functions,sky:jn})),{blendFunction:a,vertexShader:D.resolveIncludes(Kt,{parameters:j0._parameters}),attributes:vn.EffectAttribute.DEPTH,uniforms:new Map(Object.entries({normalBuffer:new d.Uniform(c),projectionMatrix:new d.Uniform(new d.Matrix4),viewMatrix:new d.Uniform(new d.Matrix4),inverseProjectionMatrix:new d.Uniform(new d.Matrix4),inverseViewMatrix:new d.Uniform(new d.Matrix4),cameraPosition:new d.Uniform(new d.Vector3),bottomRadius:new d.Uniform(o.bottomRadius),ellipsoidRadii:new d.Uniform(new d.Vector3),ellipsoidCenter:new d.Uniform(new d.Vector3),inverseEllipsoidMatrix:new d.Uniform(new d.Matrix4),altitudeCorrection:new d.Uniform(new d.Vector3),sunDirection:new d.Uniform((P==null?void 0:P.clone())??new d.Vector3),irradianceScale:new d.Uniform(c0),idealSphereAlpha:new d.Uniform(0),moonDirection:new d.Uniform((n0==null?void 0:n0.clone())??new d.Vector3),moonAngularRadius:new d.Uniform(b0),lunarRadianceScale:new d.Uniform(K0),overlayBuffer:new d.Uniform(null),shadowBuffer:new d.Uniform(null),shadowMapSize:new d.Uniform(new d.Vector2),shadowIntervals:new d.Uniform([]),shadowMatrices:new d.Uniform([]),inverseShadowMatrices:new d.Uniform([]),shadowFar:new d.Uniform(0),shadowTopHeight:new d.Uniform(0),shadowRadius:new d.Uniform(3),stbnTexture:new d.Uniform(null),frame:new d.Uniform(0),shadowLengthBuffer:new d.Uniform(null),u_solar_irradiance:new d.Uniform(o.solarIrradiance),u_sun_angular_radius:new d.Uniform(o.sunAngularRadius),u_bottom_radius:new d.Uniform(o.bottomRadius*ce),u_top_radius:new d.Uniform(o.topRadius*ce),u_rayleigh_scattering:new d.Uniform(o.rayleighScattering),u_mie_scattering:new d.Uniform(o.mieScattering),u_mie_phase_function_g:new d.Uniform(o.miePhaseFunctionG),u_mu_s_min:new d.Uniform(o.muSMin),u_irradiance_texture:new d.Uniform(u),u_scattering_texture:new d.Uniform(E),u_single_mie_scattering_texture:new d.Uniform(E),u_transmittance_texture:new d.Uniform(S)})),defines:new Map([["TRANSMITTANCE_TEXTURE_WIDTH",Ne.toFixed(0)],["TRANSMITTANCE_TEXTURE_HEIGHT",Ue.toFixed(0)],["SCATTERING_TEXTURE_R_SIZE",je.toFixed(0)],["SCATTERING_TEXTURE_MU_SIZE",qe.toFixed(0)],["SCATTERING_TEXTURE_MU_S_SIZE",Ke.toFixed(0)],["SCATTERING_TEXTURE_NU_SIZE",Je.toFixed(0)],["IRRADIANCE_TEXTURE_WIDTH",Me.toFixed(0)],["IRRADIANCE_TEXTURE_HEIGHT",De.toFixed(0)],["METER_TO_LENGTH_UNIT",ce.toFixed(7)],["SUN_SPECTRAL_RADIANCE_TO_LUMINANCE",`vec3(${o.sunRadianceToRelativeLuminance.toArray().map(H0=>H0.toFixed(12)).join(",")})`],["SKY_SPECTRAL_RADIANCE_TO_LUMINANCE",`vec3(${o.skyRadianceToRelativeLuminance.toArray().map(H0=>H0.toFixed(12)).join(",")})`]])}),this.camera=e,this.atmosphere=o,this.ellipsoidMatrix=new d.Matrix4,this.overlay=null,this.shadow=null,this.shadowLength=null,this.shadowSampleCount=8,this.octEncodedNormal=l,this.reconstructNormal=v,this.ellipsoid=g,this.correctAltitude=I,this.correctGeometricError=N,this.photometric=O,this.sunIrradiance=H,this.skyIrradiance=J,this.transmittance=t0,this.inscatter=r0,this.sky=E0,this.sun=l0,this.moon=h0}get mainCamera(){return this.camera}set mainCamera(e){this.camera=e}copyCameraSettings(e){const{projectionMatrix:n,matrixWorldInverse:o,projectionMatrixInverse:a,matrixWorld:c}=e,l=this.uniforms;l.get("projectionMatrix").value.copy(n),l.get("viewMatrix").value.copy(o),l.get("inverseProjectionMatrix").value.copy(a),l.get("inverseViewMatrix").value.copy(c);const v=e.getWorldPosition(l.get("cameraPosition").value),u=l.get("inverseEllipsoidMatrix").value.copy(this.ellipsoidMatrix).invert(),E=Qt.copy(v).applyMatrix4(u).sub(l.get("ellipsoidCenter").value);try{const g=nr.setFromECEF(E).height,I=er.set(0,this.ellipsoid.maximumRadius,-g).applyMatrix4(n);l.get("idealSphereAlpha").value=D.saturate(D.remap(I.y,41.5,13.8,0,1))}catch{return}const S=l.get("altitudeCorrection");this.correctAltitude?Qe(E,this.atmosphere.bottomRadius,this.ellipsoid,S.value):S.value.setScalar(0)}updateComposition(){const{uniforms:e,defines:n,overlay:o,shadow:a,shadowLength:c}=this,l=n.has("HAS_OVERLAY"),v=o!=null;v!==l&&(v?n.set("HAS_OVERLAY","1"):(n.delete("HAS_OVERLAY"),e.get("overlayBuffer").value=null),this.setChanged()),v&&(e.get("overlayBuffer").value=o.map);const u=n.has("HAS_SHADOW"),E=a!=null;if(E!==u&&(E?n.set("HAS_SHADOW","1"):(n.delete("HAS_SHADOW"),e.get("shadowBuffer").value=null),this.setChanged()),E){const I=n.get("SHADOW_CASCADE_COUNT"),N=`${a.cascadeCount}`;I!==N&&(n.set("SHADOW_CASCADE_COUNT",a.cascadeCount.toFixed(0)),this.setChanged()),e.get("shadowBuffer").value=a.map,e.get("shadowMapSize").value=a.mapSize,e.get("shadowIntervals").value=a.intervals,e.get("shadowMatrices").value=a.matrices,e.get("inverseShadowMatrices").value=a.inverseMatrices,e.get("shadowFar").value=a.far,e.get("shadowTopHeight").value=a.topHeight}const S=n.has("HAS_SHADOW_LENGTH"),g=c!=null;g!==S&&(g?n.set("HAS_SHADOW_LENGTH","1"):(n.delete("HAS_SHADOW_LENGTH"),e.get("shadowLengthBuffer").value=null),this.setChanged()),g&&(e.get("shadowLengthBuffer").value=c.map)}update(e,n,o){this.copyCameraSettings(this.camera),this.updateComposition(),++this.uniforms.get("frame").value}get normalBuffer(){return this.uniforms.get("normalBuffer").value}set normalBuffer(e){this.uniforms.get("normalBuffer").value=e}get irradianceTexture(){return this.uniforms.get("u_irradiance_texture").value}set irradianceTexture(e){this.uniforms.get("u_irradiance_texture").value=e}get scatteringTexture(){return this.uniforms.get("u_scattering_texture").value}set scatteringTexture(e){this.uniforms.get("u_scattering_texture").value=e,this.uniforms.get("u_single_mie_scattering_texture").value=e}get transmittanceTexture(){return this.uniforms.get("u_transmittance_texture").value}set transmittanceTexture(e){this.uniforms.get("u_transmittance_texture").value=e}get ellipsoid(){return this._ellipsoid}set ellipsoid(e){this._ellipsoid=e,this.uniforms.get("ellipsoidRadii").value.copy(e.radii)}get ellipsoidCenter(){return this.uniforms.get("ellipsoidCenter").value}get sunDirection(){return this.uniforms.get("sunDirection").value}get irradianceScale(){return this.uniforms.get("irradianceScale").value}set irradianceScale(e){this.uniforms.get("irradianceScale").value=e}get moonDirection(){return this.uniforms.get("moonDirection").value}get moonAngularRadius(){return this.uniforms.get("moonAngularRadius").value}set moonAngularRadius(e){this.uniforms.get("moonAngularRadius").value=e}get lunarRadianceScale(){return this.uniforms.get("lunarRadianceScale").value}set lunarRadianceScale(e){this.uniforms.get("lunarRadianceScale").value=e}get stbnTexture(){return this.uniforms.get("stbnTexture").value}set stbnTexture(e){this.uniforms.get("stbnTexture").value=e}get shadowRadius(){return this.uniforms.get("shadowRadius").value}set shadowRadius(e){this.uniforms.get("shadowRadius").value=e}}M0([D.define("OCT_ENCODED_NORMAL")],g0.prototype,"octEncodedNormal");M0([D.define("RECONSTRUCT_NORMAL")],g0.prototype,"reconstructNormal");M0([D.define("CORRECT_GEOMETRIC_ERROR")],g0.prototype,"correctGeometricError");M0([D.define("PHOTOMETRIC")],g0.prototype,"photometric");M0([D.define("SUN_IRRADIANCE")],g0.prototype,"sunIrradiance");M0([D.define("SKY_IRRADIANCE")],g0.prototype,"skyIrradiance");M0([D.define("TRANSMITTANCE")],g0.prototype,"transmittance");M0([D.define("INSCATTER")],g0.prototype,"inscatter");M0([D.define("SKY")],g0.prototype,"sky");M0([D.define("SUN")],g0.prototype,"sun");M0([D.define("MOON")],g0.prototype,"moon");M0([D.defineInt("SHADOW_SAMPLE_COUNT",{min:1,max:16})],g0.prototype,"shadowSampleCount");var tr=Object.defineProperty,rr=(t,e,n,o)=>{for(var a=void 0,c=t.length-1,l;c>=0;c--)(l=t[c])&&(a=l(e,n,a)||a);return a&&tr(e,n,a),a};const ir=new d.Vector3;function or(t,e){let n="",o="";for(let a=1;a<e;++a)n+=`layout(location = ${a}) out float renderTarget${a};
`,o+=`renderTarget${a} = 0.0;
`;return t.replace("#include <mrt_layout>",n).replace("#include <mrt_output>",o)}const en={ellipsoid:D.Ellipsoid.WGS84,correctAltitude:!0,photometric:!0,renderTargetCount:1};class nn extends d.RawShaderMaterial{constructor(e,n=oe.DEFAULT){const{irradianceTexture:o=null,scatteringTexture:a=null,transmittanceTexture:c=null,ellipsoid:l,correctAltitude:v,photometric:u,sunDirection:E,sunAngularRadius:S,renderTargetCount:g,...I}={...en,...e};super({toneMapped:!1,depthWrite:!1,depthTest:!1,...I,uniforms:{cameraPosition:new d.Uniform(new d.Vector3),ellipsoidCenter:new d.Uniform(new d.Vector3),inverseEllipsoidMatrix:new d.Uniform(new d.Matrix4),altitudeCorrection:new d.Uniform(new d.Vector3),sunDirection:new d.Uniform((E==null?void 0:E.clone())??new d.Vector3),u_solar_irradiance:new d.Uniform(n.solarIrradiance),u_sun_angular_radius:new d.Uniform(S??n.sunAngularRadius),u_bottom_radius:new d.Uniform(n.bottomRadius*ce),u_top_radius:new d.Uniform(n.topRadius*ce),u_rayleigh_scattering:new d.Uniform(n.rayleighScattering),u_mie_scattering:new d.Uniform(n.mieScattering),u_mie_phase_function_g:new d.Uniform(n.miePhaseFunctionG),u_mu_s_min:new d.Uniform(n.muSMin),u_irradiance_texture:new d.Uniform(o),u_scattering_texture:new d.Uniform(a),u_single_mie_scattering_texture:new d.Uniform(a),u_transmittance_texture:new d.Uniform(c),...I.uniforms},defines:{PI:`${Math.PI}`,TRANSMITTANCE_TEXTURE_WIDTH:Ne.toFixed(0),TRANSMITTANCE_TEXTURE_HEIGHT:Ue.toFixed(0),SCATTERING_TEXTURE_R_SIZE:je.toFixed(0),SCATTERING_TEXTURE_MU_SIZE:qe.toFixed(0),SCATTERING_TEXTURE_MU_S_SIZE:Ke.toFixed(0),SCATTERING_TEXTURE_NU_SIZE:Je.toFixed(0),IRRADIANCE_TEXTURE_WIDTH:Me.toFixed(0),IRRADIANCE_TEXTURE_HEIGHT:De.toFixed(0),METER_TO_LENGTH_UNIT:ce.toFixed(7),SUN_SPECTRAL_RADIANCE_TO_LUMINANCE:`vec3(${n.sunRadianceToRelativeLuminance.toArray().map(N=>N.toFixed(12)).join(",")})`,SKY_SPECTRAL_RADIANCE_TO_LUMINANCE:`vec3(${n.skyRadianceToRelativeLuminance.toArray().map(N=>N.toFixed(12)).join(",")})`,...I.defines}}),this.atmosphere=n,this.ellipsoidMatrix=new d.Matrix4,this.atmosphere=n,this.ellipsoid=l,this.correctAltitude=v,this.photometric=u,this.renderTargetCount=g}copyCameraSettings(e){const n=this.uniforms,o=e.getWorldPosition(n.cameraPosition.value),a=n.inverseEllipsoidMatrix.value.copy(this.ellipsoidMatrix).invert(),c=ir.copy(o).applyMatrix4(a).sub(n.ellipsoidCenter.value),l=n.altitudeCorrection.value;this.correctAltitude?Qe(c,this.atmosphere.bottomRadius,this.ellipsoid,l):l.setScalar(0)}onBeforeCompile(e,n){e.fragmentShader=or(e.fragmentShader,this.renderTargetCount)}onBeforeRender(e,n,o,a,c,l){this.copyCameraSettings(o)}get irradianceTexture(){return this.uniforms.u_irradiance_texture.value}set irradianceTexture(e){this.uniforms.u_irradiance_texture.value=e}get scatteringTexture(){return this.uniforms.u_scattering_texture.value}set scatteringTexture(e){this.uniforms.u_scattering_texture.value=e,this.uniforms.u_single_mie_scattering_texture.value=e}get transmittanceTexture(){return this.uniforms.u_transmittance_texture.value}set transmittanceTexture(e){this.uniforms.u_transmittance_texture.value=e}get ellipsoidCenter(){return this.uniforms.ellipsoidCenter.value}get sunDirection(){return this.uniforms.sunDirection.value}get sunAngularRadius(){return this.uniforms.u_sun_angular_radius.value}set sunAngularRadius(e){this.uniforms.u_sun_angular_radius.value=e}get renderTargetCount(){return this._renderTargetCount}set renderTargetCount(e){e!==this.renderTargetCount&&(this._renderTargetCount=e,this.needsUpdate=!0)}}rr([D.define("PHOTOMETRIC")],nn.prototype,"photometric");/**
@preserve
Astronomy library for JavaScript (browser and Node.js).
https://github.com/cosinekitty/astronomy
MIT License
Copyright (c) 2019-2023 Don Cross <cosinekitty@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*//**
* @fileoverview Astronomy calculation library for browser scripting and Node.js.
* @author Don Cross <cosinekitty@gmail.com>
* @license MIT
*/const ar=173.1446326846693,sr=14959787069098932e-8,me=.017453292519943295,cr=365.24217,Fn=new Date("2000-01-01T12:00:00Z"),Y0=2*Math.PI,ne=3600*(180/Math.PI),fe=484813681109536e-20,lr=180*60*60,ur=2*lr,dr=6378.1366,vr=dr/sr,fr=81.30056,xn=.0002959122082855911,hn=2825345909524226e-22,pn=8459715185680659e-23,mn=1292024916781969e-23,En=1524358900784276e-23;function on(t){if(!Number.isFinite(t))throw console.trace(),`Value is not a finite number: ${t}`;return t}function ve(t){return t-Math.floor(t)}var k;(function(t){t.Sun="Sun",t.Moon="Moon",t.Mercury="Mercury",t.Venus="Venus",t.Earth="Earth",t.Mars="Mars",t.Jupiter="Jupiter",t.Saturn="Saturn",t.Uranus="Uranus",t.Neptune="Neptune",t.Pluto="Pluto",t.SSB="SSB",t.EMB="EMB",t.Star1="Star1",t.Star2="Star2",t.Star3="Star3",t.Star4="Star4",t.Star5="Star5",t.Star6="Star6",t.Star7="Star7",t.Star8="Star8"})(k||(k={}));const hr=[k.Star1,k.Star2,k.Star3,k.Star4,k.Star5,k.Star6,k.Star7,k.Star8],pr=[{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0}];function mr(t){const e=hr.indexOf(t);return e>=0?pr[e]:null}function Kn(t){const e=mr(t);return e&&e.dist>0?e:null}var q0;(function(t){t[t.From2000=0]="From2000",t[t.Into2000=1]="Into2000"})(q0||(q0={}));const he={Mercury:[[[[4.40250710144,0,0],[.40989414977,1.48302034195,26087.9031415742],[.050462942,4.47785489551,52175.8062831484],[.00855346844,1.16520322459,78263.70942472259],[.00165590362,4.11969163423,104351.61256629678],[.00034561897,.77930768443,130439.51570787099],[7583476e-11,3.71348404924,156527.41884944518]],[[26087.90313685529,0,0],[.01131199811,6.21874197797,26087.9031415742],[.00292242298,3.04449355541,52175.8062831484],[.00075775081,6.08568821653,78263.70942472259],[.00019676525,2.80965111777,104351.61256629678]]],[[[.11737528961,1.98357498767,26087.9031415742],[.02388076996,5.03738959686,52175.8062831484],[.01222839532,3.14159265359,0],[.0054325181,1.79644363964,78263.70942472259],[.0012977877,4.83232503958,104351.61256629678],[.00031866927,1.58088495658,130439.51570787099],[7963301e-11,4.60972126127,156527.41884944518]],[[.00274646065,3.95008450011,26087.9031415742],[.00099737713,3.14159265359,0]]],[[[.39528271651,0,0],[.07834131818,6.19233722598,26087.9031415742],[.00795525558,2.95989690104,52175.8062831484],[.00121281764,6.01064153797,78263.70942472259],[.00021921969,2.77820093972,104351.61256629678],[4354065e-11,5.82894543774,130439.51570787099]],[[.0021734774,4.65617158665,26087.9031415742],[.00044141826,1.42385544001,52175.8062831484]]]],Venus:[[[[3.17614666774,0,0],[.01353968419,5.59313319619,10213.285546211],[.00089891645,5.30650047764,20426.571092422],[5477194e-11,4.41630661466,7860.4193924392],[3455741e-11,2.6996444782,11790.6290886588],[2372061e-11,2.99377542079,3930.2096962196],[1317168e-11,5.18668228402,26.2983197998],[1664146e-11,4.25018630147,1577.3435424478],[1438387e-11,4.15745084182,9683.5945811164],[1200521e-11,6.15357116043,30639.856638633]],[[10213.28554621638,0,0],[.00095617813,2.4640651111,10213.285546211],[7787201e-11,.6247848222,20426.571092422]]],[[[.05923638472,.26702775812,10213.285546211],[.00040107978,1.14737178112,20426.571092422],[.00032814918,3.14159265359,0]],[[.00287821243,1.88964962838,10213.285546211]]],[[[.72334820891,0,0],[.00489824182,4.02151831717,10213.285546211],[1658058e-11,4.90206728031,20426.571092422],[1378043e-11,1.12846591367,11790.6290886588],[1632096e-11,2.84548795207,7860.4193924392],[498395e-11,2.58682193892,9683.5945811164],[221985e-11,2.01346696541,19367.1891622328],[237454e-11,2.55136053886,15720.8387848784]],[[.00034551041,.89198706276,10213.285546211]]]],Earth:[[[[1.75347045673,0,0],[.03341656453,4.66925680415,6283.0758499914],[.00034894275,4.62610242189,12566.1516999828],[3417572e-11,2.82886579754,3.523118349],[3497056e-11,2.74411783405,5753.3848848968],[3135899e-11,3.62767041756,77713.7714681205],[2676218e-11,4.41808345438,7860.4193924392],[2342691e-11,6.13516214446,3930.2096962196],[1273165e-11,2.03709657878,529.6909650946],[1324294e-11,.74246341673,11506.7697697936],[901854e-11,2.04505446477,26.2983197998],[1199167e-11,1.10962946234,1577.3435424478],[857223e-11,3.50849152283,398.1490034082],[779786e-11,1.17882681962,5223.6939198022],[99025e-10,5.23268072088,5884.9268465832],[753141e-11,2.53339052847,5507.5532386674],[505267e-11,4.58292599973,18849.2275499742],[492392e-11,4.20505711826,775.522611324],[356672e-11,2.91954114478,.0673103028],[284125e-11,1.89869240932,796.2980068164],[242879e-11,.34481445893,5486.777843175],[317087e-11,5.84901948512,11790.6290886588],[271112e-11,.31486255375,10977.078804699],[206217e-11,4.80646631478,2544.3144198834],[205478e-11,1.86953770281,5573.1428014331],[202318e-11,2.45767790232,6069.7767545534],[126225e-11,1.08295459501,20.7753954924],[155516e-11,.83306084617,213.299095438]],[[6283.0758499914,0,0],[.00206058863,2.67823455808,6283.0758499914],[4303419e-11,2.63512233481,12566.1516999828]],[[8721859e-11,1.07253635559,6283.0758499914]]],[[],[[.00227777722,3.4137662053,6283.0758499914],[3805678e-11,3.37063423795,12566.1516999828]]],[[[1.00013988784,0,0],[.01670699632,3.09846350258,6283.0758499914],[.00013956024,3.05524609456,12566.1516999828],[308372e-10,5.19846674381,77713.7714681205],[1628463e-11,1.17387558054,5753.3848848968],[1575572e-11,2.84685214877,7860.4193924392],[924799e-11,5.45292236722,11506.7697697936],[542439e-11,4.56409151453,3930.2096962196],[47211e-10,3.66100022149,5884.9268465832],[85831e-11,1.27079125277,161000.6857376741],[57056e-11,2.01374292245,83996.84731811189],[55736e-11,5.2415979917,71430.69561812909],[174844e-11,3.01193636733,18849.2275499742],[243181e-11,4.2734953079,11790.6290886588]],[[.00103018607,1.10748968172,6283.0758499914],[1721238e-11,1.06442300386,12566.1516999828]],[[4359385e-11,5.78455133808,6283.0758499914]]]],Mars:[[[[6.20347711581,0,0],[.18656368093,5.0503710027,3340.6124266998],[.01108216816,5.40099836344,6681.2248533996],[.00091798406,5.75478744667,10021.8372800994],[.00027744987,5.97049513147,3.523118349],[.00010610235,2.93958560338,2281.2304965106],[.00012315897,.84956094002,2810.9214616052],[8926784e-11,4.15697846427,.0172536522],[8715691e-11,6.11005153139,13362.4497067992],[6797556e-11,.36462229657,398.1490034082],[7774872e-11,3.33968761376,5621.8429232104],[3575078e-11,1.6618650571,2544.3144198834],[4161108e-11,.22814971327,2942.4634232916],[3075252e-11,.85696614132,191.4482661116],[2628117e-11,.64806124465,3337.0893083508],[2937546e-11,6.07893711402,.0673103028],[2389414e-11,5.03896442664,796.2980068164],[2579844e-11,.02996736156,3344.1355450488],[1528141e-11,1.14979301996,6151.533888305],[1798806e-11,.65634057445,529.6909650946],[1264357e-11,3.62275122593,5092.1519581158],[1286228e-11,3.06796065034,2146.1654164752],[1546404e-11,2.91579701718,1751.539531416],[1024902e-11,3.69334099279,8962.4553499102],[891566e-11,.18293837498,16703.062133499],[858759e-11,2.4009381194,2914.0142358238],[832715e-11,2.46418619474,3340.5951730476],[83272e-10,4.49495782139,3340.629680352],[712902e-11,3.66335473479,1059.3819301892],[748723e-11,3.82248614017,155.4203994342],[723861e-11,.67497311481,3738.761430108],[635548e-11,2.92182225127,8432.7643848156],[655162e-11,.48864064125,3127.3133312618],[550474e-11,3.81001042328,.9803210682],[55275e-10,4.47479317037,1748.016413067],[425966e-11,.55364317304,6283.0758499914],[415131e-11,.49662285038,213.299095438],[472167e-11,3.62547124025,1194.4470102246],[306551e-11,.38052848348,6684.7479717486],[312141e-11,.99853944405,6677.7017350506],[293198e-11,4.22131299634,20.7753954924],[302375e-11,4.48618007156,3532.0606928114],[274027e-11,.54222167059,3340.545116397],[281079e-11,5.88163521788,1349.8674096588],[231183e-11,1.28242156993,3870.3033917944],[283602e-11,5.7688543494,3149.1641605882],[236117e-11,5.75503217933,3333.498879699],[274033e-11,.13372524985,3340.6797370026],[299395e-11,2.78323740866,6254.6266625236]],[[3340.61242700512,0,0],[.01457554523,3.60433733236,3340.6124266998],[.00168414711,3.92318567804,6681.2248533996],[.00020622975,4.26108844583,10021.8372800994],[3452392e-11,4.7321039319,3.523118349],[2586332e-11,4.60670058555,13362.4497067992],[841535e-11,4.45864030426,2281.2304965106]],[[.00058152577,2.04961712429,3340.6124266998],[.00013459579,2.45738706163,6681.2248533996]]],[[[.03197134986,3.76832042431,3340.6124266998],[.00298033234,4.10616996305,6681.2248533996],[.00289104742,0,0],[.00031365539,4.4465105309,10021.8372800994],[34841e-9,4.7881254926,13362.4497067992]],[[.00217310991,6.04472194776,3340.6124266998],[.00020976948,3.14159265359,0],[.00012834709,1.60810667915,6681.2248533996]]],[[[1.53033488271,0,0],[.1418495316,3.47971283528,3340.6124266998],[.00660776362,3.81783443019,6681.2248533996],[.00046179117,4.15595316782,10021.8372800994],[8109733e-11,5.55958416318,2810.9214616052],[7485318e-11,1.77239078402,5621.8429232104],[5523191e-11,1.3643630377,2281.2304965106],[382516e-10,4.49407183687,13362.4497067992],[2306537e-11,.09081579001,2544.3144198834],[1999396e-11,5.36059617709,3337.0893083508],[2484394e-11,4.9254563992,2942.4634232916],[1960195e-11,4.74249437639,3344.1355450488],[1167119e-11,2.11260868341,5092.1519581158],[1102816e-11,5.00908403998,398.1490034082],[899066e-11,4.40791133207,529.6909650946],[992252e-11,5.83861961952,6151.533888305],[807354e-11,2.10217065501,1059.3819301892],[797915e-11,3.44839203899,796.2980068164],[740975e-11,1.49906336885,2146.1654164752]],[[.01107433345,2.03250524857,3340.6124266998],[.00103175887,2.37071847807,6681.2248533996],[128772e-9,0,0],[.0001081588,2.70888095665,10021.8372800994]],[[.00044242249,.47930604954,3340.6124266998],[8138042e-11,.86998389204,6681.2248533996]]]],Jupiter:[[[[.59954691494,0,0],[.09695898719,5.06191793158,529.6909650946],[.00573610142,1.44406205629,7.1135470008],[.00306389205,5.41734730184,1059.3819301892],[.00097178296,4.14264726552,632.7837393132],[.00072903078,3.64042916389,522.5774180938],[.00064263975,3.41145165351,103.0927742186],[.00039806064,2.29376740788,419.4846438752],[.00038857767,1.27231755835,316.3918696566],[.00027964629,1.7845459182,536.8045120954],[.0001358973,5.7748104079,1589.0728952838],[8246349e-11,3.5822792584,206.1855484372],[8768704e-11,3.63000308199,949.1756089698],[7368042e-11,5.0810119427,735.8765135318],[626315e-10,.02497628807,213.299095438],[6114062e-11,4.51319998626,1162.4747044078],[4905396e-11,1.32084470588,110.2063212194],[5305285e-11,1.30671216791,14.2270940016],[5305441e-11,4.18625634012,1052.2683831884],[4647248e-11,4.69958103684,3.9321532631],[3045023e-11,4.31676431084,426.598190876],[2609999e-11,1.56667394063,846.0828347512],[2028191e-11,1.06376530715,3.1813937377],[1764763e-11,2.14148655117,1066.49547719],[1722972e-11,3.88036268267,1265.5674786264],[1920945e-11,.97168196472,639.897286314],[1633223e-11,3.58201833555,515.463871093],[1431999e-11,4.29685556046,625.6701923124],[973272e-11,4.09764549134,95.9792272178]],[[529.69096508814,0,0],[.00489503243,4.2208293947,529.6909650946],[.00228917222,6.02646855621,7.1135470008],[.00030099479,4.54540782858,1059.3819301892],[.0002072092,5.45943156902,522.5774180938],[.00012103653,.16994816098,536.8045120954],[6067987e-11,4.42422292017,103.0927742186],[5433968e-11,3.98480737746,419.4846438752],[4237744e-11,5.89008707199,14.2270940016]],[[.00047233601,4.32148536482,7.1135470008],[.00030649436,2.929777887,529.6909650946],[.00014837605,3.14159265359,0]]],[[[.02268615702,3.55852606721,529.6909650946],[.00109971634,3.90809347197,1059.3819301892],[.00110090358,0,0],[8101428e-11,3.60509572885,522.5774180938],[6043996e-11,4.25883108339,1589.0728952838],[6437782e-11,.30627119215,536.8045120954]],[[.00078203446,1.52377859742,529.6909650946]]],[[[5.20887429326,0,0],[.25209327119,3.49108639871,529.6909650946],[.00610599976,3.84115365948,1059.3819301892],[.00282029458,2.57419881293,632.7837393132],[.00187647346,2.07590383214,522.5774180938],[.00086792905,.71001145545,419.4846438752],[.00072062974,.21465724607,536.8045120954],[.00065517248,5.9799588479,316.3918696566],[.00029134542,1.67759379655,103.0927742186],[.00030135335,2.16132003734,949.1756089698],[.00023453271,3.54023522184,735.8765135318],[.00022283743,4.19362594399,1589.0728952838],[.00023947298,.2745803748,7.1135470008],[.00013032614,2.96042965363,1162.4747044078],[970336e-10,1.90669633585,206.1855484372],[.00012749023,2.71550286592,1052.2683831884],[7057931e-11,2.18184839926,1265.5674786264],[6137703e-11,6.26418240033,846.0828347512],[2616976e-11,2.00994012876,1581.959348283]],[[.0127180152,2.64937512894,529.6909650946],[.00061661816,3.00076460387,1059.3819301892],[.00053443713,3.89717383175,522.5774180938],[.00031185171,4.88276958012,536.8045120954],[.00041390269,0,0]]]],Saturn:[[[[.87401354025,0,0],[.11107659762,3.96205090159,213.299095438],[.01414150957,4.58581516874,7.1135470008],[.00398379389,.52112032699,206.1855484372],[.00350769243,3.30329907896,426.598190876],[.00206816305,.24658372002,103.0927742186],[792713e-9,3.84007056878,220.4126424388],[.00023990355,4.66976924553,110.2063212194],[.00016573588,.43719228296,419.4846438752],[.00014906995,5.76903183869,316.3918696566],[.0001582029,.93809155235,632.7837393132],[.00014609559,1.56518472,3.9321532631],[.00013160301,4.44891291899,14.2270940016],[.00015053543,2.71669915667,639.897286314],[.00013005299,5.98119023644,11.0457002639],[.00010725067,3.12939523827,202.2533951741],[5863206e-11,.23656938524,529.6909650946],[5227757e-11,4.20783365759,3.1813937377],[6126317e-11,1.76328667907,277.0349937414],[5019687e-11,3.17787728405,433.7117378768],[459255e-10,.61977744975,199.0720014364],[4005867e-11,2.24479718502,63.7358983034],[2953796e-11,.98280366998,95.9792272178],[387367e-10,3.22283226966,138.5174968707],[2461186e-11,2.03163875071,735.8765135318],[3269484e-11,.77492638211,949.1756089698],[1758145e-11,3.2658010994,522.5774180938],[1640172e-11,5.5050445305,846.0828347512],[1391327e-11,4.02333150505,323.5054166574],[1580648e-11,4.37265307169,309.2783226558],[1123498e-11,2.83726798446,415.5524906121],[1017275e-11,3.71700135395,227.5261894396],[848642e-11,3.1915017083,209.3669421749]],[[213.2990952169,0,0],[.01297370862,1.82834923978,213.299095438],[.00564345393,2.88499717272,7.1135470008],[.00093734369,1.06311793502,426.598190876],[.00107674962,2.27769131009,206.1855484372],[.00040244455,2.04108104671,220.4126424388],[.00019941774,1.2795439047,103.0927742186],[.00010511678,2.7488034213,14.2270940016],[6416106e-11,.38238295041,639.897286314],[4848994e-11,2.43037610229,419.4846438752],[4056892e-11,2.92133209468,110.2063212194],[3768635e-11,3.6496533078,3.9321532631]],[[.0011644133,1.17988132879,7.1135470008],[.00091841837,.0732519584,213.299095438],[.00036661728,0,0],[.00015274496,4.06493179167,206.1855484372]]],[[[.04330678039,3.60284428399,213.299095438],[.00240348302,2.85238489373,426.598190876],[.00084745939,0,0],[.00030863357,3.48441504555,220.4126424388],[.00034116062,.57297307557,206.1855484372],[.0001473407,2.11846596715,639.897286314],[9916667e-11,5.79003188904,419.4846438752],[6993564e-11,4.7360468972,7.1135470008],[4807588e-11,5.43305312061,316.3918696566]],[[.00198927992,4.93901017903,213.299095438],[.00036947916,3.14159265359,0],[.00017966989,.5197943111,426.598190876]]],[[[9.55758135486,0,0],[.52921382865,2.39226219573,213.299095438],[.01873679867,5.2354960466,206.1855484372],[.01464663929,1.64763042902,426.598190876],[.00821891141,5.93520042303,316.3918696566],[.00547506923,5.0153261898,103.0927742186],[.0037168465,2.27114821115,220.4126424388],[.00361778765,3.13904301847,7.1135470008],[.00140617506,5.70406606781,632.7837393132],[.00108974848,3.29313390175,110.2063212194],[.00069006962,5.94099540992,419.4846438752],[.00061053367,.94037691801,639.897286314],[.00048913294,1.55733638681,202.2533951741],[.00034143772,.19519102597,277.0349937414],[.00032401773,5.47084567016,949.1756089698],[.00020936596,.46349251129,735.8765135318],[9796004e-11,5.20477537945,1265.5674786264],[.00011993338,5.98050967385,846.0828347512],[208393e-9,1.52102476129,433.7117378768],[.00015298404,3.0594381494,529.6909650946],[6465823e-11,.17732249942,1052.2683831884],[.00011380257,1.7310542704,522.5774180938],[3419618e-11,4.94550542171,1581.959348283]],[[.0618298134,.2584351148,213.299095438],[.00506577242,.71114625261,206.1855484372],[.00341394029,5.79635741658,426.598190876],[.00188491195,.47215589652,220.4126424388],[.00186261486,3.14159265359,0],[.00143891146,1.40744822888,7.1135470008]],[[.00436902572,4.78671677509,213.299095438]]]],Uranus:[[[[5.48129294297,0,0],[.09260408234,.89106421507,74.7815985673],[.01504247898,3.6271926092,1.4844727083],[.00365981674,1.89962179044,73.297125859],[.00272328168,3.35823706307,149.5631971346],[.00070328461,5.39254450063,63.7358983034],[.00068892678,6.09292483287,76.2660712756],[.00061998615,2.26952066061,2.9689454166],[.00061950719,2.85098872691,11.0457002639],[.0002646877,3.14152083966,71.8126531507],[.00025710476,6.11379840493,454.9093665273],[.0002107885,4.36059339067,148.0787244263],[.00017818647,1.74436930289,36.6485629295],[.00014613507,4.73732166022,3.9321532631],[.00011162509,5.8268179635,224.3447957019],[.0001099791,.48865004018,138.5174968707],[9527478e-11,2.95516862826,35.1640902212],[7545601e-11,5.236265824,109.9456887885],[4220241e-11,3.23328220918,70.8494453042],[40519e-9,2.277550173,151.0476698429],[3354596e-11,1.0654900738,4.4534181249],[2926718e-11,4.62903718891,9.5612275556],[349034e-10,5.48306144511,146.594251718],[3144069e-11,4.75199570434,77.7505439839],[2922333e-11,5.35235361027,85.8272988312],[2272788e-11,4.36600400036,70.3281804424],[2051219e-11,1.51773566586,.1118745846],[2148602e-11,.60745949945,38.1330356378],[1991643e-11,4.92437588682,277.0349937414],[1376226e-11,2.04283539351,65.2203710117],[1666902e-11,3.62744066769,380.12776796],[1284107e-11,3.11347961505,202.2533951741],[1150429e-11,.93343589092,3.1813937377],[1533221e-11,2.58594681212,52.6901980395],[1281604e-11,.54271272721,222.8603229936],[1372139e-11,4.19641530878,111.4301614968],[1221029e-11,.1990065003,108.4612160802],[946181e-11,1.19253165736,127.4717966068],[1150989e-11,4.17898916639,33.6796175129]],[[74.7815986091,0,0],[.00154332863,5.24158770553,74.7815985673],[.00024456474,1.71260334156,1.4844727083],[9258442e-11,.4282973235,11.0457002639],[8265977e-11,1.50218091379,63.7358983034],[915016e-10,1.41213765216,149.5631971346]]],[[[.0