This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
qplanets.js/lib/qplanets.js

1 line
13 KiB
JavaScript

!function(e){var t={};function n(a){if(t[a])return t[a].exports;var r=t[a]={i:a,l:!1,exports:{}};return e[a].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,a){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(a,r,function(t){return e[t]}.bind(null,r));return a},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){THREE.Extras=THREE.Extras||{},THREE.Extras.Planet={};const a=n(1),r=n(2);class o{static _compose(e,t,n,a,r){const i=new THREE.ShaderMaterial({uniforms:{},vertexShader:n,fragmentShader:a});return o.scatterUniforms(i,e,t,r),i}static newAtmosphere(e,t,n){const r=o._compose(e,t,a.vertexUniforms+a.vertexFunctions+a.vertexAtmosphere,a.fragmentAtmosphere,n);return r.side=THREE.BackSide,r.transparent=!0,r}static newAttenuate(e,t,n){return o._compose(e,t,a.vertexUniforms+a.vertexFunctions+a.vertexGround,a.fragmentGround,n)}static scatterUniforms(e,t,n,a={}){const r=a.Kr||.0025,o=a.Km||.0015,i=a.ESun||15,l=a.scale||1/(n-t),s=a.scaleDepth||.25,f=a.g||-.95,h=a.wavelength||[.65,.57,.475];e.uniforms.invWavelength={value:[1/Math.pow(h[0],4),1/Math.pow(h[1],4),1/Math.pow(h[2],4)],type:"v3"},e.uniforms.outerRadius={value:n,type:"f"},e.uniforms.innerRadius={value:t,type:"f"},e.uniforms.Kr={value:r,type:"f"},e.uniforms.Km={value:o,type:"f"},e.uniforms.ESun={value:i,type:"f"},e.uniforms.scale={value:l,type:"f"},e.uniforms.scaleDepth={value:s,type:"f"},e.uniforms.g={value:f,type:"f"}}}for(const e in r)THREE.Extras.Planet[e]=r[e];THREE.Extras.Planet.ScatterShader=o,e.exports=THREE.Extras.Planet},function(e,t){const n={vertexUniforms:"\n#define M_PI 3.1415926535897932384626433832795\nuniform vec3 planetPosition; // Position of the planet\nuniform vec3 lightDirection; // The direction vector to the light source\nuniform vec3 invWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels\nuniform float outerRadius; // The outer (atmosphere) radius\nuniform float innerRadius; // The inner (planetary) radius\nuniform float ESun; // ESun\nuniform float Km; // Km\nuniform float Kr; // Kr\nuniform float scale; // 1 / (outerRadius - innerRadius)\nuniform float scaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)\n\nconst int nSamples = 2;\nconst float fSamples = 1.0;\n\nvarying vec3 v3Direction;\nvarying vec3 c0;\nvarying vec3 c1;\n ",vertexFunctions:"\nfloat dscale(float fCos) {\n float x = 1.0 - fCos;\n return scaleDepth * exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25))));\n}\n\nfloat calculateNearScatter(vec3 v3CameraPosition, vec3 v3Ray, float fCameraHeight, float fOuterRadius) {\n float B = 2.0 * dot(v3CameraPosition, v3Ray);\n float C = pow(fCameraHeight, 2.0) - pow(fOuterRadius, 2.0);\n float fDet = max(0.0, B * B - 4.0 * C);\n return 0.5 * (-B - sqrt(fDet));\n}\n ",vertexAtmosphere:"\nvoid main(void) {\n // Initialize variables\n float cameraHeight = length(planetPosition - cameraPosition);\n float KmESun = Km * ESun;\n float KrESun = Kr * ESun;\n float Kr4PI = Kr * 4.0 * M_PI;\n float Km4PI = Km * 4.0 * M_PI;\n float scaleOverScaleDepth = scale / scaleDepth;\n\n // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\n vec3 v3Ray = position - cameraPosition;\n float fFar = length(v3Ray);\n v3Ray /= fFar;\n\n vec3 v3Start;\n float fStartAngle;\n float fStartDepth;\n float fStartOffset;\n\n if (cameraHeight > outerRadius) {\n // Sky from space\n // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)\n float fNear = calculateNearScatter(cameraPosition, v3Ray, cameraHeight, outerRadius);\n\n // Calculate the ray's starting position, then calculate its scattering offset\n v3Start = cameraPosition + v3Ray * fNear;\n fFar -= fNear;\n fStartAngle = dot(v3Ray, v3Start) / outerRadius;\n fStartDepth = exp(-1.0 / scaleDepth);\n fStartOffset = fStartDepth * dscale(fStartAngle);\n } else {\n // Sky from within the atmosphere\n v3Start = cameraPosition;\n fStartDepth = exp(scaleOverScaleDepth * (innerRadius - cameraHeight));\n fStartAngle = dot(v3Ray, v3Start) / length(v3Start);\n fStartOffset = fStartDepth * dscale(fStartAngle);\n }\n\n // Initialize the scattering loop variables\n float fSampleLength = fFar / fSamples;\n float scaledLength = fSampleLength * scale;\n vec3 v3SampleRay = v3Ray * fSampleLength;\n vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;\n\n // Now loop through the sample rays\n vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);\n for(int i=0; i<nSamples; i++)\n {\n float fHeight = length(v3SamplePoint);\n float fDepth = exp(scaleOverScaleDepth * (innerRadius - fHeight));\n float fLightAngle = dot(lightDirection, v3SamplePoint) / fHeight;\n float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;\n float fScatter = (fStartOffset + fDepth * (dscale(fLightAngle) - dscale(fCameraAngle)));\n vec3 v3Attenuate = exp(-fScatter * (invWavelength * Kr4PI + Km4PI));\n v3FrontColor += v3Attenuate * (fDepth * scaledLength);\n v3SamplePoint += v3SampleRay;\n }\n\n // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1);\n c0 = v3FrontColor * (invWavelength * KrESun);\n c1 = v3FrontColor * KmESun;\n v3Direction = cameraPosition - position;\n}\n ",vertexGround:"\nvoid main(void) {\n // Initialize variables\n float cameraHeight = length(planetPosition - cameraPosition);\n float KmESun = Km * ESun;\n float KrESun = Kr * ESun;\n float Kr4PI = Kr * 4.0 * M_PI;\n float Km4PI = Km * 4.0 * M_PI;\n float scaleOverScaleDepth = scale / scaleDepth;\n\n // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\n vec3 v3Ray = position - cameraPosition;\n float fFar = length(v3Ray);\n v3Ray /= fFar;\n\n // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)\n float fNear = calculateNearScatter(cameraPosition, v3Ray, cameraHeight, outerRadius);\n\n // Calculate the ray's starting position, then calculate its scattering offset\n vec3 v3Start = cameraPosition + v3Ray * fNear;\n fFar -= fNear;\n float fDepth = exp((innerRadius - outerRadius) / scaleDepth);\n float fCameraAngle = dot(-v3Ray, position) / length(position);\n float fLightAngle = dot(lightDirection, position) / length(position);\n\n float fCameraScale = dscale(fCameraAngle);\n float fLightScale = dscale(fLightAngle);\n float fCameraOffset = fDepth*fCameraScale;\n float fTemp = (fLightScale + fCameraScale);\n\n // Initialize the scattering loop variables\n float fSampleLength = fFar / fSamples;\n float fScaledLength = fSampleLength * scale;\n vec3 v3SampleRay = v3Ray * fSampleLength;\n vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;\n\n // Now loop through the sample rays\n vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);\n vec3 v3Attenuate;\n for(int i=0; i<nSamples; i++)\n {\n float fHeight = length(v3SamplePoint);\n float fDepth = exp(scaleOverScaleDepth * (innerRadius - fHeight));\n float fScatter = fDepth*fTemp - fCameraOffset;\n v3Attenuate = exp(-fScatter * (invWavelength * Kr4PI + Km4PI));\n v3FrontColor += v3Attenuate * (fDepth * fScaledLength);\n v3SamplePoint += v3SampleRay;\n }\n\n // Calculate the attenuation factor for the ground\n c0 = v3Attenuate;\n c1 = v3FrontColor * (invWavelength * KrESun + KmESun);\n\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position,1);\n}\n ",fragmentAtmosphere:"\nuniform vec3 lightDirection;\nuniform float g;\n\nvarying vec3 v3Direction;\nvarying vec3 c0;\nvarying vec3 c1;\n\n// Calculates the Mie phase function\nfloat getMiePhase(float fCos, float fCos2, float g, float g2){\n return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0 * g * fCos, 1.5);\n}\n\n// Calculates the Rayleigh phase function\nfloat getRayleighPhase(float fCos2) {\n // return 0.75 + 0.75 * fCos2;\n return 0.75 * (2.0 + 0.5 * fCos2);\n}\n\nvoid main (void) {\n float fCos = dot(lightDirection, v3Direction) / length(v3Direction);\n float fCos2 = fCos * fCos;\n vec3 color = getRayleighPhase(fCos2) * c0 +\n getMiePhase(fCos, fCos2, g, pow(g, 2.0)) * c1;\n gl_FragColor = vec4(color, 1.0);\n gl_FragColor.a = gl_FragColor.b;\n}\n ",fragmentGround:"\nuniform vec3 color;\n\nvarying vec3 c0;\nvarying vec3 c1;\n\nvoid main (void) {\n gl_FragColor = vec4(c1, 1.0) + vec4(color * c0, 1.0);\n}\n "};e.exports=n},function(e,t){const n=new THREE.BufferGeometry;class a{constructor(e=!1,t=!1,n=!1,a=!1){const r=[];for(let o=0;o<14;o++){let i=o%2==0;for(let l=0;l<14;l++){const s=15*o+l,f=s+1,h=15*(o+1)+l,c=h+1;let u=i?[s,h,c]:[s,h,f],p=i?[s,c,f]:[h,c,f];e&&0===o&&(l%2==0?p=[s,c,f+1]:u=null),t&&13===l&&(p=o%2==0?[f,h,c+15]:null),a&&13===o&&(l%2==0?p=[h,c+1,f]:u=null),n&&0===l&&(u=o%2==0?[s,h+15,c]:null),u&&r.push(u[0],u[1],u[2]),p&&r.push(p[0],p[1],p[2]),i=!i}}this.length=r.length,this.indices=new THREE.Uint16BufferAttribute(r,1)}}const r={base:new a,fixT:new a(!0,!1,!1,!1),fixTR:new a(!0,!0,!1,!1),fixTL:new a(!0,!1,!0,!1),fixB:new a(!1,!1,!1,!0),fixBR:new a(!1,!0,!1,!0),fixBL:new a(!1,!1,!0,!0),fixR:new a(!1,!0,!1,!1),fixL:new a(!1,!1,!0,!1)};class o extends THREE.BufferGeometry{constructor(e){super();const t=[],n=[],a=[],o=e.root.generator.radius,i=Math.pow(2,e.level);for(let r=0,l=0;r<15;r++)for(let s=0;s<15;s++,l++){const f=r/14,h=s/14,c=e.left.clone().multiplyScalar(f).multiplyScalar(o).divideScalar(i),u=e.forward.clone().multiplyScalar(h).multiplyScalar(o).divideScalar(i),p=e.relPos.clone().add(c.add(u)).normalize(),v=e.root.generator.getHeight(p),d=p.clone().multiplyScalar(10*v+o);t[3*l]=d.x,t[3*l+1]=d.y,t[3*l+2]=d.z,n[3*l]=p.x,n[3*l+1]=p.y,n[3*l+2]=p.z,a[2*l]=r*(1/15),a[2*l+1]=s*(1/15),r===Math.floor(7.5)&&s===Math.floor(7.5)&&(e.center=d)}this.setIndex(r.base.indices),this.setAttribute("position",new THREE.Float32BufferAttribute(t,3)),this.setAttribute("normal",new THREE.Float32BufferAttribute(n,3)),this.setAttribute("uv",new THREE.Float32BufferAttribute(a,3))}}class i extends THREE.Mesh{constructor(e,t,n,a,r){super(),this.root=e,this.index=t,this.level=n,this.relPos=a,this.normal=r,this.left=new THREE.Vector3(r.y,r.z,r.x),this.forward=r.clone().cross(this.left),0===n&&(this.relPos.sub(this.left.clone().multiplyScalar(e.generator.radius/2)),this.relPos.sub(this.forward.clone().multiplyScalar(e.generator.radius/2))),e.material&&(this.material=e.material),this.generated=!1,this.generate()}generate(){this.generated||(this.geometry=new o(this),this.generated=!0)}isLeaf(){return!this.children.length}merge(){if(!this.isLeaf()){for(const e in this.children){const t=this.children[e];t.merge(),t.dispose()}this.children=[],this.generate()}}subdivide(){if(this.level===(this.root.generator.maxLOD||8))return;const e=this.level+1,t=this.left.clone().multiplyScalar(this.root.generator.radius/Math.pow(2,e)),n=this.forward.clone().multiplyScalar(this.root.generator.radius/Math.pow(2,e));this.add(new i(this.root,0,e,this.relPos.clone(),this.normal)),this.add(new i(this.root,1,e,this.relPos.clone().add(n),this.normal)),this.add(new i(this.root,2,e,this.relPos.clone().add(t.clone().add(n)),this.normal)),this.add(new i(this.root,3,e,this.relPos.clone().add(t),this.normal)),this.dispose()}dispose(){this.generated&&(this.geometry.dispose(),this.geometry=n,this.generated=!1)}setMaterial(e){this.material=e;for(const t in this.children)this.children[t].setMaterial(e)}update(e,t){if(!this.center)return;const n=e.position.clone().distanceTo(this.center),a=Math.pow(2,this.level),r=this.root.generator.radius/a;if(n<5*r&&0===this.children.length)this.subdivide();else if(n>5.5*r&&this.children.length>0)this.merge();else if(this.children.length>0)for(const n in this.children)this.children[n].update(e,t)}}class l extends THREE.Object3D{constructor(e,t){super(),this.position.copy(e),this.generator=t,this.radius=t.radius;const n=t.radius/2;this.add(new i(this,0,0,new THREE.Vector3(0,0,-n),new THREE.Vector3(0,0,-1))),this.add(new i(this,1,0,new THREE.Vector3(0,0,n),new THREE.Vector3(0,0,1))),this.add(new i(this,2,0,new THREE.Vector3(-n,0,0),new THREE.Vector3(-1,0,0))),this.add(new i(this,3,0,new THREE.Vector3(n,0,0),new THREE.Vector3(1,0,0))),this.add(new i(this,4,0,new THREE.Vector3(0,n,0),new THREE.Vector3(0,1,0))),this.add(new i(this,5,0,new THREE.Vector3(0,-n,0),new THREE.Vector3(0,-1,0)))}update(e,t){for(const n in this.children)this.children[n].update(e,t)}setMaterial(e){this.material=e;for(const t in this.children)this.children[t].setMaterial(e)}}e.exports={PlanetGenerator:class{constructor(e){this.radius=e}getHeight(e){return 0}getBiome(e){return 0}},CubePlanet:l,CubePlanetNode:i}}]);