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,56 @@
|
|
|
1
|
+
export function lab2rgb(lab) {
|
|
2
|
+
let y = (lab[0] + 16) / 116;
|
|
3
|
+
let x = lab[1] / 500 + y;
|
|
4
|
+
let z = y - lab[2] / 200;
|
|
5
|
+
let r;
|
|
6
|
+
let g;
|
|
7
|
+
let b;
|
|
8
|
+
x = 0.95047 * (x * x * x > 0.008856 ? x * x * x : (x - 16 / 116) / 7.787);
|
|
9
|
+
y = 1.00000 * (y * y * y > 0.008856 ? y * y * y : (y - 16 / 116) / 7.787);
|
|
10
|
+
z = 1.08883 * (z * z * z > 0.008856 ? z * z * z : (z - 16 / 116) / 7.787);
|
|
11
|
+
r = x * 3.2406 + y * -1.5372 + z * -0.4986;
|
|
12
|
+
g = x * -0.9689 + y * 1.8758 + z * 0.0415;
|
|
13
|
+
b = x * 0.0557 + y * -0.2040 + z * 1.0570;
|
|
14
|
+
r = r > 0.0031308 ? 1.055 * r ** (1 / 2.4) - 0.055 : 12.92 * r;
|
|
15
|
+
g = g > 0.0031308 ? 1.055 * g ** (1 / 2.4) - 0.055 : 12.92 * g;
|
|
16
|
+
b = b > 0.0031308 ? 1.055 * b ** (1 / 2.4) - 0.055 : 12.92 * b;
|
|
17
|
+
return [Math.max(0, Math.min(1, r)) * 255, Math.max(0, Math.min(1, g)) * 255, Math.max(0, Math.min(1, b)) * 255];
|
|
18
|
+
}
|
|
19
|
+
export function rgb2lab(rgb) {
|
|
20
|
+
let r = rgb.r || rgb[0] / 255;
|
|
21
|
+
let g = rgb.g || rgb[1] / 255;
|
|
22
|
+
let b = rgb.b || rgb[2] / 255;
|
|
23
|
+
let x;
|
|
24
|
+
let y;
|
|
25
|
+
let z;
|
|
26
|
+
r = r > 0.04045 ? ((r + 0.055) / 1.055) ** 2.4 : r / 12.92;
|
|
27
|
+
g = g > 0.04045 ? ((g + 0.055) / 1.055) ** 2.4 : g / 12.92;
|
|
28
|
+
b = b > 0.04045 ? ((b + 0.055) / 1.055) ** 2.4 : b / 12.92;
|
|
29
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
30
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000;
|
|
31
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
32
|
+
x = x > 0.008856 ? x ** (1 / 3) : 7.787 * x + 16 / 116;
|
|
33
|
+
y = y > 0.008856 ? y ** (1 / 3) : 7.787 * y + 16 / 116;
|
|
34
|
+
z = z > 0.008856 ? z ** (1 / 3) : 7.787 * z + 16 / 116;
|
|
35
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// calculate the perceptual distance between colors in CIELAB
|
|
39
|
+
// https://github.com/THEjoezack/ColorMine/blob/master/ColorMine/ColorSpaces/Comparisons/Cie94Comparison.cs
|
|
40
|
+
export function deltaE(rgbA, rgbB) {
|
|
41
|
+
const labA = rgb2lab(rgbA);
|
|
42
|
+
const labB = rgb2lab(rgbB);
|
|
43
|
+
const deltaL = labA[0] - labB[0];
|
|
44
|
+
const deltaA = labA[1] - labB[1];
|
|
45
|
+
const deltaB = labA[2] - labB[2];
|
|
46
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
47
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
48
|
+
const deltaC = c1 - c2;
|
|
49
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
50
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
51
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
52
|
+
const deltaCkcsc = deltaC / (1.0 + 0.045 * c1);
|
|
53
|
+
const deltaHkhsh = deltaH / (1.0 + 0.015 * c1);
|
|
54
|
+
const i = deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh;
|
|
55
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
56
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { ImageryLayers } from "../Layer/Layer.js";
|
|
2
|
+
function updateLayersOrdering(geometryLayer, imageryLayers) {
|
|
3
|
+
const sequence = ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers);
|
|
4
|
+
const cO = function (object) {
|
|
5
|
+
if (object.material?.setSequence) {
|
|
6
|
+
object.material.setSequence(sequence);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
for (const node of geometryLayer.level0Nodes) {
|
|
10
|
+
node.traverse(cO);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const COLOR_LAYERS_ORDER_CHANGED = 'layers-order-changed';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Utilitary to organize {@link ColorLayer} in a {@link View}.
|
|
17
|
+
*
|
|
18
|
+
* @module ColorLayersOrdering
|
|
19
|
+
*/
|
|
20
|
+
export default {
|
|
21
|
+
/**
|
|
22
|
+
* Moves up in the layer list. This function has no effect if the layer is
|
|
23
|
+
* moved to its current index.
|
|
24
|
+
*
|
|
25
|
+
* @param {View} view - The view in which the layer is moved up.
|
|
26
|
+
* @param {string} layerId - The ID of the layer to move.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* itowns.ColorLayersOrdering.moveLayerUp(viewer, 'idLayerToUp');
|
|
30
|
+
*/
|
|
31
|
+
moveLayerUp(view, layerId) {
|
|
32
|
+
const imageryLayers = view.getLayers(l => l.isColorLayer);
|
|
33
|
+
const layer = view.getLayerById(layerId);
|
|
34
|
+
if (layer) {
|
|
35
|
+
const previousSequence = ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers);
|
|
36
|
+
ImageryLayers.moveLayerUp(layer, imageryLayers);
|
|
37
|
+
updateLayersOrdering(view.tileLayer, imageryLayers);
|
|
38
|
+
view.dispatchEvent({
|
|
39
|
+
type: COLOR_LAYERS_ORDER_CHANGED,
|
|
40
|
+
previous: {
|
|
41
|
+
sequence: previousSequence
|
|
42
|
+
},
|
|
43
|
+
new: {
|
|
44
|
+
sequence: ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers)
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
view.notifyChange(view.tileLayer);
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error(`${layerId} isn't color layer`);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Moves down in the layer list. This function has no effect if the layer is
|
|
54
|
+
* moved to its current index.
|
|
55
|
+
*
|
|
56
|
+
* @param {View} view - The view in which the layer is moved down.
|
|
57
|
+
* @param {string} layerId - The ID of the layer to move.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* itowns.ColorLayersOrdering.moveLayerDown(viewer, 'idLayerToDown');
|
|
61
|
+
*/
|
|
62
|
+
moveLayerDown(view, layerId) {
|
|
63
|
+
const imageryLayers = view.getLayers(l => l.isColorLayer);
|
|
64
|
+
const layer = view.getLayerById(layerId);
|
|
65
|
+
if (layer) {
|
|
66
|
+
const previousSequence = ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers);
|
|
67
|
+
ImageryLayers.moveLayerDown(layer, imageryLayers);
|
|
68
|
+
updateLayersOrdering(view.tileLayer, imageryLayers);
|
|
69
|
+
view.dispatchEvent({
|
|
70
|
+
type: COLOR_LAYERS_ORDER_CHANGED,
|
|
71
|
+
previous: {
|
|
72
|
+
sequence: previousSequence
|
|
73
|
+
},
|
|
74
|
+
new: {
|
|
75
|
+
sequence: ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers)
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
view.notifyChange(view.tileLayer);
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error(`${layerId} isn't color layer`);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Moves a specific layer to a specific index in the layer list. This
|
|
85
|
+
* function has no effect if the layer is moved to its current index.
|
|
86
|
+
*
|
|
87
|
+
* @param {View} view - The view in which the layer is moved.
|
|
88
|
+
* @param {string} layerId - The ID of the layer to move.
|
|
89
|
+
* @param {number} index - The index to move the layer to.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* itowns.ColorLayersOrdering.moveLayerToIndex(viewer, 'idLayerToChangeIndex', 2);
|
|
93
|
+
*/
|
|
94
|
+
moveLayerToIndex(view, layerId, index) {
|
|
95
|
+
const imageryLayers = view.getLayers(l => l.isColorLayer);
|
|
96
|
+
const layer = view.getLayerById(layerId);
|
|
97
|
+
if (layer) {
|
|
98
|
+
const previousSequence = ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers);
|
|
99
|
+
ImageryLayers.moveLayerToIndex(layer, index, imageryLayers);
|
|
100
|
+
updateLayersOrdering(view.tileLayer, imageryLayers);
|
|
101
|
+
view.dispatchEvent({
|
|
102
|
+
type: COLOR_LAYERS_ORDER_CHANGED,
|
|
103
|
+
previous: {
|
|
104
|
+
sequence: previousSequence
|
|
105
|
+
},
|
|
106
|
+
new: {
|
|
107
|
+
sequence: ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers)
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
view.notifyChange(view.tileLayer);
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(`${layerId} isn't color layer`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
export default {
|
|
3
|
+
setDefineMapping(object, PROPERTY, mapping) {
|
|
4
|
+
Object.keys(mapping).forEach(key => {
|
|
5
|
+
object.defines[`${PROPERTY}_${key}`] = mapping[key];
|
|
6
|
+
});
|
|
7
|
+
},
|
|
8
|
+
setDefineProperty(object, property, PROPERTY, initValue) {
|
|
9
|
+
object.defines[PROPERTY] = initValue;
|
|
10
|
+
Object.defineProperty(object, property, {
|
|
11
|
+
get: () => object.defines[PROPERTY],
|
|
12
|
+
set: value => {
|
|
13
|
+
if (object.defines[PROPERTY] != value) {
|
|
14
|
+
object.defines[PROPERTY] = value;
|
|
15
|
+
object.needsUpdate = true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
setUniformProperty(object, property, initValue) {
|
|
21
|
+
object.uniforms[property] = new THREE.Uniform(initValue);
|
|
22
|
+
Object.defineProperty(object, property, {
|
|
23
|
+
get: () => object.uniforms[property].value,
|
|
24
|
+
set: value => {
|
|
25
|
+
if (object.uniforms[property].value != value) {
|
|
26
|
+
object.uniforms[property].value = value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import GlobeLayer from "../Core/Prefab/Globe/GlobeLayer.js";
|
|
3
|
+
function isIntersectedOrOverlaped(a, b) {
|
|
4
|
+
return !(a.left > b.right || a.right < b.left || a.top > b.bottom || a.bottom < b.top);
|
|
5
|
+
}
|
|
6
|
+
const frustum = new THREE.Frustum();
|
|
7
|
+
|
|
8
|
+
// A grid to manage labels on the screen.
|
|
9
|
+
export class ScreenGrid {
|
|
10
|
+
constructor() {
|
|
11
|
+
let x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 12;
|
|
12
|
+
let y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
|
|
13
|
+
let width = arguments.length > 2 ? arguments[2] : undefined;
|
|
14
|
+
let height = arguments.length > 3 ? arguments[3] : undefined;
|
|
15
|
+
this.x = x;
|
|
16
|
+
this.y = y;
|
|
17
|
+
this.grid = [];
|
|
18
|
+
this.visible = [];
|
|
19
|
+
this.resize();
|
|
20
|
+
this.reset();
|
|
21
|
+
this.width = width;
|
|
22
|
+
this.height = height;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Reset each cell and hidden and visible.
|
|
26
|
+
reset() {
|
|
27
|
+
for (let i = 0; i < this.x; i++) {
|
|
28
|
+
for (let j = 0; j < this.y; j++) {
|
|
29
|
+
// Splice is prefered to creating a new array, in term of memory
|
|
30
|
+
this.grid[i][j].splice(0, this.grid[i][j].length);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
this.visible = [];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Add rows if needed — but don't delete anything else. Columns are taken
|
|
37
|
+
// care in reset().
|
|
38
|
+
resize() {
|
|
39
|
+
for (let i = 0; i < this.x; i++) {
|
|
40
|
+
if (!this.grid[i]) {
|
|
41
|
+
this.grid[i] = [];
|
|
42
|
+
}
|
|
43
|
+
for (let j = 0; j < this.y; j++) {
|
|
44
|
+
if (!this.grid[i][j]) {
|
|
45
|
+
this.grid[i][j] = [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Insert a label using its boundaries. It is either added to hidden or
|
|
52
|
+
// visible, given the result. The grid is populated with true for every
|
|
53
|
+
// filled cell.
|
|
54
|
+
insert(obj) {
|
|
55
|
+
const minx = Math.max(0, Math.floor(obj.boundaries.left / this.width * this.x));
|
|
56
|
+
const maxx = Math.min(this.x - 1, Math.floor(obj.boundaries.right / this.width * this.x));
|
|
57
|
+
const miny = Math.max(0, Math.floor(obj.boundaries.top / this.height * this.y));
|
|
58
|
+
const maxy = Math.min(this.y - 1, Math.floor(obj.boundaries.bottom / this.height * this.y));
|
|
59
|
+
for (let i = minx; i <= maxx; i++) {
|
|
60
|
+
for (let j = miny; j <= maxy; j++) {
|
|
61
|
+
if (this.grid[i][j].length > 0) {
|
|
62
|
+
if (this.grid[i][j].some(l => isIntersectedOrOverlaped(l.boundaries, obj.boundaries))) {
|
|
63
|
+
obj.visible = false;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (let i = minx; i <= maxx; i++) {
|
|
70
|
+
for (let j = miny; j <= maxy; j++) {
|
|
71
|
+
this.grid[i][j].push(obj);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const worldPosition = new THREE.Vector3();
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* This renderer is inspired by the
|
|
81
|
+
* [`THREE.CSS2DRenderer`](https://threejs.org/docs/#examples/en/renderers/CSS2DRenderer).
|
|
82
|
+
* It is instanciated in `c3DEngine`, as another renderer to handles Labels.
|
|
83
|
+
*/
|
|
84
|
+
class Label2DRenderer {
|
|
85
|
+
constructor() {
|
|
86
|
+
this.domElement = document.createElement('div');
|
|
87
|
+
this.domElement.style.overflow = 'hidden';
|
|
88
|
+
this.domElement.style.position = 'absolute';
|
|
89
|
+
this.domElement.style.top = '0';
|
|
90
|
+
this.domElement.style.height = '100%';
|
|
91
|
+
this.domElement.style.width = '100%';
|
|
92
|
+
this.domElement.style.zIndex = 1;
|
|
93
|
+
|
|
94
|
+
// Used to destroy labels that are not added to the DOM
|
|
95
|
+
this.garbage = document.createElement('div');
|
|
96
|
+
this.garbage.style.display = 'none';
|
|
97
|
+
this.domElement.appendChild(this.garbage);
|
|
98
|
+
this.halfWidth = 0;
|
|
99
|
+
this.halfHeight = 0;
|
|
100
|
+
this.grid = new ScreenGrid();
|
|
101
|
+
this.infoTileLayer = undefined;
|
|
102
|
+
}
|
|
103
|
+
setSize(width, height) {
|
|
104
|
+
this.domElement.style.width = `${width}`;
|
|
105
|
+
this.domElement.style.height = `${height}`;
|
|
106
|
+
this.halfWidth = width / 2;
|
|
107
|
+
this.halfHeight = height / 2;
|
|
108
|
+
this.grid.width = width;
|
|
109
|
+
this.grid.height = height;
|
|
110
|
+
this.grid.x = Math.ceil(width / 20);
|
|
111
|
+
this.grid.y = Math.ceil(height / 20);
|
|
112
|
+
this.grid.resize();
|
|
113
|
+
}
|
|
114
|
+
registerLayer(layer) {
|
|
115
|
+
this.domElement.appendChild(layer.domElement.dom);
|
|
116
|
+
}
|
|
117
|
+
render(scene, camera) {
|
|
118
|
+
const labelLayers = this.infoTileLayer && this.infoTileLayer.layer.attachedLayers.filter(l => l.isLabelLayer && l.visible);
|
|
119
|
+
if (labelLayers.length == 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.grid.reset();
|
|
123
|
+
|
|
124
|
+
// set camera frustum
|
|
125
|
+
frustum.setFromProjectionMatrix(camera.projectionMatrix);
|
|
126
|
+
labelLayers.forEach(labelLayer => {
|
|
127
|
+
labelLayer.submittedLabelNodes.forEach(labelsNode => {
|
|
128
|
+
labelsNode.labels.forEach(label => {
|
|
129
|
+
labelsNode.updatePosition(label);
|
|
130
|
+
this.culling(label, camera);
|
|
131
|
+
});
|
|
132
|
+
labelsNode.domElements.labels.show();
|
|
133
|
+
labelsNode.needsUpdate = false;
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// sort by order, then by visibility inside those subsets
|
|
138
|
+
// https://docs.mapbox.com/help/troubleshooting/optimize-map-label-placement/#label-hierarchy
|
|
139
|
+
this.grid.visible.sort((a, b) => {
|
|
140
|
+
const r = b.order - a.order;
|
|
141
|
+
if (r == 0) {
|
|
142
|
+
if (!a.visible && b.visible) {
|
|
143
|
+
return 1;
|
|
144
|
+
} else {
|
|
145
|
+
return -1;
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
return r;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
this.grid.visible.forEach(l => {
|
|
152
|
+
if (this.grid.insert(l)) {
|
|
153
|
+
l.visible = true;
|
|
154
|
+
l.updateCSSPosition();
|
|
155
|
+
} else {
|
|
156
|
+
l.visible = false;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
labelLayers.forEach(labelLayer => {
|
|
160
|
+
labelLayer.toHide.children.forEach(labelsNode => labelsNode.domElements?.labels.hide());
|
|
161
|
+
labelLayer.toHide.clear();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
culling(label, camera) {
|
|
165
|
+
label.getWorldPosition(worldPosition);
|
|
166
|
+
// Check if the frustum contains tle label
|
|
167
|
+
if (!frustum.containsPoint(worldPosition.applyMatrix4(camera.matrixWorldInverse)) ||
|
|
168
|
+
// Check if globe horizon culls the label
|
|
169
|
+
// Do some horizon culling (if possible) if the tiles level is small enough.
|
|
170
|
+
label.horizonCullingPoint && GlobeLayer.horizonCulling(label.horizonCullingPoint)
|
|
171
|
+
// Why do we might need this part ?
|
|
172
|
+
// || // Check if content isn't present in visible labels
|
|
173
|
+
// this.grid.visible.some((l) => {
|
|
174
|
+
// // TODO for icon without text filter by position
|
|
175
|
+
// const textContent = label.content.textContent;
|
|
176
|
+
// return textContent !== '' && l.content.textContent.toLowerCase() == textContent.toLowerCase();
|
|
177
|
+
// })
|
|
178
|
+
) {
|
|
179
|
+
label.visible = false;
|
|
180
|
+
} else {
|
|
181
|
+
// projecting world position label
|
|
182
|
+
worldPosition.applyMatrix4(camera.projectionMatrix);
|
|
183
|
+
label.updateProjectedPosition(worldPosition.x * this.halfWidth + this.halfWidth, -worldPosition.y * this.halfHeight + this.halfHeight);
|
|
184
|
+
this.grid.visible.push(label);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
removeLabelDOM(label) {
|
|
188
|
+
this.garbage.appendChild(label.content);
|
|
189
|
+
this.garbage.innerHTML = '';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export default Label2DRenderer;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import ShaderUtils from "./Shader/ShaderUtils.js";
|
|
3
|
+
import Capabilities from "../Core/System/Capabilities.js";
|
|
4
|
+
import RenderMode from "./RenderMode.js";
|
|
5
|
+
import CommonMaterial from "./CommonMaterial.js";
|
|
6
|
+
/* babel-plugin-inline-import '../Renderer/Shader/TileVS.glsl' */
|
|
7
|
+
const TileVS = "#include <itowns/precision_qualifier>\n#include <common>\n#include <itowns/elevation_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#if NUM_CRS > 1\nattribute float uv_1;\n#endif\n\nuniform bool lightingEnabled;\nvarying vec2 vHighPrecisionZW;\n\n#if MODE == MODE_FINAL\n#include <fog_pars_vertex>\nvarying vec3 vUv;\nvarying vec3 vNormal;\n#endif\nvoid main() {\n #include <begin_vertex>\n #include <itowns/elevation_vertex>\n #include <itowns/geoid_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n vHighPrecisionZW = gl_Position.zw;\n#if MODE == MODE_FINAL\n #include <fog_vertex>\n #if NUM_CRS > 1\n vUv = vec3(uv, (uv_1 > 0.) ? uv_1 : uv.y); // set uv_1 = uv if uv_1 is undefined\n #else\n vUv = vec3(uv, 0.0);\n #endif\n vNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );\n#endif\n}\n";
|
|
8
|
+
/* babel-plugin-inline-import '../Renderer/Shader/TileFS.glsl' */
|
|
9
|
+
const TileFS = "#include <itowns/precision_qualifier>\n#include <logdepthbuf_pars_fragment>\n#include <itowns/pitUV>\n#include <itowns/color_layers_pars_fragment>\n#if MODE == MODE_FINAL\n#include <itowns/fog_pars_fragment>\n#include <itowns/overlay_pars_fragment>\n#include <itowns/lighting_pars_fragment>\n#endif\n#include <itowns/mode_pars_fragment>\n\nuniform vec3 diffuse;\nuniform float opacity;\nvarying vec3 vUv; // uv.x/uv_1.x, uv.y, uv_1.y\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n #include <logdepthbuf_fragment>\n\n#if MODE == MODE_ID\n\n #include <itowns/mode_id_fragment>\n\n#elif MODE == MODE_DEPTH\n\n #include <itowns/mode_depth_fragment>\n\n#else\n\n gl_FragColor = vec4(diffuse, opacity);\n\n uvs[0] = vec3(vUv.xy, 0.);\n\n#if NUM_CRS > 1\n uvs[1] = vec3(vUv.x, fract(vUv.z), floor(vUv.z));\n#endif\n\n vec4 color;\n #pragma unroll_loop\n for ( int i = 0; i < NUM_FS_TEXTURES; i ++ ) {\n color = getLayerColor( i , colorTextures[ i ], colorOffsetScales[ i ], colorLayers[ i ]);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, color.rgb, color.a);\n }\n\n #if defined(DEBUG)\n if (showOutline) {\n #pragma unroll_loop\n for ( int i = 0; i < NUM_CRS; i ++) {\n color = getOutlineColor( outlineColors[ i ], uvs[ i ].xy);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, color.rgb, color.a);\n }\n }\n #endif\n\n #include <itowns/fog_fragment>\n #include <itowns/lighting_fragment>\n #include <itowns/overlay_fragment>\n\n#endif\n}\n";
|
|
10
|
+
const identityOffsetScale = new THREE.Vector4(0.0, 0.0, 1.0, 1.0);
|
|
11
|
+
const defaultTex = new THREE.Texture();
|
|
12
|
+
|
|
13
|
+
// from three.js packDepthToRGBA
|
|
14
|
+
const UnpackDownscale = 255 / 256; // 0..1 -> fraction (excluding 1)
|
|
15
|
+
const bitSh = new THREE.Vector4(UnpackDownscale, UnpackDownscale / 256.0, UnpackDownscale / (256.0 * 256.0), UnpackDownscale / (256.0 * 256.0 * 256.0));
|
|
16
|
+
export function unpack1K(color, factor) {
|
|
17
|
+
return factor ? bitSh.dot(color) * factor : bitSh.dot(color);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Max sampler color count to LayeredMaterial
|
|
21
|
+
// Because there's a statement limitation to unroll, in getColorAtIdUv method
|
|
22
|
+
const maxSamplersColorCount = 15;
|
|
23
|
+
const samplersElevationCount = 1;
|
|
24
|
+
export function getMaxColorSamplerUnitsCount() {
|
|
25
|
+
const maxSamplerUnitsCount = Capabilities.getMaxTextureUnitsCount();
|
|
26
|
+
return Math.min(maxSamplerUnitsCount - samplersElevationCount, maxSamplersColorCount);
|
|
27
|
+
}
|
|
28
|
+
export const colorLayerEffects = {
|
|
29
|
+
noEffect: 0,
|
|
30
|
+
removeLightColor: 1,
|
|
31
|
+
removeWhiteColor: 2,
|
|
32
|
+
customEffect: 3
|
|
33
|
+
};
|
|
34
|
+
const defaultStructLayer = {
|
|
35
|
+
bias: 0,
|
|
36
|
+
noDataValue: -99999,
|
|
37
|
+
zmin: 0,
|
|
38
|
+
zmax: 0,
|
|
39
|
+
scale: 0,
|
|
40
|
+
mode: 0,
|
|
41
|
+
textureOffset: 0,
|
|
42
|
+
opacity: 0,
|
|
43
|
+
crs: 0,
|
|
44
|
+
effect_parameter: 0,
|
|
45
|
+
effect_type: colorLayerEffects.noEffect,
|
|
46
|
+
transparent: false
|
|
47
|
+
};
|
|
48
|
+
function updateLayersUniforms(uniforms, olayers, max) {
|
|
49
|
+
// prepare convenient access to elevation or color uniforms
|
|
50
|
+
const layers = uniforms.layers.value;
|
|
51
|
+
const textures = uniforms.textures.value;
|
|
52
|
+
const offsetScales = uniforms.offsetScales.value;
|
|
53
|
+
const textureCount = uniforms.textureCount;
|
|
54
|
+
|
|
55
|
+
// flatten the 2d array [i,j] -> layers[_layerIds[i]].textures[j]
|
|
56
|
+
let count = 0;
|
|
57
|
+
for (const layer of olayers) {
|
|
58
|
+
// textureOffset property is added to RasterTile
|
|
59
|
+
layer.textureOffset = count;
|
|
60
|
+
for (let i = 0, il = layer.textures.length; i < il; ++i, ++count) {
|
|
61
|
+
if (count < max) {
|
|
62
|
+
offsetScales[count] = layer.offsetScales[i];
|
|
63
|
+
textures[count] = layer.textures[i];
|
|
64
|
+
layers[count] = layer;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (count > max) {
|
|
69
|
+
console.warn(`LayeredMaterial: Not enough texture units (${max} < ${count}), excess textures have been discarded.`);
|
|
70
|
+
}
|
|
71
|
+
textureCount.value = count;
|
|
72
|
+
|
|
73
|
+
// WebGL 2.0 doesn't support the undefined uniforms.
|
|
74
|
+
// So the undefined uniforms are defined by default value.
|
|
75
|
+
for (let i = count; i < textures.length; i++) {
|
|
76
|
+
textures[i] = defaultTex;
|
|
77
|
+
offsetScales[i] = identityOffsetScale;
|
|
78
|
+
layers[i] = defaultStructLayer;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export const ELEVATION_MODES = {
|
|
82
|
+
RGBA: 0,
|
|
83
|
+
COLOR: 1,
|
|
84
|
+
DATA: 2
|
|
85
|
+
};
|
|
86
|
+
let nbSamplers;
|
|
87
|
+
const fragmentShader = [];
|
|
88
|
+
class LayeredMaterial extends THREE.ShaderMaterial {
|
|
89
|
+
#_visible = true;
|
|
90
|
+
constructor() {
|
|
91
|
+
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
92
|
+
let crsCount = arguments.length > 1 ? arguments[1] : undefined;
|
|
93
|
+
super(options);
|
|
94
|
+
nbSamplers = nbSamplers || [samplersElevationCount, getMaxColorSamplerUnitsCount()];
|
|
95
|
+
this.defines.NUM_VS_TEXTURES = nbSamplers[0];
|
|
96
|
+
this.defines.NUM_FS_TEXTURES = nbSamplers[1];
|
|
97
|
+
// TODO: We do not use the fog from the scene, is this a desired
|
|
98
|
+
// behavior?
|
|
99
|
+
this.defines.USE_FOG = 1;
|
|
100
|
+
this.defines.NUM_CRS = crsCount;
|
|
101
|
+
CommonMaterial.setDefineMapping(this, 'ELEVATION', ELEVATION_MODES);
|
|
102
|
+
CommonMaterial.setDefineMapping(this, 'MODE', RenderMode.MODES);
|
|
103
|
+
CommonMaterial.setDefineProperty(this, 'mode', 'MODE', RenderMode.MODES.FINAL);
|
|
104
|
+
this.vertexShader = TileVS;
|
|
105
|
+
// three loop unrolling of ShaderMaterial only supports integer bounds,
|
|
106
|
+
// see https://github.com/mrdoob/three.js/issues/28020
|
|
107
|
+
fragmentShader[crsCount] = fragmentShader[crsCount] || ShaderUtils.unrollLoops(TileFS, this.defines);
|
|
108
|
+
this.fragmentShader = fragmentShader[crsCount];
|
|
109
|
+
|
|
110
|
+
// Color uniforms
|
|
111
|
+
CommonMaterial.setUniformProperty(this, 'diffuse', new THREE.Color(0.04, 0.23, 0.35));
|
|
112
|
+
CommonMaterial.setUniformProperty(this, 'opacity', this.opacity);
|
|
113
|
+
|
|
114
|
+
// Lighting uniforms
|
|
115
|
+
CommonMaterial.setUniformProperty(this, 'lightingEnabled', false);
|
|
116
|
+
CommonMaterial.setUniformProperty(this, 'lightPosition', new THREE.Vector3(-0.5, 0.0, 1.0));
|
|
117
|
+
|
|
118
|
+
// Misc properties
|
|
119
|
+
CommonMaterial.setUniformProperty(this, 'fogDistance', 1000000000.0);
|
|
120
|
+
CommonMaterial.setUniformProperty(this, 'fogColor', new THREE.Color(0.76, 0.85, 1.0));
|
|
121
|
+
CommonMaterial.setUniformProperty(this, 'overlayAlpha', 0);
|
|
122
|
+
CommonMaterial.setUniformProperty(this, 'overlayColor', new THREE.Color(1.0, 0.3, 0.0));
|
|
123
|
+
CommonMaterial.setUniformProperty(this, 'objectId', 0);
|
|
124
|
+
CommonMaterial.setUniformProperty(this, 'geoidHeight', 0.0);
|
|
125
|
+
|
|
126
|
+
// > 0 produces gaps,
|
|
127
|
+
// < 0 causes oversampling of textures
|
|
128
|
+
// = 0 causes sampling artefacts due to bad estimation of texture-uv gradients
|
|
129
|
+
// best is a small negative number
|
|
130
|
+
CommonMaterial.setUniformProperty(this, 'minBorderDistance', -0.01);
|
|
131
|
+
|
|
132
|
+
// LayeredMaterialLayers
|
|
133
|
+
this.layers = [];
|
|
134
|
+
this.elevationLayerIds = [];
|
|
135
|
+
this.colorLayerIds = [];
|
|
136
|
+
|
|
137
|
+
// elevation layer uniforms, to be updated using updateUniforms()
|
|
138
|
+
this.uniforms.elevationLayers = new THREE.Uniform(new Array(nbSamplers[0]).fill(defaultStructLayer));
|
|
139
|
+
this.uniforms.elevationTextures = new THREE.Uniform(new Array(nbSamplers[0]).fill(defaultTex));
|
|
140
|
+
this.uniforms.elevationOffsetScales = new THREE.Uniform(new Array(nbSamplers[0]).fill(identityOffsetScale));
|
|
141
|
+
this.uniforms.elevationTextureCount = new THREE.Uniform(0);
|
|
142
|
+
|
|
143
|
+
// color layer uniforms, to be updated using updateUniforms()
|
|
144
|
+
this.uniforms.colorLayers = new THREE.Uniform(new Array(nbSamplers[1]).fill(defaultStructLayer));
|
|
145
|
+
this.uniforms.colorTextures = new THREE.Uniform(new Array(nbSamplers[1]).fill(defaultTex));
|
|
146
|
+
this.uniforms.colorOffsetScales = new THREE.Uniform(new Array(nbSamplers[1]).fill(identityOffsetScale));
|
|
147
|
+
this.uniforms.colorTextureCount = new THREE.Uniform(0);
|
|
148
|
+
|
|
149
|
+
// can't do an ES6 setter/getter here
|
|
150
|
+
Object.defineProperty(this, 'visible', {
|
|
151
|
+
// Knowing the visibility of a `LayeredMaterial` is useful. For example in a
|
|
152
|
+
// `GlobeView`, if you zoom in, "parent" tiles seems hidden; in fact, there
|
|
153
|
+
// are not, it is only their material (so `LayeredMaterial`) that is set to
|
|
154
|
+
// not visible.
|
|
155
|
+
|
|
156
|
+
// Adding an event when changing this property can be useful to hide others
|
|
157
|
+
// things, like in `TileDebug`, or in later PR to come (#1303 for example).
|
|
158
|
+
//
|
|
159
|
+
// TODO : verify if there is a better mechanism to avoid this event
|
|
160
|
+
get() {
|
|
161
|
+
return this.#_visible;
|
|
162
|
+
},
|
|
163
|
+
set(v) {
|
|
164
|
+
if (this.#_visible != v) {
|
|
165
|
+
this.#_visible = v;
|
|
166
|
+
this.dispatchEvent({
|
|
167
|
+
type: v ? 'shown' : 'hidden'
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
getUniformByType(type) {
|
|
174
|
+
return {
|
|
175
|
+
layers: this.uniforms[`${type}Layers`],
|
|
176
|
+
textures: this.uniforms[`${type}Textures`],
|
|
177
|
+
offsetScales: this.uniforms[`${type}OffsetScales`],
|
|
178
|
+
textureCount: this.uniforms[`${type}TextureCount`]
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
updateLayersUniforms() {
|
|
182
|
+
const colorlayers = this.layers.filter(l => this.colorLayerIds.includes(l.id) && l.visible && l.opacity > 0);
|
|
183
|
+
colorlayers.sort((a, b) => this.colorLayerIds.indexOf(a.id) - this.colorLayerIds.indexOf(b.id));
|
|
184
|
+
updateLayersUniforms(this.getUniformByType('color'), colorlayers, this.defines.NUM_FS_TEXTURES);
|
|
185
|
+
if (this.elevationLayerIds.some(id => this.getLayer(id)) || this.uniforms.elevationTextureCount.value && !this.elevationLayerIds.length) {
|
|
186
|
+
const elevationLayer = this.getElevationLayer() ? [this.getElevationLayer()] : [];
|
|
187
|
+
updateLayersUniforms(this.getUniformByType('elevation'), elevationLayer, this.defines.NUM_VS_TEXTURES);
|
|
188
|
+
}
|
|
189
|
+
this.layersNeedUpdate = false;
|
|
190
|
+
}
|
|
191
|
+
dispose() {
|
|
192
|
+
this.dispatchEvent({
|
|
193
|
+
type: 'dispose'
|
|
194
|
+
});
|
|
195
|
+
this.layers.forEach(l => l.dispose(true));
|
|
196
|
+
this.layers.length = 0;
|
|
197
|
+
this.layersNeedUpdate = true;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// TODO: rename to setColorLayerIds and add setElevationLayerIds ?
|
|
201
|
+
setSequence(sequenceLayer) {
|
|
202
|
+
this.colorLayerIds = sequenceLayer;
|
|
203
|
+
this.layersNeedUpdate = true;
|
|
204
|
+
}
|
|
205
|
+
setSequenceElevation(layerId) {
|
|
206
|
+
this.elevationLayerIds[0] = layerId;
|
|
207
|
+
this.layersNeedUpdate = true;
|
|
208
|
+
}
|
|
209
|
+
removeLayer(layerId) {
|
|
210
|
+
const index = this.layers.findIndex(l => l.id === layerId);
|
|
211
|
+
if (index > -1) {
|
|
212
|
+
this.layers[index].dispose();
|
|
213
|
+
this.layers.splice(index, 1);
|
|
214
|
+
const idSeq = this.colorLayerIds.indexOf(layerId);
|
|
215
|
+
if (idSeq > -1) {
|
|
216
|
+
this.colorLayerIds.splice(idSeq, 1);
|
|
217
|
+
} else {
|
|
218
|
+
this.elevationLayerIds = [];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
addLayer(rasterNode) {
|
|
223
|
+
if (rasterNode.layer.id in this.layers) {
|
|
224
|
+
console.warn('The "{layer.id}" layer was already present in the material, overwritting.');
|
|
225
|
+
}
|
|
226
|
+
this.layers.push(rasterNode);
|
|
227
|
+
}
|
|
228
|
+
getLayer(id) {
|
|
229
|
+
return this.layers.find(l => l.id === id);
|
|
230
|
+
}
|
|
231
|
+
getLayers(ids) {
|
|
232
|
+
return this.layers.filter(l => ids.includes(l.id));
|
|
233
|
+
}
|
|
234
|
+
getElevationLayer() {
|
|
235
|
+
return this.layers.find(l => l.id === this.elevationLayerIds[0]);
|
|
236
|
+
}
|
|
237
|
+
setElevationScale(scale) {
|
|
238
|
+
if (this.elevationLayerIds.length) {
|
|
239
|
+
this.getElevationLayer().scale = scale;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export default LayeredMaterial;
|