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.
Files changed (185) hide show
  1. package/dist/455.js +2 -0
  2. package/dist/455.js.map +1 -0
  3. package/dist/debug.js +3 -0
  4. package/dist/debug.js.LICENSE.txt +13 -0
  5. package/dist/debug.js.map +1 -0
  6. package/dist/itowns.js +3 -0
  7. package/dist/itowns.js.LICENSE.txt +5 -0
  8. package/dist/itowns.js.map +1 -0
  9. package/dist/itowns_lasparser.js +2 -0
  10. package/dist/itowns_lasparser.js.map +1 -0
  11. package/dist/itowns_lasworker.js +2 -0
  12. package/dist/itowns_lasworker.js.map +1 -0
  13. package/dist/itowns_potree2worker.js +2 -0
  14. package/dist/itowns_potree2worker.js.map +1 -0
  15. package/dist/itowns_widgets.js +2 -0
  16. package/dist/itowns_widgets.js.map +1 -0
  17. package/lib/Controls/FirstPersonControls.js +308 -0
  18. package/lib/Controls/FlyControls.js +175 -0
  19. package/lib/Controls/GlobeControls.js +1178 -0
  20. package/lib/Controls/PlanarControls.js +1025 -0
  21. package/lib/Controls/StateControl.js +432 -0
  22. package/lib/Controls/StreetControls.js +392 -0
  23. package/lib/Converter/Feature2Mesh.js +612 -0
  24. package/lib/Converter/Feature2Texture.js +174 -0
  25. package/lib/Converter/convertToTile.js +70 -0
  26. package/lib/Converter/textureConverter.js +43 -0
  27. package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
  28. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
  29. package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
  30. package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
  31. package/lib/Core/3DTiles/C3DTFeature.js +110 -0
  32. package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
  33. package/lib/Core/3DTiles/C3DTileset.js +99 -0
  34. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
  35. package/lib/Core/AnimationPlayer.js +142 -0
  36. package/lib/Core/CopcNode.js +174 -0
  37. package/lib/Core/Deprecated/Undeprecator.js +74 -0
  38. package/lib/Core/EntwinePointTileNode.js +126 -0
  39. package/lib/Core/Feature.js +488 -0
  40. package/lib/Core/Geographic/GeoidGrid.js +108 -0
  41. package/lib/Core/Label.js +222 -0
  42. package/lib/Core/MainLoop.js +209 -0
  43. package/lib/Core/Picking.js +255 -0
  44. package/lib/Core/PointCloudNode.js +42 -0
  45. package/lib/Core/Potree2Node.js +206 -0
  46. package/lib/Core/Potree2PointAttributes.js +139 -0
  47. package/lib/Core/PotreeNode.js +101 -0
  48. package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
  49. package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
  50. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
  51. package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
  52. package/lib/Core/Prefab/GlobeView.js +155 -0
  53. package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
  54. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
  55. package/lib/Core/Prefab/PlanarView.js +62 -0
  56. package/lib/Core/Prefab/TileBuilder.js +82 -0
  57. package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
  58. package/lib/Core/Scheduler/Cache.js +17 -0
  59. package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
  60. package/lib/Core/Scheduler/Scheduler.js +294 -0
  61. package/lib/Core/Style.js +660 -0
  62. package/lib/Core/StyleOptions.js +486 -0
  63. package/lib/Core/System/Capabilities.js +63 -0
  64. package/lib/Core/Tile/Tile.js +205 -0
  65. package/lib/Core/Tile/TileGrid.js +49 -0
  66. package/lib/Core/TileGeometry.js +124 -0
  67. package/lib/Core/TileMesh.js +108 -0
  68. package/lib/Core/View.js +1115 -0
  69. package/lib/Layer/C3DTilesLayer.js +459 -0
  70. package/lib/Layer/ColorLayer.js +154 -0
  71. package/lib/Layer/CopcLayer.js +63 -0
  72. package/lib/Layer/ElevationLayer.js +139 -0
  73. package/lib/Layer/EntwinePointTileLayer.js +71 -0
  74. package/lib/Layer/FeatureGeometryLayer.js +77 -0
  75. package/lib/Layer/GeoidLayer.js +80 -0
  76. package/lib/Layer/GeometryLayer.js +233 -0
  77. package/lib/Layer/InfoLayer.js +64 -0
  78. package/lib/Layer/LabelLayer.js +469 -0
  79. package/lib/Layer/Layer.js +335 -0
  80. package/lib/Layer/LayerUpdateState.js +89 -0
  81. package/lib/Layer/LayerUpdateStrategy.js +80 -0
  82. package/lib/Layer/OGC3DTilesLayer.js +543 -0
  83. package/lib/Layer/OrientedImageLayer.js +227 -0
  84. package/lib/Layer/PointCloudLayer.js +405 -0
  85. package/lib/Layer/Potree2Layer.js +171 -0
  86. package/lib/Layer/PotreeLayer.js +72 -0
  87. package/lib/Layer/RasterLayer.js +37 -0
  88. package/lib/Layer/ReferencingLayerProperties.js +62 -0
  89. package/lib/Layer/TiledGeometryLayer.js +459 -0
  90. package/lib/Loader/LASLoader.js +193 -0
  91. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  92. package/lib/Loader/Potree2Loader.js +207 -0
  93. package/lib/Main.js +113 -0
  94. package/lib/MainBundle.js +4 -0
  95. package/lib/Parser/B3dmParser.js +174 -0
  96. package/lib/Parser/CameraCalibrationParser.js +94 -0
  97. package/lib/Parser/GDFParser.js +72 -0
  98. package/lib/Parser/GTXParser.js +75 -0
  99. package/lib/Parser/GeoJsonParser.js +212 -0
  100. package/lib/Parser/GpxParser.js +25 -0
  101. package/lib/Parser/ISGParser.js +71 -0
  102. package/lib/Parser/KMLParser.js +25 -0
  103. package/lib/Parser/LASParser.js +137 -0
  104. package/lib/Parser/MapBoxUrlParser.js +83 -0
  105. package/lib/Parser/PntsParser.js +131 -0
  106. package/lib/Parser/Potree2BinParser.js +92 -0
  107. package/lib/Parser/PotreeBinParser.js +106 -0
  108. package/lib/Parser/PotreeCinParser.js +29 -0
  109. package/lib/Parser/ShapefileParser.js +78 -0
  110. package/lib/Parser/VectorTileParser.js +215 -0
  111. package/lib/Parser/XbilParser.js +120 -0
  112. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
  113. package/lib/Parser/iGLTFLoader.js +168 -0
  114. package/lib/Process/3dTilesProcessing.js +304 -0
  115. package/lib/Process/FeatureProcessing.js +76 -0
  116. package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
  117. package/lib/Process/ObjectRemovalHelper.js +97 -0
  118. package/lib/Process/handlerNodeError.js +23 -0
  119. package/lib/Provider/3dTilesProvider.js +149 -0
  120. package/lib/Provider/DataSourceProvider.js +24 -0
  121. package/lib/Provider/Fetcher.js +233 -0
  122. package/lib/Provider/PointCloudProvider.js +45 -0
  123. package/lib/Provider/TileProvider.js +16 -0
  124. package/lib/Provider/URLBuilder.js +116 -0
  125. package/lib/Renderer/Camera.js +281 -0
  126. package/lib/Renderer/Color.js +56 -0
  127. package/lib/Renderer/ColorLayersOrdering.js +115 -0
  128. package/lib/Renderer/CommonMaterial.js +31 -0
  129. package/lib/Renderer/Label2DRenderer.js +192 -0
  130. package/lib/Renderer/LayeredMaterial.js +243 -0
  131. package/lib/Renderer/OBB.js +150 -0
  132. package/lib/Renderer/OrientedImageCamera.js +118 -0
  133. package/lib/Renderer/OrientedImageMaterial.js +167 -0
  134. package/lib/Renderer/PointsMaterial.js +485 -0
  135. package/lib/Renderer/RasterTile.js +243 -0
  136. package/lib/Renderer/RenderMode.js +31 -0
  137. package/lib/Renderer/Shader/ShaderChunk.js +160 -0
  138. package/lib/Renderer/Shader/ShaderUtils.js +47 -0
  139. package/lib/Renderer/SphereHelper.js +17 -0
  140. package/lib/Renderer/WebXR.js +51 -0
  141. package/lib/Renderer/c3DEngine.js +214 -0
  142. package/lib/Source/C3DTilesGoogleSource.js +74 -0
  143. package/lib/Source/C3DTilesIonSource.js +54 -0
  144. package/lib/Source/C3DTilesSource.js +30 -0
  145. package/lib/Source/CopcSource.js +126 -0
  146. package/lib/Source/EntwinePointTileSource.js +72 -0
  147. package/lib/Source/FileSource.js +188 -0
  148. package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
  149. package/lib/Source/OGC3DTilesIonSource.js +34 -0
  150. package/lib/Source/OGC3DTilesSource.js +21 -0
  151. package/lib/Source/OrientedImageSource.js +59 -0
  152. package/lib/Source/Potree2Source.js +167 -0
  153. package/lib/Source/PotreeSource.js +82 -0
  154. package/lib/Source/Source.js +202 -0
  155. package/lib/Source/TMSSource.js +144 -0
  156. package/lib/Source/VectorTilesSource.js +182 -0
  157. package/lib/Source/WFSSource.js +170 -0
  158. package/lib/Source/WMSSource.js +167 -0
  159. package/lib/Source/WMTSSource.js +92 -0
  160. package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
  161. package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
  162. package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
  163. package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
  164. package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
  165. package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
  166. package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
  167. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  168. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
  169. package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
  170. package/lib/Utils/CameraUtils.js +554 -0
  171. package/lib/Utils/DEMUtils.js +350 -0
  172. package/lib/Utils/FeaturesUtils.js +156 -0
  173. package/lib/Utils/Gradients.js +16 -0
  174. package/lib/Utils/ThreeUtils.js +115 -0
  175. package/lib/Utils/gui/C3DTilesStyle.js +218 -0
  176. package/lib/Utils/gui/Main.js +7 -0
  177. package/lib/Utils/gui/Minimap.js +152 -0
  178. package/lib/Utils/gui/Navigation.js +245 -0
  179. package/lib/Utils/gui/Scale.js +104 -0
  180. package/lib/Utils/gui/Searchbar.js +234 -0
  181. package/lib/Utils/gui/Widget.js +80 -0
  182. package/lib/Utils/placeObjectOnGround.js +136 -0
  183. package/lib/Worker/LASLoaderWorker.js +19 -0
  184. package/lib/Worker/Potree2Worker.js +21 -0
  185. package/package.json +2 -2
@@ -0,0 +1,155 @@
1
+ import * as THREE from 'three';
2
+ import View, { VIEW_EVENTS } from "../View.js";
3
+ import GlobeControls from "../../Controls/GlobeControls.js";
4
+ import { Coordinates, ellipsoidSizes } from '@itowns/geographic';
5
+ import GlobeLayer from "./Globe/GlobeLayer.js";
6
+ import Atmosphere from "./Globe/Atmosphere.js";
7
+ import CameraUtils from "../../Utils/CameraUtils.js";
8
+
9
+ /**
10
+ * Fires when the view is completely loaded. Controls and view's functions can be called then.
11
+ * @event GlobeView#initialized
12
+ * @property target {view} dispatched on view
13
+ * @property type {string} initialized
14
+ */
15
+ /**
16
+ * Fires when a layer is added
17
+ * @event GlobeView#layer-added
18
+ * @property layerId {string} the id of the layer
19
+ * @property target {view} dispatched on view
20
+ * @property type {string} layers-added
21
+ */
22
+ /**
23
+ * Fires when a layer is removed
24
+ * @event GlobeView#layer-removed
25
+ * @property layerId {string} the id of the layer
26
+ * @property target {view} dispatched on view
27
+ * @property type {string} layers-added
28
+ */
29
+ /**
30
+ * Fires when the layers oder has changed
31
+ * @event GlobeView#layers-order-changed
32
+ * @property new {object}
33
+ * @property new.sequence {array}
34
+ * @property new.sequence.0 {number} the new layer at position 0
35
+ * @property new.sequence.1 {number} the new layer at position 1
36
+ * @property new.sequence.2 {number} the new layer at position 2
37
+ * @property previous {object}
38
+ * @property previous.sequence {array}
39
+ * @property previous.sequence.0 {number} the previous layer at position 0
40
+ * @property previous.sequence.1 {number} the previous layer at position 1
41
+ * @property previous.sequence.2 {number} the previous layer at position 2
42
+ * @property target {view} dispatched on view
43
+ * @property type {string} layers-order-changed
44
+ */
45
+
46
+ /**
47
+ * Globe's EVENT
48
+ * @property GLOBE_INITIALIZED {string} Deprecated: emit one time when globe is initialized (use VIEW_EVENTS.INITIALIZED instead).
49
+ * @property LAYER_ADDED {string} Deprecated: emit when layer id added in viewer (use VIEW_EVENTS.LAYER_ADDED instead).
50
+ * @property LAYER_REMOVED {string} Deprecated: emit when layer id removed in viewer (use VIEW_EVENTS.LAYER_REMOVED instead).
51
+ * @property COLOR_LAYERS_ORDER_CHANGED {string} Deprecated: emit when color layers order change (use VIEW_EVENTS.COLOR_LAYERS_ORDER_CHANGED instead).
52
+ */
53
+
54
+ export const GLOBE_VIEW_EVENTS = {
55
+ GLOBE_INITIALIZED: VIEW_EVENTS.INITIALIZED,
56
+ LAYER_ADDED: VIEW_EVENTS.LAYER_ADDED,
57
+ LAYER_REMOVED: VIEW_EVENTS.LAYER_REMOVED,
58
+ COLOR_LAYERS_ORDER_CHANGED: VIEW_EVENTS.COLOR_LAYERS_ORDER_CHANGED
59
+ };
60
+ class GlobeView extends View {
61
+ /**
62
+ * Creates a view of a globe.
63
+ *
64
+ * @extends View
65
+ *
66
+ * @example <caption><b>Instance GlobeView.</b></caption>
67
+ * var viewerDiv = document.getElementById('viewerDiv');
68
+ * const placement = {
69
+ * coord: new itowns.Coordinates('EPSG:4326', 2.351323, 48.856712),
70
+ * range: 25000000,
71
+ * }
72
+ * var view = new itowns.GlobeView(viewerDiv, placement);
73
+ *
74
+ * @param {HTMLDivElement} viewerDiv - Where to attach the view and display it
75
+ * in the DOM.
76
+ * @param {CameraTransformOptions|Extent} placement - An object to place view
77
+ * @param {object} [options] - See options of {@link View}.
78
+ * @param {Object} [options.controls] - See options of {@link GlobeControls}
79
+ */
80
+ constructor(viewerDiv) {
81
+ let placement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
82
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
83
+ THREE.Object3D.DEFAULT_UP.set(0, 0, 1);
84
+ // Setup View
85
+ super('EPSG:4978', viewerDiv, options);
86
+ this.isGlobeView = true;
87
+ this.camera3D.near = Math.max(15.0, 0.000002352 * ellipsoidSizes.x);
88
+ this.camera3D.far = ellipsoidSizes.x * 10;
89
+ const tileLayer = new GlobeLayer('globe', options.object3d, options);
90
+ this.mainLoop.gfxEngine.label2dRenderer.infoTileLayer = tileLayer.info;
91
+ this.addLayer(tileLayer);
92
+ this.tileLayer = tileLayer;
93
+ if (!placement.isExtent) {
94
+ placement.coord = placement.coord || new Coordinates('EPSG:4326', 0, 0);
95
+ placement.tilt = placement.tilt || 89.5;
96
+ placement.heading = placement.heading || 0;
97
+ placement.range = placement.range || ellipsoidSizes.x * 2.0;
98
+ }
99
+ if (options.noControls) {
100
+ CameraUtils.transformCameraToLookAtTarget(this, this.camera3D, placement);
101
+ } else {
102
+ this.controls = new GlobeControls(this, placement, options.controls);
103
+ this.controls.handleCollision = typeof options.handleCollision !== 'undefined' ? options.handleCollision : true;
104
+ }
105
+ this.addLayer(new Atmosphere('atmosphere', options.atmosphere));
106
+
107
+ // GlobeView needs this.camera.resize to set perpsective matrix camera
108
+ this.camera.resize(viewerDiv.clientWidth, viewerDiv.clientHeight);
109
+ }
110
+
111
+ /**
112
+ * Add layer in viewer.
113
+ * The layer id must be unique.
114
+ *
115
+ * The `layer.whenReady` is a promise that resolves when
116
+ * the layer is done. This promise is also returned by
117
+ * `addLayer` allowing to chain call.
118
+ *
119
+ * The layer added is attached, by default to `GlobeLayer` (`GlobeView.tileLayer`).
120
+ * If you want add a unattached layer use `View#addLayer` parent method.
121
+ *
122
+ * @param {LayerOptions|Layer|GeometryLayer} layer The layer to add in view.
123
+ * @return {Promise} a promise resolved with the new layer object when it is fully initialized or rejected if any error occurred.
124
+ */
125
+ addLayer(layer) {
126
+ if (!layer || !layer.isLayer) {
127
+ return Promise.reject(new Error('Add Layer type object'));
128
+ }
129
+ if (layer.isColorLayer) {
130
+ if (!this.tileLayer.tileMatrixSets.includes(layer.source.crs)) {
131
+ return layer._reject(`Only ${this.tileLayer.tileMatrixSets} tileMatrixSet are currently supported for color layers`);
132
+ }
133
+ } else if (layer.isElevationLayer) {
134
+ if (layer.source.crs !== this.tileLayer.tileMatrixSets[0]) {
135
+ return layer._reject(`Only ${this.tileLayer.tileMatrixSets[0]} tileMatrixSet is currently supported for elevation layers`);
136
+ }
137
+ }
138
+ return super.addLayer(layer, this.tileLayer);
139
+ }
140
+ getPixelsToDegrees() {
141
+ let pixels = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
142
+ let screenCoord = arguments.length > 1 ? arguments[1] : undefined;
143
+ return this.getMetersToDegrees(this.getPixelsToMeters(pixels, screenCoord));
144
+ }
145
+ getPixelsToDegreesFromDistance() {
146
+ let pixels = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
147
+ let distance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
148
+ return this.getMetersToDegrees(this.getPixelsToMetersFromDistance(pixels, distance));
149
+ }
150
+ getMetersToDegrees() {
151
+ let meters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
152
+ return THREE.MathUtils.radToDeg(2 * Math.asin(meters / (2 * ellipsoidSizes.x)));
153
+ }
154
+ }
155
+ export default GlobeView;
@@ -0,0 +1,59 @@
1
+ import * as THREE from 'three';
2
+ import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
3
+ import { globalExtentTMS } from "../../Tile/TileGrid.js";
4
+ import { PlanarTileBuilder } from "./PlanarTileBuilder.js";
5
+
6
+ /**
7
+ * @property {boolean} isPlanarLayer - Used to checkout whether this layer is a
8
+ * PlanarLayer. Default is true. You should not change this, as it is used
9
+ * internally for optimisation.
10
+ * @extends TiledGeometryLayer
11
+ */
12
+ class PlanarLayer extends TiledGeometryLayer {
13
+ /**
14
+ * A {@link TiledGeometryLayer} to use with a {@link PlanarView}. It has
15
+ * specific method for updating and subdivising its grid.
16
+ *
17
+ * @param {string} id - The id of the layer, that should be unique. It is
18
+ * not mandatory, but an error will be emitted if this layer is added a
19
+ * {@link View} that already has a layer going by that id.
20
+ * @param {Extent} extent - The extent to define the layer within.
21
+ * @param {THREE.Object3d} [object3d=THREE.Group] - The object3d used to
22
+ * contain the geometry of the TiledGeometryLayer. It is usually a
23
+ * `THREE.Group`, but it can be anything inheriting from a `THREE.Object3d`.
24
+ * @param {Object} [config] - Optional configuration, all elements in it
25
+ * will be merged as is in the layer. For example, if the configuration
26
+ * contains three elements `name, protocol, extent`, these elements will be
27
+ * available using `layer.name` or something else depending on the property
28
+ * name.
29
+ * @param {number} [config.maxSubdivisionLevel=5] - Maximum subdivision
30
+ * level for this tiled layer.
31
+ *
32
+ * @throws {Error} `object3d` must be a valid `THREE.Object3d`.
33
+ */
34
+ constructor(id, extent, object3d) {
35
+ let config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
36
+ const {
37
+ minSubdivisionLevel = 0,
38
+ maxSubdivisionLevel = 5,
39
+ ...tiledConfig
40
+ } = config;
41
+ const tileMatrixSets = [extent.crs];
42
+ if (!globalExtentTMS.get(extent.crs)) {
43
+ // Add new global extent for this new crs projection.
44
+ globalExtentTMS.set(extent.crs, extent);
45
+ }
46
+ const builder = new PlanarTileBuilder({
47
+ crs: extent.crs
48
+ });
49
+ super(id, object3d || new THREE.Group(), [extent], builder, {
50
+ tileMatrixSets,
51
+ ...tiledConfig
52
+ });
53
+ this.isPlanarLayer = true;
54
+ this.extent = extent;
55
+ this.minSubdivisionLevel = minSubdivisionLevel;
56
+ this.maxSubdivisionLevel = maxSubdivisionLevel;
57
+ }
58
+ }
59
+ export default PlanarLayer;
@@ -0,0 +1,71 @@
1
+ import * as THREE from 'three';
2
+ import { Coordinates, Extent } from '@itowns/geographic';
3
+ const quaternion = new THREE.Quaternion();
4
+ const center = new THREE.Vector3();
5
+
6
+ /** Specialized parameters for the [PlanarTileBuilder]. */
7
+
8
+ /**
9
+ * TileBuilder implementation for the purpose of generating planar
10
+ * tile arrangements.
11
+ */
12
+ export class PlanarTileBuilder {
13
+ constructor(options) {
14
+ if (options.projection) {
15
+ console.warn('PlanarTileBuilder projection parameter is deprecated,' + ' use crs instead.');
16
+ options.crs ??= options.projection;
17
+ }
18
+ this._crs = options.crs;
19
+ this._transform = {
20
+ coords: new Coordinates('EPSG:4326', 0, 0),
21
+ position: new THREE.Vector3(),
22
+ normal: new THREE.Vector3(0, 0, 1)
23
+ };
24
+ this._uvCount = options.uvCount ?? 1;
25
+ }
26
+ get uvCount() {
27
+ return this._uvCount;
28
+ }
29
+ get crs() {
30
+ return this._crs;
31
+ }
32
+ prepare(params) {
33
+ const newParams = params;
34
+ newParams.nbRow = 2 ** (params.level + 1.0);
35
+ newParams.coordinates = new Coordinates(this.crs);
36
+ return newParams;
37
+ }
38
+ center(extent) {
39
+ extent.center(this._transform.coords);
40
+ center.set(this._transform.coords.x, this._transform.coords.y, 0);
41
+ return center;
42
+ }
43
+ vertexPosition(coordinates) {
44
+ this._transform.position.set(coordinates.x, coordinates.y, 0);
45
+ return this._transform.position;
46
+ }
47
+ vertexNormal() {
48
+ return this._transform.normal;
49
+ }
50
+ uProject(u, extent) {
51
+ return extent.west + u * (extent.east - extent.west);
52
+ }
53
+ vProject(v, extent) {
54
+ return extent.south + v * (extent.north - extent.south);
55
+ }
56
+ computeShareableExtent(extent) {
57
+ // compute shareable extent to pool the geometries
58
+ // the geometry in common extent is identical to the existing input
59
+ // with a translation
60
+ return {
61
+ shareableExtent: new Extent(extent.crs).setFromExtent({
62
+ west: 0,
63
+ east: Math.abs(extent.west - extent.east),
64
+ south: 0,
65
+ north: Math.abs(extent.north - extent.south)
66
+ }),
67
+ quaternion,
68
+ position: this.center(extent).clone()
69
+ };
70
+ }
71
+ }
@@ -0,0 +1,62 @@
1
+ import * as THREE from 'three';
2
+ import View from "../View.js";
3
+ import CameraUtils from "../../Utils/CameraUtils.js";
4
+ import PlanarControls from "../../Controls/PlanarControls.js";
5
+ import PlanarLayer from "./Planar/PlanarLayer.js";
6
+ class PlanarView extends View {
7
+ /**
8
+ * @extends View
9
+ *
10
+ * @example <caption><b>Instance with placement on the ground.</b></caption>
11
+ * var viewerDiv = document.getElementById('viewerDiv');
12
+ * const extent = new Extent('EPSG:3946', 1837816.94334, 1847692.32501, 5170036.4587, 5178412.82698);
13
+ * var view = new itowns.PlanarView(viewerDiv, extent, { placement: { heading: -49.6, range: 6200, tilt: 17 } });
14
+ *
15
+ * @param {HTMLDivElement} viewerDiv - Where to attach the view and display it
16
+ * in the DOM.
17
+ * @param {Extent} extent - The ground extent.
18
+ * @param {Object} [options] - See options of {@link View}.
19
+ * @param {boolean} [options.noControls=false] - If true, no controls are associated to the view.
20
+ * @param {Object} [options.controls] - options for the {@link PlanarControls} associated to the view, if
21
+ * `options.noControls` is false.
22
+ * @param {CameraUtils~CameraTransformOptions|Extent} [options.placement] - The
23
+ * {@link CameraUtils~CameraTransformOptions} to apply to view's camera or the extent it must display at
24
+ * initialization. By default, camera will display the view's extent (given in `extent` parameter).
25
+ */
26
+ constructor(viewerDiv, extent) {
27
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
28
+ THREE.Object3D.DEFAULT_UP.set(0, 0, 1);
29
+
30
+ // Setup View
31
+ super(extent.crs, viewerDiv, options);
32
+ this.isPlanarView = true;
33
+
34
+ // Configure camera
35
+ const dim = extent.planarDimensions();
36
+ const max = Math.max(dim.x, dim.y);
37
+ this.camera3D.near = 0.1;
38
+ this.camera3D.far = this.camera3D.isOrthographicCamera ? 2000 : 2 * max;
39
+ this.camera3D.updateProjectionMatrix();
40
+ const tileLayer = new PlanarLayer('planar', extent, options.object3d, options);
41
+ this.mainLoop.gfxEngine.label2dRenderer.infoTileLayer = tileLayer.info;
42
+ this.addLayer(tileLayer);
43
+
44
+ // Configure camera
45
+ const placement = options.placement || {};
46
+ if (!placement.isExtent) {
47
+ placement.coord = placement.coord || extent.center();
48
+ placement.tilt = placement.tilt || 90;
49
+ placement.heading = placement.heading || 0;
50
+ placement.range = placement.range || max;
51
+ }
52
+ CameraUtils.transformCameraToLookAtTarget(this, this.camera3D, placement);
53
+ if (!options.noControls) {
54
+ this.controls = new PlanarControls(this, options.controls);
55
+ }
56
+ this.tileLayer = tileLayer;
57
+ }
58
+ addLayer(layer) {
59
+ return super.addLayer(layer, this.tileLayer);
60
+ }
61
+ }
62
+ export default PlanarView;
@@ -0,0 +1,82 @@
1
+ import * as THREE from 'three';
2
+ import { TileGeometry } from "../TileGeometry.js";
3
+ import { LRUCache } from 'lru-cache';
4
+ import { computeBuffers } from "./computeBufferTileGeometry.js";
5
+ import OBB from "../../Renderer/OBB.js";
6
+ const cacheBuffer = new Map();
7
+ const cacheTile = new LRUCache({
8
+ max: 500
9
+ });
10
+
11
+ /**
12
+ * Reference to a tile's extent with rigid transformations.
13
+ * Enables reuse of geometry, saving a bit of memory.
14
+ */
15
+
16
+ export function newTileGeometry(builder, params) {
17
+ const {
18
+ shareableExtent,
19
+ quaternion,
20
+ position
21
+ } = builder.computeShareableExtent(params.extent);
22
+ const south = shareableExtent.south.toFixed(6);
23
+ const bufferKey = `${builder.crs}_${params.disableSkirt ? 0 : 1}_${params.segments}`;
24
+ const key = `s${south}l${params.level}bK${bufferKey}`;
25
+ let promiseGeometry = cacheTile.get(key);
26
+
27
+ // build geometry if doesn't exist
28
+ if (!promiseGeometry) {
29
+ let resolve;
30
+ promiseGeometry = new Promise(r => {
31
+ resolve = r;
32
+ });
33
+ cacheTile.set(key, promiseGeometry);
34
+ params.extent = shareableExtent;
35
+ params.center = builder.center(params.extent).clone();
36
+ // Read previously cached values (index and uv.wgs84 only
37
+ // depend on the # of triangles)
38
+ let cachedBuffers = cacheBuffer.get(bufferKey);
39
+ let buffers;
40
+ try {
41
+ buffers = computeBuffers(builder, params, cachedBuffers !== undefined ? {
42
+ index: cachedBuffers.index.array,
43
+ uv: cachedBuffers.uv.array
44
+ } : undefined);
45
+ } catch (e) {
46
+ return Promise.reject(e);
47
+ }
48
+ if (!cachedBuffers) {
49
+ // We know the fields will exist due to the condition
50
+ // matching with the one for buildIndexAndUv_0.
51
+ // TODO: Make this brain-based check compiler-based.
52
+
53
+ cachedBuffers = {
54
+ index: new THREE.BufferAttribute(buffers.index, 1),
55
+ uv: new THREE.BufferAttribute(buffers.uvs[0], 2)
56
+ };
57
+
58
+ // Update cacheBuffer
59
+ cacheBuffer.set(bufferKey, cachedBuffers);
60
+ }
61
+ const gpuBuffers = {
62
+ index: cachedBuffers.index,
63
+ uvs: [cachedBuffers.uv, ...(buffers.uvs[1] !== undefined ? [new THREE.BufferAttribute(buffers.uvs[1], 1)] : [])],
64
+ position: new THREE.BufferAttribute(buffers.position, 3),
65
+ normal: new THREE.BufferAttribute(buffers.normal, 3)
66
+ };
67
+ const geometry = new TileGeometry(builder, params, gpuBuffers);
68
+ geometry.OBB = new OBB(geometry.boundingBox.min, geometry.boundingBox.max);
69
+ geometry.initRefCount(cacheTile, key);
70
+ resolve(geometry);
71
+ return Promise.resolve({
72
+ geometry,
73
+ quaternion,
74
+ position
75
+ });
76
+ }
77
+ return promiseGeometry.then(geometry => ({
78
+ geometry,
79
+ quaternion,
80
+ position
81
+ }));
82
+ }
@@ -0,0 +1,248 @@
1
+ import * as THREE from 'three';
2
+ export function getBufferIndexSize(segments, noSkirt) {
3
+ const triangles = segments * segments * 2 + (noSkirt ? 0 : 4 * segments * 2);
4
+ return triangles * 3;
5
+ }
6
+ function getUintArrayConstructor(highestValue) {
7
+ let picked = null;
8
+ if (highestValue < 2 ** 8) {
9
+ picked = Uint8Array;
10
+ } else if (highestValue < 2 ** 16) {
11
+ picked = Uint16Array;
12
+ } else if (highestValue < 2 ** 32) {
13
+ picked = Uint32Array;
14
+ } else {
15
+ throw new Error('Value is too high');
16
+ }
17
+ return picked;
18
+ }
19
+ function allocateIndexBuffer(nVertex, nSeg, params, cache) {
20
+ const indexBufferSize = getBufferIndexSize(nSeg, params.disableSkirt);
21
+ const indexConstructor = getUintArrayConstructor(nVertex);
22
+ const tileLen = indexBufferSize;
23
+ const skirtLen = 4 * nSeg;
24
+ if (cache !== undefined) {
25
+ return {
26
+ index: cache,
27
+ skirt: cache.subarray(tileLen, tileLen + skirtLen)
28
+ };
29
+ }
30
+ const indexBuffer = new ArrayBuffer((
31
+ // Tile
32
+ tileLen
33
+ // Skirt
34
+ + (params.disableSkirt ? 0 : skirtLen)) * indexConstructor.BYTES_PER_ELEMENT);
35
+ const index = new indexConstructor(indexBuffer);
36
+ const skirt = !params.disableSkirt ? index.subarray(tileLen, tileLen + skirtLen) : undefined;
37
+ return {
38
+ index,
39
+ skirt
40
+ };
41
+ }
42
+ function allocateBuffers(nVertex, nSeg, builder, params, cache) {
43
+ const {
44
+ index,
45
+ skirt
46
+ } = allocateIndexBuffer(nVertex, nSeg, params, cache?.index);
47
+ return {
48
+ index,
49
+ skirt,
50
+ position: new Float32Array(nVertex * 3),
51
+ normal: new Float32Array(nVertex * 3),
52
+ // 2 UV set per tile: wgs84 (uv[0]) and pseudo-mercator (pm, uv[1])
53
+ // - wgs84: 1 texture per tile because tiles are using wgs84
54
+ // projection
55
+ // - pm: use multiple textures per tile.
56
+ // +-------------------------+
57
+ // | |
58
+ // | Texture 0 |
59
+ // +-------------------------+
60
+ // | |
61
+ // | Texture 1 |
62
+ // +-------------------------+
63
+ // | |
64
+ // | Texture 2 |
65
+ // +-------------------------+
66
+ // * u = wgs84.u
67
+ // * v = textureid + v in builder texture
68
+ uvs: [cache?.uv ?? new Float32Array(nVertex * 2), builder.computeExtraOffset !== undefined ? new Float32Array(nVertex) : undefined]
69
+ };
70
+ }
71
+ function computeUv0(uv, id, u, v) {
72
+ uv[id * 2 + 0] = u;
73
+ uv[id * 2 + 1] = v;
74
+ }
75
+ function initComputeUv1(value) {
76
+ return (uv, id) => {
77
+ uv[id] = value;
78
+ };
79
+ }
80
+ /** Compute buffers describing a tile according to a builder and its params. */
81
+ // TODO: Split this even further into subfunctions
82
+ export function computeBuffers(builder, params, cache) {
83
+ // n seg, n+1 vert + <- skirt, n verts per side
84
+ // <---------------> / |
85
+ // +---+---+---+---+ |
86
+ // | / | / | / | / | | Vertices:
87
+ // +---+---+---+---+ - + tile = (n + 1)^2
88
+ // | / | / | / | / | | skirt = 4n
89
+ // +---+---+---+---+ - +
90
+ // | / | / | / | / | | Segments:
91
+ // +---+---+---+---+ - + tile = 2 * n * (n + 1) + n^2
92
+ // | / | / | / | / | | skirt = 2n * 4
93
+ // +---+---+---+---+ |
94
+ const nSeg = Math.max(2, params.segments);
95
+ const nVertex = nSeg + 1;
96
+ const nTileVertex = nVertex ** 2;
97
+ const nSkirtVertex = params.disableSkirt ? 0 : 4 * nSeg;
98
+ const nTotalVertex = nTileVertex + nSkirtVertex;
99
+
100
+ // Computer should combust before this happens
101
+ if (nTotalVertex > 2 ** 32) {
102
+ throw new Error('Tile segments count is too big');
103
+ }
104
+ const outBuffers = allocateBuffers(nTotalVertex, nSeg, builder, params, cache);
105
+ const computeUvs = [cache === undefined ? computeUv0 : () => {}];
106
+ params = builder.prepare(params);
107
+ for (let y = 0; y <= nSeg; y++) {
108
+ const v = y / nSeg;
109
+ params.coordinates.y = builder.vProject(v, params.extent);
110
+ if (builder.computeExtraOffset !== undefined) {
111
+ computeUvs[1] = initComputeUv1(builder.computeExtraOffset(params));
112
+ }
113
+ for (let x = 0; x <= nSeg; x++) {
114
+ const u = x / nSeg;
115
+ const id_m3 = (y * nVertex + x) * 3;
116
+ params.coordinates.x = builder.uProject(u, params.extent);
117
+ const vertex = builder.vertexPosition(params.coordinates);
118
+ const normal = builder.vertexNormal();
119
+
120
+ // move geometry to center world
121
+ vertex.sub(params.center);
122
+
123
+ // align normal to z axis
124
+ // HACK: this check style is not great
125
+ if ('quatNormalToZ' in params) {
126
+ const quat = params.quatNormalToZ;
127
+ vertex.applyQuaternion(quat);
128
+ normal.applyQuaternion(quat);
129
+ }
130
+ vertex.toArray(outBuffers.position, id_m3);
131
+ normal.toArray(outBuffers.normal, id_m3);
132
+ for (const [index, computeUv] of computeUvs.entries()) {
133
+ if (computeUv !== undefined) {
134
+ computeUv(outBuffers.uvs[index], y * nVertex + x, u, v);
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ // Fill skirt index buffer
141
+ if (cache === undefined && !params.disableSkirt) {
142
+ for (let x = 0; x < nVertex; x++) {
143
+ // -------->
144
+ // 0---1---2
145
+ // | / | / | [0-9] = assign order
146
+ // +---+---+
147
+ // | / | / |
148
+ // +---+---+
149
+ outBuffers.skirt[x] = x;
150
+ // +---+---+
151
+ // | / | / | [0-9] = assign order
152
+ // +---+---x x = skipped for now
153
+ // | / | / |
154
+ // 0---1---2
155
+ // <--------
156
+ outBuffers.skirt[2 * nVertex - 2 + x] = nVertex ** 2 - (x + 1);
157
+ }
158
+ for (let y = 1; y < nVertex - 1; y++) {
159
+ // +---+---s |
160
+ // | / | / | | o = stored vertices
161
+ // +---+---o | s = already stored
162
+ // | / | / | |
163
+ // +---+---s v
164
+ outBuffers.skirt[nVertex - 1 + y] = y * nVertex + (nVertex - 1);
165
+ // ^ s---+---+
166
+ // | | / | / | o = stored vertices
167
+ // | o---+---+ s = already stored
168
+ // | | / | / |
169
+ // | s---+---+
170
+ outBuffers.skirt[3 * nVertex - 3 + y] = nVertex * (nVertex - 1 - y);
171
+ }
172
+ }
173
+
174
+ /** Copy passed indices at the desired index of the output index buffer. */
175
+ function bufferizeTri(id, va, vb, vc) {
176
+ outBuffers.index[id + 0] = va;
177
+ outBuffers.index[id + 1] = vb;
178
+ outBuffers.index[id + 2] = vc;
179
+ }
180
+ if (cache === undefined) {
181
+ for (let y = 0; y < nSeg; y++) {
182
+ for (let x = 0; x < nSeg; x++) {
183
+ const v1 = y * nVertex + (x + 1);
184
+ const v2 = y * nVertex + x;
185
+ const v3 = (y + 1) * nVertex + x;
186
+ const v4 = (y + 1) * nVertex + (x + 1);
187
+ const id = (y * nSeg + x) * 6;
188
+ bufferizeTri(id, /**/v4, v2, v1);
189
+ bufferizeTri(id + 3, v4, v3, v2);
190
+ }
191
+ }
192
+ }
193
+
194
+ // PERF: Beware skirt's size influences performance
195
+ // INFO: The size of the skirt is now a ratio of the size of the tile.
196
+ // To be perfect it should depend on the real elevation delta but too heavy
197
+ // to compute
198
+ if (!params.disableSkirt) {
199
+ // We compute the actual size of tile segment to use later for
200
+ // the skirt.
201
+ const segmentSize = new THREE.Vector3().fromArray(outBuffers.position).distanceTo(new THREE.Vector3().fromArray(outBuffers.position, 3));
202
+ const buildSkirt = cache === undefined ? {
203
+ index: (id, v1, v2, v3, v4) => {
204
+ bufferizeTri(id, v1, v2, v3);
205
+ bufferizeTri(id + 3, v1, v3, v4);
206
+ return id + 6;
207
+ },
208
+ uv: (buf, idTo, idFrom) => {
209
+ buf[idTo * 2 + 0] = buf[idFrom * 2 + 0];
210
+ buf[idTo * 2 + 1] = buf[idFrom * 2 + 1];
211
+ }
212
+ } : {
213
+ index: () => {},
214
+ uv: () => {}
215
+ };
216
+
217
+ // Alias for readability
218
+ const start = nTileVertex;
219
+ for (let i = 0; i < outBuffers.skirt.length; i++) {
220
+ const id = outBuffers.skirt[i];
221
+ const id_m3 = (start + i) * 3;
222
+ const id2_m3 = id * 3;
223
+ outBuffers.position[id_m3 + 0] = outBuffers.position[id2_m3 + 0] - outBuffers.normal[id2_m3 + 0] * segmentSize;
224
+ outBuffers.position[id_m3 + 1] = outBuffers.position[id2_m3 + 1] - outBuffers.normal[id2_m3 + 1] * segmentSize;
225
+ outBuffers.position[id_m3 + 2] = outBuffers.position[id2_m3 + 2] - outBuffers.normal[id2_m3 + 2] * segmentSize;
226
+ outBuffers.normal[id_m3 + 0] = outBuffers.normal[id2_m3 + 0];
227
+ outBuffers.normal[id_m3 + 1] = outBuffers.normal[id2_m3 + 1];
228
+ outBuffers.normal[id_m3 + 2] = outBuffers.normal[id2_m3 + 2];
229
+ buildSkirt.uv(outBuffers.uvs[0], start + i, id);
230
+ if (outBuffers.uvs[1] !== undefined) {
231
+ outBuffers.uvs[1][start + i] = outBuffers.uvs[1][id];
232
+ }
233
+ const idf = (i + 1) % outBuffers.skirt.length;
234
+ const v2 = start + i;
235
+ const v3 = idf === 0 ? start : start + i + 1;
236
+ const v4 = outBuffers.skirt[idf];
237
+ buildSkirt.index(6 * nSeg ** 2 + i * 6, id, v2, v3, v4);
238
+ }
239
+ }
240
+
241
+ // Dropping skirt view
242
+ return {
243
+ index: outBuffers.index,
244
+ position: outBuffers.position,
245
+ uvs: outBuffers.uvs,
246
+ normal: outBuffers.normal
247
+ };
248
+ }