itowns 2.45.1-next.0 → 2.45.1-next.1
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.
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/debug.js +3 -0
- package/dist/debug.js.LICENSE.txt +13 -0
- package/dist/debug.js.map +1 -0
- package/dist/itowns.js +3 -0
- package/dist/itowns.js.LICENSE.txt +5 -0
- package/dist/itowns.js.map +1 -0
- package/dist/itowns_lasparser.js +2 -0
- package/dist/itowns_lasparser.js.map +1 -0
- package/dist/itowns_lasworker.js +2 -0
- package/dist/itowns_lasworker.js.map +1 -0
- package/dist/itowns_potree2worker.js +2 -0
- package/dist/itowns_potree2worker.js.map +1 -0
- package/dist/itowns_widgets.js +2 -0
- package/dist/itowns_widgets.js.map +1 -0
- package/lib/Controls/FirstPersonControls.js +308 -0
- package/lib/Controls/FlyControls.js +175 -0
- package/lib/Controls/GlobeControls.js +1178 -0
- package/lib/Controls/PlanarControls.js +1025 -0
- package/lib/Controls/StateControl.js +432 -0
- package/lib/Controls/StreetControls.js +392 -0
- package/lib/Converter/Feature2Mesh.js +612 -0
- package/lib/Converter/Feature2Texture.js +174 -0
- package/lib/Converter/convertToTile.js +70 -0
- package/lib/Converter/textureConverter.js +43 -0
- package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
- package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
- package/lib/Core/3DTiles/C3DTFeature.js +110 -0
- package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
- package/lib/Core/3DTiles/C3DTileset.js +99 -0
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
- package/lib/Core/AnimationPlayer.js +142 -0
- package/lib/Core/CopcNode.js +174 -0
- package/lib/Core/Deprecated/Undeprecator.js +74 -0
- package/lib/Core/EntwinePointTileNode.js +126 -0
- package/lib/Core/Feature.js +488 -0
- package/lib/Core/Geographic/GeoidGrid.js +108 -0
- package/lib/Core/Label.js +222 -0
- package/lib/Core/MainLoop.js +209 -0
- package/lib/Core/Picking.js +255 -0
- package/lib/Core/PointCloudNode.js +42 -0
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/PotreeNode.js +101 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
- package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
- package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
- package/lib/Core/Prefab/GlobeView.js +155 -0
- package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
- package/lib/Core/Prefab/PlanarView.js +62 -0
- package/lib/Core/Prefab/TileBuilder.js +82 -0
- package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
- package/lib/Core/Scheduler/Cache.js +17 -0
- package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
- package/lib/Core/Scheduler/Scheduler.js +294 -0
- package/lib/Core/Style.js +660 -0
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/System/Capabilities.js +63 -0
- package/lib/Core/Tile/Tile.js +205 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +124 -0
- package/lib/Core/TileMesh.js +108 -0
- package/lib/Core/View.js +1115 -0
- package/lib/Layer/C3DTilesLayer.js +459 -0
- package/lib/Layer/ColorLayer.js +154 -0
- package/lib/Layer/CopcLayer.js +63 -0
- package/lib/Layer/ElevationLayer.js +139 -0
- package/lib/Layer/EntwinePointTileLayer.js +71 -0
- package/lib/Layer/FeatureGeometryLayer.js +77 -0
- package/lib/Layer/GeoidLayer.js +80 -0
- package/lib/Layer/GeometryLayer.js +233 -0
- package/lib/Layer/InfoLayer.js +64 -0
- package/lib/Layer/LabelLayer.js +469 -0
- package/lib/Layer/Layer.js +335 -0
- package/lib/Layer/LayerUpdateState.js +89 -0
- package/lib/Layer/LayerUpdateStrategy.js +80 -0
- package/lib/Layer/OGC3DTilesLayer.js +543 -0
- package/lib/Layer/OrientedImageLayer.js +227 -0
- package/lib/Layer/PointCloudLayer.js +405 -0
- package/lib/Layer/Potree2Layer.js +171 -0
- package/lib/Layer/PotreeLayer.js +72 -0
- package/lib/Layer/RasterLayer.js +37 -0
- package/lib/Layer/ReferencingLayerProperties.js +62 -0
- package/lib/Layer/TiledGeometryLayer.js +459 -0
- package/lib/Loader/LASLoader.js +193 -0
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +113 -0
- package/lib/MainBundle.js +4 -0
- package/lib/Parser/B3dmParser.js +174 -0
- package/lib/Parser/CameraCalibrationParser.js +94 -0
- package/lib/Parser/GDFParser.js +72 -0
- package/lib/Parser/GTXParser.js +75 -0
- package/lib/Parser/GeoJsonParser.js +212 -0
- package/lib/Parser/GpxParser.js +25 -0
- package/lib/Parser/ISGParser.js +71 -0
- package/lib/Parser/KMLParser.js +25 -0
- package/lib/Parser/LASParser.js +137 -0
- package/lib/Parser/MapBoxUrlParser.js +83 -0
- package/lib/Parser/PntsParser.js +131 -0
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/PotreeBinParser.js +106 -0
- package/lib/Parser/PotreeCinParser.js +29 -0
- package/lib/Parser/ShapefileParser.js +78 -0
- package/lib/Parser/VectorTileParser.js +215 -0
- package/lib/Parser/XbilParser.js +120 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
- package/lib/Parser/iGLTFLoader.js +168 -0
- package/lib/Process/3dTilesProcessing.js +304 -0
- package/lib/Process/FeatureProcessing.js +76 -0
- package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
- package/lib/Process/ObjectRemovalHelper.js +97 -0
- package/lib/Process/handlerNodeError.js +23 -0
- package/lib/Provider/3dTilesProvider.js +149 -0
- package/lib/Provider/DataSourceProvider.js +24 -0
- package/lib/Provider/Fetcher.js +233 -0
- package/lib/Provider/PointCloudProvider.js +45 -0
- package/lib/Provider/TileProvider.js +16 -0
- package/lib/Provider/URLBuilder.js +116 -0
- package/lib/Renderer/Camera.js +281 -0
- package/lib/Renderer/Color.js +56 -0
- package/lib/Renderer/ColorLayersOrdering.js +115 -0
- package/lib/Renderer/CommonMaterial.js +31 -0
- package/lib/Renderer/Label2DRenderer.js +192 -0
- package/lib/Renderer/LayeredMaterial.js +243 -0
- package/lib/Renderer/OBB.js +150 -0
- package/lib/Renderer/OrientedImageCamera.js +118 -0
- package/lib/Renderer/OrientedImageMaterial.js +167 -0
- package/lib/Renderer/PointsMaterial.js +485 -0
- package/lib/Renderer/RasterTile.js +243 -0
- package/lib/Renderer/RenderMode.js +31 -0
- package/lib/Renderer/Shader/ShaderChunk.js +160 -0
- package/lib/Renderer/Shader/ShaderUtils.js +47 -0
- package/lib/Renderer/SphereHelper.js +17 -0
- package/lib/Renderer/WebXR.js +51 -0
- package/lib/Renderer/c3DEngine.js +214 -0
- package/lib/Source/C3DTilesGoogleSource.js +74 -0
- package/lib/Source/C3DTilesIonSource.js +54 -0
- package/lib/Source/C3DTilesSource.js +30 -0
- package/lib/Source/CopcSource.js +126 -0
- package/lib/Source/EntwinePointTileSource.js +72 -0
- package/lib/Source/FileSource.js +188 -0
- package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
- package/lib/Source/OGC3DTilesIonSource.js +34 -0
- package/lib/Source/OGC3DTilesSource.js +21 -0
- package/lib/Source/OrientedImageSource.js +59 -0
- package/lib/Source/Potree2Source.js +167 -0
- package/lib/Source/PotreeSource.js +82 -0
- package/lib/Source/Source.js +202 -0
- package/lib/Source/TMSSource.js +144 -0
- package/lib/Source/VectorTilesSource.js +182 -0
- package/lib/Source/WFSSource.js +170 -0
- package/lib/Source/WMSSource.js +167 -0
- package/lib/Source/WMTSSource.js +92 -0
- package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
- package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
- package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
- package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
- package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
- package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
- package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
- package/lib/Utils/CameraUtils.js +554 -0
- package/lib/Utils/DEMUtils.js +350 -0
- package/lib/Utils/FeaturesUtils.js +156 -0
- package/lib/Utils/Gradients.js +16 -0
- package/lib/Utils/ThreeUtils.js +115 -0
- package/lib/Utils/gui/C3DTilesStyle.js +218 -0
- package/lib/Utils/gui/Main.js +7 -0
- package/lib/Utils/gui/Minimap.js +152 -0
- package/lib/Utils/gui/Navigation.js +245 -0
- package/lib/Utils/gui/Scale.js +104 -0
- package/lib/Utils/gui/Searchbar.js +234 -0
- package/lib/Utils/gui/Widget.js +80 -0
- package/lib/Utils/placeObjectOnGround.js +136 -0
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- package/package.json +2 -2
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import GeometryLayer from "../../../Layer/GeometryLayer.js";
|
|
3
|
+
import { Coordinates, ellipsoidSizes, CoordStars } from '@itowns/geographic';
|
|
4
|
+
import Sky from "./SkyShader.js";
|
|
5
|
+
/* babel-plugin-inline-import './Shaders/skyFS.glsl' */
|
|
6
|
+
const skyFS = "uniform vec3 v3LightPos;\nuniform float g;\nuniform float g2;\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}\n\nvoid main (void) {\n float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);\n float fCos2 = fCos * fCos;\n\n vec3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1;\n\n gl_FragColor = vec4(color, 1.0);\n gl_FragColor.a = gl_FragColor.b;\n}";
|
|
7
|
+
/* babel-plugin-inline-import './Shaders/skyVS.glsl' */
|
|
8
|
+
const skyVS = "uniform vec3 v3LightPosition; // The direction vector to the light source\nuniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels\nuniform float fCameraHeight; // The camera's current height\nuniform float fCameraHeight2; // fCameraHeight^2\nuniform float fOuterRadius; // The outer (atmosphere) radius\nuniform float fOuterRadius2; // fOuterRadius^2\nuniform float fInnerRadius; // The inner (planetary) radius\nuniform float fInnerRadius2; // fInnerRadius^2\nuniform float fKrESun; // Kr * ESun\nuniform float fKmESun; // Km * ESun\nuniform float fKr4PI; // Kr * 4 * PI\nuniform float fKm4PI; // Km * 4 * PI\nuniform float fScale; // 1 / (fOuterRadius - fInnerRadius)\nuniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)\nuniform float fScaleOverScaleDepth; // fScale / fScaleDepth\n\nconst int nSamples = 3;\nconst float fSamples = 3.0;\n\nvarying vec3 v3Direction;\nvarying vec3 c0;\nvarying vec3 c1;\n\nfloat scale(float fCos) {\n float x = 1.0 - fCos;\n return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\n}\n\nvoid main(void) {\n float lengthCamera = length(cameraPosition);\n float cameraHeight2 = lengthCamera * lengthCamera;\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 B = 2.0 * dot(cameraPosition, v3Ray);\n float C = cameraHeight2 - fOuterRadius2;\n float fDet = max(0.0, B*B - 4.0 * C);\n float fNear = 0.5 * (-B - sqrt(fDet));\n\n // Calculate the ray's starting position, then calculate its scattering offset\n vec3 v3Start = cameraPosition + v3Ray * fNear;\n fFar -= fNear;\n float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;\n float fStartDepth = exp(-1.0 / fScaleDepth);\n float fStartOffset = fStartDepth * scale(fStartAngle);\n\n // Initialize the scattering loop variables\n float fSampleLength = fFar / fSamples;\n float fScaledLength = fSampleLength * fScale;\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(fScaleOverScaleDepth * (fInnerRadius - fHeight));\n float fLightAngle = dot(v3LightPosition, v3SamplePoint) / fHeight;\n float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;\n float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));\n vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));\n\n v3FrontColor += v3Attenuate * (fDepth * fScaledLength);\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 * modelViewMatrix * vec4( position, 1.0 );\n c0 = v3FrontColor * (v3InvWavelength * fKrESun);\n c1 = v3FrontColor * fKmESun;\n v3Direction = cameraPosition - position;\n}";
|
|
9
|
+
/* babel-plugin-inline-import './Shaders/groundFS.glsl' */
|
|
10
|
+
const groundFS = "varying vec3 c0;\nvarying vec3 c1;\n\nvoid main (void) {\n\tgl_FragColor = vec4(c1, 1.0 - c0/4.);\n}";
|
|
11
|
+
/* babel-plugin-inline-import './Shaders/groundVS.glsl' */
|
|
12
|
+
const groundVS = "uniform vec3 v3LightPosition; // The direction vector to the light source\nuniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels\nuniform float fCameraHeight; // The camera's current height\nuniform float fCameraHeight2; // fCameraHeight^2\nuniform float fOuterRadius; // The outer (atmosphere) radius\nuniform float fOuterRadius2; // fOuterRadius^2\nuniform float fInnerRadius; // The inner (planetary) radius\nuniform float fInnerRadius2; // fInnerRadius^2\nuniform float fKrESun; // Kr * ESun\nuniform float fKmESun; // Km * ESun\nuniform float fKr4PI; // Kr * 4 * PI\nuniform float fKm4PI; // Km * 4 * PI\nuniform float fScale; // 1 / (fOuterRadius - fInnerRadius)\nuniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)\nuniform float fScaleOverScaleDepth; // fScale / fScaleDepth\n\nvarying vec3 c0;\nvarying vec3 c1;\n\nconst int nSamples = 3;\nconst float fSamples = 3.0;\n\nfloat scale(float fCos)\n{\n float x = 1.0 - fCos;\n return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\n}\n\nvoid main(void) {\n\n float cameraHeight2 = length(cameraPosition) * length(cameraPosition);\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 B = 2.0 * dot(cameraPosition, v3Ray);\n float C = cameraHeight2 - fOuterRadius2;\n float fDet = max(0.0, B*B - 4.0 * C);\n float fNear = 0.5 * (-B - sqrt(fDet));\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((fInnerRadius - fOuterRadius) / fScaleDepth);\n float fCameraAngle = dot(-v3Ray, position) / length(position);\n float fLightAngle = dot(v3LightPosition, position) / length(position);\n float fCameraScale = scale(fCameraAngle);\n float fLightScale = scale(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 * fScale;\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 = 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(fScaleOverScaleDepth * (fInnerRadius - fHeight));\n float fScatter = fDepth*fTemp - fCameraOffset;\n v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));\n v3FrontColor += v3Attenuate * (fDepth * fScaledLength);\n v3SamplePoint += v3SampleRay;\n }\n\n // Calculate the attenuation factor for the ground\n c0 = v3Attenuate;\n c1 = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun);\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
|
|
13
|
+
/* babel-plugin-inline-import './Shaders/GlowFS.glsl' */
|
|
14
|
+
const GlowFS = "#include <logdepthbuf_pars_fragment>\n\nuniform int atmoIN;\nvarying float intensity;\n\nvec4 glowColor = vec4(0.45, 0.74, 1. ,1.0);\n\nvoid main() {\n #include <logdepthbuf_fragment>\n gl_FragColor = glowColor * intensity;\n}\n\n";
|
|
15
|
+
/* babel-plugin-inline-import './Shaders/GlowVS.glsl' */
|
|
16
|
+
const GlowVS = "#include <common>\n#include <logdepthbuf_pars_vertex>\n\nuniform int atmoIN;\nvarying float intensity;\n\nvoid main()\n{\n vec3 normalES = normalize( normalMatrix * normal );\n vec3 normalCAMES = normalize( normalMatrix * cameraPosition );\n\n if(atmoIN == 0) {\n intensity = pow(0.666 - dot(normalES, normalCAMES), 4. );\n } else {\n intensity = pow( 1. - dot(normalES, normalCAMES), 0.8 );\n }\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n #include <logdepthbuf_vertex>\n}\n\n\n";
|
|
17
|
+
const LIGHTING_POSITION = new THREE.Vector3(1, 0, 0);
|
|
18
|
+
const v = new THREE.Vector3();
|
|
19
|
+
const coordCam = new Coordinates('EPSG:4326');
|
|
20
|
+
const coordGeoCam = new Coordinates('EPSG:4326');
|
|
21
|
+
const skyBaseColor = new THREE.Color(0x93d5f8);
|
|
22
|
+
const colorSky = new THREE.Color();
|
|
23
|
+
const spaceColor = new THREE.Color(0x030508);
|
|
24
|
+
const limitAlti = 600000;
|
|
25
|
+
const mfogDistance = ellipsoidSizes.x * 160.0;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @extends GeometryLayer
|
|
29
|
+
*/
|
|
30
|
+
class Atmosphere extends GeometryLayer {
|
|
31
|
+
/**
|
|
32
|
+
* It's layer to simulate Globe atmosphere.
|
|
33
|
+
* There's 2 modes : simple and realistic (atmospheric-scattering).
|
|
34
|
+
*
|
|
35
|
+
* The atmospheric-scattering it is taken from :
|
|
36
|
+
* * [Atmosphere Shader From Space (Atmospheric scattering)](http://stainlessbeer.weebly.com/planets-9-atmospheric-scattering.html)
|
|
37
|
+
* * [Accurate Atmospheric Scattering (NVIDIA GPU Gems 2)](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering).
|
|
38
|
+
*
|
|
39
|
+
* @param {string} id - The id of the layer Atmosphere.
|
|
40
|
+
* @param {Object} [options] - options layer.
|
|
41
|
+
* @param {number} [options.Kr] - `Kr` is the rayleigh scattering constant.
|
|
42
|
+
* @param {number} [options.Km] - `Km` is the Mie scattering constant.
|
|
43
|
+
* @param {number} [options.ESun] - `ESun` is the brightness of the sun.
|
|
44
|
+
* @param {number} [options.g] - constant `g` that affects the symmetry of the scattering.
|
|
45
|
+
* @param {number} [options.innerRadius] - The inner (planetary) radius
|
|
46
|
+
* @param {number} [options.outerRadius] - The outer (Atmosphere) radius
|
|
47
|
+
* @param {number[]} [options.wavelength] - The constant is the `wavelength` (or color) of light.
|
|
48
|
+
* @param {number} [options.scaleDepth] - The `scale depth` (i.e. the altitude at which the atmosphere's average density is found).
|
|
49
|
+
* @param {number} [options.mieScaleDepth] - not used.
|
|
50
|
+
*/
|
|
51
|
+
constructor() {
|
|
52
|
+
let id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'atmosphere';
|
|
53
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
54
|
+
options.source = false;
|
|
55
|
+
super(id, new THREE.Object3D(), options);
|
|
56
|
+
this.isAtmosphere = true;
|
|
57
|
+
const material = new THREE.ShaderMaterial({
|
|
58
|
+
uniforms: {
|
|
59
|
+
atmoIN: {
|
|
60
|
+
type: 'i',
|
|
61
|
+
value: 0
|
|
62
|
+
},
|
|
63
|
+
screenSize: {
|
|
64
|
+
type: 'v2',
|
|
65
|
+
value: new THREE.Vector2(window.innerWidth, window.innerHeight)
|
|
66
|
+
} // Should be updated on screen resize...
|
|
67
|
+
},
|
|
68
|
+
vertexShader: GlowVS,
|
|
69
|
+
fragmentShader: GlowFS,
|
|
70
|
+
side: THREE.BackSide,
|
|
71
|
+
blending: THREE.AdditiveBlending,
|
|
72
|
+
transparent: true,
|
|
73
|
+
wireframe: false
|
|
74
|
+
});
|
|
75
|
+
const sphereGeometry = new THREE.SphereGeometry(1, 64, 64);
|
|
76
|
+
const basicAtmosphereOut = new THREE.Mesh(sphereGeometry, material);
|
|
77
|
+
basicAtmosphereOut.scale.copy(ellipsoidSizes).multiplyScalar(1.14);
|
|
78
|
+
this.basicAtmosphere = new THREE.Object3D();
|
|
79
|
+
this.realisticAtmosphere = new THREE.Object3D();
|
|
80
|
+
this.realisticAtmosphere.visible = false;
|
|
81
|
+
this.object3d.add(this.basicAtmosphere);
|
|
82
|
+
this.object3d.add(this.realisticAtmosphere);
|
|
83
|
+
this.basicAtmosphere.add(basicAtmosphereOut);
|
|
84
|
+
const materialAtmoIn = new THREE.ShaderMaterial({
|
|
85
|
+
uniforms: {
|
|
86
|
+
atmoIN: {
|
|
87
|
+
type: 'i',
|
|
88
|
+
value: 1
|
|
89
|
+
},
|
|
90
|
+
screenSize: {
|
|
91
|
+
type: 'v2',
|
|
92
|
+
value: new THREE.Vector2(window.innerWidth, window.innerHeight)
|
|
93
|
+
} // Should be updated on screen resize...
|
|
94
|
+
},
|
|
95
|
+
vertexShader: GlowVS,
|
|
96
|
+
fragmentShader: GlowFS,
|
|
97
|
+
side: THREE.FrontSide,
|
|
98
|
+
blending: THREE.AdditiveBlending,
|
|
99
|
+
transparent: true,
|
|
100
|
+
depthWrite: false
|
|
101
|
+
});
|
|
102
|
+
const basicAtmosphereIn = new THREE.Mesh(sphereGeometry, materialAtmoIn);
|
|
103
|
+
basicAtmosphereIn.scale.copy(ellipsoidSizes).multiplyScalar(1.002);
|
|
104
|
+
this.basicAtmosphere.add(basicAtmosphereIn);
|
|
105
|
+
this.realisticLightingPosition = {
|
|
106
|
+
x: -0.5,
|
|
107
|
+
y: 0.0,
|
|
108
|
+
z: 1.0
|
|
109
|
+
};
|
|
110
|
+
this.fog = {
|
|
111
|
+
enable: true,
|
|
112
|
+
distance: mfogDistance
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Atmosphere Shader From Space (Atmospheric scattering)
|
|
116
|
+
// http://stainlessbeer.weebly.com/planets-9-atmospheric-scattering.html
|
|
117
|
+
// https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering
|
|
118
|
+
this.realisticAtmosphereInitParams = options.Kr ? options : {
|
|
119
|
+
Kr: 0.0025,
|
|
120
|
+
Km: 0.0015,
|
|
121
|
+
ESun: 20.0,
|
|
122
|
+
g: -0.950,
|
|
123
|
+
innerRadius: 6400000,
|
|
124
|
+
outerRadius: 6700000,
|
|
125
|
+
wavelength: [0.650, 0.570, 0.475],
|
|
126
|
+
scaleDepth: 0.25
|
|
127
|
+
// mieScaleDepth: 0.1,
|
|
128
|
+
};
|
|
129
|
+
this.object3d.updateMatrixWorld();
|
|
130
|
+
}
|
|
131
|
+
update(context, layer, node) {
|
|
132
|
+
// update uniforms
|
|
133
|
+
node.material.fogDistance = this.fog.distance;
|
|
134
|
+
node.material.lightingEnabled = this.realisticAtmosphere.visible;
|
|
135
|
+
node.material.lightPosition = this.realisticLightingPosition;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// eslint-disable-next-line no-unused-vars
|
|
139
|
+
preUpdate(context) {
|
|
140
|
+
const cameraPosition = context.view.camera3D.position;
|
|
141
|
+
if (this.fog.enable) {
|
|
142
|
+
v.setFromMatrixPosition(context.view.tileLayer.object3d.matrixWorld);
|
|
143
|
+
const len = v.distanceTo(cameraPosition);
|
|
144
|
+
// Compute fog distance, this function makes it possible to have a shorter distance
|
|
145
|
+
// when the camera approaches the ground
|
|
146
|
+
this.fog.distance = mfogDistance * ((len - ellipsoidSizes.x * 0.99) * 0.25 / ellipsoidSizes.x) ** 1.5;
|
|
147
|
+
} else {
|
|
148
|
+
this.fog.distance = 10e10;
|
|
149
|
+
}
|
|
150
|
+
const renderer = context.view.mainLoop.gfxEngine.renderer;
|
|
151
|
+
// get altitude camera
|
|
152
|
+
coordCam.crs = context.view.referenceCrs;
|
|
153
|
+
coordCam.setFromVector3(cameraPosition).as('EPSG:4326', coordGeoCam);
|
|
154
|
+
const altitude = coordGeoCam.altitude;
|
|
155
|
+
|
|
156
|
+
// If the camera altitude is below limitAlti,
|
|
157
|
+
// we interpolate between the sky color and the space color
|
|
158
|
+
if (altitude < limitAlti) {
|
|
159
|
+
colorSky.copy(spaceColor).lerp(skyBaseColor, (limitAlti - altitude) / limitAlti);
|
|
160
|
+
renderer.setClearColor(colorSky, renderer.getClearAlpha());
|
|
161
|
+
} else {
|
|
162
|
+
renderer.setClearColor(spaceColor, renderer.getClearAlpha());
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// default to non-realistic lightning
|
|
167
|
+
_initRealisticLighning() {
|
|
168
|
+
const atmosphere = this.realisticAtmosphereInitParams;
|
|
169
|
+
const uniformsAtmosphere = {
|
|
170
|
+
v3LightPosition: {
|
|
171
|
+
value: LIGHTING_POSITION.clone().normalize()
|
|
172
|
+
},
|
|
173
|
+
v3InvWavelength: {
|
|
174
|
+
value: new THREE.Vector3(1 / atmosphere.wavelength[0] ** 4, 1 / atmosphere.wavelength[1] ** 4, 1 / atmosphere.wavelength[2] ** 4)
|
|
175
|
+
},
|
|
176
|
+
fCameraHeight: {
|
|
177
|
+
value: 0.0
|
|
178
|
+
},
|
|
179
|
+
fCameraHeight2: {
|
|
180
|
+
value: 0.0
|
|
181
|
+
},
|
|
182
|
+
fInnerRadius: {
|
|
183
|
+
value: atmosphere.innerRadius
|
|
184
|
+
},
|
|
185
|
+
fInnerRadius2: {
|
|
186
|
+
value: atmosphere.innerRadius * atmosphere.innerRadius
|
|
187
|
+
},
|
|
188
|
+
fOuterRadius: {
|
|
189
|
+
value: atmosphere.outerRadius
|
|
190
|
+
},
|
|
191
|
+
fOuterRadius2: {
|
|
192
|
+
value: atmosphere.outerRadius * atmosphere.outerRadius
|
|
193
|
+
},
|
|
194
|
+
fKrESun: {
|
|
195
|
+
value: atmosphere.Kr * atmosphere.ESun
|
|
196
|
+
},
|
|
197
|
+
fKmESun: {
|
|
198
|
+
value: atmosphere.Km * atmosphere.ESun
|
|
199
|
+
},
|
|
200
|
+
fKr4PI: {
|
|
201
|
+
value: atmosphere.Kr * 4.0 * Math.PI
|
|
202
|
+
},
|
|
203
|
+
fKm4PI: {
|
|
204
|
+
value: atmosphere.Km * 4.0 * Math.PI
|
|
205
|
+
},
|
|
206
|
+
fScale: {
|
|
207
|
+
value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius)
|
|
208
|
+
},
|
|
209
|
+
fScaleDepth: {
|
|
210
|
+
value: atmosphere.scaleDepth
|
|
211
|
+
},
|
|
212
|
+
fScaleOverScaleDepth: {
|
|
213
|
+
value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) / atmosphere.scaleDepth
|
|
214
|
+
},
|
|
215
|
+
g: {
|
|
216
|
+
value: atmosphere.g
|
|
217
|
+
},
|
|
218
|
+
g2: {
|
|
219
|
+
value: atmosphere.g * atmosphere.g
|
|
220
|
+
},
|
|
221
|
+
nSamples: {
|
|
222
|
+
value: 3
|
|
223
|
+
},
|
|
224
|
+
fSamples: {
|
|
225
|
+
value: 3.0
|
|
226
|
+
},
|
|
227
|
+
tDisplacement: {
|
|
228
|
+
value: new THREE.Texture()
|
|
229
|
+
},
|
|
230
|
+
tSkyboxDiffuse: {
|
|
231
|
+
value: new THREE.Texture()
|
|
232
|
+
},
|
|
233
|
+
fNightScale: {
|
|
234
|
+
value: 1.0
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
const geometryAtmosphereIn = new THREE.SphereGeometry(atmosphere.innerRadius, 50, 50);
|
|
238
|
+
const materialAtmosphereIn = new THREE.ShaderMaterial({
|
|
239
|
+
uniforms: uniformsAtmosphere,
|
|
240
|
+
vertexShader: groundVS,
|
|
241
|
+
fragmentShader: groundFS,
|
|
242
|
+
blending: THREE.AdditiveBlending,
|
|
243
|
+
transparent: true,
|
|
244
|
+
depthTest: false,
|
|
245
|
+
depthWrite: false
|
|
246
|
+
});
|
|
247
|
+
const ground = new THREE.Mesh(geometryAtmosphereIn, materialAtmosphereIn);
|
|
248
|
+
const geometryAtmosphereOut = new THREE.SphereGeometry(atmosphere.outerRadius, 196, 196);
|
|
249
|
+
const materialAtmosphereOut = new THREE.ShaderMaterial({
|
|
250
|
+
uniforms: uniformsAtmosphere,
|
|
251
|
+
vertexShader: skyVS,
|
|
252
|
+
fragmentShader: skyFS,
|
|
253
|
+
transparent: true,
|
|
254
|
+
side: THREE.BackSide
|
|
255
|
+
});
|
|
256
|
+
const sky = new THREE.Mesh(geometryAtmosphereOut, materialAtmosphereOut);
|
|
257
|
+
const skyDome = new Sky();
|
|
258
|
+
skyDome.frustumCulled = false;
|
|
259
|
+
this.realisticAtmosphere.add(ground);
|
|
260
|
+
this.realisticAtmosphere.add(sky);
|
|
261
|
+
this.realisticAtmosphere.add(skyDome);
|
|
262
|
+
const effectController = {
|
|
263
|
+
turbidity: 10,
|
|
264
|
+
reileigh: 2,
|
|
265
|
+
mieCoefficient: 0.005,
|
|
266
|
+
mieDirectionalG: 0.8,
|
|
267
|
+
luminance: 1,
|
|
268
|
+
inclination: 0.49,
|
|
269
|
+
// elevation / inclination
|
|
270
|
+
azimuth: 0.25,
|
|
271
|
+
// Facing front,
|
|
272
|
+
sun: !true
|
|
273
|
+
};
|
|
274
|
+
skyDome.material.uniforms.turbidity.value = effectController.turbidity;
|
|
275
|
+
skyDome.material.uniforms.reileigh.value = effectController.reileigh;
|
|
276
|
+
skyDome.material.uniforms.luminance.value = effectController.luminance;
|
|
277
|
+
skyDome.material.uniforms.mieCoefficient.value = effectController.mieCoefficient;
|
|
278
|
+
skyDome.material.uniforms.mieDirectionalG.value = effectController.mieDirectionalG;
|
|
279
|
+
skyDome.material.uniforms.up.value = new THREE.Vector3(); // no more necessary, estimate normal from cam..
|
|
280
|
+
}
|
|
281
|
+
setRealisticOn(bool) {
|
|
282
|
+
if (bool) {
|
|
283
|
+
if (!this.realisticAtmosphere.children.length) {
|
|
284
|
+
this._initRealisticLighning();
|
|
285
|
+
}
|
|
286
|
+
this.realisticLightingPosition = CoordStars.getSunPositionInScene(new Date().getTime(), 48.85, 2.35).normalize();
|
|
287
|
+
this.realisticAtmosphere.children.forEach(obj => obj.material.uniforms.v3LightPosition.value.copy(this.realisticLightingPosition));
|
|
288
|
+
}
|
|
289
|
+
this.basicAtmosphere.visible = !bool;
|
|
290
|
+
this.realisticAtmosphere.visible = bool;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
export default Atmosphere;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
|
|
3
|
+
import { ellipsoidSizes } from '@itowns/geographic';
|
|
4
|
+
import { globalExtentTMS, schemeTiles } from "../../Tile/TileGrid.js";
|
|
5
|
+
import { GlobeTileBuilder } from "./GlobeTileBuilder.js";
|
|
6
|
+
|
|
7
|
+
// matrix to convert sphere to ellipsoid
|
|
8
|
+
const worldToScaledEllipsoid = new THREE.Matrix4();
|
|
9
|
+
// camera's position in worldToScaledEllipsoid system
|
|
10
|
+
const cameraPosition = new THREE.Vector3();
|
|
11
|
+
let magnitudeSquared = 0.0;
|
|
12
|
+
|
|
13
|
+
// vectors for operation purpose
|
|
14
|
+
const scaledHorizonCullingPoint = new THREE.Vector3();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @property {boolean} isGlobeLayer - Used to checkout whether this layer is a
|
|
18
|
+
* GlobeLayer. Default is true. You should not change this, as it is used
|
|
19
|
+
* internally for optimisation.
|
|
20
|
+
*
|
|
21
|
+
* @extends TiledGeometryLayer
|
|
22
|
+
*/
|
|
23
|
+
class GlobeLayer extends TiledGeometryLayer {
|
|
24
|
+
/**
|
|
25
|
+
* A {@link TiledGeometryLayer} to use with a {@link GlobeView}. It has
|
|
26
|
+
* specific method for updating and subdivising its grid.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} id - The id of the layer, that should be unique. It is
|
|
29
|
+
* not mandatory, but an error will be emitted if this layer is added a
|
|
30
|
+
* {@link View} that already has a layer going by that id.
|
|
31
|
+
* @param {THREE.Object3D} [object3d=THREE.Group] - The object3d used to
|
|
32
|
+
* contain the geometry of the TiledGeometryLayer. It is usually a
|
|
33
|
+
* `THREE.Group`, but it can be anything inheriting from a `THREE.Object3d`.
|
|
34
|
+
* @param {Object} [config] - Optional configuration, all elements in it
|
|
35
|
+
* will be merged as is in the layer. For example, if the configuration
|
|
36
|
+
* contains three elements `name, protocol, extent`, these elements will be
|
|
37
|
+
* available using `layer.name` or something else depending on the property
|
|
38
|
+
* name.
|
|
39
|
+
* @param {number} [config.minSubdivisionLevel=2] - Minimum subdivision
|
|
40
|
+
* level for this tiled layer.
|
|
41
|
+
* @param {number} [config.maxSubdivisionLevel=18] - Maximum subdivision
|
|
42
|
+
* level for this tiled layer.
|
|
43
|
+
* @param {number} [config.sseSubdivisionThreshold=1] - Threshold level for
|
|
44
|
+
* the SSE.
|
|
45
|
+
*
|
|
46
|
+
* @throws {Error} `object3d` must be a valid `THREE.Object3d`.
|
|
47
|
+
*/
|
|
48
|
+
constructor(id, object3d) {
|
|
49
|
+
let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
50
|
+
const {
|
|
51
|
+
minSubdivisionLevel = 2,
|
|
52
|
+
maxSubdivisionLevel = 19,
|
|
53
|
+
...tiledConfig
|
|
54
|
+
} = config;
|
|
55
|
+
|
|
56
|
+
// Configure tiles
|
|
57
|
+
const scheme = schemeTiles.get('EPSG:4326');
|
|
58
|
+
const schemeTile = globalExtentTMS.get('EPSG:4326').subdivisionByScheme(scheme);
|
|
59
|
+
|
|
60
|
+
// Supported tile matrix set for color/elevation layer
|
|
61
|
+
const tileMatrixSets = ['EPSG:4326', 'EPSG:3857'];
|
|
62
|
+
const uvCount = tileMatrixSets.length;
|
|
63
|
+
const builder = new GlobeTileBuilder({
|
|
64
|
+
uvCount
|
|
65
|
+
});
|
|
66
|
+
super(id, object3d || new THREE.Group(), schemeTile, builder, {
|
|
67
|
+
tileMatrixSets,
|
|
68
|
+
...tiledConfig
|
|
69
|
+
});
|
|
70
|
+
this.isGlobeLayer = true;
|
|
71
|
+
this.options.defaultPickingRadius = 5;
|
|
72
|
+
this.minSubdivisionLevel = minSubdivisionLevel;
|
|
73
|
+
this.maxSubdivisionLevel = maxSubdivisionLevel;
|
|
74
|
+
this.extent = this.schemeTile[0].clone();
|
|
75
|
+
for (let i = 1; i < this.schemeTile.length; i++) {
|
|
76
|
+
this.extent.union(this.schemeTile[i]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// We're going to use the method described here:
|
|
80
|
+
// https://cesiumjs.org/2013/04/25/Horizon-culling/
|
|
81
|
+
// This method assumes that the globe is a unit sphere at 0,0,0 so
|
|
82
|
+
// we setup a world-to-scaled-ellipsoid matrix4
|
|
83
|
+
worldToScaledEllipsoid.copy(this.object3d.matrixWorld).invert();
|
|
84
|
+
worldToScaledEllipsoid.premultiply(new THREE.Matrix4().makeScale(1 / ellipsoidSizes.x, 1 / ellipsoidSizes.y, 1 / ellipsoidSizes.z));
|
|
85
|
+
}
|
|
86
|
+
preUpdate(context, changeSources) {
|
|
87
|
+
// pre-horizon culling
|
|
88
|
+
cameraPosition.copy(context.camera.camera3D.position).applyMatrix4(worldToScaledEllipsoid);
|
|
89
|
+
magnitudeSquared = cameraPosition.lengthSq() - 1.0;
|
|
90
|
+
return super.preUpdate(context, changeSources);
|
|
91
|
+
}
|
|
92
|
+
countColorLayersTextures() {
|
|
93
|
+
let occupancy = 0;
|
|
94
|
+
for (var _len = arguments.length, layers = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
95
|
+
layers[_key] = arguments[_key];
|
|
96
|
+
}
|
|
97
|
+
for (const layer of layers) {
|
|
98
|
+
const crs = layer.crs || layer.source.crs;
|
|
99
|
+
// 'EPSG:3857' occupies the maximum 3 textures on tiles
|
|
100
|
+
// 'EPSG:4326' occupies 1 textures on tile
|
|
101
|
+
occupancy += crs == 'EPSG:3857' ? 3 : 1;
|
|
102
|
+
}
|
|
103
|
+
return occupancy;
|
|
104
|
+
}
|
|
105
|
+
subdivision(context, layer, node) {
|
|
106
|
+
if (node.level == 5) {
|
|
107
|
+
const row = node.getExtentsByProjection('EPSG:4326')[0].row;
|
|
108
|
+
if (row == 31 || row == 0) {
|
|
109
|
+
// doesn't subdivise the pole
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return super.subdivision(context, layer, node);
|
|
114
|
+
}
|
|
115
|
+
culling(node, camera) {
|
|
116
|
+
if (super.culling(node, camera)) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
if (node.level < this.minSubdivisionLevel) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
return GlobeLayer.horizonCulling(node.horizonCullingPointElevationScaled);
|
|
123
|
+
}
|
|
124
|
+
static horizonCulling(point) {
|
|
125
|
+
// see https://cesiumjs.org/2013/04/25/Horizon-culling/
|
|
126
|
+
scaledHorizonCullingPoint.copy(point).applyMatrix4(worldToScaledEllipsoid);
|
|
127
|
+
scaledHorizonCullingPoint.sub(cameraPosition);
|
|
128
|
+
const vtMagnitudeSquared = scaledHorizonCullingPoint.lengthSq();
|
|
129
|
+
const dot = -scaledHorizonCullingPoint.dot(cameraPosition);
|
|
130
|
+
const isOccluded = magnitudeSquared < 0 ? dot > 0 : magnitudeSquared < dot && magnitudeSquared < dot * dot / vtMagnitudeSquared;
|
|
131
|
+
return isOccluded;
|
|
132
|
+
}
|
|
133
|
+
computeTileZoomFromDistanceCamera(distance, camera) {
|
|
134
|
+
const preSinus = this.sizeDiagonalTexture * (this.sseSubdivisionThreshold * 0.5) / camera._preSSE / ellipsoidSizes.x;
|
|
135
|
+
let sinus = distance * preSinus;
|
|
136
|
+
let zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
|
|
137
|
+
const delta = Math.PI / 2 ** zoom;
|
|
138
|
+
const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
|
|
139
|
+
// adjust with bounding sphere rayon
|
|
140
|
+
sinus = (distance - circleChord * 0.5) * preSinus;
|
|
141
|
+
zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
|
|
142
|
+
return isNaN(zoom) ? 0 : Math.round(zoom);
|
|
143
|
+
}
|
|
144
|
+
computeDistanceCameraFromTileZoom(zoom, camera) {
|
|
145
|
+
const delta = Math.PI / 2 ** zoom;
|
|
146
|
+
const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
|
|
147
|
+
const radius = circleChord * 0.5;
|
|
148
|
+
const error = radius / this.sizeDiagonalTexture;
|
|
149
|
+
return camera._preSSE * error / (this.sseSubdivisionThreshold * 0.5) + radius;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export default GlobeLayer;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { Coordinates, Extent } from '@itowns/geographic';
|
|
3
|
+
const PI_OV_FOUR = Math.PI / 4;
|
|
4
|
+
const INV_TWO_PI = 1.0 / (Math.PI * 2);
|
|
5
|
+
const axisZ = new THREE.Vector3(0, 0, 1);
|
|
6
|
+
const axisY = new THREE.Vector3(0, 1, 0);
|
|
7
|
+
const quatToAlignLongitude = new THREE.Quaternion();
|
|
8
|
+
const quatToAlignLatitude = new THREE.Quaternion();
|
|
9
|
+
const quatNormalToZ = new THREE.Quaternion();
|
|
10
|
+
|
|
11
|
+
/** Transforms a WGS84 latitude into a usable texture offset. */
|
|
12
|
+
function WGS84ToOneSubY(latitude) {
|
|
13
|
+
return 1.0 - (0.5 - Math.log(Math.tan(PI_OV_FOUR + THREE.MathUtils.degToRad(latitude) * 0.5)) * INV_TWO_PI);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Specialized parameters for the [GlobeTileBuilder]. */
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* TileBuilder implementation for the purpose of generating globe (or more
|
|
20
|
+
* precisely ellipsoidal) tile arrangements.
|
|
21
|
+
*/
|
|
22
|
+
export class GlobeTileBuilder {
|
|
23
|
+
static _crs = 'EPSG:4978';
|
|
24
|
+
static _computeExtraOffset(params) {
|
|
25
|
+
const t = WGS84ToOneSubY(params.coordinates.latitude) * params.nbRow;
|
|
26
|
+
return (!isFinite(t) ? 0 : t) - params.deltaUV1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Buffer holding information about the tile/vertex currently being
|
|
31
|
+
* processed.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
get crs() {
|
|
35
|
+
return GlobeTileBuilder._crs;
|
|
36
|
+
}
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this._transform = {
|
|
39
|
+
coords: [new Coordinates('EPSG:4326', 0, 0), new Coordinates('EPSG:4326', 0, 0)],
|
|
40
|
+
position: new THREE.Vector3(),
|
|
41
|
+
dimension: new THREE.Vector2()
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// UV: Normalized coordinates (from degree) on the entire tile
|
|
45
|
+
// EPSG:4326
|
|
46
|
+
// Offset: Float row coordinate from Pseudo mercator coordinates
|
|
47
|
+
// EPSG:3857
|
|
48
|
+
if (options.uvCount > 1) {
|
|
49
|
+
this.computeExtraOffset = GlobeTileBuilder._computeExtraOffset;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
prepare(params) {
|
|
53
|
+
const nbRow = 2 ** (params.level + 1.0);
|
|
54
|
+
let st1 = WGS84ToOneSubY(params.extent.south);
|
|
55
|
+
if (!isFinite(st1)) {
|
|
56
|
+
st1 = 0;
|
|
57
|
+
}
|
|
58
|
+
const start = st1 % (1.0 / nbRow);
|
|
59
|
+
const newParams = {
|
|
60
|
+
nbRow,
|
|
61
|
+
deltaUV1: (st1 - start) * nbRow,
|
|
62
|
+
// transformation to align tile's normal to z axis
|
|
63
|
+
quatNormalToZ: quatNormalToZ.setFromAxisAngle(axisY, -(Math.PI * 0.5 - THREE.MathUtils.degToRad(params.extent.center().latitude))),
|
|
64
|
+
// let's avoid building too much temp objects
|
|
65
|
+
coordinates: new Coordinates(this.crs)
|
|
66
|
+
};
|
|
67
|
+
params.extent.planarDimensions(this._transform.dimension);
|
|
68
|
+
return {
|
|
69
|
+
...params,
|
|
70
|
+
...newParams
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
center(extent) {
|
|
74
|
+
return extent.center(this._transform.coords[0]).as(this.crs, this._transform.coords[1]).toVector3();
|
|
75
|
+
}
|
|
76
|
+
vertexPosition(coordinates) {
|
|
77
|
+
return this._transform.coords[0].setFromValues(coordinates.x, coordinates.y).as(this.crs, this._transform.coords[1]).toVector3(this._transform.position);
|
|
78
|
+
}
|
|
79
|
+
vertexNormal() {
|
|
80
|
+
return this._transform.coords[1].geodesicNormal;
|
|
81
|
+
}
|
|
82
|
+
uProject(u, extent) {
|
|
83
|
+
return extent.west + u * this._transform.dimension.x;
|
|
84
|
+
}
|
|
85
|
+
vProject(v, extent) {
|
|
86
|
+
return extent.south + v * this._transform.dimension.y;
|
|
87
|
+
}
|
|
88
|
+
computeShareableExtent(extent) {
|
|
89
|
+
// NOTE: It should be possible to take advantage of equatorial plane
|
|
90
|
+
// symmetry, for which we'd have to reverse the tile's UVs.
|
|
91
|
+
// This would halve the memory requirement when viewing a full globe,
|
|
92
|
+
// but that case is not that relevant for iTowns' usual use cases and
|
|
93
|
+
// the globe mesh memory usage is already inconsequential.
|
|
94
|
+
const sizeLongitude = Math.abs(extent.west - extent.east) / 2;
|
|
95
|
+
const shareableExtent = new Extent(extent.crs, -sizeLongitude, sizeLongitude, extent.south, extent.north);
|
|
96
|
+
|
|
97
|
+
// Compute rotation to transform the tile to position on the ellispoid.
|
|
98
|
+
// This transformation takes the parents' transformation into account.
|
|
99
|
+
const rotLon = THREE.MathUtils.degToRad(extent.west - shareableExtent.west);
|
|
100
|
+
const rotLat = THREE.MathUtils.degToRad(90 - extent.center(this._transform.coords[0]).latitude);
|
|
101
|
+
quatToAlignLongitude.setFromAxisAngle(axisZ, rotLon);
|
|
102
|
+
quatToAlignLatitude.setFromAxisAngle(axisY, rotLat);
|
|
103
|
+
quatToAlignLongitude.multiply(quatToAlignLatitude);
|
|
104
|
+
return {
|
|
105
|
+
shareableExtent,
|
|
106
|
+
quaternion: quatToAlignLongitude.clone(),
|
|
107
|
+
position: this.center(extent)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author zz85 / https://github.com/zz85
|
|
3
|
+
*
|
|
4
|
+
* Based on "A Practical Analytic Model for Daylight"
|
|
5
|
+
* aka The Preetham Model, the de facto standard analytic skydome model
|
|
6
|
+
* http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
|
|
7
|
+
*
|
|
8
|
+
* First implemented by Simon Wallner
|
|
9
|
+
* http://www.simonwallner.at/projects/atmospheric-scattering
|
|
10
|
+
*
|
|
11
|
+
* Improved by Martin Upitis
|
|
12
|
+
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
|
|
13
|
+
*
|
|
14
|
+
* Three.js integration by zz85 http://twitter.com/blurspline
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as THREE from 'three';
|
|
18
|
+
const skyShader = {
|
|
19
|
+
uniforms: {
|
|
20
|
+
luminance: {
|
|
21
|
+
type: 'f',
|
|
22
|
+
value: 1
|
|
23
|
+
},
|
|
24
|
+
turbidity: {
|
|
25
|
+
type: 'f',
|
|
26
|
+
value: 2
|
|
27
|
+
},
|
|
28
|
+
reileigh: {
|
|
29
|
+
type: 'f',
|
|
30
|
+
value: 1
|
|
31
|
+
},
|
|
32
|
+
mieCoefficient: {
|
|
33
|
+
type: 'f',
|
|
34
|
+
value: 0.005
|
|
35
|
+
},
|
|
36
|
+
mieDirectionalG: {
|
|
37
|
+
type: 'f',
|
|
38
|
+
value: 0.8
|
|
39
|
+
},
|
|
40
|
+
v3LightPosition: {
|
|
41
|
+
type: 'v3',
|
|
42
|
+
value: new THREE.Vector3()
|
|
43
|
+
},
|
|
44
|
+
up: {
|
|
45
|
+
type: 'v3',
|
|
46
|
+
value: new THREE.Vector3(0.0, 1.0, 0.0)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
vertexShader: ['varying vec3 vWorldPosition;', 'void main() {', 'vec4 worldPosition = modelMatrix * vec4( cameraPosition + position, 1.0 );', 'vWorldPosition = worldPosition.xyz;', 'gl_Position = projectionMatrix * modelViewMatrix * vec4( cameraPosition + position, 1.0 );', '}'].join('\n'),
|
|
50
|
+
fragmentShader: ['uniform sampler2D skySampler;', 'uniform vec3 v3LightPosition;', 'uniform vec3 up;', 'varying vec3 vWorldPosition;',
|
|
51
|
+
// "vec3 cameraPos = cameraPosition; //vec3(0., 0., 0.);",
|
|
52
|
+
'// uniform sampler2D sDiffuse;', '// const float turbidity = 10.0; //', '// const float reileigh = 2.; //', '// const float luminance = 1.0; //', '// const float mieCoefficient = 0.005;', '// const float mieDirectionalG = 0.8;', 'uniform float luminance;', 'uniform float turbidity;', 'uniform float reileigh;', 'uniform float mieCoefficient;', 'uniform float mieDirectionalG;', '// constants for atmospheric scattering', 'const float e = 2.71828182845904523536028747135266249775724709369995957;', 'const float pi = 3.141592653589793238462643383279502884197169;', 'const float n = 1.0003; // refractive index of air', 'const float N = 2.545E25; // number of molecules per unit volume for air at', '// 288.15K and 1013mb (sea level -45 celsius)', 'const float pn = 0.035; // depolatization factor for standard air', '// wavelength of used primaries, according to preetham', 'const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);', '// mie stuff', '// K coefficient for the primaries', 'const vec3 K = vec3(0.686, 0.678, 0.666);', 'const float v = 4.0;', '// optical length at zenith for molecules', 'const float rayleighZenithLength = 8.4E3;', 'const float mieZenithLength = 1.25E3;',
|
|
53
|
+
// "const vec3 up = vec3(0.0, 1.0, 0.0);",
|
|
54
|
+
|
|
55
|
+
'const float EE = 1000.0;', 'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;', '// 66 arc seconds -> degrees, and the cosine of that', '// earth shadow hack', 'const float cutoffAngle = pi/1.95;', 'const float steepness = 1.5;', 'vec3 totalRayleigh(vec3 lambda)', '{', 'return (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn));', '}',
|
|
56
|
+
// see http://blenderartists.org/forum/showthread.php?321110-Shaders-and-Skybox-madness
|
|
57
|
+
'// A simplied version of the total Reayleigh scattering to works on browsers that use ANGLE', 'vec3 simplifiedRayleigh()', '{', 'return 0.0005 / vec3(94, 40, 18);',
|
|
58
|
+
// return 0.00054532832366 / (3.0 * 2.545E25 * pow(vec3(680E-9, 550E-9, 450E-9), vec3(4.0)) * 6.245);
|
|
59
|
+
'}', 'float rayleighPhase(float cosTheta)', '{ ', 'return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));', '// return (1.0 / (3.0*pi)) * (1.0 + pow(cosTheta, 2.0));', '// return (3.0 / 4.0) * (1.0 + pow(cosTheta, 2.0));', '}', 'vec3 totalMie(vec3 lambda, vec3 K, float T)', '{', 'float c = (0.2 * T ) * 10E-18;', 'return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;', '}', 'float hgPhase(float cosTheta, float g)', '{', 'return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));', '}', 'float sunIntensity(float zenithAngleCos)', '{', 'return EE * max(0.0, 1.0 - exp(-((cutoffAngle - acos(zenithAngleCos))/steepness)));', '}', '// float logLuminance(vec3 c)', '// {', '// return log(c.r * 0.2126 + c.g * 0.7152 + c.b * 0.0722);', '// }', '// Filmic ToneMapping http://filmicgames.com/archives/75', 'float A = 0.15;', 'float B = 0.50;', 'float C = 0.10;', 'float D = 0.20;', 'float E = 0.02;', 'float F = 0.30;', 'float W = 1000.0;', 'vec3 Uncharted2Tonemap(vec3 x)', '{', 'return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;', '}', 'void main() ', '{', 'vec3 up2 = normalize(cameraPosition.xyz);', 'float sunfade = 1.0-clamp(1.0-exp((v3LightPosition.y/450000.0)),0.0,1.0);', 'float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));', 'vec3 sunDirection = normalize(v3LightPosition);', 'float sunE = sunIntensity(dot(sunDirection, up2));', '// extinction (absorbtion + out scattering) ', '// rayleigh coefficients',
|
|
60
|
+
// "vec3 betaR = totalRayleigh(lambda) * reileighCoefficient;",
|
|
61
|
+
'vec3 betaR = simplifiedRayleigh() * reileighCoefficient;', '// mie coefficients', 'vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;', '// optical length', '// cutoff angle at 90 to avoid singularity in next formula.', 'float zenithAngle = acos(max(0.0, dot(up2, normalize(vWorldPosition - cameraPosition))));', 'float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));', 'float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));', '// combined extinction factor', 'vec3 Fex = exp(-(betaR * sR + betaM * sM));', '// in scattering', 'float cosTheta = dot(normalize(vWorldPosition - cameraPosition), sunDirection);', 'float rPhase = rayleighPhase(cosTheta*0.5+0.5);', 'vec3 betaRTheta = betaR * rPhase;', 'float mPhase = hgPhase(cosTheta, mieDirectionalG);', 'vec3 betaMTheta = betaM * mPhase;', 'vec3 Lin = pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex),vec3(1.5));', 'Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up2, sunDirection),5.0),0.0,1.0));', '//nightsky', 'vec3 direction = normalize(vWorldPosition - cameraPosition);', 'float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]', 'float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]', 'vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);', '// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;', 'vec3 L0 = vec3(0.1) * Fex;', '// composition + solar disc', '//if (cosTheta > sunAngularDiameterCos)', 'float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);', '// if (normalize(vWorldPosition - cameraPosition).y>0.0)', 'L0 += (sunE * 19000.0 * Fex)*sundisk;', 'vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));', 'vec3 texColor = (Lin+L0); ', 'texColor *= 0.04 ;', 'texColor += vec3(0.0,0.001,0.0025)*0.3;', 'float g_fMaxLuminance = 1.0;', 'float fLumScaled = 0.1 / luminance; ', 'float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ', 'float ExposureBias = fLumCompressed;', 'vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);', 'vec3 color = curr*whiteScale;', 'vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));', 'gl_FragColor.rgb = retColor;', 'gl_FragColor.a = 1. - ( (length(cameraPosition) - 6400000.) / 1000.);', '}'].join('\n')
|
|
62
|
+
};
|
|
63
|
+
class Sky extends THREE.Mesh {
|
|
64
|
+
constructor() {
|
|
65
|
+
const skyUniforms = THREE.UniformsUtils.clone(skyShader.uniforms);
|
|
66
|
+
const skyMat = new THREE.ShaderMaterial({
|
|
67
|
+
fragmentShader: skyShader.fragmentShader,
|
|
68
|
+
vertexShader: skyShader.vertexShader,
|
|
69
|
+
uniforms: skyUniforms,
|
|
70
|
+
side: THREE.BackSide,
|
|
71
|
+
transparent: true,
|
|
72
|
+
depthWrite: false
|
|
73
|
+
});
|
|
74
|
+
const skyGeo = new THREE.SphereGeometry(40000, 32, 15);
|
|
75
|
+
super(skyGeo, skyMat);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export default Sky;
|