@rr0/ufoathome 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -5520,7 +5520,7 @@ void main()
|
|
|
5520
5520
|
|
|
5521
5521
|
gl_FragColor = vec4(finalColor, max(dazzleAlpha, artifactsAlpha));
|
|
5522
5522
|
}
|
|
5523
|
-
`;let Yr;function L2(){if(Yr)return Yr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return Yr=new Vn(e),Yr}function N2(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Se(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:L2()}},e=new Gt({uniforms:i,vertexShader:D2,fragmentShader:P2,transparent:!0,depthWrite:!1,depthTest:!1,blending:da,fog:!1,name:"LensFlareShader"}),t=new yt(new sr(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const is=["front","behind","left","right","front-left","front-right","behind-left","behind-right"];function Dc(i){return i==="vehicle"?["front","behind","front-left","front-right","behind-left","behind-right"]:["front","behind","left","right"]}function U2(i){return i==="vehicle"?["front-left","front-right","behind-left","behind-right"]:Dc(i)}const ec=90,F2=50;function O2(i){if(!a0(i))return;const e={};for(const t of Dc(i))e[t]=tc(i,t)?F2:ec;return e}const ca=2;function a0(i){return i==="building"||i==="vehicle"}function tc(i,e){return i==="building"?!0:i==="vehicle"?e!=="front"&&e!=="behind":!1}function $s(i){return i==="building"||i==="vehicle"}function nc(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const Sd=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new nr({color:new Se(...t)}):new rr({color:new Se(...t)}),a=new yt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const o0=[.32,.32,.3],l0=[1,.85,.5],c0=[.25,.25,.25],h0=[1,.97,.85],B2=[.55,.68,.72],gn=.03,vn=.05,d0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function kt(i,e){return i?.[e]}function _n(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new rr({color:new Se(...B2),transparent:!0,opacity:o/100}),c=new yt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,Ao=[.6,.58,.53],yd=[.5,.5,.48];function us(i,e,t,n,s,r,a,o){const l=new rr({color:new Se(...o),side:Dt}),c=new yt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}function z2(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(v,y,m,f)=>{v<=0||(e?us(i,v,y,Jt,m,o+f,a,l):us(i,Jt,y,v,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const u=[...s].sort((v,y)=>v.center-y.center);let d=-t/2;for(const v of u){const m=v.center-v.main/2-d;h(m,r,d+m/2,0),d=v.center+v.main/2}const p=t/2-d;h(p,r,d+p/2,0)}function u0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,u=s-n,d=(p,v,y,m)=>{p.length===0?v?us(i,y,u,Jt,0,h,m,Ao):us(i,Jt,u,y,m,h,0,Ao):z2(i,v,y,u,p,r,m,h,Ao)};d(a,!0,e*2,-t+Jt),d(o,!0,e*2,t-Jt),d(l,!1,t*2,-e+Jt),d(c,!1,t*2,e-Jt),us(i,e*2,Jt,t*2,0,n+Jt,0,yd),us(i,e*2,Jt,t*2,0,s-Jt,0,yd)}function ic(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function f0(i,e,t,n,s,r,a){const o=g0();o.scale.setScalar(n),o.rotation.y=d0[e];const{x:l,z:c}=ic(e,s,r,a);o.position.set(l,t,c),i.add(o)}const sc=6,rc=6,ii=3,Bs=1.4,zs=ii*.5,p0=1.2,m0=.35,k2=.75,G2=1.6;function H2(i,e,t,n){const s=new Mn,r=Math.max(1,i+1),a=r*ii;tn(s,new An(sc,a,rc),[.55,.54,.5],a/2);const o=sc/2,l=rc/2;for(let c=0;c<r;c++){const h=c*ii+ii/2;_n(s,Bs,zs,vn,0,h,-l-gn,kt(e,"front")),_n(s,Bs,zs,vn,0,h,l+gn,kt(e,"behind")),_n(s,vn,zs,Bs,-o-gn,h,0,kt(e,"left")),_n(s,vn,zs,Bs,o+gn,h,0,kt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);f0(s,t,c*ii,.72,o,l,p0);const h=u=>kt(e,u)!==void 0?[{main:Bs,center:0}]:[];u0(s,o,l,c*ii,(c+1)*ii,zs,h("front"),h("behind"),h("left"),h("right"))}return s}function V2(){const i=new Mn;return tn(i,new Ni(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Da(1.4,3,8),[.16,.32,.14],3.5),i}function W2(i){const e=new Mn;return tn(e,new Ni(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new ui(.25,12,8),i?l0:o0,5.1,!0),e}const X2=[.08,.08,.08],ni=.8,ls=1,pn=1.7,Io=.6,_i=.4,qr=1.2,ss=.7,xn=.5,Y2=pn;function q2(i,e,t){const n=new Mn;tn(n,new An(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new An(ni*2,Io,ls*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ni(.4,.4,.3,12),X2,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?h0:c0;for(const r of[-.7,.7])tn(n,new ui(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(_n(n,qr,_i,vn,0,pn,-ls-gn,kt(e,"front")),_n(n,qr,_i,vn,0,pn,ls+gn,kt(e,"behind")),_n(n,vn,_i,ss,-ni-gn,pn,-xn,kt(e,"front-left")),_n(n,vn,_i,ss,-ni-gn,pn,xn,kt(e,"behind-left")),_n(n,vn,_i,ss,ni+gn,pn,-xn,kt(e,"front-right")),_n(n,vn,_i,ss,ni+gn,pn,xn,kt(e,"behind-right")),t){f0(n,t,k2,.5,ni,ls,m0);const r=(l,c)=>{const h=[];return kt(e,l)!==void 0&&h.push({main:ss,center:-xn}),kt(e,c)!==void 0&&h.push({main:ss,center:xn}),h},a=kt(e,"front")!==void 0?[{main:qr,center:0}]:[],o=kt(e,"behind")!==void 0?[{main:qr,center:0}]:[];u0(n,ni,ls,pn-Io/2,pn+Io/2,_i,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const $2=[.95,.9,.82];function g0(){const i=new Mn;tn(i,new Ni(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new ui(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Da(.07,.16,8),$2,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class ks{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?ic(t,ni,ls,m0):ic(t,sc/2,rc/2,p0),r=e.kind==="vehicle"?Y2:(e.occupiedFloor??0)*ii+G2,a=(e.headingDeg??0)-d0[t]/Sd;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?H2(e.floors??ca,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?V2():e.kind==="streetlight"?W2(t):e.kind==="vehicle"?q2(t,e.windows,e.witnessSide):g0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*Sd),n}static setLit(e,t,n){const s=t==="streetlight"?n?l0:o0:n?h0:c0;for(const r of e.children)!(r instanceof yt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof yt&&(t.geometry.dispose(),t.material.dispose())}}function K2(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const $r=900,Z2=.5,J2=900,Ro=.5,Q2=850,Co=850,Do=4,j2=1.5,eS=-1,tS=6,ac=-4,bd=ac,nS=3,iS=.15,sS=.6,rS=40,aS=30,oS=[0,45,90,135,180,225,270,315],lS={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},cS=["en","fr"],hS=880,Md=40,dS=10,uS=1,fS=150,Po=55,Ed=.5,pS=700,mS=5,rs=[.92,.92,.95],Lo=[.15,.15,.19],wd={snow:{fallSpeedMPerS:2,size:.3,color:new Se(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Se(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},cs=0,gS=0,Td=3e3,Gs=20,vS=15,Ad=cs,_S=40,Id=1,xS=9;function SS(i){return Id+(xS-Id)*i}const yS=new Se(.75,.82,.92),bS=10,MS=.5;function ES(i){return v0(i/bS,MS,1)}const as=200,Rd=.18,Cd=.32,wS=.35,TS=new Se(.85,.9,.98),Dd=5,Pd=.85,Ld=.01;function No(i,e){return Math.round(i*(Ld+(1-Ld)*e))}const Nd=230,Ud=.7,Fd=.05,AS=.6,IS=.7,RS=.15,Od=.35,CS=3,DS=1/12,PS=.5,Bd=8,zd=25,kd=.12,LS={Venus:new Se(1,.96,.85),Mars:new Se(1,.55,.4),Jupiter:new Se(.95,.87,.72),Saturn:new Se(.92,.86,.68)};class NS{renderer;scene=new up;camera;celestialGroup=new Mn;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new Up(16777215,0);celestialLightTarget=new bt;skyLight=new Dp(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new mo;weather=$d;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new U;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new U;sunVisible=!1;lensFlareScratch=new U;sunOcclusionRaycaster=new mo;sunOcclusionDirectionScratch=new U;ufoOcclusionRaycaster=new mo;onLightningFlash;constructor(e,t=u2(),n){this.renderer=new L_({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Ks,this.camera=new Yt(60,e.width/Math.max(e.height,1),.1,$r*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Di(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<fS)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;g2(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=uS,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=Ed*e,this.lastSunPosition&&this.applyLensFlareTint(Fs(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(Po*this.dazzleIntensity*e[0],Po*this.dazzleIntensity*e[1],Po*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){K2(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=PS,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())this.scene.remove(t),ks.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=ks.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Di(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&$s(a.kind)),r={x:0,z:0};if(s){const a=ks.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,u=-s.northM+n.z;r.x=-(h+l),r.z=-(u+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,gS,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=nc(t,e);ks.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new Lp(16764006,rS,aS);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=Uu(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,Do,new Se(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new yc(new Se(...n),$r*.2,$r),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=sS;const s=e.sun.altitudeDeg>=bd,r=!s&&e.moon.altitudeDeg>=bd;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=ts(a.altitudeDeg,a.azimuthDeg,Co);this.celestialLight.position.set(o,l,c);const h=Fs(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const u=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?nS:iS)*u,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=Z2,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())ks.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.scene.remove(this.lensFlare.mesh),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,DS);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new ui($r,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=O_(n.getX(a),n.getY(a),n.getZ(a)),c=k_(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new Mt(s,3));const r=new nr({vertexColors:!0,side:Dt,fog:!1});this.skyMesh=new yt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new Ec(J2,48),t=new rr({color:new Se(Ro,Ro,Ro),fog:!0});this.groundMesh=new yt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<ac){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=ts(t.altitudeDeg,t.azimuthDeg,Co),c=Fs(t.altitudeDeg),h=new Se(s.r*c[0],s.g*c[1],s.b*c[2]),u=new ui(n,16,16),d=new nr({color:h,fog:!1}),p=new yt(u,d);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=N2(),this.lensFlare.uniforms.uOpacity.value=Ed*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<ac){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=ts(e.altitudeDeg,e.azimuthDeg,Co),a=Fs(e.altitudeDeg),o=new Se(a[0],a[1],a[2]),l=new Ws({map:WS(e.phase),color:o,fog:!1}),c=new br(l);c.position.set(n,s,r);const h=Do*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,Do),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new Ws({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new br(a);o.position.set(t,n,s);const l=r*tS;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=H_(r);if(o<=0)return;const l=X_(o),c=new Ws({map:VS(),color:a,transparent:!0,opacity:$_(o),blending:da,depthWrite:!1,fog:!1}),h=new br(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=td(n.magnitude),r=nd(s),a=LS[n.body]??new Se(1,1,1),o=new Se(a.r*r,a.g*r,a.b*r),l=j2*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=N_(t),o=Uo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:u,azimuthDeg:d}=Kx(n.ra[c],n.dec[c],s,r);if(u<eS)continue;const{x:p,y:v,z:y}=ts(u,d,Q2);l.push({x:p,y:v,z:y,brightness:td(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=Ou.map((c,h)=>{const u=l.filter(x=>Z_(x.brightness)===h),d=new Float32Array(u.length*3),p=new Float32Array(u.length),v=new Float32Array(u.length),y=new Float32Array(u.length);u.forEach((x,b)=>{d[b*3]=x.x,d[b*3+1]=x.y,d[b*3+2]=x.z,p[b]=x.brightness,v[b]=x.phase,y[b]=x.speedFactor});const m=new Et;m.setAttribute("position",new mt(d,3));const f=new mt(new Float32Array(u.length*3),3);m.setAttribute("color",f);const T=new Su({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),A=new aa(m,T);return this.celestialGroup.add(A),{points:A,colorAttribute:f,brightness:p,phase:v,speedFactor:y}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=j_(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=nd(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Se(rs[0]+(Lo[0]-rs[0])*e,rs[1]+(Lo[1]-rs[1])*e,rs[2]+(Lo[2]-rs[2])*e),{material:n,uniforms:s}=I2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=C2(pS);this.cloudMesh=new yt(r,n),this.cloudMesh.renderOrder=mS,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=ts(e.altitudeDeg,e.azimuthDeg,1),a=Fs(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.scene.remove(this.cloudMesh),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.scene.remove(this.precipitationPoints),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=wd[e],n=t.poolSize,s=Uo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),u=new Float32Array(n),d=new Float32Array(n),p=new Float32Array(n),v=new Float32Array(n);for(let A=0;A<n;A++){const x=s()*Math.PI*2,b=s()*t.radiusM;r[A*3]=Math.cos(x)*b,r[A*3+1]=cs+s()*(t.topYM-cs),r[A*3+2]=Math.sin(x)*b,a[A]=s()*Math.PI*2,o[A]=.7+s()*.6,l[A]=.6+s()*.8,c[A]=.4+s()*1.2}const y=new Et;y.setAttribute("position",new mt(r,3)),y.setDrawRange(0,No(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Se(...this.baseFogColor)},uTexture:{value:US(e)},uNearFocusDistance:{value:Dd},uHazeDistance:{value:t.radiusM*Pd}},f=new Gt({uniforms:m,vertexShader:GS,fragmentShader:HS,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const T=new aa(y,f);this.scene.add(T),this.precipitationPoints=T,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=u,this.precipitationBounceDuration=d,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=v}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=wd[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,u=this.precipitationWobbleFreqJitter,d=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,v=this.precipitationBounceHeight,y=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,T=n==="snow"&&u&&d,A=n==="hail"&&p&&v&&y&&m&&f;for(let x=0,b=0;x<l.length;x+=3,b++){if(A&&p[b]>0){if(p[b]-=t,p[b]<=0){const _=Math.random()*Math.PI*2,M=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(_)*M,l[x+1]=s.topYM,l[x+2]=Math.sin(_)*M,p[b]=0}else{const _=1-p[b]/y[b];l[x+1]=cs+Math.sin(Math.PI*_)*v[b],l[x]=Zr(l[x]+(a+m[b])*t,s.radiusM),l[x+2]=Zr(l[x+2]+(o+f[b])*t,s.radiusM)}continue}let E=0,I=0;if(T){const _=AS*u[b],M=IS*d[b];E=Math.sin(e*_*Math.PI*2+c[b])*M,I=Math.sin(e*_*Math.PI*2+c[b]+Math.PI/2)*M}if(l[x]+=(a+E)*t,l[x+1]-=s.fallSpeedMPerS*h[b]*t,l[x+2]+=(o+I)*t,l[x]=Zr(l[x],s.radiusM),l[x+2]=Zr(l[x+2],s.radiusM),l[x+1]<cs){if(A){v[b]=Od*(.2+Math.random()*1.6),y[b]=RS*(.5+Math.random()),p[b]=y[b];const C=Math.random()*Math.PI*2,R=CS*(v[b]/Od);m[b]=Math.cos(C)*R,f[b]=Math.sin(C)*R,l[x+1]=cs;continue}const _=Math.random()*Math.PI*2,M=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(_)*M,l[x+1]=s.topYM,l[x+2]=Math.sin(_)*M}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=SS(this.weather.precipitationIntensity);this.rainSystem=w2({count:Td,radiusM:Gs,heightM:vS,bottomYM:Ad,overallSpeed:_S,color:yS,opacity:.85,visibleCount:No(Td,this.weather.precipitationIntensity),speedStreak:ES(e),pixelSize:Nd,seed:9001,nearFocusDistanceM:Dd,hazeDistanceM:Gs*Pd,hazeColor:new Se(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=Uo(4242),t=new Float32Array(as*3),n=new Float32Array(as),s=new Float32Array(as),r=new Float32Array(as);for(let h=0;h<as;h++){const u=e()*Math.PI*2,d=Math.sqrt(e())*Gs;t[h*3]=Math.cos(u)*d,t[h*3+1]=Ad,t[h*3+2]=Math.sin(u)*d,s[h]=Kr(Rd,Cd),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new mt(t,3));const o=new mt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,No(as,this.weather.precipitationIntensity));const l=new Gt({uniforms:{uMaxSize:{value:wS},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:TS},uTexture:{value:BS()}},vertexShader:zS,fragmentShader:kS,transparent:!0,depthWrite:!1}),c=new aa(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.scene.remove(this.rainSystem.points),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.scene.remove(this.rainSplashSystem.points),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Gs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=Ud+(1-Ud)*(1-l),h=Fd+(1-Fd)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=Nd*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,u=Math.sqrt(Math.random())*Gs;n[l]=Math.cos(h)*u,n[l+2]=Math.sin(h)*u,r[c]=Kr(Rd,Cd),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/kd;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Kr(Bd,zd);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=kd,this.nextLightningAtS=e+Kr(Bd,zd),this.onLightningFlash?.())}}buildCompassLabels(){const e=Aa(navigator.languages,cS),t=lS[e];this.compassSprites=oS.map((n,s)=>{const r=t[s],a=new Ws({map:XS(r),depthTest:!1,fog:!1}),o=new br(a),{x:l,y:c,z:h}=ts(0,n,hS);return o.position.set(l,c,h),o.scale.set(Md,Md,1),o.renderOrder=dS,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)this.scene.remove(e),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;this.scene.remove(e),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function v0(i,e,t){return Math.max(e,Math.min(t,i))}function Kr(i,e){return i+Math.random()*(e-i)}function Zr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let Jr,Qr;function US(i){switch(i){case"snow":return FS();case"hail":return OS()}}function FS(){if(Jr)return Jr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Jr=new Vn(e),Jr}function OS(){if(Qr)return Qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Qr=new Vn(e),Qr}let jr;function BS(){if(jr)return jr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),jr=new Vn(e),jr}const zS=`
|
|
5523
|
+
`;let Yr;function L2(){if(Yr)return Yr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return Yr=new Vn(e),Yr}function N2(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Se(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:L2()}},e=new Gt({uniforms:i,vertexShader:D2,fragmentShader:P2,transparent:!0,depthWrite:!1,depthTest:!1,blending:da,fog:!1,name:"LensFlareShader"}),t=new yt(new sr(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const is=["front","behind","left","right","front-left","front-right","behind-left","behind-right"];function Dc(i){return i==="vehicle"?["front","behind","front-left","front-right","behind-left","behind-right"]:["front","behind","left","right"]}function U2(i){return i==="vehicle"?["front-left","front-right","behind-left","behind-right"]:Dc(i)}const ec=90,F2=50;function O2(i){if(!a0(i))return;const e={};for(const t of Dc(i))e[t]=tc(i,t)?F2:ec;return e}const ca=2;function a0(i){return i==="building"||i==="vehicle"}function tc(i,e){return i==="building"?!0:i==="vehicle"?e!=="front"&&e!=="behind":!1}function $s(i){return i==="building"||i==="vehicle"}function nc(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const Sd=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new nr({color:new Se(...t)}):new rr({color:new Se(...t)}),a=new yt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const o0=[.32,.32,.3],l0=[1,.85,.5],c0=[.25,.25,.25],h0=[1,.97,.85],B2=[.55,.68,.72],gn=.03,vn=.05,d0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function kt(i,e){return i?.[e]}function _n(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new rr({color:new Se(...B2),transparent:!0,opacity:o/100}),c=new yt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,Ao=[.6,.58,.53],yd=[.5,.5,.48];function us(i,e,t,n,s,r,a,o){const l=new rr({color:new Se(...o),side:Dt}),c=new yt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}function z2(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(v,y,m,f)=>{v<=0||(e?us(i,v,y,Jt,m,o+f,a,l):us(i,Jt,y,v,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const u=[...s].sort((v,y)=>v.center-y.center);let d=-t/2;for(const v of u){const m=v.center-v.main/2-d;h(m,r,d+m/2,0),d=v.center+v.main/2}const p=t/2-d;h(p,r,d+p/2,0)}function u0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,u=s-n,d=(p,v,y,m)=>{p.length===0?v?us(i,y,u,Jt,0,h,m,Ao):us(i,Jt,u,y,m,h,0,Ao):z2(i,v,y,u,p,r,m,h,Ao)};d(a,!0,e*2,-t+Jt),d(o,!0,e*2,t-Jt),d(l,!1,t*2,-e+Jt),d(c,!1,t*2,e-Jt),us(i,e*2,Jt,t*2,0,n+Jt,0,yd),us(i,e*2,Jt,t*2,0,s-Jt,0,yd)}function ic(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function f0(i,e,t,n,s,r,a){const o=g0();o.scale.setScalar(n),o.rotation.y=d0[e];const{x:l,z:c}=ic(e,s,r,a);o.position.set(l,t,c),i.add(o)}const sc=6,rc=6,ii=3,Bs=1.4,zs=ii*.5,p0=1.2,m0=.35,k2=.75,G2=1.6;function H2(i,e,t,n){const s=new Mn,r=Math.max(1,i+1),a=r*ii;tn(s,new An(sc,a,rc),[.55,.54,.5],a/2);const o=sc/2,l=rc/2;for(let c=0;c<r;c++){const h=c*ii+ii/2;_n(s,Bs,zs,vn,0,h,-l-gn,kt(e,"front")),_n(s,Bs,zs,vn,0,h,l+gn,kt(e,"behind")),_n(s,vn,zs,Bs,-o-gn,h,0,kt(e,"left")),_n(s,vn,zs,Bs,o+gn,h,0,kt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);f0(s,t,c*ii,.72,o,l,p0);const h=u=>kt(e,u)!==void 0?[{main:Bs,center:0}]:[];u0(s,o,l,c*ii,(c+1)*ii,zs,h("front"),h("behind"),h("left"),h("right"))}return s}function V2(){const i=new Mn;return tn(i,new Ni(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Da(1.4,3,8),[.16,.32,.14],3.5),i}function W2(i){const e=new Mn;return tn(e,new Ni(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new ui(.25,12,8),i?l0:o0,5.1,!0),e}const X2=[.08,.08,.08],ni=.8,ls=1,pn=1.7,Io=.6,_i=.4,qr=1.2,ss=.7,xn=.5,Y2=pn;function q2(i,e,t){const n=new Mn;tn(n,new An(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new An(ni*2,Io,ls*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ni(.4,.4,.3,12),X2,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?h0:c0;for(const r of[-.7,.7])tn(n,new ui(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(_n(n,qr,_i,vn,0,pn,-ls-gn,kt(e,"front")),_n(n,qr,_i,vn,0,pn,ls+gn,kt(e,"behind")),_n(n,vn,_i,ss,-ni-gn,pn,-xn,kt(e,"front-left")),_n(n,vn,_i,ss,-ni-gn,pn,xn,kt(e,"behind-left")),_n(n,vn,_i,ss,ni+gn,pn,-xn,kt(e,"front-right")),_n(n,vn,_i,ss,ni+gn,pn,xn,kt(e,"behind-right")),t){f0(n,t,k2,.5,ni,ls,m0);const r=(l,c)=>{const h=[];return kt(e,l)!==void 0&&h.push({main:ss,center:-xn}),kt(e,c)!==void 0&&h.push({main:ss,center:xn}),h},a=kt(e,"front")!==void 0?[{main:qr,center:0}]:[],o=kt(e,"behind")!==void 0?[{main:qr,center:0}]:[];u0(n,ni,ls,pn-Io/2,pn+Io/2,_i,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const $2=[.95,.9,.82];function g0(){const i=new Mn;tn(i,new Ni(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new ui(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Da(.07,.16,8),$2,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class ks{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?ic(t,ni,ls,m0):ic(t,sc/2,rc/2,p0),r=e.kind==="vehicle"?Y2:(e.occupiedFloor??0)*ii+G2,a=(e.headingDeg??0)-d0[t]/Sd;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?H2(e.floors??ca,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?V2():e.kind==="streetlight"?W2(t):e.kind==="vehicle"?q2(t,e.windows,e.witnessSide):g0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*Sd),n}static setLit(e,t,n){const s=t==="streetlight"?n?l0:o0:n?h0:c0;for(const r of e.children)!(r instanceof yt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof yt&&(t.geometry.dispose(),t.material.dispose())}}function K2(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const $r=900,Z2=.5,J2=900,Ro=.5,Q2=850,Co=850,Do=4,j2=1.5,eS=-1,tS=6,ac=-4,bd=ac,nS=3,iS=.15,sS=.6,rS=40,aS=30,oS=[0,45,90,135,180,225,270,315],lS={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},cS=["en","fr"],hS=880,Md=40,dS=10,uS=1,fS=150,Po=55,Ed=.5,pS=700,mS=5,rs=[.92,.92,.95],Lo=[.15,.15,.19],wd={snow:{fallSpeedMPerS:2,size:.3,color:new Se(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Se(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},cs=0,gS=0,Td=3e3,Gs=20,vS=15,Ad=cs,_S=40,Id=1,xS=9;function SS(i){return Id+(xS-Id)*i}const yS=new Se(.75,.82,.92),bS=10,MS=.5;function ES(i){return v0(i/bS,MS,1)}const as=200,Rd=.18,Cd=.32,wS=.35,TS=new Se(.85,.9,.98),Dd=5,Pd=.85,Ld=.01;function No(i,e){return Math.round(i*(Ld+(1-Ld)*e))}const Nd=230,Ud=.7,Fd=.05,AS=.6,IS=.7,RS=.15,Od=.35,CS=3,DS=1/12,PS=.5,Bd=8,zd=25,kd=.12,LS={Venus:new Se(1,.96,.85),Mars:new Se(1,.55,.4),Jupiter:new Se(.95,.87,.72),Saturn:new Se(.92,.86,.68)};class NS{renderer;scene=new up;camera;celestialGroup=new Mn;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new Up(16777215,0);celestialLightTarget=new bt;skyLight=new Dp(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new mo;weather=$d;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new U;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new U;sunVisible=!1;lensFlareScratch=new U;sunOcclusionRaycaster=new mo;sunOcclusionDirectionScratch=new U;ufoOcclusionRaycaster=new mo;onLightningFlash;constructor(e,t=u2(),n){this.renderer=new L_({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Ks,this.camera=new Yt(60,e.width/Math.max(e.height,1),.1,$r*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Di(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<fS)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;g2(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=uS,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=Ed*e,this.lastSunPosition&&this.applyLensFlareTint(Fs(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(Po*this.dazzleIntensity*e[0],Po*this.dazzleIntensity*e[1],Po*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){K2(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=PS,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())t.removeFromParent(),ks.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=ks.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Di(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&$s(a.kind)),r={x:0,z:0};if(s){const a=ks.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,u=-s.northM+n.z;r.x=-(h+l),r.z=-(u+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,gS,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=nc(t,e);ks.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new Lp(16764006,rS,aS);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=Uu(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,Do,new Se(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new yc(new Se(...n),$r*.2,$r),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=sS;const s=e.sun.altitudeDeg>=bd,r=!s&&e.moon.altitudeDeg>=bd;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=ts(a.altitudeDeg,a.azimuthDeg,Co);this.celestialLight.position.set(o,l,c);const h=Fs(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const u=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?nS:iS)*u,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=Z2,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())ks.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.lensFlare.mesh.removeFromParent(),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,DS);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new ui($r,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=O_(n.getX(a),n.getY(a),n.getZ(a)),c=k_(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new Mt(s,3));const r=new nr({vertexColors:!0,side:Dt,fog:!1});this.skyMesh=new yt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new Ec(J2,48),t=new rr({color:new Se(Ro,Ro,Ro),fog:!0});this.groundMesh=new yt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<ac){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=ts(t.altitudeDeg,t.azimuthDeg,Co),c=Fs(t.altitudeDeg),h=new Se(s.r*c[0],s.g*c[1],s.b*c[2]),u=new ui(n,16,16),d=new nr({color:h,fog:!1}),p=new yt(u,d);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=N2(),this.lensFlare.uniforms.uOpacity.value=Ed*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<ac){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=ts(e.altitudeDeg,e.azimuthDeg,Co),a=Fs(e.altitudeDeg),o=new Se(a[0],a[1],a[2]),l=new Ws({map:WS(e.phase),color:o,fog:!1}),c=new br(l);c.position.set(n,s,r);const h=Do*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,Do),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new Ws({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new br(a);o.position.set(t,n,s);const l=r*tS;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=H_(r);if(o<=0)return;const l=X_(o),c=new Ws({map:VS(),color:a,transparent:!0,opacity:$_(o),blending:da,depthWrite:!1,fog:!1}),h=new br(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=td(n.magnitude),r=nd(s),a=LS[n.body]??new Se(1,1,1),o=new Se(a.r*r,a.g*r,a.b*r),l=j2*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=N_(t),o=Uo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:u,azimuthDeg:d}=Kx(n.ra[c],n.dec[c],s,r);if(u<eS)continue;const{x:p,y:v,z:y}=ts(u,d,Q2);l.push({x:p,y:v,z:y,brightness:td(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=Ou.map((c,h)=>{const u=l.filter(x=>Z_(x.brightness)===h),d=new Float32Array(u.length*3),p=new Float32Array(u.length),v=new Float32Array(u.length),y=new Float32Array(u.length);u.forEach((x,b)=>{d[b*3]=x.x,d[b*3+1]=x.y,d[b*3+2]=x.z,p[b]=x.brightness,v[b]=x.phase,y[b]=x.speedFactor});const m=new Et;m.setAttribute("position",new mt(d,3));const f=new mt(new Float32Array(u.length*3),3);m.setAttribute("color",f);const T=new Su({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),A=new aa(m,T);return this.celestialGroup.add(A),{points:A,colorAttribute:f,brightness:p,phase:v,speedFactor:y}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=j_(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=nd(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Se(rs[0]+(Lo[0]-rs[0])*e,rs[1]+(Lo[1]-rs[1])*e,rs[2]+(Lo[2]-rs[2])*e),{material:n,uniforms:s}=I2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=C2(pS);this.cloudMesh=new yt(r,n),this.cloudMesh.renderOrder=mS,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=ts(e.altitudeDeg,e.azimuthDeg,1),a=Fs(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.cloudMesh.removeFromParent(),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.precipitationPoints.removeFromParent(),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=wd[e],n=t.poolSize,s=Uo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),u=new Float32Array(n),d=new Float32Array(n),p=new Float32Array(n),v=new Float32Array(n);for(let A=0;A<n;A++){const x=s()*Math.PI*2,b=s()*t.radiusM;r[A*3]=Math.cos(x)*b,r[A*3+1]=cs+s()*(t.topYM-cs),r[A*3+2]=Math.sin(x)*b,a[A]=s()*Math.PI*2,o[A]=.7+s()*.6,l[A]=.6+s()*.8,c[A]=.4+s()*1.2}const y=new Et;y.setAttribute("position",new mt(r,3)),y.setDrawRange(0,No(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Se(...this.baseFogColor)},uTexture:{value:US(e)},uNearFocusDistance:{value:Dd},uHazeDistance:{value:t.radiusM*Pd}},f=new Gt({uniforms:m,vertexShader:GS,fragmentShader:HS,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const T=new aa(y,f);this.scene.add(T),this.precipitationPoints=T,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=u,this.precipitationBounceDuration=d,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=v}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=wd[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,u=this.precipitationWobbleFreqJitter,d=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,v=this.precipitationBounceHeight,y=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,T=n==="snow"&&u&&d,A=n==="hail"&&p&&v&&y&&m&&f;for(let x=0,b=0;x<l.length;x+=3,b++){if(A&&p[b]>0){if(p[b]-=t,p[b]<=0){const _=Math.random()*Math.PI*2,M=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(_)*M,l[x+1]=s.topYM,l[x+2]=Math.sin(_)*M,p[b]=0}else{const _=1-p[b]/y[b];l[x+1]=cs+Math.sin(Math.PI*_)*v[b],l[x]=Zr(l[x]+(a+m[b])*t,s.radiusM),l[x+2]=Zr(l[x+2]+(o+f[b])*t,s.radiusM)}continue}let E=0,I=0;if(T){const _=AS*u[b],M=IS*d[b];E=Math.sin(e*_*Math.PI*2+c[b])*M,I=Math.sin(e*_*Math.PI*2+c[b]+Math.PI/2)*M}if(l[x]+=(a+E)*t,l[x+1]-=s.fallSpeedMPerS*h[b]*t,l[x+2]+=(o+I)*t,l[x]=Zr(l[x],s.radiusM),l[x+2]=Zr(l[x+2],s.radiusM),l[x+1]<cs){if(A){v[b]=Od*(.2+Math.random()*1.6),y[b]=RS*(.5+Math.random()),p[b]=y[b];const C=Math.random()*Math.PI*2,R=CS*(v[b]/Od);m[b]=Math.cos(C)*R,f[b]=Math.sin(C)*R,l[x+1]=cs;continue}const _=Math.random()*Math.PI*2,M=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(_)*M,l[x+1]=s.topYM,l[x+2]=Math.sin(_)*M}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=SS(this.weather.precipitationIntensity);this.rainSystem=w2({count:Td,radiusM:Gs,heightM:vS,bottomYM:Ad,overallSpeed:_S,color:yS,opacity:.85,visibleCount:No(Td,this.weather.precipitationIntensity),speedStreak:ES(e),pixelSize:Nd,seed:9001,nearFocusDistanceM:Dd,hazeDistanceM:Gs*Pd,hazeColor:new Se(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=Uo(4242),t=new Float32Array(as*3),n=new Float32Array(as),s=new Float32Array(as),r=new Float32Array(as);for(let h=0;h<as;h++){const u=e()*Math.PI*2,d=Math.sqrt(e())*Gs;t[h*3]=Math.cos(u)*d,t[h*3+1]=Ad,t[h*3+2]=Math.sin(u)*d,s[h]=Kr(Rd,Cd),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new mt(t,3));const o=new mt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,No(as,this.weather.precipitationIntensity));const l=new Gt({uniforms:{uMaxSize:{value:wS},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:TS},uTexture:{value:BS()}},vertexShader:zS,fragmentShader:kS,transparent:!0,depthWrite:!1}),c=new aa(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.rainSystem.points.removeFromParent(),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.rainSplashSystem.points.removeFromParent(),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Gs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=Ud+(1-Ud)*(1-l),h=Fd+(1-Fd)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=Nd*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,u=Math.sqrt(Math.random())*Gs;n[l]=Math.cos(h)*u,n[l+2]=Math.sin(h)*u,r[c]=Kr(Rd,Cd),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/kd;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Kr(Bd,zd);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=kd,this.nextLightningAtS=e+Kr(Bd,zd),this.onLightningFlash?.())}}buildCompassLabels(){const e=Aa(navigator.languages,cS),t=lS[e];this.compassSprites=oS.map((n,s)=>{const r=t[s],a=new Ws({map:XS(r),depthTest:!1,fog:!1}),o=new br(a),{x:l,y:c,z:h}=ts(0,n,hS);return o.position.set(l,c,h),o.scale.set(Md,Md,1),o.renderOrder=dS,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)e.removeFromParent(),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;e.removeFromParent(),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function v0(i,e,t){return Math.max(e,Math.min(t,i))}function Kr(i,e){return i+Math.random()*(e-i)}function Zr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let Jr,Qr;function US(i){switch(i){case"snow":return FS();case"hail":return OS()}}function FS(){if(Jr)return Jr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Jr=new Vn(e),Jr}function OS(){if(Qr)return Qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Qr=new Vn(e),Qr}let jr;function BS(){if(jr)return jr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),jr=new Vn(e),jr}const zS=`
|
|
5524
5524
|
uniform float uMaxSize;
|
|
5525
5525
|
uniform float uScale;
|
|
5526
5526
|
attribute float aLife;
|
|
@@ -5295,7 +5295,7 @@ void main()
|
|
|
5295
5295
|
|
|
5296
5296
|
gl_FragColor = vec4(finalColor, max(dazzleAlpha, artifactsAlpha));
|
|
5297
5297
|
}
|
|
5298
|
-
`;let Gr;function c2(){if(Gr)return Gr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return Gr=new Vn(e),Gr}function h2(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Me(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:c2()}},e=new kt({uniforms:i,vertexShader:o2,fragmentShader:l2,transparent:!0,depthWrite:!1,depthTest:!1,blending:sa,fog:!1,name:"LensFlareShader"}),t=new Mt(new Js(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const u2=2;function d2(i){return i==="building"||i==="vehicle"}function f2(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const ru=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new Zs({color:new Me(...t)}):new Qs({color:new Me(...t)}),a=new Mt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const G0=[.32,.32,.3],H0=[1,.85,.5],V0=[.25,.25,.25],W0=[1,.97,.85],p2=[.55,.68,.72],gn=.03,_n=.05,X0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function zt(i,e){return i?.[e]}function vn(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new Qs({color:new Me(...p2),transparent:!0,opacity:o/100}),c=new Mt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,vo=[.6,.58,.53],au=[.5,.5,.48];function os(i,e,t,n,s,r,a,o){const l=new Qs({color:new Me(...o),side:Pt}),c=new Mt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}function m2(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(_,S,m,f)=>{_<=0||(e?os(i,_,S,Jt,m,o+f,a,l):os(i,Jt,S,_,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const d=[...s].sort((_,S)=>_.center-S.center);let u=-t/2;for(const _ of d){const m=_.center-_.main/2-u;h(m,r,u+m/2,0),u=_.center+_.main/2}const p=t/2-u;h(p,r,u+p/2,0)}function Y0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,d=s-n,u=(p,_,S,m)=>{p.length===0?_?os(i,S,d,Jt,0,h,m,vo):os(i,Jt,d,S,m,h,0,vo):m2(i,_,S,d,p,r,m,h,vo)};u(a,!0,e*2,-t+Jt),u(o,!0,e*2,t-Jt),u(l,!1,t*2,-e+Jt),u(c,!1,t*2,e-Jt),os(i,e*2,Jt,t*2,0,n+Jt,0,au),os(i,e*2,Jt,t*2,0,s-Jt,0,au)}function Wl(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function q0(i,e,t,n,s,r,a){const o=K0();o.scale.setScalar(n),o.rotation.y=X0[e];const{x:l,z:c}=Wl(e,s,r,a);o.position.set(l,t,c),i.add(o)}const Xl=6,Yl=6,ni=3,Ls=1.4,Us=ni*.5,$0=1.2,Z0=.35,g2=.75,_2=1.6;function v2(i,e,t,n){const s=new En,r=Math.max(1,i+1),a=r*ni;tn(s,new An(Xl,a,Yl),[.55,.54,.5],a/2);const o=Xl/2,l=Yl/2;for(let c=0;c<r;c++){const h=c*ni+ni/2;vn(s,Ls,Us,_n,0,h,-l-gn,zt(e,"front")),vn(s,Ls,Us,_n,0,h,l+gn,zt(e,"behind")),vn(s,_n,Us,Ls,-o-gn,h,0,zt(e,"left")),vn(s,_n,Us,Ls,o+gn,h,0,zt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);q0(s,t,c*ni,.72,o,l,$0);const h=d=>zt(e,d)!==void 0?[{main:Ls,center:0}]:[];Y0(s,o,l,c*ni,(c+1)*ni,Us,h("front"),h("behind"),h("left"),h("right"))}return s}function x2(){const i=new En;return tn(i,new Ii(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Ea(1.4,3,8),[.16,.32,.14],3.5),i}function M2(i){const e=new En;return tn(e,new Ii(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new hi(.25,12,8),i?H0:G0,5.1,!0),e}const S2=[.08,.08,.08],ti=.8,is=1,pn=1.7,xo=.6,gi=.4,Hr=1.2,es=.7,xn=.5,y2=pn;function E2(i,e,t){const n=new En;tn(n,new An(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new An(ti*2,xo,is*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ii(.4,.4,.3,12),S2,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?W0:V0;for(const r of[-.7,.7])tn(n,new hi(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(vn(n,Hr,gi,_n,0,pn,-is-gn,zt(e,"front")),vn(n,Hr,gi,_n,0,pn,is+gn,zt(e,"behind")),vn(n,_n,gi,es,-ti-gn,pn,-xn,zt(e,"front-left")),vn(n,_n,gi,es,-ti-gn,pn,xn,zt(e,"behind-left")),vn(n,_n,gi,es,ti+gn,pn,-xn,zt(e,"front-right")),vn(n,_n,gi,es,ti+gn,pn,xn,zt(e,"behind-right")),t){q0(n,t,g2,.5,ti,is,Z0);const r=(l,c)=>{const h=[];return zt(e,l)!==void 0&&h.push({main:es,center:-xn}),zt(e,c)!==void 0&&h.push({main:es,center:xn}),h},a=zt(e,"front")!==void 0?[{main:Hr,center:0}]:[],o=zt(e,"behind")!==void 0?[{main:Hr,center:0}]:[];Y0(n,ti,is,pn-xo/2,pn+xo/2,gi,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const b2=[.95,.9,.82];function K0(){const i=new En;tn(i,new Ii(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new hi(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Ea(.07,.16,8),b2,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class Ns{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?Wl(t,ti,is,Z0):Wl(t,Xl/2,Yl/2,$0),r=e.kind==="vehicle"?y2:(e.occupiedFloor??0)*ni+_2,a=(e.headingDeg??0)-X0[t]/ru;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?v2(e.floors??u2,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?x2():e.kind==="streetlight"?M2(t):e.kind==="vehicle"?E2(t,e.windows,e.witnessSide):K0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*ru),n}static setLit(e,t,n){const s=t==="streetlight"?n?H0:G0:n?W0:V0;for(const r of e.children)!(r instanceof Mt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof Mt&&(t.geometry.dispose(),t.material.dispose())}}function T2(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const Vr=900,w2=.5,A2=900,Mo=.5,R2=850,So=850,yo=4,C2=1.5,P2=-1,I2=6,ql=-4,ou=ql,D2=3,L2=.15,U2=.6,N2=40,F2=30,O2=[0,45,90,135,180,225,270,315],B2={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},z2=["en","fr"],k2=880,lu=40,G2=10,H2=1,V2=150,Eo=55,cu=.5,W2=700,X2=5,ts=[.92,.92,.95],bo=[.15,.15,.19],hu={snow:{fallSpeedMPerS:2,size:.3,color:new Me(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Me(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},ss=0,Y2=0,uu=3e3,Fs=20,q2=15,du=ss,$2=40,fu=1,Z2=9;function K2(i){return fu+(Z2-fu)*i}const J2=new Me(.75,.82,.92),Q2=10,j2=.5;function e3(i){return J0(i/Q2,j2,1)}const ns=200,pu=.18,mu=.32,t3=.35,n3=new Me(.85,.9,.98),gu=5,_u=.85,vu=.01;function To(i,e){return Math.round(i*(vu+(1-vu)*e))}const xu=230,Mu=.7,Su=.05,i3=.6,s3=.7,r3=.15,yu=.35,a3=3,o3=1/12,l3=.5,Eu=8,bu=25,Tu=.12,c3={Venus:new Me(1,.96,.85),Mars:new Me(1,.55,.4),Jupiter:new Me(.95,.87,.72),Saturn:new Me(.92,.86,.68)};class h3{renderer;scene=new Vf;camera;celestialGroup=new En;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new dp(16777215,0);celestialLightTarget=new St;skyLight=new lp(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new ro;weather=Ru;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new N;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new N;sunVisible=!1;lensFlareScratch=new N;sunOcclusionRaycaster=new ro;sunOcclusionDirectionScratch=new N;ufoOcclusionRaycaster=new ro;onLightningFlash;constructor(e,t=Hx(),n){this.renderer=new hv({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Hs,this.camera=new Yt(60,e.width/Math.max(e.height,1),.1,Vr*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Ri(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<V2)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;Yx(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=H2,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=cu*e,this.lastSunPosition&&this.applyLensFlareTint(Is(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(Eo*this.dazzleIntensity*e[0],Eo*this.dazzleIntensity*e[1],Eo*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){T2(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=l3,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())this.scene.remove(t),Ns.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=Ns.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Ri(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&d2(a.kind)),r={x:0,z:0};if(s){const a=Ns.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,d=-s.northM+n.z;r.x=-(h+l),r.z=-(d+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,Y2,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=f2(t,e);Ns.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new hp(16764006,N2,F2);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=m0(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,yo,new Me(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new lc(new Me(...n),Vr*.2,Vr),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=U2;const s=e.sun.altitudeDeg>=ou,r=!s&&e.moon.altitudeDeg>=ou;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=Qi(a.altitudeDeg,a.azimuthDeg,So);this.celestialLight.position.set(o,l,c);const h=Is(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const d=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?D2:L2)*d,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=w2,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())Ns.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.scene.remove(this.lensFlare.mesh),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,o3);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new hi(Vr,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=pv(n.getX(a),n.getY(a),n.getZ(a)),c=_v(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new yt(s,3));const r=new Zs({vertexColors:!0,side:Pt,fog:!1});this.skyMesh=new Mt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new uc(A2,48),t=new Qs({color:new Me(Mo,Mo,Mo),fog:!0});this.groundMesh=new Mt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<ql){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=Qi(t.altitudeDeg,t.azimuthDeg,So),c=Is(t.altitudeDeg),h=new Me(s.r*c[0],s.g*c[1],s.b*c[2]),d=new hi(n,16,16),u=new Zs({color:h,fog:!1}),p=new Mt(d,u);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=h2(),this.lensFlare.uniforms.uOpacity.value=cu*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<ql){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,So),a=Is(e.altitudeDeg),o=new Me(a[0],a[1],a[2]),l=new Bs({map:M3(e.phase),color:o,fog:!1}),c=new _r(l);c.position.set(n,s,r);const h=yo*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,yo),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new Bs({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new _r(a);o.position.set(t,n,s);const l=r*I2;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=xv(r);if(o<=0)return;const l=yv(o),c=new Bs({map:x3(),color:a,transparent:!0,opacity:Tv(o),blending:sa,depthWrite:!1,fog:!1}),h=new _r(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=kh(n.magnitude),r=Gh(s),a=c3[n.body]??new Me(1,1,1),o=new Me(a.r*r,a.g*r,a.b*r),l=C2*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=uv(t),o=wo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:d,azimuthDeg:u}=wx(n.ra[c],n.dec[c],s,r);if(d<P2)continue;const{x:p,y:_,z:S}=Qi(d,u,R2);l.push({x:p,y:_,z:S,brightness:kh(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=_0.map((c,h)=>{const d=l.filter(x=>Av(x.brightness)===h),u=new Float32Array(d.length*3),p=new Float32Array(d.length),_=new Float32Array(d.length),S=new Float32Array(d.length);d.forEach((x,y)=>{u[y*3]=x.x,u[y*3+1]=x.y,u[y*3+2]=x.z,p[y]=x.brightness,_[y]=x.phase,S[y]=x.speedFactor});const m=new Et;m.setAttribute("position",new pt(u,3));const f=new pt(new Float32Array(d.length*3),3);m.setAttribute("color",f);const w=new e0({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),A=new ea(m,w);return this.celestialGroup.add(A),{points:A,colorAttribute:f,brightness:p,phase:_,speedFactor:S}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=Pv(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=Gh(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Me(ts[0]+(bo[0]-ts[0])*e,ts[1]+(bo[1]-ts[1])*e,ts[2]+(bo[2]-ts[2])*e),{material:n,uniforms:s}=s2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=a2(W2);this.cloudMesh=new Mt(r,n),this.cloudMesh.renderOrder=X2,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,1),a=Is(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.scene.remove(this.cloudMesh),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.scene.remove(this.precipitationPoints),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=hu[e],n=t.poolSize,s=wo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),d=new Float32Array(n),u=new Float32Array(n),p=new Float32Array(n),_=new Float32Array(n);for(let A=0;A<n;A++){const x=s()*Math.PI*2,y=s()*t.radiusM;r[A*3]=Math.cos(x)*y,r[A*3+1]=ss+s()*(t.topYM-ss),r[A*3+2]=Math.sin(x)*y,a[A]=s()*Math.PI*2,o[A]=.7+s()*.6,l[A]=.6+s()*.8,c[A]=.4+s()*1.2}const S=new Et;S.setAttribute("position",new pt(r,3)),S.setDrawRange(0,To(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Me(...this.baseFogColor)},uTexture:{value:u3(e)},uNearFocusDistance:{value:gu},uHazeDistance:{value:t.radiusM*_u}},f=new kt({uniforms:m,vertexShader:_3,fragmentShader:v3,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const w=new ea(S,f);this.scene.add(w),this.precipitationPoints=w,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=d,this.precipitationBounceDuration=u,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=_}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=hu[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,d=this.precipitationWobbleFreqJitter,u=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,_=this.precipitationBounceHeight,S=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,w=n==="snow"&&d&&u,A=n==="hail"&&p&&_&&S&&m&&f;for(let x=0,y=0;x<l.length;x+=3,y++){if(A&&p[y]>0){if(p[y]-=t,p[y]<=0){const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E,p[y]=0}else{const v=1-p[y]/S[y];l[x+1]=ss+Math.sin(Math.PI*v)*_[y],l[x]=Xr(l[x]+(a+m[y])*t,s.radiusM),l[x+2]=Xr(l[x+2]+(o+f[y])*t,s.radiusM)}continue}let b=0,R=0;if(w){const v=i3*d[y],E=s3*u[y];b=Math.sin(e*v*Math.PI*2+c[y])*E,R=Math.sin(e*v*Math.PI*2+c[y]+Math.PI/2)*E}if(l[x]+=(a+b)*t,l[x+1]-=s.fallSpeedMPerS*h[y]*t,l[x+2]+=(o+R)*t,l[x]=Xr(l[x],s.radiusM),l[x+2]=Xr(l[x+2],s.radiusM),l[x+1]<ss){if(A){_[y]=yu*(.2+Math.random()*1.6),S[y]=r3*(.5+Math.random()),p[y]=S[y];const P=Math.random()*Math.PI*2,C=a3*(_[y]/yu);m[y]=Math.cos(P)*C,f[y]=Math.sin(P)*C,l[x+1]=ss;continue}const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=K2(this.weather.precipitationIntensity);this.rainSystem=t2({count:uu,radiusM:Fs,heightM:q2,bottomYM:du,overallSpeed:$2,color:J2,opacity:.85,visibleCount:To(uu,this.weather.precipitationIntensity),speedStreak:e3(e),pixelSize:xu,seed:9001,nearFocusDistanceM:gu,hazeDistanceM:Fs*_u,hazeColor:new Me(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=wo(4242),t=new Float32Array(ns*3),n=new Float32Array(ns),s=new Float32Array(ns),r=new Float32Array(ns);for(let h=0;h<ns;h++){const d=e()*Math.PI*2,u=Math.sqrt(e())*Fs;t[h*3]=Math.cos(d)*u,t[h*3+1]=du,t[h*3+2]=Math.sin(d)*u,s[h]=Wr(pu,mu),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new pt(t,3));const o=new pt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,To(ns,this.weather.precipitationIntensity));const l=new kt({uniforms:{uMaxSize:{value:t3},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:n3},uTexture:{value:p3()}},vertexShader:m3,fragmentShader:g3,transparent:!0,depthWrite:!1}),c=new ea(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.scene.remove(this.rainSystem.points),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.scene.remove(this.rainSplashSystem.points),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Fs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=Mu+(1-Mu)*(1-l),h=Su+(1-Su)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=xu*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,d=Math.sqrt(Math.random())*Fs;n[l]=Math.cos(h)*d,n[l+2]=Math.sin(h)*d,r[c]=Wr(pu,mu),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/Tu;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Wr(Eu,bu);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=Tu,this.nextLightningAtS=e+Wr(Eu,bu),this.onLightningFlash?.())}}buildCompassLabels(){const e=Ma(navigator.languages,z2),t=B2[e];this.compassSprites=O2.map((n,s)=>{const r=t[s],a=new Bs({map:S3(r),depthTest:!1,fog:!1}),o=new _r(a),{x:l,y:c,z:h}=Qi(0,n,k2);return o.position.set(l,c,h),o.scale.set(lu,lu,1),o.renderOrder=G2,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)this.scene.remove(e),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;this.scene.remove(e),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function J0(i,e,t){return Math.max(e,Math.min(t,i))}function Wr(i,e){return i+Math.random()*(e-i)}function Xr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let Yr,qr;function u3(i){switch(i){case"snow":return d3();case"hail":return f3()}}function d3(){if(Yr)return Yr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Yr=new Vn(e),Yr}function f3(){if(qr)return qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),qr=new Vn(e),qr}let $r;function p3(){if($r)return $r;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),$r=new Vn(e),$r}const m3=`
|
|
5298
|
+
`;let Gr;function c2(){if(Gr)return Gr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return Gr=new Vn(e),Gr}function h2(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Me(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:c2()}},e=new kt({uniforms:i,vertexShader:o2,fragmentShader:l2,transparent:!0,depthWrite:!1,depthTest:!1,blending:sa,fog:!1,name:"LensFlareShader"}),t=new Mt(new Js(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const u2=2;function d2(i){return i==="building"||i==="vehicle"}function f2(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const ru=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new Zs({color:new Me(...t)}):new Qs({color:new Me(...t)}),a=new Mt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const G0=[.32,.32,.3],H0=[1,.85,.5],V0=[.25,.25,.25],W0=[1,.97,.85],p2=[.55,.68,.72],gn=.03,_n=.05,X0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function zt(i,e){return i?.[e]}function vn(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new Qs({color:new Me(...p2),transparent:!0,opacity:o/100}),c=new Mt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,vo=[.6,.58,.53],au=[.5,.5,.48];function os(i,e,t,n,s,r,a,o){const l=new Qs({color:new Me(...o),side:Pt}),c=new Mt(new An(e,t,n),l);c.position.set(s,r,a),i.add(c)}function m2(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(_,S,m,f)=>{_<=0||(e?os(i,_,S,Jt,m,o+f,a,l):os(i,Jt,S,_,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const d=[...s].sort((_,S)=>_.center-S.center);let u=-t/2;for(const _ of d){const m=_.center-_.main/2-u;h(m,r,u+m/2,0),u=_.center+_.main/2}const p=t/2-u;h(p,r,u+p/2,0)}function Y0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,d=s-n,u=(p,_,S,m)=>{p.length===0?_?os(i,S,d,Jt,0,h,m,vo):os(i,Jt,d,S,m,h,0,vo):m2(i,_,S,d,p,r,m,h,vo)};u(a,!0,e*2,-t+Jt),u(o,!0,e*2,t-Jt),u(l,!1,t*2,-e+Jt),u(c,!1,t*2,e-Jt),os(i,e*2,Jt,t*2,0,n+Jt,0,au),os(i,e*2,Jt,t*2,0,s-Jt,0,au)}function Wl(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function q0(i,e,t,n,s,r,a){const o=K0();o.scale.setScalar(n),o.rotation.y=X0[e];const{x:l,z:c}=Wl(e,s,r,a);o.position.set(l,t,c),i.add(o)}const Xl=6,Yl=6,ni=3,Ls=1.4,Us=ni*.5,$0=1.2,Z0=.35,g2=.75,_2=1.6;function v2(i,e,t,n){const s=new En,r=Math.max(1,i+1),a=r*ni;tn(s,new An(Xl,a,Yl),[.55,.54,.5],a/2);const o=Xl/2,l=Yl/2;for(let c=0;c<r;c++){const h=c*ni+ni/2;vn(s,Ls,Us,_n,0,h,-l-gn,zt(e,"front")),vn(s,Ls,Us,_n,0,h,l+gn,zt(e,"behind")),vn(s,_n,Us,Ls,-o-gn,h,0,zt(e,"left")),vn(s,_n,Us,Ls,o+gn,h,0,zt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);q0(s,t,c*ni,.72,o,l,$0);const h=d=>zt(e,d)!==void 0?[{main:Ls,center:0}]:[];Y0(s,o,l,c*ni,(c+1)*ni,Us,h("front"),h("behind"),h("left"),h("right"))}return s}function x2(){const i=new En;return tn(i,new Ii(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Ea(1.4,3,8),[.16,.32,.14],3.5),i}function M2(i){const e=new En;return tn(e,new Ii(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new hi(.25,12,8),i?H0:G0,5.1,!0),e}const S2=[.08,.08,.08],ti=.8,is=1,pn=1.7,xo=.6,gi=.4,Hr=1.2,es=.7,xn=.5,y2=pn;function E2(i,e,t){const n=new En;tn(n,new An(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new An(ti*2,xo,is*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ii(.4,.4,.3,12),S2,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?W0:V0;for(const r of[-.7,.7])tn(n,new hi(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(vn(n,Hr,gi,_n,0,pn,-is-gn,zt(e,"front")),vn(n,Hr,gi,_n,0,pn,is+gn,zt(e,"behind")),vn(n,_n,gi,es,-ti-gn,pn,-xn,zt(e,"front-left")),vn(n,_n,gi,es,-ti-gn,pn,xn,zt(e,"behind-left")),vn(n,_n,gi,es,ti+gn,pn,-xn,zt(e,"front-right")),vn(n,_n,gi,es,ti+gn,pn,xn,zt(e,"behind-right")),t){q0(n,t,g2,.5,ti,is,Z0);const r=(l,c)=>{const h=[];return zt(e,l)!==void 0&&h.push({main:es,center:-xn}),zt(e,c)!==void 0&&h.push({main:es,center:xn}),h},a=zt(e,"front")!==void 0?[{main:Hr,center:0}]:[],o=zt(e,"behind")!==void 0?[{main:Hr,center:0}]:[];Y0(n,ti,is,pn-xo/2,pn+xo/2,gi,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const b2=[.95,.9,.82];function K0(){const i=new En;tn(i,new Ii(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new hi(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Ea(.07,.16,8),b2,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class Ns{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?Wl(t,ti,is,Z0):Wl(t,Xl/2,Yl/2,$0),r=e.kind==="vehicle"?y2:(e.occupiedFloor??0)*ni+_2,a=(e.headingDeg??0)-X0[t]/ru;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?v2(e.floors??u2,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?x2():e.kind==="streetlight"?M2(t):e.kind==="vehicle"?E2(t,e.windows,e.witnessSide):K0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*ru),n}static setLit(e,t,n){const s=t==="streetlight"?n?H0:G0:n?W0:V0;for(const r of e.children)!(r instanceof Mt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof Mt&&(t.geometry.dispose(),t.material.dispose())}}function T2(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const Vr=900,w2=.5,A2=900,Mo=.5,R2=850,So=850,yo=4,C2=1.5,P2=-1,I2=6,ql=-4,ou=ql,D2=3,L2=.15,U2=.6,N2=40,F2=30,O2=[0,45,90,135,180,225,270,315],B2={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},z2=["en","fr"],k2=880,lu=40,G2=10,H2=1,V2=150,Eo=55,cu=.5,W2=700,X2=5,ts=[.92,.92,.95],bo=[.15,.15,.19],hu={snow:{fallSpeedMPerS:2,size:.3,color:new Me(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Me(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},ss=0,Y2=0,uu=3e3,Fs=20,q2=15,du=ss,$2=40,fu=1,Z2=9;function K2(i){return fu+(Z2-fu)*i}const J2=new Me(.75,.82,.92),Q2=10,j2=.5;function e3(i){return J0(i/Q2,j2,1)}const ns=200,pu=.18,mu=.32,t3=.35,n3=new Me(.85,.9,.98),gu=5,_u=.85,vu=.01;function To(i,e){return Math.round(i*(vu+(1-vu)*e))}const xu=230,Mu=.7,Su=.05,i3=.6,s3=.7,r3=.15,yu=.35,a3=3,o3=1/12,l3=.5,Eu=8,bu=25,Tu=.12,c3={Venus:new Me(1,.96,.85),Mars:new Me(1,.55,.4),Jupiter:new Me(.95,.87,.72),Saturn:new Me(.92,.86,.68)};class h3{renderer;scene=new Vf;camera;celestialGroup=new En;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new dp(16777215,0);celestialLightTarget=new St;skyLight=new lp(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new ro;weather=Ru;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new N;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new N;sunVisible=!1;lensFlareScratch=new N;sunOcclusionRaycaster=new ro;sunOcclusionDirectionScratch=new N;ufoOcclusionRaycaster=new ro;onLightningFlash;constructor(e,t=Hx(),n){this.renderer=new hv({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Hs,this.camera=new Yt(60,e.width/Math.max(e.height,1),.1,Vr*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Ri(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<V2)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;Yx(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=H2,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=cu*e,this.lastSunPosition&&this.applyLensFlareTint(Is(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(Eo*this.dazzleIntensity*e[0],Eo*this.dazzleIntensity*e[1],Eo*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){T2(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=l3,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())t.removeFromParent(),Ns.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=Ns.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Ri(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&d2(a.kind)),r={x:0,z:0};if(s){const a=Ns.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,d=-s.northM+n.z;r.x=-(h+l),r.z=-(d+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,Y2,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=f2(t,e);Ns.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new hp(16764006,N2,F2);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=m0(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,yo,new Me(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new lc(new Me(...n),Vr*.2,Vr),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=U2;const s=e.sun.altitudeDeg>=ou,r=!s&&e.moon.altitudeDeg>=ou;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=Qi(a.altitudeDeg,a.azimuthDeg,So);this.celestialLight.position.set(o,l,c);const h=Is(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const d=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?D2:L2)*d,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=w2,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())Ns.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.lensFlare.mesh.removeFromParent(),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,o3);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new hi(Vr,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=pv(n.getX(a),n.getY(a),n.getZ(a)),c=_v(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new yt(s,3));const r=new Zs({vertexColors:!0,side:Pt,fog:!1});this.skyMesh=new Mt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new uc(A2,48),t=new Qs({color:new Me(Mo,Mo,Mo),fog:!0});this.groundMesh=new Mt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<ql){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=Qi(t.altitudeDeg,t.azimuthDeg,So),c=Is(t.altitudeDeg),h=new Me(s.r*c[0],s.g*c[1],s.b*c[2]),d=new hi(n,16,16),u=new Zs({color:h,fog:!1}),p=new Mt(d,u);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=h2(),this.lensFlare.uniforms.uOpacity.value=cu*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<ql){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,So),a=Is(e.altitudeDeg),o=new Me(a[0],a[1],a[2]),l=new Bs({map:M3(e.phase),color:o,fog:!1}),c=new _r(l);c.position.set(n,s,r);const h=yo*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,yo),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new Bs({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new _r(a);o.position.set(t,n,s);const l=r*I2;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=xv(r);if(o<=0)return;const l=yv(o),c=new Bs({map:x3(),color:a,transparent:!0,opacity:Tv(o),blending:sa,depthWrite:!1,fog:!1}),h=new _r(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=kh(n.magnitude),r=Gh(s),a=c3[n.body]??new Me(1,1,1),o=new Me(a.r*r,a.g*r,a.b*r),l=C2*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=uv(t),o=wo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:d,azimuthDeg:u}=wx(n.ra[c],n.dec[c],s,r);if(d<P2)continue;const{x:p,y:_,z:S}=Qi(d,u,R2);l.push({x:p,y:_,z:S,brightness:kh(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=_0.map((c,h)=>{const d=l.filter(x=>Av(x.brightness)===h),u=new Float32Array(d.length*3),p=new Float32Array(d.length),_=new Float32Array(d.length),S=new Float32Array(d.length);d.forEach((x,y)=>{u[y*3]=x.x,u[y*3+1]=x.y,u[y*3+2]=x.z,p[y]=x.brightness,_[y]=x.phase,S[y]=x.speedFactor});const m=new Et;m.setAttribute("position",new pt(u,3));const f=new pt(new Float32Array(d.length*3),3);m.setAttribute("color",f);const w=new e0({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),A=new ea(m,w);return this.celestialGroup.add(A),{points:A,colorAttribute:f,brightness:p,phase:_,speedFactor:S}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=Pv(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=Gh(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Me(ts[0]+(bo[0]-ts[0])*e,ts[1]+(bo[1]-ts[1])*e,ts[2]+(bo[2]-ts[2])*e),{material:n,uniforms:s}=s2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=a2(W2);this.cloudMesh=new Mt(r,n),this.cloudMesh.renderOrder=X2,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,1),a=Is(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.cloudMesh.removeFromParent(),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.precipitationPoints.removeFromParent(),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=hu[e],n=t.poolSize,s=wo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),d=new Float32Array(n),u=new Float32Array(n),p=new Float32Array(n),_=new Float32Array(n);for(let A=0;A<n;A++){const x=s()*Math.PI*2,y=s()*t.radiusM;r[A*3]=Math.cos(x)*y,r[A*3+1]=ss+s()*(t.topYM-ss),r[A*3+2]=Math.sin(x)*y,a[A]=s()*Math.PI*2,o[A]=.7+s()*.6,l[A]=.6+s()*.8,c[A]=.4+s()*1.2}const S=new Et;S.setAttribute("position",new pt(r,3)),S.setDrawRange(0,To(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Me(...this.baseFogColor)},uTexture:{value:u3(e)},uNearFocusDistance:{value:gu},uHazeDistance:{value:t.radiusM*_u}},f=new kt({uniforms:m,vertexShader:_3,fragmentShader:v3,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const w=new ea(S,f);this.scene.add(w),this.precipitationPoints=w,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=d,this.precipitationBounceDuration=u,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=_}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=hu[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,d=this.precipitationWobbleFreqJitter,u=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,_=this.precipitationBounceHeight,S=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,w=n==="snow"&&d&&u,A=n==="hail"&&p&&_&&S&&m&&f;for(let x=0,y=0;x<l.length;x+=3,y++){if(A&&p[y]>0){if(p[y]-=t,p[y]<=0){const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E,p[y]=0}else{const v=1-p[y]/S[y];l[x+1]=ss+Math.sin(Math.PI*v)*_[y],l[x]=Xr(l[x]+(a+m[y])*t,s.radiusM),l[x+2]=Xr(l[x+2]+(o+f[y])*t,s.radiusM)}continue}let b=0,R=0;if(w){const v=i3*d[y],E=s3*u[y];b=Math.sin(e*v*Math.PI*2+c[y])*E,R=Math.sin(e*v*Math.PI*2+c[y]+Math.PI/2)*E}if(l[x]+=(a+b)*t,l[x+1]-=s.fallSpeedMPerS*h[y]*t,l[x+2]+=(o+R)*t,l[x]=Xr(l[x],s.radiusM),l[x+2]=Xr(l[x+2],s.radiusM),l[x+1]<ss){if(A){_[y]=yu*(.2+Math.random()*1.6),S[y]=r3*(.5+Math.random()),p[y]=S[y];const P=Math.random()*Math.PI*2,C=a3*(_[y]/yu);m[y]=Math.cos(P)*C,f[y]=Math.sin(P)*C,l[x+1]=ss;continue}const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=K2(this.weather.precipitationIntensity);this.rainSystem=t2({count:uu,radiusM:Fs,heightM:q2,bottomYM:du,overallSpeed:$2,color:J2,opacity:.85,visibleCount:To(uu,this.weather.precipitationIntensity),speedStreak:e3(e),pixelSize:xu,seed:9001,nearFocusDistanceM:gu,hazeDistanceM:Fs*_u,hazeColor:new Me(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=wo(4242),t=new Float32Array(ns*3),n=new Float32Array(ns),s=new Float32Array(ns),r=new Float32Array(ns);for(let h=0;h<ns;h++){const d=e()*Math.PI*2,u=Math.sqrt(e())*Fs;t[h*3]=Math.cos(d)*u,t[h*3+1]=du,t[h*3+2]=Math.sin(d)*u,s[h]=Wr(pu,mu),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new pt(t,3));const o=new pt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,To(ns,this.weather.precipitationIntensity));const l=new kt({uniforms:{uMaxSize:{value:t3},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:n3},uTexture:{value:p3()}},vertexShader:m3,fragmentShader:g3,transparent:!0,depthWrite:!1}),c=new ea(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.rainSystem.points.removeFromParent(),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.rainSplashSystem.points.removeFromParent(),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Fs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=Mu+(1-Mu)*(1-l),h=Su+(1-Su)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=xu*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,d=Math.sqrt(Math.random())*Fs;n[l]=Math.cos(h)*d,n[l+2]=Math.sin(h)*d,r[c]=Wr(pu,mu),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/Tu;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Wr(Eu,bu);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=Tu,this.nextLightningAtS=e+Wr(Eu,bu),this.onLightningFlash?.())}}buildCompassLabels(){const e=Ma(navigator.languages,z2),t=B2[e];this.compassSprites=O2.map((n,s)=>{const r=t[s],a=new Bs({map:S3(r),depthTest:!1,fog:!1}),o=new _r(a),{x:l,y:c,z:h}=Qi(0,n,k2);return o.position.set(l,c,h),o.scale.set(lu,lu,1),o.renderOrder=G2,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)e.removeFromParent(),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;e.removeFromParent(),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function J0(i,e,t){return Math.max(e,Math.min(t,i))}function Wr(i,e){return i+Math.random()*(e-i)}function Xr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let Yr,qr;function u3(i){switch(i){case"snow":return d3();case"hail":return f3()}}function d3(){if(Yr)return Yr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Yr=new Vn(e),Yr}function f3(){if(qr)return qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),qr=new Vn(e),qr}let $r;function p3(){if($r)return $r;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),$r=new Vn(e),$r}const m3=`
|
|
5299
5299
|
uniform float uMaxSize;
|
|
5300
5300
|
uniform float uScale;
|
|
5301
5301
|
attribute float aLife;
|
|
@@ -5361,4 +5361,4 @@ void main() {
|
|
|
5361
5361
|
gl_FragColor = vec4(color, tex.a * uOpacity * (1.0 - blur * 0.5));
|
|
5362
5362
|
}
|
|
5363
5363
|
`;let Zr;function x3(){if(Zr)return Zr;const i=128,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.4,"rgba(255,255,255,0.35)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Zr=new Vn(e),Zr}function M3(i){const t=document.createElement("canvas");t.width=128,t.height=128;const n=t.getContext("2d"),s=128/2-2,r=128/2,a=128/2,o="#2e2b26",l="#f4f1e2";n.fillStyle=o,n.beginPath(),n.arc(r,a,s,0,Math.PI*2),n.fill();const c=J0(i.illuminatedFraction,0,1),h=i.phaseFraction<.5,d=s*Math.abs(1-2*c),u=c<.5;return n.save(),n.beginPath(),n.arc(r,a,s,0,Math.PI*2),n.clip(),n.fillStyle=l,n.beginPath(),h?(n.arc(r,a,s,-Math.PI/2,Math.PI/2,!1),n.ellipse(r,a,d,s,0,Math.PI/2,-Math.PI/2,u)):(n.arc(r,a,s,Math.PI/2,-Math.PI/2,!1),n.ellipse(r,a,d,s,0,-Math.PI/2,Math.PI/2,u)),n.fill(),n.restore(),new Vn(t)}function S3(i){const e=document.createElement("canvas");e.width=128,e.height=128;const t=e.getContext("2d");return t.fillStyle="rgba(0, 0, 0, 0.55)",t.beginPath(),t.arc(64,64,60,0,Math.PI*2),t.fill(),t.fillStyle="#ffffff",t.font="bold 52px sans-serif",t.textAlign="center",t.textBaseline="middle",t.fillText(i,64,68),new Vn(e)}function wo(i){let e=i;return function(){e|=0,e=e+1831565813|0;let n=Math.imul(e^e>>>15,1|e);return n=n+Math.imul(n^n>>>7,61|n)^n,((n^n>>>14)>>>0)/4294967296}}const wu=new Map;function y3(i){const e=i.byteLength/(4*Float32Array.BYTES_PER_ELEMENT),t=e,n=t*Float32Array.BYTES_PER_ELEMENT;return{count:e,ra:new Float32Array(i,0*n,t),dec:new Float32Array(i,1*n,t),mag:new Float32Array(i,2*n,t),ci:new Float32Array(i,3*n,t)}}function E3(i){let e=wu.get(i);return e||(e=fetch(i).then(t=>t.arrayBuffer()).then(y3),wu.set(i,e)),e}const b3=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,T3=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,w3=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,A3=20,R3=1;class C3{context;buffers=new Map;ambientSource;ambientGain;ambientKey="none";ambientToken=0;ambientVolume=0;windSource;windGain;windActive=!1;windToken=0;windVolume=0;resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("WeatherAudio: Web Audio unavailable, weather sounds disabled:",e);return}}this.context.state==="suspended"&&this.context.resume()}setAmbient(e,t,n){if(!this.context)return;const s=e==="rain"||e==="hail"?e:"none";if(this.ambientVolume=s==="hail"?Math.min(1,t*1.3+.2):s==="rain"?t:0,s!==this.ambientKey){this.ambientKey=s;const a=++this.ambientToken;this.stopSource(this.ambientSource,this.ambientGain),this.ambientSource=void 0,this.ambientGain=void 0,s!=="none"&&this.startLoop(b3,this.ambientVolume).then(o=>this.applyIfCurrent(o,a,()=>this.ambientToken,l=>{this.ambientSource=l?.source,this.ambientGain=l?.gain,l&&(l.gain.gain.value=this.ambientVolume)}))}else this.ambientGain&&(this.ambientGain.gain.value=this.ambientVolume);this.windVolume=Math.min(n/A3,1);const r=n>R3;if(r!==this.windActive){this.windActive=r;const a=++this.windToken;this.stopSource(this.windSource,this.windGain),this.windSource=void 0,this.windGain=void 0,r&&this.startLoop(T3,this.windVolume).then(o=>this.applyIfCurrent(o,a,()=>this.windToken,l=>{this.windSource=l?.source,this.windGain=l?.gain,l&&(l.gain.gain.value=this.windVolume)}))}else this.windGain&&(this.windGain.gain.value=this.windVolume)}playThunder(){this.context&&this.playOneShot(w3,.9)}dispose(){this.ambientToken++,this.windToken++,this.stopSource(this.ambientSource,this.ambientGain),this.stopSource(this.windSource,this.windGain),this.ambientSource=void 0,this.ambientGain=void 0,this.windSource=void 0,this.windGain=void 0,this.context?.close(),this.context=void 0,this.buffers.clear()}applyIfCurrent(e,t,n,s){if(t!==n()){e?.source.stop();return}s(e)}async startLoop(e,t){const n=this.context;if(n)try{const s=await this.getBuffer(e),r=n.createBufferSource();r.buffer=s,r.loop=!0;const a=n.createGain();return a.gain.value=t,r.connect(a).connect(n.destination),r.start(),{source:r,gain:a}}catch(s){console.warn("Weather ambient sound failed to load, staying silent:",s);return}}async playOneShot(e,t){const n=this.context;if(n)try{const s=await this.getBuffer(e),r=n.createBufferSource();r.buffer=s;const a=n.createGain();a.gain.value=t,r.connect(a).connect(n.destination),r.start()}catch(s){console.warn("Thunder sound failed to load:",s)}}async getBuffer(e){const t=this.context;if(!t)throw new Error("WeatherAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(s=>{if(!s.ok)throw new Error(`Audio fetch failed (${s.status}): ${e}`);return s.arrayBuffer()}).then(s=>t.decodeAudioData(s)),this.buffers.set(e,n)),n}stopSource(e,t){try{e?.stop()}catch{}e?.disconnect(),t?.disconnect()}}Du();const P3={sun:{en:"Sun",fr:"Soleil"},moon:{en:"Moon",fr:"Lune"},Venus:{en:"Venus",fr:"Vénus"},Mars:{en:"Mars",fr:"Mars"},Jupiter:{en:"Jupiter",fr:"Jupiter"},Saturn:{en:"Saturn",fr:"Saturne"}},I3=["en","fr"],D3={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},streetlight:{en:"Streetlight",fr:"Lampadaire"},vehicle:{en:"Vehicle",fr:"Véhicule"},witness:{en:"Witness",fr:"Témoin"}},L3=new URL(""+new URL("stars-mag7.5-DDr9QasD.bin",import.meta.url).href,import.meta.url).href,U3={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},Ao={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class N3 extends HTMLElement{static get observedAttributes(){return["src","star-catalog-src","show-compass","lens-flare-intensity","lens-flare-brightness"]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;lastTimeMs=0;starCatalog;weatherAudio=new C3;thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=e=>{this.sceneRenderer.setCompassHovered(!0);const t=this.ufoElement.canvasElement,n=t.getBoundingClientRect();if(n.width===0||n.height===0)return;const s=(e.clientX-n.left)/n.width*t.width,r=(e.clientY-n.top)/n.height*t.height;if(this.ufoElement.hasVisibleShapeAt(s,r)){this.hoverTooltip.hidden=!0;return}const a=(e.clientX-n.left)/n.width*2-1,o=-((e.clientY-n.top)/n.height*2-1),l=Ma(navigator.languages,I3),c=this.sceneRenderer.pickBodyAt(a,o);if(c){this.showHoverTooltip(e,P3[c]?.[l]??c);return}const h=this.sceneRenderer.pickDecorAt(a,o),d=h?this.ufoElement.sighting.decor.find(u=>u.id===h):void 0;if(d){this.showHoverTooltip(e,d.title||D3[d.kind][l]);return}this.hoverTooltip.hidden=!0};showHoverTooltip(e,t){this.hoverTooltip.textContent=t,this.hoverTooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${e.clientX-n.left+12}px`,this.hoverTooltip.style.top=`${e.clientY-n.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash=()=>{clearTimeout(this.thunderTimeoutId);const e=(.5+Math.random()*3.5)*1e3;this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),e)};handleFirstInteraction=()=>{this.weatherAudio.resume(),this.setWeather(Ic(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=e=>{this.lastTimeMs=e.detail.time,this.updateAstronomy(this.lastTimeMs),this.updateUfoOcclusion(this.lastTimeMs)};constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${hd}</style>${cd}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.frameElement=this.shadow.getElementById("frame"),this.sceneCanvas=this.shadow.getElementById("scene-canvas"),this.sceneRenderer=new h3(this.sceneCanvas,void 0,this.handleLightningFlash),this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(Io),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.style.setProperty("--ufo-canvas-background","transparent"),this.ufoElement.style.setProperty("--ufo-canvas-border","none"),this.ufoElement.fullscreenTarget=this.stageElement,this.shadow.getElementById("ufo-slot").replaceWith(this.ufoElement),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave),this.ufoElement.canvasElement.addEventListener("pointerdown",this.handleFirstInteraction,{once:!0})}connectedCallback(){this.resizeToStage(),this.updateAstronomy(this.lastTimeMs),this.loadStars(),this.resizeObserver=new ResizeObserver(()=>this.resizeToStage()),this.resizeObserver.observe(this.frameElement),document.addEventListener("fullscreenchange",this.handleFullscreenChange);const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose()}attributeChangedCallback(e,t,n){if(e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),e==="star-catalog-src"&&n!==t&&this.isConnected&&this.loadStars(),e==="show-compass"&&n!==t&&this.sceneRenderer.setShowCompass(this.hasAttribute("show-compass")),e==="lens-flare-intensity"&&n!==t){const s=n===null?NaN:parseFloat(n);this.sceneRenderer.setLensFlareArtifactIntensity(Number.isFinite(s)?s:0)}if(e==="lens-flare-brightness"&&n!==t){const s=n===null?NaN:parseFloat(n);this.sceneRenderer.setDazzleIntensity(Number.isFinite(s)?s:1)}}setCompassForced(e){this.sceneRenderer.setCompassForced(e)}setIndoorLook(e,t){this.sceneRenderer.setIndoorLook(e,t)}setWeather(e){this.sceneRenderer.setWeather(e),this.weatherAudio.setAmbient(e.precipitationType,e.precipitationIntensity,e.windSpeed)}pickDecorAt(e,t){return this.sceneRenderer.pickDecorAt(e,t)}resumeWeatherAudio(){this.weatherAudio.resume()}async loadFromSrc(e){const t=await fetch(e);this.sightingData=await t.json()}get sightingData(){return this.ufoElement.sightingData}set sightingData(e){this.ufoElement.sightingData=e,this.lastTimeMs=0,this.updateAstronomy(0)}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}resizeToStage(){const e=this.frameElement.getBoundingClientRect(),t=Math.max(1,Math.round(e.width)),n=Math.max(1,Math.round(e.height));this.sceneCanvas.width=t,this.sceneCanvas.height=n,this.sceneRenderer.resize(t,n)}async loadStars(){const e=this.getAttribute("star-catalog-src")??L3;this.starCatalog=await E3(e),this.updateAstronomy(this.lastTimeMs)}updateAstronomy(e){const t=this.ufoElement.sighting;this.setWeather(Ic(t,e)),this.sceneRenderer.setDecor(t.decor);const n=Pc(t,e);this.sceneRenderer.setObserverPose(n??Ao),this.sceneRenderer.updateDecorAnchoring(Pc(t,0),n),this.sceneRenderer.updateDecorLitState(e),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng);const s=n?.lat??Ao.lat,r=n?.lng??Ao.lng,a=N0(t.event.time??{},r,t.event.utcOffsetHours);if(!a){this.sceneRenderer.setAstronomy(U3);return}const o=new Date(a.getTime()+e),l={lat:s,lng:r,elevationM:n?.elevationM??0},c={...mo("Sun",o,l),magnitude:go("Sun",o)},h={...mo("Moon",o,l),phase:Ax(o),magnitude:go("Moon",o)},d=Tx.map(u=>({body:u,position:mo(u,o,l),magnitude:go(u,o)}));this.sceneRenderer.setAstronomy({sun:c,moon:h,planets:d,stars:this.starCatalog?{catalog:this.starCatalog,date:o,observer:l}:void 0})}updateUfoOcclusion(e){const t=this.ufoElement.sighting.timeline,n=this.ufoElement.canvasElement,s=new Set;for(const r of t.sourceIds){const a=t.getInterpolatedShapeAt(e,r);if(!a)continue;const o=(a.bounds.x+a.bounds.width/2)/n.width*2-1,l=-((a.bounds.y+a.bounds.height/2)/n.height*2-1);this.sceneRenderer.isScreenPointOccluded(o,l,r)&&s.add(r)}this.ufoElement.setOccludedSourceIds(s)}}const $l="rr0-scene";function Q0(){Du(),customElements.get($l)||customElements.define($l,N3)}const j0={testimonyBy:"Testimony by",about:"About",close:"Close",observation:"Observation",date:"Date",location:"Location",case:"Case",description:"Description",tags:"Tags",credits:"Credits",editThisObservation:"Edit this observation",embed:"Embed",embedReplay:"Replay",embedEdit:"Editor",embedCopy:"Copy",embedCopied:"Copied"},F3=Object.freeze(Object.defineProperty({__proto__:null,eyewitnessMessages_en:j0},Symbol.toStringTag,{value:"Module"}));Q0();const O3="“Thunder” by Jerimee",B3="https://creativecommons.org/licenses/by/3.0/",z3="CC BY 3.0",Ro="https://ufoathome.org";class k3 extends HTMLElement{static get observedAttributes(){return["src"]}shadow;sceneElement;toolbarElement;testimonyPrefix;witnessText;witnessSelect;infoButton;infoPanel;infoAppLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;infoEmbedToggle;infoEmbedPanel;embedReplayRadio;embedEditRadio;labelEmbedReplay;labelEmbedEdit;embedMarkup;embedCopyButton;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];currentSrc;infoOpen=!1;creditsOpen=!1;embedOpen=!1;language="en";messages=j0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${ld}</style>${od}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.sceneElement=document.createElement($l),this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.testimonyPrefix=this.shadow.getElementById("testimony-prefix"),this.witnessText=this.shadow.getElementById("witness-text"),this.witnessSelect=this.shadow.getElementById("witness"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.infoEmbedToggle=this.shadow.getElementById("info-embed-toggle"),this.infoEmbedPanel=this.shadow.getElementById("info-embed"),this.embedReplayRadio=this.shadow.getElementById("embed-kind-replay"),this.embedEditRadio=this.shadow.getElementById("embed-kind-edit"),this.labelEmbedReplay=this.shadow.getElementById("label-embed-replay"),this.labelEmbedEdit=this.shadow.getElementById("label-embed-edit"),this.embedMarkup=this.shadow.getElementById("embed-markup"),this.embedCopyButton=this.shadow.getElementById("embed-copy"),this.witnessSelect.addEventListener("change",()=>this.selectWitness(this.witnessSelect.value)),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",t=>{t.newState==="open"&&this.populateInfoPanel()}),this.infoPanel.addEventListener("toggle",t=>this.syncInfoOpen(t.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.infoEmbedToggle.addEventListener("click",()=>this.toggleEmbed());for(const t of[this.embedReplayRadio,this.embedEditRadio])t.addEventListener("change",()=>this.refreshEmbedMarkup());this.embedCopyButton.addEventListener("click",()=>void this.copyEmbedMarkup()),this.loadLocaleMessages()}async loadLocaleMessages(){this.language=Ma(navigator.languages,Pu),this.language!=="en"&&(this.messages=await Vd(this.language),this.testimonyPrefix.textContent=this.messages.testimonyBy,this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.infoEmbedToggle.textContent=this.messages.embed,this.labelEmbedReplay.textContent=this.messages.embedReplay,this.labelEmbedEdit.textContent=this.messages.embedEdit,this.embedCopyButton.textContent=this.messages.embedCopy,this.infoOpen&&this.populateInfoPanel(),this.updateTestimonyLine())}connectedCallback(){const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(e,t,n){e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n)}async loadFromSrc(e){const n=await(await fetch(e)).json();Array.isArray(n)?await this.loadWitnessUrls(n):this.setEntries([{src:e,sighting:n}])}get witnessUrls(){return this.entries.map(e=>e.src)}set witnessUrls(e){this.loadWitnessUrls(e)}async loadWitnessUrls(e){const t=await Promise.all(e.map(async n=>{const s=await fetch(n);return{src:n,sighting:await s.json()}}));this.setEntries(t)}setEntries(e){this.entries=e,this.warnOnMismatchedCaseIds(e),this.toolbarElement.hidden=e.length===0;const t=e.length>1;this.witnessSelect.hidden=!t,this.witnessText.hidden=t,this.witnessSelect.innerHTML="";for(const s of e){const r=document.createElement("option");r.value=s.src,r.textContent=this.witnessDisplayName(s.sighting.witness)??s.src,this.witnessSelect.appendChild(r)}const n=e.find(s=>s.src===this.currentSrc)??e[0];n?this.selectWitness(n.src):this.updateTestimonyLine()}editorUrl(){if(!this.currentSrc)return Ro;const e=new URL(this.currentSrc,location.href);return e.origin===location.origin?`${Ro}${e.pathname}`:`${Ro}/?sighting=${encodeURIComponent(e.href)}`}embedMarkupFor(e){const t=e==="edit"?"rr0-ufo-recorder":"rr0-eyewitness",n=new URL(`${t}.mjs`,import.meta.url).href,s=this.currentSrc?new URL(this.currentSrc,location.href).href:"";return`<script type="module" src="${n}"><\/script>
|
|
5364
|
-
<${t} src="${s}"></${t}>`}refreshEmbedMarkup(){this.embedMarkup.value=this.embedMarkupFor(this.embedEditRadio.checked?"edit":"replay")}async copyEmbedMarkup(){try{await navigator.clipboard.writeText(this.embedMarkup.value),this.embedCopyButton.textContent=this.messages.embedCopied,window.setTimeout(()=>this.embedCopyButton.textContent=this.messages.embedCopy,1500)}catch{this.embedMarkup.select()}}warnOnMismatchedCaseIds(e){const t=new Set(e.map(n=>n.sighting.caseId).filter(n=>n!==void 0));t.size>1&&console.warn(`<rr0-eyewitness>: witnesses declare different case ids (${[...t].join(", ")}) — they may not belong to the same case.`)}selectWitness(e){const t=this.entries.find(n=>n.src===e);t&&(this.currentSrc=e,this.witnessSelect.value=e,this.sceneElement.sightingData=t.sighting,this.updateTestimonyLine(),this.infoOpen&&this.populateInfoPanel())}updateTestimonyLine(){const e=this.entries.find(t=>t.src===this.currentSrc);e&&(this.witnessText.textContent=this.witnessDisplayName(e.sighting.witness)??e.src)}witnessDisplayName(e){if(!e)return;const t=[...e.firstNames??[],e.lastName].filter(Boolean).join(" ");return e.title||t||e.id||e.dirName}formatDate(e){const t=e.place?.[0],n=N0(e.time??{},t?.lng??0,e.utcOffsetHours);if(!n)return;const s=n.getTime()+this.utcOffsetHoursOf(e,t?.lng??0)*36e5;return new Intl.DateTimeFormat(this.language==="fr"?"fr-FR":"en-US",{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(s))}utcOffsetHoursOf(e,t){return e.utcOffsetHours??Math.round(t/15)}formatLocation(e){const t=e.place?.[0];if(t)return`${t.lat.toFixed(4)}, ${t.lng.toFixed(4)}`}toggleInfoPanel(){const e=!this.infoOpen;if(this.supportsPopover){const t=this.infoPanel.matches(":popover-open");e&&!t?this.infoPanel.showPopover():!e&&t&&this.infoPanel.hidePopover();return}this.syncInfoOpen(e),this.infoPanel.hidden=!e,e?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}syncInfoOpen(e){e!==this.infoOpen&&(this.infoOpen=e,this.infoButton.setAttribute("aria-expanded",String(e)),e?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false"),this.embedOpen=!1,this.infoEmbedPanel.hidden=!0,this.infoEmbedToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=e=>{const t=e.composedPath();!t.includes(this.infoPanel)&&!t.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}toggleEmbed(){this.embedOpen=!this.embedOpen,this.infoEmbedPanel.hidden=!this.embedOpen,this.infoEmbedToggle.setAttribute("aria-expanded",String(this.embedOpen)),this.embedOpen&&(this.refreshEmbedMarkup(),this.revealInPanel(this.infoEmbedPanel))}revealInPanel(e){e.scrollIntoView?.({block:"nearest"})}populateInfoPanel(){const e=this.entries.find(r=>r.src===this.currentSrc);if(this.infoObservationList.innerHTML="",e){const r=this.formatDate(e.sighting);r&&this.appendInfoRow(this.infoObservationList,this.messages.date,r);const a=this.formatLocation(e.sighting);a&&this.appendInfoRow(this.infoObservationList,this.messages.location,a),e.sighting.caseId&&this.appendInfoRow(this.infoObservationList,this.messages.case,e.sighting.caseId),e.sighting.description&&this.appendInfoRow(this.infoObservationList,this.messages.description,e.sighting.description),e.sighting.tags&&e.sighting.tags.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,e.sighting.tags.join(", "))}this.refreshEmbedMarkup(),this.infoAppLink.href=this.editorUrl(),this.infoAppLink.textContent="UFO@home v0.13.
|
|
5364
|
+
<${t} src="${s}"></${t}>`}refreshEmbedMarkup(){this.embedMarkup.value=this.embedMarkupFor(this.embedEditRadio.checked?"edit":"replay")}async copyEmbedMarkup(){try{await navigator.clipboard.writeText(this.embedMarkup.value),this.embedCopyButton.textContent=this.messages.embedCopied,window.setTimeout(()=>this.embedCopyButton.textContent=this.messages.embedCopy,1500)}catch{this.embedMarkup.select()}}warnOnMismatchedCaseIds(e){const t=new Set(e.map(n=>n.sighting.caseId).filter(n=>n!==void 0));t.size>1&&console.warn(`<rr0-eyewitness>: witnesses declare different case ids (${[...t].join(", ")}) — they may not belong to the same case.`)}selectWitness(e){const t=this.entries.find(n=>n.src===e);t&&(this.currentSrc=e,this.witnessSelect.value=e,this.sceneElement.sightingData=t.sighting,this.updateTestimonyLine(),this.infoOpen&&this.populateInfoPanel())}updateTestimonyLine(){const e=this.entries.find(t=>t.src===this.currentSrc);e&&(this.witnessText.textContent=this.witnessDisplayName(e.sighting.witness)??e.src)}witnessDisplayName(e){if(!e)return;const t=[...e.firstNames??[],e.lastName].filter(Boolean).join(" ");return e.title||t||e.id||e.dirName}formatDate(e){const t=e.place?.[0],n=N0(e.time??{},t?.lng??0,e.utcOffsetHours);if(!n)return;const s=n.getTime()+this.utcOffsetHoursOf(e,t?.lng??0)*36e5;return new Intl.DateTimeFormat(this.language==="fr"?"fr-FR":"en-US",{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(s))}utcOffsetHoursOf(e,t){return e.utcOffsetHours??Math.round(t/15)}formatLocation(e){const t=e.place?.[0];if(t)return`${t.lat.toFixed(4)}, ${t.lng.toFixed(4)}`}toggleInfoPanel(){const e=!this.infoOpen;if(this.supportsPopover){const t=this.infoPanel.matches(":popover-open");e&&!t?this.infoPanel.showPopover():!e&&t&&this.infoPanel.hidePopover();return}this.syncInfoOpen(e),this.infoPanel.hidden=!e,e?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}syncInfoOpen(e){e!==this.infoOpen&&(this.infoOpen=e,this.infoButton.setAttribute("aria-expanded",String(e)),e?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false"),this.embedOpen=!1,this.infoEmbedPanel.hidden=!0,this.infoEmbedToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=e=>{const t=e.composedPath();!t.includes(this.infoPanel)&&!t.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}toggleEmbed(){this.embedOpen=!this.embedOpen,this.infoEmbedPanel.hidden=!this.embedOpen,this.infoEmbedToggle.setAttribute("aria-expanded",String(this.embedOpen)),this.embedOpen&&(this.refreshEmbedMarkup(),this.revealInPanel(this.infoEmbedPanel))}revealInPanel(e){e.scrollIntoView?.({block:"nearest"})}populateInfoPanel(){const e=this.entries.find(r=>r.src===this.currentSrc);if(this.infoObservationList.innerHTML="",e){const r=this.formatDate(e.sighting);r&&this.appendInfoRow(this.infoObservationList,this.messages.date,r);const a=this.formatLocation(e.sighting);a&&this.appendInfoRow(this.infoObservationList,this.messages.location,a),e.sighting.caseId&&this.appendInfoRow(this.infoObservationList,this.messages.case,e.sighting.caseId),e.sighting.description&&this.appendInfoRow(this.infoObservationList,this.messages.description,e.sighting.description),e.sighting.tags&&e.sighting.tags.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,e.sighting.tags.join(", "))}this.refreshEmbedMarkup(),this.infoAppLink.href=this.editorUrl(),this.infoAppLink.textContent="UFO@home v0.13.2",this.infoAppLink.title=this.messages.editThisObservation,this.infoAppLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCreditsList.innerHTML="";const t=this.sceneElement.currentTerrainAttribution;if(t){const r=document.createElement("li");r.textContent=t,this.infoCreditsList.appendChild(r)}const n=document.createElement("li");n.textContent=`${O3} (`;const s=document.createElement("a");s.href=B3,s.target="_blank",s.rel="noopener",s.textContent=z3,n.appendChild(s),n.appendChild(document.createTextNode(")")),this.infoCreditsList.appendChild(n)}appendInfoRow(e,t,n){const s=document.createElement("dt");s.textContent=t;const r=document.createElement("dd");r.textContent=n,e.appendChild(s),e.appendChild(r)}}const Au="rr0-eyewitness";function G3(){Q0(),customElements.get(Au)||customElements.define(Au,k3)}G3();
|
|
@@ -5032,7 +5032,7 @@ void main()
|
|
|
5032
5032
|
|
|
5033
5033
|
gl_FragColor = vec4(finalColor, max(dazzleAlpha, artifactsAlpha));
|
|
5034
5034
|
}
|
|
5035
|
-
`;let kr;function tx(){if(kr)return kr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return kr=new Vn(e),kr}function nx(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Me(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:tx()}},e=new Gt({uniforms:i,vertexShader:j2,fragmentShader:ex,transparent:!0,depthWrite:!1,depthTest:!1,blending:ia,fog:!1,name:"LensFlareShader"}),t=new Mt(new Js(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const ix=2;function sx(i){return i==="building"||i==="vehicle"}function rx(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const iu=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new $s({color:new Me(...t)}):new Qs({color:new Me(...t)}),a=new Mt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const O0=[.32,.32,.3],z0=[1,.85,.5],B0=[.25,.25,.25],G0=[1,.97,.85],ax=[.55,.68,.72],gn=.03,_n=.05,k0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function Bt(i,e){return i?.[e]}function vn(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new Qs({color:new Me(...ax),transparent:!0,opacity:o/100}),c=new Mt(new wn(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,go=[.6,.58,.53],su=[.5,.5,.48];function os(i,e,t,n,s,r,a,o){const l=new Qs({color:new Me(...o),side:Pt}),c=new Mt(new wn(e,t,n),l);c.position.set(s,r,a),i.add(c)}function ox(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(_,S,m,f)=>{_<=0||(e?os(i,_,S,Jt,m,o+f,a,l):os(i,Jt,S,_,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const d=[...s].sort((_,S)=>_.center-S.center);let u=-t/2;for(const _ of d){const m=_.center-_.main/2-u;h(m,r,u+m/2,0),u=_.center+_.main/2}const p=t/2-u;h(p,r,u+p/2,0)}function H0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,d=s-n,u=(p,_,S,m)=>{p.length===0?_?os(i,S,d,Jt,0,h,m,go):os(i,Jt,d,S,m,h,0,go):ox(i,_,S,d,p,r,m,h,go)};u(a,!0,e*2,-t+Jt),u(o,!0,e*2,t-Jt),u(l,!1,t*2,-e+Jt),u(c,!1,t*2,e-Jt),os(i,e*2,Jt,t*2,0,n+Jt,0,su),os(i,e*2,Jt,t*2,0,s-Jt,0,su)}function kl(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function V0(i,e,t,n,s,r,a){const o=q0();o.scale.setScalar(n),o.rotation.y=k0[e];const{x:l,z:c}=kl(e,s,r,a);o.position.set(l,t,c),i.add(o)}const Hl=6,Vl=6,ni=3,Ls=1.4,Us=ni*.5,W0=1.2,X0=.35,lx=.75,cx=1.6;function hx(i,e,t,n){const s=new En,r=Math.max(1,i+1),a=r*ni;tn(s,new wn(Hl,a,Vl),[.55,.54,.5],a/2);const o=Hl/2,l=Vl/2;for(let c=0;c<r;c++){const h=c*ni+ni/2;vn(s,Ls,Us,_n,0,h,-l-gn,Bt(e,"front")),vn(s,Ls,Us,_n,0,h,l+gn,Bt(e,"behind")),vn(s,_n,Us,Ls,-o-gn,h,0,Bt(e,"left")),vn(s,_n,Us,Ls,o+gn,h,0,Bt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);V0(s,t,c*ni,.72,o,l,W0);const h=d=>Bt(e,d)!==void 0?[{main:Ls,center:0}]:[];H0(s,o,l,c*ni,(c+1)*ni,Us,h("front"),h("behind"),h("left"),h("right"))}return s}function ux(){const i=new En;return tn(i,new Ii(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Sa(1.4,3,8),[.16,.32,.14],3.5),i}function dx(i){const e=new En;return tn(e,new Ii(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new hi(.25,12,8),i?z0:O0,5.1,!0),e}const fx=[.08,.08,.08],ti=.8,is=1,pn=1.7,_o=.6,gi=.4,Hr=1.2,es=.7,xn=.5,px=pn;function mx(i,e,t){const n=new En;tn(n,new wn(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new wn(ti*2,_o,is*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ii(.4,.4,.3,12),fx,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?G0:B0;for(const r of[-.7,.7])tn(n,new hi(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(vn(n,Hr,gi,_n,0,pn,-is-gn,Bt(e,"front")),vn(n,Hr,gi,_n,0,pn,is+gn,Bt(e,"behind")),vn(n,_n,gi,es,-ti-gn,pn,-xn,Bt(e,"front-left")),vn(n,_n,gi,es,-ti-gn,pn,xn,Bt(e,"behind-left")),vn(n,_n,gi,es,ti+gn,pn,-xn,Bt(e,"front-right")),vn(n,_n,gi,es,ti+gn,pn,xn,Bt(e,"behind-right")),t){V0(n,t,lx,.5,ti,is,X0);const r=(l,c)=>{const h=[];return Bt(e,l)!==void 0&&h.push({main:es,center:-xn}),Bt(e,c)!==void 0&&h.push({main:es,center:xn}),h},a=Bt(e,"front")!==void 0?[{main:Hr,center:0}]:[],o=Bt(e,"behind")!==void 0?[{main:Hr,center:0}]:[];H0(n,ti,is,pn-_o/2,pn+_o/2,gi,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const gx=[.95,.9,.82];function q0(){const i=new En;tn(i,new Ii(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new hi(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Sa(.07,.16,8),gx,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class Ns{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?kl(t,ti,is,X0):kl(t,Hl/2,Vl/2,W0),r=e.kind==="vehicle"?px:(e.occupiedFloor??0)*ni+cx,a=(e.headingDeg??0)-k0[t]/iu;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?hx(e.floors??ix,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?ux():e.kind==="streetlight"?dx(t):e.kind==="vehicle"?mx(t,e.windows,e.witnessSide):q0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*iu),n}static setLit(e,t,n){const s=t==="streetlight"?n?z0:O0:n?G0:B0;for(const r of e.children)!(r instanceof Mt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof Mt&&(t.geometry.dispose(),t.material.dispose())}}function _x(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const Vr=900,vx=.5,xx=900,vo=.5,Mx=850,xo=850,Mo=4,Sx=1.5,yx=-1,Ex=6,Wl=-4,ru=Wl,bx=3,Tx=.15,Ax=.6,wx=40,Rx=30,Cx=[0,45,90,135,180,225,270,315],Px={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},Ix=["en","fr"],Dx=880,au=40,Lx=10,Ux=1,Nx=150,So=55,ou=.5,Fx=700,Ox=5,ts=[.92,.92,.95],yo=[.15,.15,.19],lu={snow:{fallSpeedMPerS:2,size:.3,color:new Me(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Me(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},ss=0,zx=0,cu=3e3,Fs=20,Bx=15,hu=ss,Gx=40,uu=1,kx=9;function Hx(i){return uu+(kx-uu)*i}const Vx=new Me(.75,.82,.92),Wx=10,Xx=.5;function qx(i){return Y0(i/Wx,Xx,1)}const ns=200,du=.18,fu=.32,Yx=.35,Zx=new Me(.85,.9,.98),pu=5,mu=.85,gu=.01;function Eo(i,e){return Math.round(i*(gu+(1-gu)*e))}const _u=230,vu=.7,xu=.05,$x=.6,Kx=.7,Jx=.15,Mu=.35,Qx=3,jx=1/12,e3=.5,Su=8,yu=25,Eu=.12,t3={Venus:new Me(1,.96,.85),Mars:new Me(1,.55,.4),Jupiter:new Me(.95,.87,.72),Saturn:new Me(.92,.86,.68)};class n3{renderer;scene=new Uf;camera;celestialGroup=new En;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new ip(16777215,0);celestialLightTarget=new St;skyLight=new jf(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new io;weather=Au;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new N;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new N;sunVisible=!1;lensFlareScratch=new N;sunOcclusionRaycaster=new io;sunOcclusionDirectionScratch=new N;ufoOcclusionRaycaster=new io;onLightningFlash;constructor(e,t=U2(),n){this.renderer=new tv({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Hs,this.camera=new qt(60,e.width/Math.max(e.height,1),.1,Vr*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Ri(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<Nx)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;z2(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=Ux,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=ou*e,this.lastSunPosition&&this.applyLensFlareTint(Is(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(So*this.dazzleIntensity*e[0],So*this.dazzleIntensity*e[1],So*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){_x(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=e3,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())this.scene.remove(t),Ns.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=Ns.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Ri(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&sx(a.kind)),r={x:0,z:0};if(s){const a=Ns.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,d=-s.northM+n.z;r.x=-(h+l),r.z=-(d+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,zx,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=rx(t,e);Ns.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new tp(16764006,wx,Rx);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=d0(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,Mo,new Me(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new rc(new Me(...n),Vr*.2,Vr),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=Ax;const s=e.sun.altitudeDeg>=ru,r=!s&&e.moon.altitudeDeg>=ru;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=Qi(a.altitudeDeg,a.azimuthDeg,xo);this.celestialLight.position.set(o,l,c);const h=Is(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const d=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?bx:Tx)*d,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=vx,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())Ns.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.scene.remove(this.lensFlare.mesh),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,jx);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new hi(Vr,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=rv(n.getX(a),n.getY(a),n.getZ(a)),c=lv(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new yt(s,3));const r=new $s({vertexColors:!0,side:Pt,fog:!1});this.skyMesh=new Mt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new lc(xx,48),t=new Qs({color:new Me(vo,vo,vo),fog:!0});this.groundMesh=new Mt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<Wl){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=Qi(t.altitudeDeg,t.azimuthDeg,xo),c=Is(t.altitudeDeg),h=new Me(s.r*c[0],s.g*c[1],s.b*c[2]),d=new hi(n,16,16),u=new $s({color:h,fog:!1}),p=new Mt(d,u);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=nx(),this.lensFlare.uniforms.uOpacity.value=ou*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<Wl){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,xo),a=Is(e.altitudeDeg),o=new Me(a[0],a[1],a[2]),l=new zs({map:d3(e.phase),color:o,fog:!1}),c=new _r(l);c.position.set(n,s,r);const h=Mo*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,Mo),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new zs({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new _r(a);o.position.set(t,n,s);const l=r*Ex;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=hv(r);if(o<=0)return;const l=fv(o),c=new zs({map:u3(),color:a,transparent:!0,opacity:gv(o),blending:ia,depthWrite:!1,fog:!1}),h=new _r(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(this.scene.remove(t),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=zh(n.magnitude),r=Bh(s),a=t3[n.body]??new Me(1,1,1),o=new Me(a.r*r,a.g*r,a.b*r),l=Sx*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=nv(t),o=bo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:d,azimuthDeg:u}=_2(n.ra[c],n.dec[c],s,r);if(d<yx)continue;const{x:p,y:_,z:S}=Qi(d,u,Mx);l.push({x:p,y:_,z:S,brightness:zh(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=p0.map((c,h)=>{const d=l.filter(x=>vv(x.brightness)===h),u=new Float32Array(d.length*3),p=new Float32Array(d.length),_=new Float32Array(d.length),S=new Float32Array(d.length);d.forEach((x,y)=>{u[y*3]=x.x,u[y*3+1]=x.y,u[y*3+2]=x.z,p[y]=x.brightness,_[y]=x.phase,S[y]=x.speedFactor});const m=new Et;m.setAttribute("position",new pt(u,3));const f=new pt(new Float32Array(d.length*3),3);m.setAttribute("color",f);const A=new Ju({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),w=new ea(m,A);return this.celestialGroup.add(w),{points:w,colorAttribute:f,brightness:p,phase:_,speedFactor:S}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=Sv(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=Bh(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Me(ts[0]+(yo[0]-ts[0])*e,ts[1]+(yo[1]-ts[1])*e,ts[2]+(yo[2]-ts[2])*e),{material:n,uniforms:s}=K2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=Q2(Fx);this.cloudMesh=new Mt(r,n),this.cloudMesh.renderOrder=Ox,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,1),a=Is(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.scene.remove(this.cloudMesh),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.scene.remove(this.precipitationPoints),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=lu[e],n=t.poolSize,s=bo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),d=new Float32Array(n),u=new Float32Array(n),p=new Float32Array(n),_=new Float32Array(n);for(let w=0;w<n;w++){const x=s()*Math.PI*2,y=s()*t.radiusM;r[w*3]=Math.cos(x)*y,r[w*3+1]=ss+s()*(t.topYM-ss),r[w*3+2]=Math.sin(x)*y,a[w]=s()*Math.PI*2,o[w]=.7+s()*.6,l[w]=.6+s()*.8,c[w]=.4+s()*1.2}const S=new Et;S.setAttribute("position",new pt(r,3)),S.setDrawRange(0,Eo(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Me(...this.baseFogColor)},uTexture:{value:i3(e)},uNearFocusDistance:{value:pu},uHazeDistance:{value:t.radiusM*mu}},f=new Gt({uniforms:m,vertexShader:c3,fragmentShader:h3,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const A=new ea(S,f);this.scene.add(A),this.precipitationPoints=A,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=d,this.precipitationBounceDuration=u,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=_}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=lu[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,d=this.precipitationWobbleFreqJitter,u=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,_=this.precipitationBounceHeight,S=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,A=n==="snow"&&d&&u,w=n==="hail"&&p&&_&&S&&m&&f;for(let x=0,y=0;x<l.length;x+=3,y++){if(w&&p[y]>0){if(p[y]-=t,p[y]<=0){const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E,p[y]=0}else{const v=1-p[y]/S[y];l[x+1]=ss+Math.sin(Math.PI*v)*_[y],l[x]=Xr(l[x]+(a+m[y])*t,s.radiusM),l[x+2]=Xr(l[x+2]+(o+f[y])*t,s.radiusM)}continue}let b=0,R=0;if(A){const v=$x*d[y],E=Kx*u[y];b=Math.sin(e*v*Math.PI*2+c[y])*E,R=Math.sin(e*v*Math.PI*2+c[y]+Math.PI/2)*E}if(l[x]+=(a+b)*t,l[x+1]-=s.fallSpeedMPerS*h[y]*t,l[x+2]+=(o+R)*t,l[x]=Xr(l[x],s.radiusM),l[x+2]=Xr(l[x+2],s.radiusM),l[x+1]<ss){if(w){_[y]=Mu*(.2+Math.random()*1.6),S[y]=Jx*(.5+Math.random()),p[y]=S[y];const P=Math.random()*Math.PI*2,C=Qx*(_[y]/Mu);m[y]=Math.cos(P)*C,f[y]=Math.sin(P)*C,l[x+1]=ss;continue}const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=Hx(this.weather.precipitationIntensity);this.rainSystem=Y2({count:cu,radiusM:Fs,heightM:Bx,bottomYM:hu,overallSpeed:Gx,color:Vx,opacity:.85,visibleCount:Eo(cu,this.weather.precipitationIntensity),speedStreak:qx(e),pixelSize:_u,seed:9001,nearFocusDistanceM:pu,hazeDistanceM:Fs*mu,hazeColor:new Me(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=bo(4242),t=new Float32Array(ns*3),n=new Float32Array(ns),s=new Float32Array(ns),r=new Float32Array(ns);for(let h=0;h<ns;h++){const d=e()*Math.PI*2,u=Math.sqrt(e())*Fs;t[h*3]=Math.cos(d)*u,t[h*3+1]=hu,t[h*3+2]=Math.sin(d)*u,s[h]=Wr(du,fu),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new pt(t,3));const o=new pt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,Eo(ns,this.weather.precipitationIntensity));const l=new Gt({uniforms:{uMaxSize:{value:Yx},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:Zx},uTexture:{value:a3()}},vertexShader:o3,fragmentShader:l3,transparent:!0,depthWrite:!1}),c=new ea(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.scene.remove(this.rainSystem.points),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.scene.remove(this.rainSplashSystem.points),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Fs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=vu+(1-vu)*(1-l),h=xu+(1-xu)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=_u*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,d=Math.sqrt(Math.random())*Fs;n[l]=Math.cos(h)*d,n[l+2]=Math.sin(h)*d,r[c]=Wr(du,fu),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/Eu;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Wr(Su,yu);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=Eu,this.nextLightningAtS=e+Wr(Su,yu),this.onLightningFlash?.())}}buildCompassLabels(){const e=ql(navigator.languages,Ix),t=Px[e];this.compassSprites=Cx.map((n,s)=>{const r=t[s],a=new zs({map:f3(r),depthTest:!1,fog:!1}),o=new _r(a),{x:l,y:c,z:h}=Qi(0,n,Dx);return o.position.set(l,c,h),o.scale.set(au,au,1),o.renderOrder=Lx,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)this.scene.remove(e),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;this.scene.remove(e),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function Y0(i,e,t){return Math.max(e,Math.min(t,i))}function Wr(i,e){return i+Math.random()*(e-i)}function Xr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let qr,Yr;function i3(i){switch(i){case"snow":return s3();case"hail":return r3()}}function s3(){if(qr)return qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),qr=new Vn(e),qr}function r3(){if(Yr)return Yr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Yr=new Vn(e),Yr}let Zr;function a3(){if(Zr)return Zr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Zr=new Vn(e),Zr}const o3=`
|
|
5035
|
+
`;let kr;function tx(){if(kr)return kr;const i=256,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d");t.fillStyle="rgba(60,60,60,1)",t.fillRect(0,0,i,i);const n=[[.3,.35,.22,.5],[.7,.6,.16,.35],[.55,.8,.3,.4],[.15,.7,.12,.3],[.85,.2,.18,.3]];for(const[s,r,a,o]of n){const l=t.createRadialGradient(s*i,r*i,0,s*i,r*i,a*i);l.addColorStop(0,`rgba(200,200,200,${o})`),l.addColorStop(1,"rgba(200,200,200,0)"),t.fillStyle=l,t.fillRect(0,0,i,i)}return kr=new Vn(e),kr}function nx(){const i={uTime:{value:0},uResolution:{value:new Fe(1,1)},uLensPosition:{value:new Fe(0,0)},uColorGain:{value:new Me(55,55,51)},uOpacity:{value:.5},uFlareIntensity:{value:0},uStarPoints:{value:6},uGlareSize:{value:.55},uFlareSize:{value:.0025},uFlareSpeed:{value:.4},uFlareShape:{value:1.2},uHaloScale:{value:.5},uGhostScale:{value:.3},uAnimated:{value:!1},uAnamorphic:{value:!1},uSecondaryGhosts:{value:!0},uStarBurst:{value:!0},uAdditionalStreaks:{value:!0},uLensDirtTexture:{value:tx()}},e=new Gt({uniforms:i,vertexShader:j2,fragmentShader:ex,transparent:!0,depthWrite:!1,depthTest:!1,blending:ia,fog:!1,name:"LensFlareShader"}),t=new Mt(new Js(2,2),e);return t.frustumCulled=!1,t.renderOrder=20,{mesh:t,uniforms:i}}const ix=2;function sx(i){return i==="building"||i==="vehicle"}function rx(i,e){const t=i.litKeyframes;if(!t||t.length===0)return i.lit??!1;let n=t[0];for(const s of t){if(s.t>e)break;n=s}return n.lit}const iu=Math.PI/180;function tn(i,e,t,n,s=!1){const r=s?new $s({color:new Me(...t)}):new Qs({color:new Me(...t)}),a=new Mt(e,r);return a.position.y=n,a.userData={emissive:s},a.castShadow=!s,a.receiveShadow=!s,i.add(a),a}const O0=[.32,.32,.3],z0=[1,.85,.5],B0=[.25,.25,.25],G0=[1,.97,.85],ax=[.55,.68,.72],gn=.03,_n=.05,k0={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function Bt(i,e){return i?.[e]}function vn(i,e,t,n,s,r,a,o){if(o===void 0)return;const l=new Qs({color:new Me(...ax),transparent:!0,opacity:o/100}),c=new Mt(new wn(e,t,n),l);c.position.set(s,r,a),i.add(c)}const Jt=.05,go=[.6,.58,.53],su=[.5,.5,.48];function os(i,e,t,n,s,r,a,o){const l=new Qs({color:new Me(...o),side:Pt}),c=new Mt(new wn(e,t,n),l);c.position.set(s,r,a),i.add(c)}function ox(i,e,t,n,s,r,a,o,l){const c=(n-r)/2,h=(_,S,m,f)=>{_<=0||(e?os(i,_,S,Jt,m,o+f,a,l):os(i,Jt,S,_,a,o+f,m,l))};h(t,c,0,n/2-c/2),h(t,c,0,-(n/2-c/2));const d=[...s].sort((_,S)=>_.center-S.center);let u=-t/2;for(const _ of d){const m=_.center-_.main/2-u;h(m,r,u+m/2,0),u=_.center+_.main/2}const p=t/2-u;h(p,r,u+p/2,0)}function H0(i,e,t,n,s,r,a,o,l,c){const h=(n+s)/2,d=s-n,u=(p,_,S,m)=>{p.length===0?_?os(i,S,d,Jt,0,h,m,go):os(i,Jt,d,S,m,h,0,go):ox(i,_,S,d,p,r,m,h,go)};u(a,!0,e*2,-t+Jt),u(o,!0,e*2,t-Jt),u(l,!1,t*2,-e+Jt),u(c,!1,t*2,e-Jt),os(i,e*2,Jt,t*2,0,n+Jt,0,su),os(i,e*2,Jt,t*2,0,s-Jt,0,su)}function kl(i,e,t,n){switch(i){case"front":return{x:0,z:-(t-n)};case"behind":return{x:0,z:t-n};case"left":return{x:-(e-n),z:0};case"right":return{x:e-n,z:0};case"front-left":return{x:-(e-n),z:-xn};case"front-right":return{x:e-n,z:-xn};case"behind-left":return{x:-(e-n),z:xn};case"behind-right":return{x:e-n,z:xn}}}function V0(i,e,t,n,s,r,a){const o=q0();o.scale.setScalar(n),o.rotation.y=k0[e];const{x:l,z:c}=kl(e,s,r,a);o.position.set(l,t,c),i.add(o)}const Hl=6,Vl=6,ni=3,Ls=1.4,Us=ni*.5,W0=1.2,X0=.35,lx=.75,cx=1.6;function hx(i,e,t,n){const s=new En,r=Math.max(1,i+1),a=r*ni;tn(s,new wn(Hl,a,Vl),[.55,.54,.5],a/2);const o=Hl/2,l=Vl/2;for(let c=0;c<r;c++){const h=c*ni+ni/2;vn(s,Ls,Us,_n,0,h,-l-gn,Bt(e,"front")),vn(s,Ls,Us,_n,0,h,l+gn,Bt(e,"behind")),vn(s,_n,Us,Ls,-o-gn,h,0,Bt(e,"left")),vn(s,_n,Us,Ls,o+gn,h,0,Bt(e,"right"))}if(t){const c=Math.min(Math.max(n??0,0),r-1);V0(s,t,c*ni,.72,o,l,W0);const h=d=>Bt(e,d)!==void 0?[{main:Ls,center:0}]:[];H0(s,o,l,c*ni,(c+1)*ni,Us,h("front"),h("behind"),h("left"),h("right"))}return s}function ux(){const i=new En;return tn(i,new Ii(.15,.22,2,8),[.32,.22,.14],1),tn(i,new Sa(1.4,3,8),[.16,.32,.14],3.5),i}function dx(i){const e=new En;return tn(e,new Ii(.05,.08,5,8),[.28,.28,.3],2.5),tn(e,new hi(.25,12,8),i?z0:O0,5.1,!0),e}const fx=[.08,.08,.08],ti=.8,is=1,pn=1.7,_o=.6,gi=.4,Hr=1.2,es=.7,xn=.5,px=pn;function mx(i,e,t){const n=new En;tn(n,new wn(1.8,1.4,4.2),[.45,.14,.14],.7),tn(n,new wn(ti*2,_o,is*2),[.4,.12,.12],pn);for(const r of[-1.4,1.4])for(const a of[-.95,.95]){const o=tn(n,new Ii(.4,.4,.3,12),fx,.4);o.rotation.z=Math.PI/2,o.position.x=a,o.position.z=r}const s=i?G0:B0;for(const r of[-.7,.7])tn(n,new hi(.15,8,6),s,.7,!0).position.set(r,.7,-2.1);if(vn(n,Hr,gi,_n,0,pn,-is-gn,Bt(e,"front")),vn(n,Hr,gi,_n,0,pn,is+gn,Bt(e,"behind")),vn(n,_n,gi,es,-ti-gn,pn,-xn,Bt(e,"front-left")),vn(n,_n,gi,es,-ti-gn,pn,xn,Bt(e,"behind-left")),vn(n,_n,gi,es,ti+gn,pn,-xn,Bt(e,"front-right")),vn(n,_n,gi,es,ti+gn,pn,xn,Bt(e,"behind-right")),t){V0(n,t,lx,.5,ti,is,X0);const r=(l,c)=>{const h=[];return Bt(e,l)!==void 0&&h.push({main:es,center:-xn}),Bt(e,c)!==void 0&&h.push({main:es,center:xn}),h},a=Bt(e,"front")!==void 0?[{main:Hr,center:0}]:[],o=Bt(e,"behind")!==void 0?[{main:Hr,center:0}]:[];H0(n,ti,is,pn-_o/2,pn+_o/2,gi,a,o,r("front-left","behind-left"),r("front-right","behind-right"))}return n}const gx=[.95,.9,.82];function q0(){const i=new En;tn(i,new Ii(.25,.3,1.5,10),[.3,.3,.35],.75),tn(i,new hi(.22,10,8),[.62,.52,.46],1.72);const e=tn(i,new Sa(.07,.16,8),gx,1.72);return e.rotation.x=-Math.PI/2,e.position.z=-.2,i}class Ns{static occupantView(e){const t=e.witnessSide;if(!t)throw new Error("occupantView requires object.witnessSide to be set");const{x:n,z:s}=e.kind==="vehicle"?kl(t,ti,is,X0):kl(t,Hl/2,Vl/2,W0),r=e.kind==="vehicle"?px:(e.occupiedFloor??0)*ni+cx,a=(e.headingDeg??0)-k0[t]/iu;return{x:n,z:s,eyeY:r,headingDeg:a}}static build(e,t){const n=e.kind==="building"?hx(e.floors??ix,e.windows,e.witnessSide,e.occupiedFloor):e.kind==="tree"?ux():e.kind==="streetlight"?dx(t):e.kind==="vehicle"?mx(t,e.windows,e.witnessSide):q0();return e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*iu),n}static setLit(e,t,n){const s=t==="streetlight"?n?z0:O0:n?G0:B0;for(const r of e.children)!(r instanceof Mt)||!r.userData.emissive||r.material.color.setRGB(...s)}static dispose(e){for(const t of e.children)t instanceof Mt&&(t.geometry.dispose(),t.material.dispose())}}function _x(i,e){return i.cloudCover===e.cloudCover&&i.cloudDarkness===e.cloudDarkness&&i.precipitationType===e.precipitationType&&i.precipitationIntensity===e.precipitationIntensity&&i.windDirectionDeg===e.windDirectionDeg&&i.windSpeed===e.windSpeed&&i.storm===e.storm}const Vr=900,vx=.5,xx=900,vo=.5,Mx=850,xo=850,Mo=4,Sx=1.5,yx=-1,Ex=6,Wl=-4,ru=Wl,bx=3,Tx=.15,Ax=.6,wx=40,Rx=30,Cx=[0,45,90,135,180,225,270,315],Px={en:["N","NE","E","SE","S","SW","W","NW"],fr:["N","NE","E","SE","S","SO","O","NO"]},Ix=["en","fr"],Dx=880,au=40,Lx=10,Ux=1,Nx=150,So=55,ou=.5,Fx=700,Ox=5,ts=[.92,.92,.95],yo=[.15,.15,.19],lu={snow:{fallSpeedMPerS:2,size:.3,color:new Me(1,1,1),driftSensitivity:1,radiusM:25,topYM:20,opacity:.75,poolSize:2400},hail:{fallSpeedMPerS:14,size:.5,color:new Me(.95,.98,1),driftSensitivity:.25,radiusM:25,topYM:10,opacity:.95,poolSize:1200}},ss=0,zx=0,cu=3e3,Fs=20,Bx=15,hu=ss,Gx=40,uu=1,kx=9;function Hx(i){return uu+(kx-uu)*i}const Vx=new Me(.75,.82,.92),Wx=10,Xx=.5;function qx(i){return Y0(i/Wx,Xx,1)}const ns=200,du=.18,fu=.32,Yx=.35,Zx=new Me(.85,.9,.98),pu=5,mu=.85,gu=.01;function Eo(i,e){return Math.round(i*(gu+(1-gu)*e))}const _u=230,vu=.7,xu=.05,$x=.6,Kx=.7,Jx=.15,Mu=.35,Qx=3,jx=1/12,e3=.5,Su=8,yu=25,Eu=.12,t3={Venus:new Me(1,.96,.85),Mars:new Me(1,.55,.4),Jupiter:new Me(.95,.87,.72),Saturn:new Me(.92,.86,.68)};class n3{renderer;scene=new Uf;camera;celestialGroup=new En;skyMesh;groundMesh;terrainMesh;terrainProviders;terrainOrigin;terrainBuildToken=0;terrainAttribution;starTiers=[];bodyMeshes=new Map;hitAreas=new Map;glareSprites=new Map;decorObjects=[];decorGroups=new Map;celestialLight=new ip(16777215,0);celestialLightTarget=new St;skyLight=new jf(16777215,0,0);streetlightLights=new Map;compassSprites=[];showCompass=!1;compassHovered=!1;compassForced=!1;animationFrameId=null;raycaster=new io;weather=Au;cloudMesh;cloudMaterial;cloudUniforms;precipitationPoints;precipitationPositions;precipitationPhase;precipitationSpeedJitter;precipitationWobbleFreqJitter;precipitationWobbleAmpJitter;precipitationBounceRemaining;precipitationBounceHeight;precipitationBounceDuration;precipitationBounceVelX;precipitationBounceVelZ;precipitationUniforms;rainSystem;rainSplashSystem;rainCameraDirection=new N;rainLastVerticalFacing=-1;lightningArmed=!1;nextLightningAtS=null;lightningFlashRemainingS=0;baseFogColor=[0,0,0];lastSunPosition;lensFlare;dazzleIntensity=1;lensFlareArtifactIntensity=0;sunWorldPosition=new N;sunVisible=!1;lensFlareScratch=new N;sunOcclusionRaycaster=new io;sunOcclusionDirectionScratch=new N;ufoOcclusionRaycaster=new io;onLightningFlash;constructor(e,t=U2(),n){this.renderer=new tv({canvas:e,antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Hs,this.camera=new qt(60,e.width/Math.max(e.height,1),.1,Vr*1.2),this.camera.position.set(0,1.6,0),this.terrainProviders=t,this.onLightningFlash=n,this.celestialLight.shadow.mapSize.set(1024,1024),this.celestialLight.shadow.camera.left=-120,this.celestialLight.shadow.camera.right=120,this.celestialLight.shadow.camera.top=120,this.celestialLight.shadow.camera.bottom=-120,this.celestialLight.shadow.camera.near=1,this.celestialLight.shadow.camera.far=1e3,this.celestialLight.shadow.bias=-.0015,this.celestialLight.target=this.celestialLightTarget,this.scene.add(this.celestialLight,this.celestialLightTarget,this.skyLight),this.scene.add(this.celestialGroup)}get currentTerrainAttribution(){return this.terrainAttribution}resize(e,t){this.renderer.setSize(e,t,!1),this.camera.aspect=e/Math.max(t,1),this.camera.updateProjectionMatrix(),this.render()}setObserverPose(e){e.headingDeg!==void 0?this.camera.rotation.set(e.pitchDeg*Ln,-e.headingDeg*Ln,0,"YXZ"):this.camera.rotation.set(e.pitchDeg*Ln,this.camera.rotation.y,0,"YXZ"),this.camera.position.y=1.6+e.elevationM,this.celestialGroup.position.y=this.camera.position.y,this.camera.fov!==e.fovDeg&&(this.camera.fov=e.fovDeg,this.camera.updateProjectionMatrix())}setTerrainOrigin(e,t,n){if(e===void 0||t===void 0)return;if(this.terrainOrigin){const{x:r,z:a}=Ri(e,t,this.terrainOrigin.lat,this.terrainOrigin.lng);if(Math.sqrt(r*r+a*a)<Nx)return}this.terrainOrigin={lat:e,lng:t};const s=++this.terrainBuildToken;z2(e,t,this.terrainProviders).then(({mesh:r,attribution:a})=>{s===this.terrainBuildToken&&(this.disposeMesh(this.terrainMesh),r.renderOrder=Ux,this.terrainMesh=r,this.terrainAttribution=a,this.scene.add(r),this.render(),n?.())}).catch(r=>{console.warn("Terrain build failed, keeping the flat ground fallback:",r),n?.()})}setShowCompass(e){this.showCompass!==e&&(this.showCompass=e,this.disposeCompassLabels(),e&&this.buildCompassLabels(),this.render())}setDazzleIntensity(e){this.dazzleIntensity!==e&&(this.dazzleIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uOpacity.value=ou*e,this.lastSunPosition&&this.applyLensFlareTint(Is(this.lastSunPosition.altitudeDeg))),this.render())}setLensFlareArtifactIntensity(e){this.lensFlareArtifactIntensity!==e&&(this.lensFlareArtifactIntensity=e,this.lensFlare&&(this.lensFlare.uniforms.uFlareIntensity.value=e),this.render())}applyLensFlareTint(e){this.lensFlare&&this.lensFlare.uniforms.uColorGain.value.setRGB(So*this.dazzleIntensity*e[0],So*this.dazzleIntensity*e[1],So*this.dazzleIntensity*e[2])}setCompassHovered(e){this.compassHovered!==e&&(this.compassHovered=e,this.updateCompassVisibility())}setCompassForced(e){this.compassForced!==e&&(this.compassForced=e,this.updateCompassVisibility())}updateCompassVisibility(){const e=this.compassHovered||this.compassForced;for(const t of this.compassSprites)t.visible=e;this.render()}setWeather(e){_x(this.weather,e)||(this.weather=e,this.buildClouds(),this.buildPrecipitation(),this.lightningArmed=e.storm&&e.cloudDarkness>=e3,this.lightningArmed||(this.nextLightningAtS=null,this.lightningFlashRemainingS=0,this.scene.fog&&this.scene.fog.color.setRGB(...this.baseFogColor)),this.syncAnimationLoop(),this.render())}setDecor(e){if(this.decorObjects!==e){this.decorObjects=e;for(const t of this.decorGroups.values())t.removeFromParent(),Ns.dispose(t);this.decorGroups.clear(),this.streetlightLights.clear();for(const t of e){const n=Ns.build(t,t.lit??!1);this.scene.add(n),this.decorGroups.set(t.id,n),t.kind==="streetlight"&&this.addStreetlightLight(t.id,n)}this.celestialLight.castShadow=this.decorGroups.size>0}}updateDecorAnchoring(e,t){const n=e?.lat!==void 0&&e.lng!==void 0&&t?.lat!==void 0&&t?.lng!==void 0?Ri(e.lat,e.lng,t.lat,t.lng):{x:0,z:0},s=this.decorObjects.find(a=>a.witnessSide!==void 0&&sx(a.kind)),r={x:0,z:0};if(s){const a=Ns.occupantView(s),o=-(s.headingDeg??0)*Ln,l=a.x*Math.cos(o)+a.z*Math.sin(o),c=-a.x*Math.sin(o)+a.z*Math.cos(o),h=s.eastM+n.x,d=-s.northM+n.z;r.x=-(h+l),r.z=-(d+c),this.camera.position.y=a.eyeY,this.camera.rotation.set(this.indoorLookPitchDeg*Ln,-(a.headingDeg+this.indoorLookYawDeg)*Ln,0,"YXZ")}for(const a of this.decorObjects){const o=this.decorGroups.get(a.id);o&&o.position.set(a.eastM+n.x+r.x,zx,-a.northM+n.z+r.z)}}indoorLookYawDeg=0;indoorLookPitchDeg=0;setIndoorLook(e,t){this.indoorLookYawDeg=e,this.indoorLookPitchDeg=t}updateDecorLitState(e){for(const t of this.decorObjects){if(t.kind!=="streetlight"&&t.kind!=="vehicle")continue;const n=this.decorGroups.get(t.id);if(!n)continue;const s=rx(t,e);Ns.setLit(n,t.kind,s);const r=this.streetlightLights.get(t.id);r&&(r.visible=s)}}addStreetlightLight(e,t){const n=t.children.find(r=>r.userData.emissive);if(!n)return;const s=new tp(16764006,wx,Rx);s.position.copy(n.position),s.castShadow=!0,s.shadow.mapSize.set(512,512),s.shadow.bias=-.002,t.add(s),this.streetlightLights.set(e,s)}setAstronomy(e){const t=d0(e.sun.altitudeDeg),n=t.horizon;this.baseFogColor=n,this.lastSunPosition=e.sun,this.buildSky(e.sun),this.buildGround(),this.updateCloudLighting(e.sun,n),this.updateCelestialLight(e,t.zenith,n),this.buildStars(e.stars,e.sun.altitudeDeg),this.setBodyMesh("sun",e.sun,Mo,new Me(1,.96,.88),e.sun.magnitude),this.setMoonMesh(e.moon),this.buildPlanets(e.planets),this.scene.fog=new rc(new Me(...n),Vr*.2,Vr),this.syncAnimationLoop(),this.render()}updateCelestialLight(e,t,n){this.skyLight.color.setRGB(t[0],t[1],t[2]),this.skyLight.groundColor.setRGB(n[0],n[1],n[2]),this.skyLight.intensity=Ax;const s=e.sun.altitudeDeg>=ru,r=!s&&e.moon.altitudeDeg>=ru;if(!s&&!r){this.celestialLight.intensity=0;return}const a=s?e.sun:e.moon,{x:o,y:l,z:c}=Qi(a.altitudeDeg,a.azimuthDeg,xo);this.celestialLight.position.set(o,l,c);const h=Is(a.altitudeDeg);this.celestialLight.color.setRGB(h[0],h[1],h[2]);const d=Math.max(0,Math.sin(Math.max(a.altitudeDeg,0)*Ln));this.celestialLight.intensity=(s?bx:Tx)*d,this.celestialLight.castShadow=this.decorGroups.size>0}render(){this.updateLensFlarePosition(),this.renderer.render(this.scene,this.camera)}updateLensFlarePosition(){const e=this.lensFlare;if(!e)return;if(!this.sunVisible){e.mesh.visible=!1;return}if(this.camera.updateMatrixWorld(),this.lensFlareScratch.copy(this.sunWorldPosition).applyMatrix4(this.camera.matrixWorldInverse),this.lensFlareScratch.z>0){e.mesh.visible=!1;return}if(this.isSunOccluded()){e.mesh.visible=!1;return}e.mesh.visible=!0;const t=this.lensFlareScratch.copy(this.sunWorldPosition).project(this.camera);e.uniforms.uLensPosition.value.set(t.x,t.y),e.uniforms.uResolution.value.set(this.renderer.domElement.width,this.renderer.domElement.height)}isSunOccluded(){const e=[];this.groundMesh&&e.push(this.groundMesh),this.terrainMesh&&e.push(this.terrainMesh);for(const r of this.decorGroups.values())e.push(r);if(e.length===0)return!1;const t=this.sunOcclusionDirectionScratch.copy(this.sunWorldPosition).sub(this.camera.position),n=t.length();t.normalize(),this.sunOcclusionRaycaster.set(this.camera.position,t);const s=this.sunOcclusionRaycaster.intersectObjects(e,!0)[0];return s!==void 0&&s.distance<n}isScreenPointOccluded(e,t,n){const s=[];for(const r of this.decorObjects){if(!r.occludesSourceIds?.includes(n))continue;const a=this.decorGroups.get(r.id);a&&s.push(a)}return s.length===0?!1:(this.ufoOcclusionRaycaster.setFromCamera(new Fe(e,t),this.camera),this.ufoOcclusionRaycaster.near=vx,this.ufoOcclusionRaycaster.intersectObjects(s,!0).length>0)}pickBodyAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.hitAreas.entries()],s=this.raycaster.intersectObjects(n.map(([,r])=>r))[0];if(s)return n.find(([,r])=>r===s.object)?.[0]}pickDecorAt(e,t){this.raycaster.setFromCamera(new Fe(e,t),this.camera);const n=[...this.decorGroups.entries()],s=this.raycaster.intersectObjects(n.map(([,a])=>a),!0)[0];if(!s)return;let r=s.object;for(;r&&!n.some(([,a])=>a===r);)r=r.parent;return n.find(([,a])=>a===r)?.[0]}dispose(){this.stopTwinkle(),this.terrainBuildToken++,this.disposeMesh(this.skyMesh),this.disposeMesh(this.groundMesh),this.disposeMesh(this.terrainMesh),this.disposeCloudSystem(),this.disposePrecipitationPoints(),this.disposeRain(),this.disposeStarTiers();for(const e of this.bodyMeshes.values())this.disposeMesh(e);this.bodyMeshes.clear();for(const e of[...this.hitAreas.keys()])this.disposeHitArea(e);for(const e of[...this.glareSprites.keys()])this.disposeGlare(e);this.disposeCompassLabels();for(const e of this.decorGroups.values())Ns.dispose(e);this.decorGroups.clear(),this.streetlightLights.clear(),this.lensFlare&&(this.lensFlare.mesh.removeFromParent(),this.lensFlare.mesh.geometry.dispose(),this.lensFlare.mesh.material.dispose(),this.lensFlare=void 0),this.renderer.dispose()}startTwinkle(){if(this.animationFrameId!==null||!this.needsAnimationLoop())return;let e;const t=n=>{const s=e===void 0?0:Math.min((n-e)/1e3,jx);e=n,this.updateTwinkle(n/1e3),this.updatePrecipitation(n/1e3,s),this.updateRain(s),this.updateLightning(n/1e3,s),this.lensFlare&&(this.lensFlare.uniforms.uTime.value=n/1e3),this.render(),this.animationFrameId=requestAnimationFrame(t)};this.animationFrameId=requestAnimationFrame(t)}stopTwinkle(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}needsAnimationLoop(){return this.starTiers.length>0||this.precipitationPoints!==void 0||this.rainSystem!==void 0||this.lightningArmed||this.lensFlare!==void 0&&this.sunVisible}syncAnimationLoop(){this.needsAnimationLoop()?this.startTwinkle():this.stopTwinkle()}buildSky(e){this.disposeMesh(this.skyMesh);const t=new hi(Vr,32,16),n=t.attributes.position,s=[];for(let a=0;a<n.count;a++){const{altitudeDeg:o,azimuthDeg:l}=rv(n.getX(a),n.getY(a),n.getZ(a)),c=lv(o,l,e.azimuthDeg,e.altitudeDeg);s.push(c[0],c[1],c[2])}t.setAttribute("color",new yt(s,3));const r=new $s({vertexColors:!0,side:Pt,fog:!1});this.skyMesh=new Mt(t,r),this.celestialGroup.add(this.skyMesh)}buildGround(){this.disposeMesh(this.groundMesh);const e=new lc(xx,48),t=new Qs({color:new Me(vo,vo,vo),fog:!0});this.groundMesh=new Mt(e,t),this.groundMesh.rotation.x=-Math.PI/2,this.groundMesh.position.y=0,this.groundMesh.receiveShadow=!0,this.scene.add(this.groundMesh)}setBodyMesh(e,t,n,s,r){if(this.disposeMesh(this.bodyMeshes.get(e)),this.disposeHitArea(e),this.disposeGlare(e),t.altitudeDeg<Wl){this.bodyMeshes.delete(e),e==="sun"&&(this.sunVisible=!1);return}const{x:a,y:o,z:l}=Qi(t.altitudeDeg,t.azimuthDeg,xo),c=Is(t.altitudeDeg),h=new Me(s.r*c[0],s.g*c[1],s.b*c[2]),d=new hi(n,16,16),u=new $s({color:h,fog:!1}),p=new Mt(d,u);p.position.set(a,o,l),this.celestialGroup.add(p),this.bodyMeshes.set(e,p),this.setHitArea(e,a,o,l,n),e!=="sun"&&this.setGlare(e,a,o,l,r,h),e==="sun"&&(this.sunVisible=!0,this.sunWorldPosition.set(a,o+this.celestialGroup.position.y,l),this.lensFlare||(this.lensFlare=nx(),this.lensFlare.uniforms.uOpacity.value=ou*this.dazzleIntensity,this.lensFlare.uniforms.uFlareIntensity.value=this.lensFlareArtifactIntensity,this.scene.add(this.lensFlare.mesh)),this.applyLensFlareTint(c))}setMoonMesh(e){const t="moon";if(this.disposeMesh(this.bodyMeshes.get(t)),this.disposeHitArea(t),this.disposeGlare(t),e.altitudeDeg<Wl){this.bodyMeshes.delete(t);return}const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,xo),a=Is(e.altitudeDeg),o=new Me(a[0],a[1],a[2]),l=new zs({map:d3(e.phase),color:o,fog:!1}),c=new _r(l);c.position.set(n,s,r);const h=Mo*2;c.scale.set(h,h,1),this.celestialGroup.add(c),this.bodyMeshes.set(t,c),this.setHitArea(t,n,s,r,Mo),this.setGlare(t,n,s,r,e.magnitude,o)}setHitArea(e,t,n,s,r){const a=new zs({transparent:!0,opacity:0,depthTest:!1,depthWrite:!1,fog:!1}),o=new _r(a);o.position.set(t,n,s);const l=r*Ex;o.scale.set(l,l,1),this.celestialGroup.add(o),this.hitAreas.set(e,o)}disposeHitArea(e){const t=this.hitAreas.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.hitAreas.delete(e))}setGlare(e,t,n,s,r,a){this.disposeGlare(e);const o=hv(r);if(o<=0)return;const l=fv(o),c=new zs({map:u3(),color:a,transparent:!0,opacity:gv(o),blending:ia,depthWrite:!1,fog:!1}),h=new _r(c);h.position.set(t,n,s),h.scale.set(l*2,l*2,1),this.celestialGroup.add(h),this.glareSprites.set(e,h)}disposeGlare(e){const t=this.glareSprites.get(e);t&&(t.removeFromParent(),t.material.dispose(),this.glareSprites.delete(e))}buildPlanets(e){const t=new Set(["sun","moon"]);for(const n of e){t.add(n.body);const s=zh(n.magnitude),r=Bh(s),a=t3[n.body]??new Me(1,1,1),o=new Me(a.r*r,a.g*r,a.b*r),l=Sx*(.5+.5*s);this.setBodyMesh(n.body,n.position,l,o,n.magnitude)}for(const n of[...this.bodyMeshes.keys()])t.has(n)||(this.disposeMesh(this.bodyMeshes.get(n)),this.bodyMeshes.delete(n),this.disposeHitArea(n),this.disposeGlare(n))}buildStars(e,t){if(this.disposeStarTiers(),!e||e.catalog.count===0){this.syncAnimationLoop();return}const{catalog:n,date:s,observer:r}=e,a=nv(t),o=bo(1337),l=[];for(let c=0;c<n.count;c++){const h=n.mag[c];if(h>a)continue;const{altitudeDeg:d,azimuthDeg:u}=_2(n.ra[c],n.dec[c],s,r);if(d<yx)continue;const{x:p,y:_,z:S}=Qi(d,u,Mx);l.push({x:p,y:_,z:S,brightness:zh(h),phase:o()*Math.PI*2,speedFactor:.7+o()*.6})}this.starTiers=p0.map((c,h)=>{const d=l.filter(x=>vv(x.brightness)===h),u=new Float32Array(d.length*3),p=new Float32Array(d.length),_=new Float32Array(d.length),S=new Float32Array(d.length);d.forEach((x,y)=>{u[y*3]=x.x,u[y*3+1]=x.y,u[y*3+2]=x.z,p[y]=x.brightness,_[y]=x.phase,S[y]=x.speedFactor});const m=new Et;m.setAttribute("position",new pt(u,3));const f=new pt(new Float32Array(d.length*3),3);m.setAttribute("color",f);const A=new Ju({vertexColors:!0,size:c.size,sizeAttenuation:!1,fog:!1}),w=new ea(m,A);return this.celestialGroup.add(w),{points:w,colorAttribute:f,brightness:p,phase:_,speedFactor:S}}),this.updateTwinkle(0),this.startTwinkle()}updateTwinkle(e){for(const t of this.starTiers){const n=t.colorAttribute.array;for(let s=0;s<t.brightness.length;s++){const r=Sv(t.brightness[s],{phase:t.phase[s],speedFactor:t.speedFactor[s]},e),a=Bh(t.brightness[s])*r;n[s*3]=a,n[s*3+1]=a,n[s*3+2]=a}t.colorAttribute.needsUpdate=!0}}buildClouds(){if(this.disposeCloudSystem(),this.weather.cloudCover<=0)return;const e=this.weather.cloudDarkness,t=new Me(ts[0]+(yo[0]-ts[0])*e,ts[1]+(yo[1]-ts[1])*e,ts[2]+(yo[2]-ts[2])*e),{material:n,uniforms:s}=K2(t,this.weather.cloudCover);this.cloudMaterial=n,this.cloudUniforms=s,this.lastSunPosition&&this.updateCloudLighting(this.lastSunPosition,this.baseFogColor);const r=Q2(Fx);this.cloudMesh=new Mt(r,n),this.cloudMesh.renderOrder=Ox,this.celestialGroup.add(this.cloudMesh)}updateCloudLighting(e,t){if(!this.cloudUniforms)return;const{x:n,y:s,z:r}=Qi(e.altitudeDeg,e.azimuthDeg,1),a=Is(e.altitudeDeg);this.cloudUniforms.sunDir.value.set(n,s,r),this.cloudUniforms.sunColor.value.setRGB(a[0],.96*a[1],.88*a[2]),this.cloudUniforms.ambientColor.value.setRGB(t[0],t[1],t[2])}disposeCloudSystem(){this.cloudMesh&&(this.cloudMesh.removeFromParent(),this.cloudMesh.geometry.dispose()),this.cloudMaterial?.dispose(),this.cloudMesh=void 0,this.cloudMaterial=void 0,this.cloudUniforms=void 0}disposePrecipitationPoints(){this.precipitationPoints&&(this.precipitationPoints.removeFromParent(),this.precipitationPoints.geometry.dispose(),this.precipitationPoints.material.dispose()),this.precipitationPoints=void 0,this.precipitationPositions=void 0,this.precipitationPhase=void 0,this.precipitationSpeedJitter=void 0,this.precipitationWobbleFreqJitter=void 0,this.precipitationWobbleAmpJitter=void 0,this.precipitationBounceRemaining=void 0,this.precipitationBounceHeight=void 0,this.precipitationBounceDuration=void 0,this.precipitationBounceVelX=void 0,this.precipitationBounceVelZ=void 0,this.precipitationUniforms=void 0}buildPrecipitation(){this.disposePrecipitationPoints(),this.disposeRain();const e=this.weather.precipitationType;if(e==="none")return;if(e==="rain"){this.buildRain();return}const t=lu[e],n=t.poolSize,s=bo(9001),r=new Float32Array(n*3),a=new Float32Array(n),o=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),h=new Float32Array(n),d=new Float32Array(n),u=new Float32Array(n),p=new Float32Array(n),_=new Float32Array(n);for(let w=0;w<n;w++){const x=s()*Math.PI*2,y=s()*t.radiusM;r[w*3]=Math.cos(x)*y,r[w*3+1]=ss+s()*(t.topYM-ss),r[w*3+2]=Math.sin(x)*y,a[w]=s()*Math.PI*2,o[w]=.7+s()*.6,l[w]=.6+s()*.8,c[w]=.4+s()*1.2}const S=new Et;S.setAttribute("position",new pt(r,3)),S.setDrawRange(0,Eo(n,this.weather.precipitationIntensity));const m={uSize:{value:t.size},uScale:{value:.5*this.renderer.domElement.height},uOpacity:{value:t.opacity},uColor:{value:t.color},uHazeColor:{value:new Me(...this.baseFogColor)},uTexture:{value:i3(e)},uNearFocusDistance:{value:pu},uHazeDistance:{value:t.radiusM*mu}},f=new Gt({uniforms:m,vertexShader:c3,fragmentShader:h3,transparent:!0,depthWrite:!1});this.precipitationUniforms=m;const A=new ea(S,f);this.scene.add(A),this.precipitationPoints=A,this.precipitationPositions=r,this.precipitationPhase=a,this.precipitationSpeedJitter=o,this.precipitationWobbleFreqJitter=l,this.precipitationWobbleAmpJitter=c,this.precipitationBounceRemaining=h,this.precipitationBounceHeight=d,this.precipitationBounceDuration=u,this.precipitationBounceVelX=p,this.precipitationBounceVelZ=_}updatePrecipitation(e,t){if(!this.precipitationPoints||!this.precipitationPositions||!this.precipitationPhase||!this.precipitationSpeedJitter||(this.precipitationUniforms?.uHazeColor.value.setRGB(...this.baseFogColor),t<=0))return;const n=this.weather.precipitationType;if(n==="none"||n==="rain")return;const s=lu[n],r=this.weather.windDirectionDeg*Ln,a=Math.sin(r)*this.weather.windSpeed*s.driftSensitivity,o=-Math.cos(r)*this.weather.windSpeed*s.driftSensitivity,l=this.precipitationPositions,c=this.precipitationPhase,h=this.precipitationSpeedJitter,d=this.precipitationWobbleFreqJitter,u=this.precipitationWobbleAmpJitter,p=this.precipitationBounceRemaining,_=this.precipitationBounceHeight,S=this.precipitationBounceDuration,m=this.precipitationBounceVelX,f=this.precipitationBounceVelZ,A=n==="snow"&&d&&u,w=n==="hail"&&p&&_&&S&&m&&f;for(let x=0,y=0;x<l.length;x+=3,y++){if(w&&p[y]>0){if(p[y]-=t,p[y]<=0){const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E,p[y]=0}else{const v=1-p[y]/S[y];l[x+1]=ss+Math.sin(Math.PI*v)*_[y],l[x]=Xr(l[x]+(a+m[y])*t,s.radiusM),l[x+2]=Xr(l[x+2]+(o+f[y])*t,s.radiusM)}continue}let b=0,R=0;if(A){const v=$x*d[y],E=Kx*u[y];b=Math.sin(e*v*Math.PI*2+c[y])*E,R=Math.sin(e*v*Math.PI*2+c[y]+Math.PI/2)*E}if(l[x]+=(a+b)*t,l[x+1]-=s.fallSpeedMPerS*h[y]*t,l[x+2]+=(o+R)*t,l[x]=Xr(l[x],s.radiusM),l[x+2]=Xr(l[x+2],s.radiusM),l[x+1]<ss){if(w){_[y]=Mu*(.2+Math.random()*1.6),S[y]=Jx*(.5+Math.random()),p[y]=S[y];const P=Math.random()*Math.PI*2,C=Qx*(_[y]/Mu);m[y]=Math.cos(P)*C,f[y]=Math.sin(P)*C,l[x+1]=ss;continue}const v=Math.random()*Math.PI*2,E=Math.sqrt(Math.random())*s.radiusM;l[x]=Math.cos(v)*E,l[x+1]=s.topYM,l[x+2]=Math.sin(v)*E}}this.precipitationPoints.geometry.attributes.position.needsUpdate=!0}buildRain(){const e=Hx(this.weather.precipitationIntensity);this.rainSystem=Y2({count:cu,radiusM:Fs,heightM:Bx,bottomYM:hu,overallSpeed:Gx,color:Vx,opacity:.85,visibleCount:Eo(cu,this.weather.precipitationIntensity),speedStreak:qx(e),pixelSize:_u,seed:9001,nearFocusDistanceM:pu,hazeDistanceM:Fs*mu,hazeColor:new Me(...this.baseFogColor)}),this.rainLastVerticalFacing=-1,this.scene.add(this.rainSystem.points),this.buildRainSplashes()}buildRainSplashes(){const e=bo(4242),t=new Float32Array(ns*3),n=new Float32Array(ns),s=new Float32Array(ns),r=new Float32Array(ns);for(let h=0;h<ns;h++){const d=e()*Math.PI*2,u=Math.sqrt(e())*Fs;t[h*3]=Math.cos(d)*u,t[h*3+1]=hu,t[h*3+2]=Math.sin(d)*u,s[h]=Wr(du,fu),n[h]=e()*s[h],r[h]=n[h]/s[h]}const a=new Et;a.setAttribute("position",new pt(t,3));const o=new pt(r,1);a.setAttribute("aLife",o),a.setDrawRange(0,Eo(ns,this.weather.precipitationIntensity));const l=new Gt({uniforms:{uMaxSize:{value:Yx},uScale:{value:.5*this.renderer.domElement.height},uColor:{value:Zx},uTexture:{value:a3()}},vertexShader:o3,fragmentShader:l3,transparent:!0,depthWrite:!1}),c=new ea(a,l);this.scene.add(c),this.rainSplashSystem={points:c,positions:t,life:n,duration:s,lifeAttribute:o}}disposeRain(){this.rainSystem&&(this.rainSystem.points.removeFromParent(),this.rainSystem.points.geometry.dispose(),this.rainSystem.points.material.dispose()),this.rainSystem=void 0,this.disposeRainSplashes()}disposeRainSplashes(){this.rainSplashSystem&&(this.rainSplashSystem.points.removeFromParent(),this.rainSplashSystem.points.geometry.dispose(),this.rainSplashSystem.points.material.dispose()),this.rainSplashSystem=void 0}updateRain(e){const t=this.rainSystem;if(!t)return;t.uniforms.uTime.value+=e,t.uniforms.uHazeColor.value.setRGB(...this.baseFogColor);const n=this.weather.windDirectionDeg*Ln,s=Math.sin(n)*this.weather.windSpeed,r=-Math.cos(n)*this.weather.windSpeed,a=Fs,o=c=>(c%(a*2)+a*3)%(a*2)-a;t.uniforms.uWindOffset.value.set(o(t.uniforms.uWindOffset.value.x+s*e),o(t.uniforms.uWindOffset.value.y+r*e)),this.camera.getWorldDirection(this.rainCameraDirection);const l=Math.abs(this.rainCameraDirection.y);if(Math.abs(l-this.rainLastVerticalFacing)>.001){this.rainLastVerticalFacing=l;const c=vu+(1-vu)*(1-l),h=xu+(1-xu)*(1-l);t.uniforms.uUvSquash.value=h,t.uniforms.uPixelSize.value=_u*c*(.5+.5*h)}this.updateRainSplashes(e)}updateRainSplashes(e){const t=this.rainSplashSystem;if(!t||e<=0)return;const{positions:n,life:s,duration:r,lifeAttribute:a}=t,o=a.array;for(let l=0,c=0;l<n.length;l+=3,c++){if(s[c]+=e,s[c]>=r[c]){const h=Math.random()*Math.PI*2,d=Math.sqrt(Math.random())*Fs;n[l]=Math.cos(h)*d,n[l+2]=Math.sin(h)*d,r[c]=Wr(du,fu),s[c]=0}o[c]=s[c]/r[c]}t.points.geometry.attributes.position.needsUpdate=!0,a.needsUpdate=!0}updateLightning(e,t){if(this.lightningArmed){if(this.lightningFlashRemainingS>0){this.lightningFlashRemainingS=Math.max(0,this.lightningFlashRemainingS-t);const n=this.lightningFlashRemainingS/Eu;this.scene.fog&&this.scene.fog.color.setRGB(this.baseFogColor[0]+(1-this.baseFogColor[0])*n,this.baseFogColor[1]+(1-this.baseFogColor[1])*n,this.baseFogColor[2]+(1-this.baseFogColor[2])*n);return}if(this.nextLightningAtS===null){this.nextLightningAtS=e+Wr(Su,yu);return}e>=this.nextLightningAtS&&(this.lightningFlashRemainingS=Eu,this.nextLightningAtS=e+Wr(Su,yu),this.onLightningFlash?.())}}buildCompassLabels(){const e=ql(navigator.languages,Ix),t=Px[e];this.compassSprites=Cx.map((n,s)=>{const r=t[s],a=new zs({map:f3(r),depthTest:!1,fog:!1}),o=new _r(a),{x:l,y:c,z:h}=Qi(0,n,Dx);return o.position.set(l,c,h),o.scale.set(au,au,1),o.renderOrder=Lx,o.visible=this.compassHovered||this.compassForced,this.celestialGroup.add(o),o})}disposeCompassLabels(){for(const e of this.compassSprites)e.removeFromParent(),e.material.map?.dispose(),e.material.dispose();this.compassSprites=[]}disposeStarTiers(){for(const e of this.starTiers)this.disposeMesh(e.points);this.starTiers=[]}disposeMesh(e){if(!e)return;e.removeFromParent(),"geometry"in e&&e.geometry.dispose();const t=e.material;for(const n of Array.isArray(t)?t:[t]){const s=n.map;s&&s.dispose(),n.dispose()}}}const Ln=Math.PI/180;function Y0(i,e,t){return Math.max(e,Math.min(t,i))}function Wr(i,e){return i+Math.random()*(e-i)}function Xr(i,e){return(i%(e*2)+e*3)%(e*2)-e}let qr,Yr;function i3(i){switch(i){case"snow":return s3();case"hail":return r3()}}function s3(){if(qr)return qr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0.95)"),n.addColorStop(.5,"rgba(255,255,255,0.55)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),qr=new Vn(e),qr}function r3(){if(Yr)return Yr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.55,"rgba(255,255,255,0.95)"),n.addColorStop(.8,"rgba(255,255,255,0.4)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Yr=new Vn(e),Yr}let Zr;function a3(){if(Zr)return Zr;const i=64,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,0)"),n.addColorStop(.4,"rgba(255,255,255,0)"),n.addColorStop(.6,"rgba(255,255,255,0.9)"),n.addColorStop(.8,"rgba(255,255,255,0.25)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),Zr=new Vn(e),Zr}const o3=`
|
|
5036
5036
|
uniform float uMaxSize;
|
|
5037
5037
|
uniform float uScale;
|
|
5038
5038
|
attribute float aLife;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rr0/ufoathome",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.2",
|
|
5
5
|
"description": "UFO@home — record and replay a UFO sighting's shape, movement and appearance",
|
|
6
6
|
"author": "Jérôme Beau <rr0@rr0.org> (https://rr0.org)",
|
|
7
7
|
"license": "MIT",
|